📄 mystr.cpp
字号:
/*=========================================================
* File name : MyStr.cpp
* Description : 字符串处理,支持多线程
*
* Modify :
*=========================================================*
#include "mystr.h"
#include "stdlib.h"
#include "stdio.h"
#include "stdarg.h"
#include "string.h"
*/
/*********************************************************************
* Proc: cstr_abort_application
* Purpose: 简单的错误处理,有对话框提示
*********************************************************************/
//static char buf[65535];
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "pthread.h"
#include "mystr.h"
#include "memmgr.h"
#include "ctype.h"
void cstr_abort_application(int fatal_type)
{
// Display message and abort
char msg[64];
sprintf (msg, "CStr fatal %d", fatal_type);
abort();
}
// Define specific type of ASSERT
#ifdef _DEBUG
#define CSTR_ASSERT(x) { if ((x) == 0) cstr_abort_application (1111); }
#else
#define CSTR_ASSERT(x) { }
#endif
/*********************************************************************
* Proc: CStr::destructor
*********************************************************************/
CStr::~CStr()
{
// MyMemFree associated text block and descriptor
MyMemFree (data.m_Text);
}
/*********************************************************************
* Proc: CStr::NewFromString
* Purpose: Core code for 'copy char* constructor' and '= operator'.
* Assumes our 'data' field is garbage on entry.
*********************************************************************/
void CStr::NewFromString(const char* s, int slen, int prealloc)
{
// Determine actual size of buffer that needs to be allocated
if (slen > prealloc)
prealloc = slen;
// Empty string?
if (slen == 0 && prealloc == 0) {
return;
}
// Round up to MyMemAlloc() granularity
// Get memory for string
char* target = (char*) MyMemAlloc (prealloc+1);
ThrowIfNull(target);
// Copy the string bytes, including the null
memcpy (target, s, slen+1);
target[ slen ] = 0;//set NULL terminated
if( data.m_Text != NULL )MyMemFree(data.m_Text);
// Locate MyMemFree descriptor, fill it in
data.m_Text = target;
data.m_Length = slen;
data.m_Alloc = prealloc;
}
/*********************************************************************
* Proc: CStr::CStr (UINT prealloc)
* Purpose: Instantiates an empty string, but with the specified
* number of bytes in the preallocated buffer.
* In: prealloc - number of bytes to reserve
*********************************************************************/
CStr::CStr(int prealloc)//default value is 32
{
m_wordfindpos =0;
if( prealloc <= 0 )prealloc=DEFAULT_CSTR_LENGTH;
// Get memory for string
char* target = (char*) MyMemAlloc (prealloc+1);
if (target == NULL)
return ;
ThrowIfNull(target);
target[0] = 0;
// Locate MyMemFree descriptor, fill it in
data.m_Text = target;
data.m_Length = 0;
data.m_Alloc = prealloc;
}
/*********************************************************************
* Proc: CStr::CStr(const char*)
* Purpose: Construct an instance that exactly copies the specified
* string. An optional second parameter specifies the buffer
* size (will be ignored if it is less than what's needed)
*********************************************************************/
CStr::CStr(const char* s, int prealloc /*= 32*/)
{
int slen = 0;
m_wordfindpos =0;
data.m_Text = NULL;
data.m_Alloc = 0;
data.m_Length = 0;
if( prealloc <= 0 )prealloc=DEFAULT_CSTR_LENGTH;
// No need to check for limit in CSTR_LARGE_STRINGS, because
// NewFromString will blow up because of the buffer size
slen = strlen(s);
NewFromString(s, slen, prealloc);
}
/*********************************************************************
* Proc: CStr::copy constructor
*********************************************************************/
CStr::CStr(const CStr& source)
{
// Determine actual size of buffer that needs to be allocated
int slen = source.GetLength();
int prealloc = DEFAULT_CSTR_LENGTH;
data.m_Length = 0;
data.m_Alloc = 0;
data.m_Text = NULL;
m_wordfindpos =0;
// Empty string?
if( slen > prealloc )
{
prealloc = slen;
}
// Round up to MyMemAlloc() granularity
// Get memory for string
char* target = (char*) MyMemAlloc (prealloc+1);
ThrowIfNull(target);
// Locate MyMemFree descriptor, fill it in
data.m_Text = target;
data.m_Length = slen;
data.m_Alloc = prealloc;
// Copy the string bytes, including the null
memcpy (target, source.GetString(), slen+1);
target[ slen ] = 0;//set NULL terminated
}
CStr::CStr( const CStr * source )
{
// Determine actual size of buffer that needs to be allocated
int slen = source->GetLength();
int prealloc;
data.m_Length = 0;
data.m_Alloc = 0;
data.m_Text = NULL;
m_wordfindpos =0;
// Empty string?
if( slen == 0 )
{
prealloc = DEFAULT_CSTR_LENGTH;
}
// Round up to MyMemAlloc() granularity
// Get memory for string
char* target = (char*) MyMemAlloc (prealloc+1);
ThrowIfNull(target);
// Locate MyMemFree descriptor, fill it in
data.m_Text = target;
data.m_Length = slen;
data.m_Alloc = prealloc;
// Copy the string bytes, including the null
memcpy (target, source->GetString(), slen+1);
target[ slen ] = 0;//set NULL terminated
}
/*********************************************************************
* Proc: CStr::operator = CStr
* Purpose: Copies a string into another string, destroying the
* previous content.
*********************************************************************/
const CStr& CStr::operator=(const CStr& source)
{
// Determine actual size of buffer that needs to be allocated
int slen = source.GetLength();
m_wordfindpos =0;
// Empty string?
if( slen == 0 )
{
return *this;
}
char* target;
if( data.m_Alloc < slen )
{
MyMemFree( data.m_Text );
// Round up to MyMemAlloc() granularity
// Get memory for string
target = (char*) MyMemAlloc (slen+1);
ThrowIfNull(target);
data.m_Text = target;
data.m_Alloc = slen;
}
else
{
target = data.m_Text;
}
// Locate MyMemFree descriptor, fill it in
data.m_Length = slen;
// Copy the string bytes, including the null
memcpy (target, source.GetString(), slen+1);
target[ slen ] = 0;//set NULL terminated
return *this;
}
/*********************************************************************
* Proc: CStr::Buffer
* Purpose: Helper. Makes sure that our internal buffer has
* the specified number of bytes available, and that
* we can overwrite it (i.e. m_Usage is 1). If this
* isn't so, prepares a copy of our internal data.
*********************************************************************/
void CStr::Buffer (int newlength)
{
// Reallocate. First handle case where we cannot just
// touch the buffer. We don't need to test for m_Null
// here because it's m_Usage field is always >1
// Buffer already big enough?
if (data.m_Alloc >= newlength)
return;
int prevLength = data.m_Length;
if (newlength < prevLength)
newlength = prevLength;
NewFromString( data.m_Text, prevLength, newlength);
}
/*********************************************************************
* Proc: CStr::operator = const char
* Purpose: Copies a char into our internal buffer, if it is big
* enough and is used only by us; otherwise, MyMemFrees the
* current instance and allocates a new one.
*********************************************************************/
const CStr& CStr::operator=(const char ch)
{
m_wordfindpos =0;
// Check for zero length string.
char s[2];
s[0] = ch;
s[1] = '\0';
// Check for zero length string.
int slen = 1;
// Can we handle this without reallocations? NOTE: we do
// not use Buffer() here because if the string needs to
// be expanded, the old one will be copied, and we don't
// care about it anyway.
if ( data.m_Alloc > slen)
{
// Yes, copy bytes and get out
memcpy (data.m_Text, s, slen+1);
data.m_Length = (int) slen;
return *this;
}
// No. MyMemFree old string, allocate new one.
NewFromString(s, (int) slen, 1);
return *this;
}
/*********************************************************************
* Proc: CStr::operator = const char*
* Purpose: Copies a string into our internal buffer, if it is big
* enough and is used only by us; otherwise, MyMemFrees the
* current instance and allocates a new one.
*********************************************************************/
const CStr& CStr::operator=(const char* s)
{
m_wordfindpos =0;
// Check for zero length string.
int slen = strlen(s);
if (slen == 0)
{
if ( data.m_Text != 0 )
data.m_Text[0] = 0;;
data.m_Length = 0;
return *this;
}
// Can we handle this without reallocations? NOTE: we do
// not use Buffer() here because if the string needs to
// be expanded, the old one will be copied, and we don't
// care about it anyway.
if ( data.m_Alloc > slen)
{
// Yes, copy bytes and get out
memcpy (data.m_Text, s, slen+1);
data.m_Length = (int) slen;
return *this;
}
// No. MyMemFree old string, allocate new one.
NewFromString(s, (int) slen, 0);
return *this;
}
/*********************************************************************
* Proc: CStr::Empty
* Purpose: Sets the string to NULL. However, the allocated buffer
* is not released.
*********************************************************************/
void CStr::Empty()
{
m_wordfindpos =0;
if( data.m_Text != NULL )data.m_Text[0] = 0;
data.m_Length = 0;
}
/*********************************************************************
* Proc: CStr::AddChar
* Purpose: Appends a single character to the end of the string
*********************************************************************/
void CStr::AddChar(char ch)
{
// Get a copy if m_Usage>1, expand buffer if necessary
UINT cur_len = data.m_Length;
Buffer (int(cur_len + 1));
// And append the character (no need for CStrCritical because of Buffer)
data.m_Text[cur_len] = ch;
data.m_Text[cur_len+1] = 0;
data.m_Length = int(cur_len+1);
}
/*********************************************************************
* Proc: CStr::AddInt
* Purpose: Appends a decimal signed integer, possibly with - sign
*********************************************************************/
void CStr::AddInt(int value)
{
char buf[32];
sprintf( buf, "%d", value );
AddString (buf);
}
/*********************************************************************
* Proc: CStr::AddDouble
* Purpose: Appends a signed double value, uses specified # of digits
*********************************************************************/
void CStr::AddDouble(double value, UINT after_dot)
{
if (after_dot > 48)
after_dot = 48;
char fmt[16];
sprintf (fmt, "%%.%df", (int) after_dot);
char buf[256];
sprintf (buf, fmt, value);
AddString (buf);
}
/*********************************************************************
* Proc: CStr::CoreAddChars
* Purpose: Core code for AddChars() and operators +=; assumes
* howmany is bigger than 0
*********************************************************************/
void CStr::CoreAddChars(const char* s, int howmany)
{
if(howmany <= 0)
{
return;
}
assert(howmany>=0&&howmany<1024*1024);
// Prepare big enough buffer
Buffer (int(data.m_Length + howmany));
// And copy the bytes
char* dest = data.m_Text + data.m_Length;
memcpy (dest, s, howmany);
dest[howmany] = 0;
data.m_Length = int(data.m_Length + howmany);
}
/*********************************************************************
* Proc: CStr::operator += (both from const char* and from CStr)
* Purpose: Append a string to what we already contain.
*********************************************************************/
void CStr::operator += (const CStr& obj)
{
if (obj.data.m_Length != 0)
CoreAddChars (obj.data.m_Text, obj.data.m_Length);
}
void CStr::operator += (const char* s)
{
UINT slen = strlen(s);
if (slen != 0) {
CoreAddChars (s, (int) slen);
}
}
/*********************************************************************
* Proc: CStr::AddChars
* Purpose: Catenates a number of characters to our internal data.
*********************************************************************/
void CStr::AddChars(const char* s, int startat, int howmany)
{
if (howmany != 0) {
CoreAddChars (s+startat, howmany);
}
}
/*********************************************************************
* Proc: CStr::AddStringAtLeft
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -