Mercurial > projects > hoofbaby
diff deps/Platinum/ThirdParty/Neptune/Source/Core/NptStrings.cpp @ 0:3425707ddbf6
Initial import (hopefully this mercurial stuff works...)
author | fraserofthenight |
---|---|
date | Mon, 06 Jul 2009 08:06:28 -0700 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/deps/Platinum/ThirdParty/Neptune/Source/Core/NptStrings.cpp Mon Jul 06 08:06:28 2009 -0700 @@ -0,0 +1,1056 @@ +/***************************************************************** +| +| Neptune - String Objects +| +| Copyright (c) 2002-2008, Axiomatic Systems, LLC. +| All rights reserved. +| +| Redistribution and use in source and binary forms, with or without +| modification, are permitted provided that the following conditions are met: +| * Redistributions of source code must retain the above copyright +| notice, this list of conditions and the following disclaimer. +| * Redistributions in binary form must reproduce the above copyright +| notice, this list of conditions and the following disclaimer in the +| documentation and/or other materials provided with the distribution. +| * Neither the name of Axiomatic Systems nor the +| names of its contributors may be used to endorse or promote products +| derived from this software without specific prior written permission. +| +| THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY +| EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +| DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY +| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +| + ****************************************************************/ + +/*---------------------------------------------------------------------- +| includes ++---------------------------------------------------------------------*/ +#include "NptConfig.h" +#include "NptTypes.h" +#include "NptConstants.h" +#include "NptStrings.h" +#include "NptResults.h" +#include "NptUtils.h" +#include "NptDebug.h" + +/*---------------------------------------------------------------------- +| constants ++---------------------------------------------------------------------*/ +#define NPT_STRINGS_WHITESPACE_CHARS "\r\n\t " + +const unsigned int NPT_STRING_FORMAT_BUFFER_DEFAULT_SIZE = 256; +const unsigned int NPT_STRING_FORMAT_BUFFER_MAX_SIZE = 0x80000; // 512k + +/*---------------------------------------------------------------------- +| helpers ++---------------------------------------------------------------------*/ +inline char NPT_Uppercase(char x) { + return (x >= 'a' && x <= 'z') ? x&0xdf : x; +} + +inline char NPT_Lowercase(char x) { + return (x >= 'A' && x <= 'Z') ? x^32 : x; +} + +/*---------------------------------------------------------------------- +| NPT_String::EmptyString ++---------------------------------------------------------------------*/ +char NPT_String::EmptyString = '\0'; + +/*---------------------------------------------------------------------- +| NPT_String::FromInteger ++---------------------------------------------------------------------*/ +NPT_String +NPT_String::FromInteger(NPT_Int64 value) +{ + char str[32]; + char* c = &str[31]; + *c-- = '\0'; + + // handle the sign + bool negative = false; + if (value < 0) { + negative = true; + value = -value; + } + + // process the digits + do { + int digit = (int)(value%10); + *c-- = '0'+digit; + value /= 10; + } while(value); + + if (negative) { + *c = '-'; + } else { + ++c; + } + + return NPT_String(c); +} + +/*---------------------------------------------------------------------- +| NPT_String::FromIntegerU ++---------------------------------------------------------------------*/ +NPT_String +NPT_String::FromIntegerU(NPT_UInt64 value) +{ + char str[32]; + char* c = &str[31]; + *c = '\0'; + + // process the digits + do { + int digit = (int)(value%10); + *--c = '0'+digit; + value /= 10; + } while(value); + + return NPT_String(c); +} + +/*---------------------------------------------------------------------- +| NPT_String::Format ++---------------------------------------------------------------------*/ +NPT_String +NPT_String::Format(const char* format, ...) +{ + NPT_String result; + NPT_Size buffer_size = NPT_STRING_FORMAT_BUFFER_DEFAULT_SIZE; // default value + + va_list args; + va_start(args, format); + + for(;;) { + /* try to format (it might not fit) */ + result.Reserve(buffer_size); + char* buffer = result.UseChars(); + int f_result = NPT_FormatStringVN(buffer, buffer_size, format, args); + if (f_result >= (int)(buffer_size)) f_result = -1; + if (f_result >= 0) { + result.SetLength(f_result); + break; + } + + /* the buffer was too small, try something bigger */ + /* (we don't trust the return value of NPT_FormatStringVN */ + /* for the actual size needed) */ + buffer_size *= 2; + if (buffer_size > NPT_STRING_FORMAT_BUFFER_MAX_SIZE) break; + } + + va_end(args); + + return result; +} + +/*---------------------------------------------------------------------- +| NPT_String::NPT_String ++---------------------------------------------------------------------*/ +NPT_String::NPT_String(const char* str) +{ + if (str == NULL) { + m_Chars = NULL; + } else { + m_Chars = Buffer::Create(str); + } +} + +/*---------------------------------------------------------------------- +| NPT_String::NPT_String ++---------------------------------------------------------------------*/ +NPT_String::NPT_String(const char* str, NPT_Size length) +{ + if (str == NULL || length == 0) { + m_Chars = NULL; + } else { + m_Chars = Buffer::Create(str, length); + } +} + +/*---------------------------------------------------------------------- +| NPT_String::NPT_String ++---------------------------------------------------------------------*/ +NPT_String::NPT_String(const NPT_String& str) +{ + if (str.GetLength() == 0) { + m_Chars = NULL; + } else { + m_Chars = Buffer::Create(str.GetChars(), str.GetLength()); + } +} + +/*---------------------------------------------------------------------- +| NPT_String::NPT_String ++---------------------------------------------------------------------*/ +NPT_String::NPT_String(const char* str, + NPT_Ordinal first, + NPT_Size length) +{ + // shortcut + if (str != NULL && length != 0) { + // truncate length + NPT_Size str_length = StringLength(str); + if (first < str_length) { + if (first+length > str_length) { + length = str_length-first; + } + if (length != 0) { + m_Chars = Buffer::Create(str+first, length); + return; + } + } + } + m_Chars = NULL; +} + +/*---------------------------------------------------------------------- +| NPT_String::NPT_String ++---------------------------------------------------------------------*/ +NPT_String::NPT_String(char c, NPT_Cardinal repeat) +{ + if (repeat != 0) { + m_Chars = Buffer::Create(c, repeat); + } else { + m_Chars = NULL; + } +} + +/*---------------------------------------------------------------------- +| NPT_String::SetLength ++---------------------------------------------------------------------*/ +NPT_Result +NPT_String::SetLength(NPT_Size length, bool pad) +{ + // special case for 0 + if (length == 0) { + Reset(); + return NPT_SUCCESS; + } + + // reserve the space + Reserve(length); + + // pad with spaces if necessary + char* chars = UseChars(); + if (pad) { + unsigned int current_length = GetLength(); + if (length > current_length) { + unsigned int pad_length = length-current_length; + NPT_SetMemory(chars+current_length, ' ', pad_length); + } + } + + // update the length and terminate the buffer + GetBuffer()->SetLength(length); + chars[length] = '\0'; + + return NPT_SUCCESS; +} + +/*---------------------------------------------------------------------- +| NPT_String::PrepareToWrite ++---------------------------------------------------------------------*/ +inline char* +NPT_String::PrepareToWrite(NPT_Size length) +{ + NPT_ASSERT(length != 0); + if (m_Chars == NULL || GetBuffer()->GetAllocated() < length) { + // the buffer is too small, we need to allocate a new one. + NPT_Size needed = length; + if (m_Chars != NULL) { + NPT_Size grow = GetBuffer()->GetAllocated()*2; + if (grow > length) needed = grow; + delete GetBuffer(); + } + m_Chars = Buffer::Create(needed); + } + GetBuffer()->SetLength(length); + return m_Chars; +} + +/*---------------------------------------------------------------------- +| NPT_String::Reserve ++---------------------------------------------------------------------*/ +void +NPT_String::Reserve(NPT_Size allocate) +{ + if (m_Chars == NULL || GetBuffer()->GetAllocated() < allocate) { + // the buffer is too small, we need to allocate a new one. + NPT_Size needed = allocate; + if (m_Chars != NULL) { + NPT_Size grow = GetBuffer()->GetAllocated()*2; + if (grow > allocate) needed = grow; + } + NPT_Size length = GetLength(); + char* copy = Buffer::Create(needed, length); + if (m_Chars != NULL) { + CopyString(copy, m_Chars); + delete GetBuffer(); + } else { + copy[0] = '\0'; + } + m_Chars = copy; + } +} + +/*---------------------------------------------------------------------- +| NPT_String::Assign ++---------------------------------------------------------------------*/ +void +NPT_String::Assign(const char* str, NPT_Size length) +{ + if (str == NULL || length == 0) { + Reset(); + } else { + PrepareToWrite(length); + CopyBuffer(m_Chars, str, length); + m_Chars[length] = '\0'; + } +} + +/*---------------------------------------------------------------------- +| NPT_String::operator= ++---------------------------------------------------------------------*/ +NPT_String& +NPT_String::operator=(const char* str) +{ + if (str == NULL) { + Reset(); + } else { + NPT_Size length = StringLength(str); + if (length == 0) { + Reset(); + } else { + CopyString(PrepareToWrite(length), str); + } + } + + return *this; +} + +/*---------------------------------------------------------------------- +| NPT_String::operator= ++---------------------------------------------------------------------*/ +NPT_String& +NPT_String::operator=(const NPT_String& str) +{ + // do nothing if we're assigning to ourselves + if (this != &str) { + Assign(str.GetChars(), str.GetLength()); + } + return *this; +} + +/*---------------------------------------------------------------------- +| NPT_String::Append ++---------------------------------------------------------------------*/ +void +NPT_String::Append(const char* str, NPT_Size length) +{ + // shortcut + if (str == NULL || length == 0) return; + + // compute the new length + NPT_Size old_length = GetLength(); + NPT_Size new_length = old_length + length; + + // allocate enough space + Reserve(new_length); + + // append the new string at the end of the current one + CopyBuffer(m_Chars+old_length, str, length); + m_Chars[new_length] = '\0'; + + // update the length + GetBuffer()->SetLength(new_length); +} + +/*---------------------------------------------------------------------- +| NPT_String::Compare ++---------------------------------------------------------------------*/ +int +NPT_String::Compare(const char *s, bool ignore_case) const +{ + return NPT_String::Compare(GetChars(), s, ignore_case); +} + +/*---------------------------------------------------------------------- +| NPT_String::Compare ++---------------------------------------------------------------------*/ +int +NPT_String::Compare(const char *s1, const char *s2, bool ignore_case) +{ + const char *r1 = s1; + const char *r2 = s2; + + if (ignore_case) { + while (NPT_Uppercase(*r1) == NPT_Uppercase(*r2)) { + if (*r1++ == '\0') { + return 0; + } + r2++; + } + return NPT_Uppercase(*r1) - NPT_Uppercase(*r2); + } else { + while (*r1 == *r2) { + if (*r1++ == '\0') { + return 0; + } + r2++; + } + return (*r1 - *r2); + } +} + +/*---------------------------------------------------------------------- +| NPT_String::CompareN ++---------------------------------------------------------------------*/ +int +NPT_String::CompareN(const char *s, NPT_Size count, bool ignore_case) const +{ + return NPT_String::CompareN(GetChars(), s, count, ignore_case); +} + +/*---------------------------------------------------------------------- +| NPT_String::CompareN ++---------------------------------------------------------------------*/ +int +NPT_String::CompareN(const char* s1, const char *s2, NPT_Size count, bool ignore_case) +{ + const char* me = s1; + + if (ignore_case) { + for (unsigned int i=0; i<count; i++) { + if (NPT_Uppercase(me[i]) != NPT_Uppercase(s2[i])) { + return NPT_Uppercase(me[i]) - NPT_Uppercase(s2[i]); + } + } + return 0; + } else { + for (unsigned int i=0; i<count; i++) { + if (me[i] != s2[i]) { + return (me[i] - s2[i]); + } + } + return 0; + } +} + +/*---------------------------------------------------------------------- +| NPT_String::Split ++---------------------------------------------------------------------*/ +NPT_List<NPT_String> +NPT_String::Split(const char* separator) const +{ + NPT_List<NPT_String> result; + NPT_Size separator_length = NPT_StringLength(separator); + + // sepcial case for empty separators + if (separator_length == 0) { + result.Add(*this); + return result; + } + + int current = 0; + int next; + do { + next = Find(separator, current); + unsigned int end = (next>=0?next:GetLength()); + result.Add(SubString(current, end-current)); + current = next+separator_length; + } while (next >= 0); + + return result; +} + +/*---------------------------------------------------------------------- +| NPT_String::SubString ++---------------------------------------------------------------------*/ +NPT_String +NPT_String::SubString(NPT_Ordinal first, NPT_Size length) const +{ + if (first >= GetLength()) { + first = GetLength(); + length = 0; + } else if (first+length >= GetLength()) { + length = GetLength()-first; + } + return NPT_String(GetChars()+first, length); +} + +/*---------------------------------------------------------------------- +| NPT_StringStartsWith +| +| returns: +| 1 if str starts with sub, +| 0 if str is large enough but does not start with sub +| -1 if str is too short to start with sub ++---------------------------------------------------------------------*/ +static inline int +NPT_StringStartsWith(const char* str, const char* sub, bool ignore_case) +{ + if (ignore_case) { + while (NPT_Uppercase(*str) == NPT_Uppercase(*sub)) { + if (*str++ == '\0') { + return 1; + } + sub++; + } + } else { + while (*str == *sub) { + if (*str++ == '\0') { + return 1; + } + sub++; + } + } + return (*sub == '\0') ? 1 : (*str == '\0' ? -1 : 0); +} + +/*---------------------------------------------------------------------- +| NPT_String::StartsWith ++---------------------------------------------------------------------*/ +bool +NPT_String::StartsWith(const char *s, bool ignore_case) const +{ + if (s == NULL) return false; + return NPT_StringStartsWith(GetChars(), s, ignore_case) == 1; +} + +/*---------------------------------------------------------------------- +| NPT_String::EndsWith ++---------------------------------------------------------------------*/ +bool +NPT_String::EndsWith(const char *s, bool ignore_case) const +{ + if (s == NULL) return false; + NPT_Size str_length = NPT_StringLength(s); + if (str_length > GetLength()) return false; + return NPT_StringStartsWith(GetChars()+GetLength()-str_length, s, ignore_case) == 1; +} + +/*---------------------------------------------------------------------- +| NPT_String::Find ++---------------------------------------------------------------------*/ +int +NPT_String::Find(const char* str, NPT_Ordinal start, bool ignore_case) const +{ + // check args + if (str == NULL || start >= GetLength()) return -1; + + // skip to start position + const char* src = m_Chars + start; + + // look for a substring + while (*src) { + int cmp = NPT_StringStartsWith(src, str, ignore_case); + switch (cmp) { + case -1: + // ref is too short, abort + return -1; + case 1: + // match + return (int)(src-m_Chars); + } + src++; + } + + return -1; +} + +/*---------------------------------------------------------------------- +| NPT_String::Find ++---------------------------------------------------------------------*/ +int +NPT_String::Find(char c, NPT_Ordinal start, bool ignore_case) const +{ + // check args + if (start >= GetLength()) return -1; + + // skip to start position + const char* src = m_Chars + start; + + // look for the character + if (ignore_case) { + while (*src) { + if (NPT_Uppercase(*src) == NPT_Uppercase(c)) { + return (int)(src-m_Chars); + } + src++; + } + } else { + while (*src) { + if (*src == c) return (int)(src-m_Chars); + src++; + } + } + + return -1; +} + +/*---------------------------------------------------------------------- +| NPT_String::ReverseFind ++---------------------------------------------------------------------*/ +int +NPT_String::ReverseFind(const char* str, NPT_Ordinal start, bool ignore_case) const +{ + // check args + if (str == NULL || *str == '\0') return -1; + + // look for a substring + NPT_Size my_length = GetLength(); + NPT_Size str_length = NPT_StringLength(str); + int i=my_length-start-str_length; + const char* src = GetChars(); + if (i<0) return -1; + for (;i>=0; i--) { + int cmp = NPT_StringStartsWith(src+i, str, ignore_case); + if (cmp == 1) { + // match + return i; + } + } + + return -1; +} + +/*---------------------------------------------------------------------- +| NPT_String::ReverseFind ++---------------------------------------------------------------------*/ +int +NPT_String::ReverseFind(char c, NPT_Ordinal start, bool ignore_case) const +{ + // check args + NPT_Size length = GetLength(); + int i = length-start-1; + if (i < 0) return -1; + + // look for the character + const char* src = GetChars(); + if (ignore_case) { + for (;i>=0;i--) { + if (NPT_Uppercase(src[i]) == NPT_Uppercase(c)) { + return i; + } + } + } else { + for (;i>=0;i--) { + if (src[i] == c) return i; + } + } + + return -1; +} + +/*---------------------------------------------------------------------- +| NPT_String::MakeLowercase ++---------------------------------------------------------------------*/ +void +NPT_String::MakeLowercase() +{ + // the source is the current buffer + const char* src = GetChars(); + + // convert all the characters of the existing buffer + char* dst = const_cast<char*>(src); + while (*dst != '\0') { + *dst = NPT_Lowercase(*dst); + dst++; + } +} + +/*---------------------------------------------------------------------- +| NPT_String::MakeUppercase ++---------------------------------------------------------------------*/ +void +NPT_String::MakeUppercase() +{ + // the source is the current buffer + const char* src = GetChars(); + + // convert all the characters of the existing buffer + char* dst = const_cast<char*>(src); + while (*dst != '\0') { + *dst = NPT_Uppercase(*dst); + dst++; + } +} + +/*---------------------------------------------------------------------- +| NPT_String::ToLowercase ++---------------------------------------------------------------------*/ +NPT_String +NPT_String::ToLowercase() const +{ + NPT_String result(*this); + result.MakeLowercase(); + return result; +} + +/*---------------------------------------------------------------------- +| NPT_String::ToUppercase ++---------------------------------------------------------------------*/ +NPT_String +NPT_String::ToUppercase() const +{ + NPT_String result(*this); + result.MakeUppercase(); + return result; +} + +/*---------------------------------------------------------------------- +| NPT_String::Replace ++---------------------------------------------------------------------*/ +void +NPT_String::Replace(char a, char b) +{ + // check args + if (m_Chars == NULL || a == '\0' || b == '\0') return; + + // we are going to modify the characters + char* src = m_Chars; + + // process the buffer in place + while (*src) { + if (*src == a) *src = b; + src++; + } +} + +/*---------------------------------------------------------------------- +| NPT_String::Replace ++---------------------------------------------------------------------*/ +void +NPT_String::Replace(char a, const char* str) +{ + // check args + if (m_Chars == NULL || a == '\0' || str == NULL || str[0] == '\0') return; + + // optimization + if (NPT_StringLength(str) == 1) return Replace(a, str[0]); + + // we are going to create a new string + NPT_String dst; + char* src = m_Chars; + + // reserve at least as much as input + dst.Reserve(GetLength()); + + // process the buffer + while (*src) { + if (*src == a) { + dst += str; + } else { + dst += *src; + } + src++; + } + + Assign(dst.GetChars(), dst.GetLength()); +} + +/*---------------------------------------------------------------------- +| NPT_String::Insert ++---------------------------------------------------------------------*/ +void +NPT_String::Insert(const char* str, NPT_Ordinal where) +{ + // check args + if (str == NULL || where > GetLength()) return; + + // measure the string to insert + NPT_Size str_length = StringLength(str); + if (str_length == 0) return; + + // compute the size of the new string + NPT_Size old_length = GetLength(); + NPT_Size new_length = str_length + GetLength(); + + // prepare to write the new string + char* src = m_Chars; + char* nst = Buffer::Create(new_length, new_length); + char* dst = nst; + + // copy the beginning of the old string + if (where > 0) { + CopyBuffer(dst, src, where); + src += where; + dst += where; + } + + // copy the inserted string + CopyString(dst, str); + dst += str_length; + + // copy the end of the old string + if (old_length > where) { + CopyString(dst, src); + } + + // use the new string + if (m_Chars) delete GetBuffer(); + m_Chars = nst; +} + +/*---------------------------------------------------------------------- +| NPT_String::Erase ++---------------------------------------------------------------------*/ +void +NPT_String::Erase(NPT_Ordinal start, NPT_Cardinal count /* = 1 */) +{ + // check bounds + NPT_Size length = GetLength(); + if (start+count > length) { + if (start >= length) return; + count = length-start; + } + if (count == 0) return; + + CopyString(m_Chars+start, m_Chars+start+count); + GetBuffer()->SetLength(length-count); +} + +/*---------------------------------------------------------------------- +| NPT_String::ToInteger ++---------------------------------------------------------------------*/ +NPT_Result +NPT_String::ToInteger(NPT_Int32& value, bool relaxed) const +{ + return NPT_ParseInteger32(GetChars(), value, relaxed); +} + +/*---------------------------------------------------------------------- +| NPT_String::ToInteger ++---------------------------------------------------------------------*/ +NPT_Result +NPT_String::ToInteger(NPT_UInt32& value, bool relaxed) const +{ + return NPT_ParseInteger32U(GetChars(), value, relaxed); +} + +/*---------------------------------------------------------------------- +| NPT_String::ToInteger ++---------------------------------------------------------------------*/ +NPT_Result +NPT_String::ToInteger(NPT_Int64& value, bool relaxed) const +{ + return NPT_ParseInteger64(GetChars(), value, relaxed); +} + +/*---------------------------------------------------------------------- +| NPT_String::ToInteger ++---------------------------------------------------------------------*/ +NPT_Result +NPT_String::ToInteger(NPT_UInt64& value, bool relaxed) const +{ + return NPT_ParseInteger64U(GetChars(), value, relaxed); +} + +/*---------------------------------------------------------------------- +| NPT_String::ToFloat ++---------------------------------------------------------------------*/ +NPT_Result +NPT_String::ToFloat(float& value, bool relaxed) const +{ + return NPT_ParseFloat(GetChars(), value, relaxed); +} + +/*---------------------------------------------------------------------- +| NPT_String::TrimLeft ++---------------------------------------------------------------------*/ +void +NPT_String::TrimLeft() +{ + TrimLeft(NPT_STRINGS_WHITESPACE_CHARS); +} + +/*---------------------------------------------------------------------- +| NPT_String::TrimLeft ++---------------------------------------------------------------------*/ +void +NPT_String::TrimLeft(char c) +{ + char s[2] = {c, 0}; + TrimLeft((const char*)s); +} + +/*---------------------------------------------------------------------- +| NPT_String::TrimLeft ++---------------------------------------------------------------------*/ +void +NPT_String::TrimLeft(const char* chars) +{ + if (m_Chars == NULL) return; + const char* s = m_Chars; + while (char c = *s) { + const char* x = chars; + while (*x) { + if (*x == c) break; + x++; + } + if (*x == 0) break; // not found + s++; + } + if (s == m_Chars) { + // nothing was trimmed + return; + } + + // shift chars to the left + char* d = m_Chars; + GetBuffer()->SetLength(GetLength()-(s-d)); + while ((*d++ = *s++)) {}; +} + +/*---------------------------------------------------------------------- +| NPT_String::TrimRight ++---------------------------------------------------------------------*/ +void +NPT_String::TrimRight() +{ + TrimRight(NPT_STRINGS_WHITESPACE_CHARS); +} + +/*---------------------------------------------------------------------- +| NPT_String::TrimRight ++---------------------------------------------------------------------*/ +void +NPT_String::TrimRight(char c) +{ + char s[2] = {c, 0}; + TrimRight((const char*)s); +} + +/*---------------------------------------------------------------------- +| NPT_String::TrimRight ++---------------------------------------------------------------------*/ +void +NPT_String::TrimRight(const char* chars) +{ + if (m_Chars == NULL || m_Chars[0] == '\0') return; + char* tail = m_Chars+GetLength()-1; + char* s = tail; + while (s != m_Chars-1) { + const char* x = chars; + while (*x) { + if (*x == *s) { + *s = '\0'; + break; + } + x++; + } + if (*x == 0) break; // not found + s--; + } + if (s == tail) { + // nothing was trimmed + return; + } + GetBuffer()->SetLength(1+(int)(s-m_Chars)); +} + +/*---------------------------------------------------------------------- +| NPT_String::Trim ++---------------------------------------------------------------------*/ +void +NPT_String::Trim() +{ + TrimLeft(); + TrimRight(); +} + +/*---------------------------------------------------------------------- +| NPT_String::Trim ++---------------------------------------------------------------------*/ +void +NPT_String::Trim(char c) +{ + char s[2] = {c, 0}; + TrimLeft((const char*)s); + TrimRight((const char*)s); +} + +/*---------------------------------------------------------------------- +| NPT_String::Trim ++---------------------------------------------------------------------*/ +void +NPT_String::Trim(const char* chars) +{ + TrimLeft(chars); + TrimRight(chars); +} + +/*---------------------------------------------------------------------- +| NPT_String::operator+(const NPT_String&, const char*) ++---------------------------------------------------------------------*/ +NPT_String +operator+(const NPT_String& s1, const char* s2) +{ + // shortcut + if (s2 == NULL) return NPT_String(s1); + + // measure strings + NPT_Size s1_length = s1.GetLength(); + NPT_Size s2_length = NPT_String::StringLength(s2); + + // allocate space for the new string + NPT_String result; + char* start = result.PrepareToWrite(s1_length+s2_length); + + // concatenate the two strings into the result + NPT_String::CopyBuffer(start, s1, s1_length); + NPT_String::CopyString(start+s1_length, s2); + + return result; +} + +/*---------------------------------------------------------------------- +| NPT_String::operator+(const NPT_String& , const char*) ++---------------------------------------------------------------------*/ +NPT_String +operator+(const char* s1, const NPT_String& s2) +{ + // shortcut + if (s1 == NULL) return NPT_String(s2); + + // measure strings + NPT_Size s1_length = NPT_String::StringLength(s1); + NPT_Size s2_length = s2.GetLength(); + + // allocate space for the new string + NPT_String result; + char* start = result.PrepareToWrite(s1_length+s2_length); + + // concatenate the two strings into the result + NPT_String::CopyBuffer(start, s1, s1_length); + NPT_String::CopyString(start+s1_length, s2.GetChars()); + + return result; +} + +/*---------------------------------------------------------------------- +| NPT_String::operator+(const NPT_String& , char) ++---------------------------------------------------------------------*/ +NPT_String +operator+(const NPT_String& s1, char c) +{ + // allocate space for the new string + NPT_String result; + result.Reserve(s1.GetLength()+1); + + // append + result = s1; + result += c; + + return result; +} +