contain.cxx
来自「opal的ptlib c++源程序 可以从官方网站上下载」· CXX 代码 · 共 2,763 行 · 第 1/4 页
CXX
2,763 行
return P_MAX_INDEX;
PINDEX len = GetLength();
while (offset < len) {
const char * p = cset;
while (*p != '\0') {
if (InternalCompare(offset, *p) == EqualTo)
return offset;
p++;
}
offset++;
}
return P_MAX_INDEX;
}
PINDEX PString::FindSpan(const char * cset, PINDEX offset) const
{
if (cset == NULL || *cset == '\0' || offset < 0)
return P_MAX_INDEX;
PINDEX len = GetLength();
while (offset < len) {
const char * p = cset;
while (InternalCompare(offset, *p) != EqualTo) {
if (*++p == '\0')
return offset;
}
offset++;
}
return P_MAX_INDEX;
}
PINDEX PString::FindRegEx(const PRegularExpression & regex, PINDEX offset) const
{
if (offset < 0)
return P_MAX_INDEX;
PINDEX pos = 0;
PINDEX len = 0;
if (FindRegEx(regex, pos, len, offset))
return pos;
return P_MAX_INDEX;
}
PBoolean PString::FindRegEx(const PRegularExpression & regex,
PINDEX & pos,
PINDEX & len,
PINDEX offset,
PINDEX maxPos) const
{
if (offset < 0 || maxPos < 0 || offset >= GetLength())
return PFalse;
if (!regex.Execute(&theArray[offset], pos, len, 0))
return PFalse;
pos += offset;
if (pos+len > maxPos)
return PFalse;
return PTrue;
}
void PString::Replace(const PString & target,
const PString & subs,
PBoolean all, PINDEX offset)
{
if (offset < 0)
return;
MakeUnique();
PINDEX tlen = target.GetLength();
PINDEX slen = subs.GetLength();
do {
PINDEX pos = Find(target, offset);
if (pos == P_MAX_INDEX)
return;
Splice(subs, pos, tlen);
offset = pos + slen;
} while (all);
}
void PString::Splice(const char * cstr, PINDEX pos, PINDEX len)
{
if (len < 0 || pos < 0)
return;
register PINDEX slen = GetLength();
if (pos >= slen)
operator+=(cstr);
else {
MakeUnique();
PINDEX clen = cstr != NULL ? strlen(cstr) : 0;
PINDEX newlen = slen-len+clen;
if (clen > len)
SetSize(newlen+1);
if (pos+len < slen)
memmove(theArray+pos+clen, theArray+pos+len, slen-pos-len+1);
if (clen > 0)
memcpy(theArray+pos, cstr, clen);
theArray[newlen] = '\0';
}
}
PStringArray
PString::Tokenise(const char * separators, PBoolean onePerSeparator) const
{
PStringArray tokens;
if (separators == NULL || IsEmpty()) // No tokens
return tokens;
PINDEX token = 0;
PINDEX p1 = 0;
PINDEX p2 = FindOneOf(separators);
if (p2 == 0) {
if (onePerSeparator) { // first character is a token separator
tokens[token] = Empty();
token++; // make first string in array empty
p1 = 1;
p2 = FindOneOf(separators, 1);
}
else {
do {
p1 = p2 + 1;
} while ((p2 = FindOneOf(separators, p1)) == p1);
}
}
while (p2 != P_MAX_INDEX) {
if (p2 > p1)
tokens[token] = operator()(p1, p2-1);
else
tokens[token] = Empty();
token++;
// Get next separator. If not one token per separator then continue
// around loop to skip over all the consecutive separators.
do {
p1 = p2 + 1;
} while ((p2 = FindOneOf(separators, p1)) == p1 && !onePerSeparator);
}
tokens[token] = operator()(p1, P_MAX_INDEX);
return tokens;
}
PStringArray PString::Lines() const
{
PStringArray lines;
if (IsEmpty())
return lines;
PINDEX line = 0;
PINDEX p1 = 0;
PINDEX p2;
while ((p2 = FindOneOf("\r\n", p1)) != P_MAX_INDEX) {
lines[line++] = operator()(p1, p2-1);
p1 = p2 + 1;
if (theArray[p2] == '\r' && theArray[p1] == '\n') // CR LF pair
p1++;
}
if (p1 < GetLength())
lines[line] = operator()(p1, P_MAX_INDEX);
return lines;
}
PStringArray & PStringArray::operator += (const PStringArray & v)
{
PINDEX i;
for (i = 0; i < v.GetSize(); i++)
AppendString(v[i]);
return *this;
}
PString PString::LeftTrim() const
{
const char * lpos = theArray;
while (isspace(*lpos & 0xff))
lpos++;
return PString(lpos);
}
PString PString::RightTrim() const
{
char * rpos = theArray+GetLength()-1;
if (!isspace(*rpos & 0xff))
return *this;
while (isspace(*rpos & 0xff)) {
if (rpos == theArray)
return Empty();
rpos--;
}
// make Apple & Tornado gnu compiler happy
PString retval(theArray, rpos - theArray + 1);
return retval;
}
PString PString::Trim() const
{
const char * lpos = theArray;
while (isspace(*lpos & 0xff))
lpos++;
if (*lpos == '\0')
return Empty();
const char * rpos = theArray+GetLength()-1;
if (!isspace(*rpos & 0xff)) {
if (lpos == theArray)
return *this;
else
return PString(lpos);
}
while (isspace(*rpos & 0xff))
rpos--;
return PString(lpos, rpos - lpos + 1);
}
PString PString::ToLower() const
{
PString newStr(theArray);
for (char *cpos = newStr.theArray; *cpos != '\0'; cpos++) {
if (isupper(*cpos & 0xff))
*cpos = (char)tolower(*cpos & 0xff);
}
return newStr;
}
PString PString::ToUpper() const
{
PString newStr(theArray);
for (char *cpos = newStr.theArray; *cpos != '\0'; cpos++) {
if (islower(*cpos & 0xff))
*cpos = (char)toupper(*cpos & 0xff);
}
return newStr;
}
long PString::AsInteger(unsigned base) const
{
PAssert(base >= 2 && base <= 36, PInvalidParameter);
char * dummy;
return strtol(theArray, &dummy, base);
}
DWORD PString::AsUnsigned(unsigned base) const
{
PAssert(base >= 2 && base <= 36, PInvalidParameter);
char * dummy;
return strtoul(theArray, &dummy, base);
}
double PString::AsReal() const
{
#ifndef __HAS_NO_FLOAT
char * dummy;
return strtod(theArray, &dummy);
#else
return 0.0;
#endif
}
PWCharArray PString::AsUCS2() const
{
PWCharArray ucs2(1); // Null terminated empty string
if (IsEmpty())
return ucs2;
#ifdef P_HAS_G_CONVERT
gsize g_len = 0;
gchar * g_ucs2 = g_convert(theArray, GetSize()-1, "UCS-2", "UTF-8", 0, &g_len, 0);
if (g_ucs2 != NULL) {
if (ucs2.SetSize(g_len))
memcpy(ucs2.GetPointer(), g_ucs2, g_len*2);
g_free(g_ucs2);
return ucs2;
}
PTRACE(1, "PTLib\tg_convert failed with error " << errno);
#elif defined(_WIN32)
// Note that MB_ERR_INVALID_CHARS is the only dwFlags value supported by Code page 65001 (UTF-8). Windows XP and later.
PINDEX length = GetLength();
PINDEX count = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, theArray, length, NULL, 0);
if (count > 0 && ucs2.SetSize(count+1)) { // Allow for trailing NULL
MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, theArray, length, ucs2.GetPointer(), ucs2.GetSize());
return ucs2;
}
#if PTRACING
if (GetLastError() == ERROR_NO_UNICODE_TRANSLATION)
PTRACE(1, "PTLib\tMultiByteToWideChar failed on non legal UTF-8 \"" << theArray << '"');
else
PTRACE(1, "PTLib\tMultiByteToWideChar failed with error " << ::GetLastError());
#endif
#endif
if (ucs2.SetSize(GetSize())) { // Will be at least this big
PINDEX count = 0;
PINDEX i = 0;
PINDEX length = GetSize(); // Include the trailing '\0'
while (i < length) {
int c = theArray[i];
if ((c&0x80) == 0)
ucs2[count++] = (BYTE)theArray[i++];
else if ((c&0xe0) == 0xc0) {
if (i < length-1)
ucs2[count++] = (WORD)(((theArray[i ]&0x1f)<<6)|
(theArray[i+1]&0x3f));
i += 2;
}
else if ((c&0xf0) == 0xe0) {
if (i < length-2)
ucs2[count++] = (WORD)(((theArray[i ]&0x0f)<<12)|
((theArray[i+1]&0x3f)<< 6)|
(theArray[i+2]&0x3f));
i += 3;
}
else {
if ((c&0xf8) == 0xf0)
i += 4;
else if ((c&0xfc) == 0xf8)
i += 5;
else
i += 6;
if (i <= length)
ucs2[count++] = 0xffff;
}
}
ucs2.SetSize(count); // Final size
}
return ucs2;
}
void PString::InternalFromUCS2(const wchar_t * ptr, PINDEX len)
{
if (ptr == NULL || len <= 0) {
*this = Empty();
return;
}
#ifdef P_HAS_G_CONVERT
gsize g_len = 0;
gchar * g_utf8 = g_convert(ptr, len, "UTF-8", "UCS-2", 0, &g_len, 0);
if (g_utf8 == NULL) {
*this = Empty();
return;
}
if (SetSize(&g_len))
memcpy(theArray, g_char, g_len);
g_free(g_utf8);
#elif defined(_WIN32)
PINDEX count = WideCharToMultiByte(CP_UTF8, 0, ptr, len, NULL, 0, NULL, NULL);
if (SetSize(count+1))
WideCharToMultiByte(CP_UTF8, 0, ptr, len, GetPointer(), GetSize(), NULL, NULL);
#else
PINDEX i;
PINDEX count = 1;
for (i = 0; i < len; i++) {
if (ptr[i] < 0x80)
count++;
else if (ptr[i] < 0x800)
count += 2;
else
count += 3;
}
if (SetSize(count)) {
count = 0;
for (i = 0; i < len; i++) {
unsigned v = *ptr++;
if (v < 0x80)
theArray[count++] = (char)v;
else if (v < 0x800) {
theArray[count++] = (char)(0xc0+(v>>6));
theArray[count++] = (char)(0x80+(v&0x3f));
}
else {
theArray[count++] = (char)(0xd0+(v>>12));
theArray[count++] = (char)(0x80+((v>>6)&0x3f));
theArray[count++] = (char)(0x80+(v&0x3f));
}
}
}
#endif
}
PBYTEArray PString::ToPascal() const
{
PINDEX len = GetLength();
PAssert(len < 256, "Cannot convert to PASCAL string");
BYTE buf[256];
buf[0] = (BYTE)len;
memcpy(&buf[1], theArray, len);
return PBYTEArray(buf, len+1);
}
PString PString::ToLiteral() const
{
PString str('"');
for (char * p = theArray; *p != '\0'; p++) {
if (*p == '"')
str += "\\\"";
else if (isprint(*p & 0xff))
str += *p;
else {
PINDEX i;
for (i = 0; i < PARRAYSIZE(PStringEscapeValue); i++) {
if (*p == PStringEscapeValue[i]) {
str += PString('\\') + (char)PStringEscapeCode[i];
break;
}
}
if (i >= PARRAYSIZE(PStringEscapeValue))
str.sprintf("\\%03o", *p & 0xff);
}
}
return str + '"';
}
PString & PString::sprintf(const char * fmt, ...)
{
va_list args;
va_start(args, fmt);
return vsprintf(fmt, args);
}
#if defined(__GNUC__) || defined(__SUNPRO_CC)
#define _vsnprintf vsnprintf
#endif
PString & PString::vsprintf(const char * fmt, va_list arg)
{
PINDEX len = theArray != NULL ? GetLength() : 0;
#ifdef P_VXWORKS
// The library provided with tornado 2.0 does not have the implementation
// for vsnprintf
// as workaround, just use a array size of 2000
PAssert(SetSize(2000), POutOfMemory);
::vsprintf(theArray+len, fmt, arg);
#else
PINDEX size = len;
do {
size += 1000;
PAssert(SetSize(size), POutOfMemory);
} while (_vsnprintf(theArray+len, size-len, fmt, arg) == -1);
#endif // P_VXWORKS
PAssert(MakeMinimumSize(), POutOfMemory);
return *this;
}
PString psprintf(const char * fmt, ...)
{
PString str;
va_list args;
va_start(args, fmt);
return str.vsprintf(fmt, args);
}
PString pvsprintf(const char * fmt, va_list arg)
{
PString str;
return str.vsprintf(fmt, arg);
}
///////////////////////////////////////////////////////////////////////////////
PObject * PCaselessString::Clone() const
{
return new PCaselessString(*this);
}
PObject::Comparison PCaselessString::InternalCompare(PINDEX offset, char c) const
{
if (offset < 0)
return LessThan;
int c1 = toupper(theArray[offset] & 0xff);
int c2 = toupper(c & 0xff);
if (c1 < c2)
return LessThan;
if (c1 > c2)
return GreaterThan;
return EqualTo;
}
PObject::Comparison PCaselessString::InternalCompare(
PINDEX offset, PINDEX length, const char * cstr) const
{
if (offset < 0 || length < 0)
return LessThan;
if (cstr == NULL)
return IsEmpty() ? EqualTo : LessThan;
while (length-- > 0 && (theArray[offset] != '\0' || *cstr != '\0')) {
Comparison c = PCaselessString::InternalCompare(offset++, *cstr++);
if (c != EqualTo)
return c;
}
return EqualTo;
}
///////////////////////////////////////////////////////////////////////////////
PStringStream::Buffer::Buffer(PStringStream & str, PINDEX size)
: string(str),
fixedBufferSize(size != 0)
{
string.SetMinSize(size > 0 ? size : 256);
sync();
}
int PStringStream::Buffer::overflow(int c)
{
if (pptr() >= epptr()) {
if (fixedBufferSize)
return EOF;
int gpos = gptr() - eback();
int ppos = pptr() - pbase();
char * newptr = string.GetPointer(string.GetSize() + 32);
setp(newptr, newptr + string.GetSize() - 1);
pbump(ppos);
setg(newptr, newptr + gpos, newptr + ppos);
}
if (c != EOF) {
*pptr() = (char)c;
pbump(1);
}
return 0;
}
int PStringStream::Buffer::underflow()
{
return gptr() >= egptr() ? EOF : *gptr();
}
int PStringStream::Buffer::sync()
{
char * base = string.GetPointer();
PINDEX len = string.GetLength();
setg(base, base, base + len);
setp(base, base + string.GetSize() - 1);
pbump(len);
return 0;
}
#ifdef __USE_STL__
streambuf::pos_type PStringStream::Buffer::seekoff(off_type off, ios_base::seekdir dir, ios_base::openmode mode)
#else
streampos PStringStream::Buffer::seekoff(streamoff off, ios::seek_dir dir, int mode)
#endif
{
int len = string.GetLength();
int gpos = gptr() - eback();
int ppos = pptr() - pbase();
char * newgptr;
char * newpptr;
switch (dir) {
case ios::beg :
if (off < 0)
newpptr = newgptr = eback();
else if (off >= len)
newpptr = newgptr = egptr();
else
newpptr = newgptr = eback()+off;
break;
case ios::cur :
if (off < -ppos)
newpptr = eback();
else if (off >= len-ppos)
newpptr = epptr();
else
newpptr = pptr()+off;
if (off < -gpos)
newgptr = eback();
else if (off >= len-gpos)
newgptr = egptr();
else
newgptr = gptr()+off;
break;
case ios::end :
if (off < -len)
newpptr = newgptr = eback();
else if (off >= 0)
newpptr = newgptr = egptr();
else
newpptr = newgptr = egptr()+off;
break;
default:
PAssertAlways2(string.GetClass(), PInvalidParameter);
newgptr = gptr();
newpptr = pptr();
}
if ((mode&ios::in) != 0)
setg(eback(), newgptr, egptr());
if ((mode&ios::out) != 0)
setp(newpptr, epptr());
return 0;
}
#ifdef __USE_STL__
streampos PStringStream::Buffer::seekpos(pos_type pos, ios_base::openmode mode)
{
return seekoff(pos, ios_base::beg, mode);
}
#endif
#ifdef _MSC_VER
#pragma warning(disable:4355)
#endif
PStringStream::PStringStream()
: iostream(new PStringStream::Buffer(*this, 0))
{
}
PStringStream::PStringStream(PINDEX fixedBufferSize)
: iostream(new PStringStream::Buffer(*this, fixedBufferSize))
{
}
PStringStream::PStringStream(const PString & str)
: PString(str),
iostream(new PStringStream::Buffer(*this, 0))
{
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?