#pragma once #ifdef DSTRING_EXPORTS #define DSTRING_API _declspec(dllexport) #else #define DSTRING_API _declspec(dllimport) #endif class InBuffer; class OutBuffer; struct DStringData { long nRefs; // reference count int nDataLength; // length of data (including terminator) int nAllocLength; // length of allocation // char data[nAllocLength] char * data () // char* to managed data { return (char*) (this+1); } }; class DSTRING_API DString { public: // Constructors // constructs empty DString DString (); // copy constructor DString (const DString& stringSrc); // move constructor DString (DString && stringSrc); // from an ANSI string (converts to char) DString (const char * lpsz); // subset of characters from an ANSI string (converts to char) DString (const char * lpch, int nLength); // from unsigned characters DString (const unsigned char * lpsz) { Init(); *this = (const char *) lpsz; } // Attributes & Operations // get data length int GetLength () const { return GetData ()->nDataLength; } int GetByteLength () const { return GetLength (); } // TRUE if zero length bool IsEmpty () const { return (GetData ()->nDataLength == 0); } // clear contents to empty void Empty (); // free all data void Release (); // return single character at zero-based index char GetAt (int nIndex) const { // ASSERT(nIndex >= 0); // ASSERT(nIndex < GetData()->nDataLength); return m_pchData[nIndex]; } // return single character at zero-based index char operator [] (int nIndex) const { return GetAt (nIndex); } // set a single character at zero-based index void SetAt (int nIndex, char ch); // Number of ch int Count (char ch) const; // Number of lpszSub int Count (const char * lpszSub) const; // overloaded assignment // ref-counted copy from another DString DString & operator = (const DString & stringSrc); // set string content to single character DString & operator = (char ch); // copy string content from ANSI string (converts to char) DString & operator = (const char * lpsz); // copy string content from unsigned chars DString & operator = (const unsigned char * lpsz) { *this = (const char *) lpsz; return *this; } DString & operator = (DString && stringSrc); // string concatenation // concatenate from another DString DString & Append (const DString & string) { ConcatInPlace (string.GetData ()->nDataLength, string.m_pchData); return *this; } // concatenate a single character DString & Append (char ch) { ConcatInPlace (1, &ch); return *this; } DString & Append (const char * lpsz) { ConcatInPlace ((int)strlen (lpsz), lpsz); return *this; } // concatenate from another DString DString & operator += (const DString & string) { return Append (string); } // concatenate a single character DString & operator += (char ch) { return Append (ch); } DString & operator += (const char * lpsz) { return Append (lpsz); } DString & operator << (const DString & string) { return Append (string); } DString & operator << (char ch) { return Append (ch); } DString & operator << (const char * lpsz) { return Append (lpsz); } DSTRING_API friend DString operator + (const DString & string1, const DString & string2); DSTRING_API friend DString operator + (const DString & string, char ch); DSTRING_API friend DString operator + (char ch, const DString & string); DSTRING_API friend DString operator + (const DString & string, const char * lpsz); DSTRING_API friend DString operator + (const char * lpsz, const DString & string); // string comparison // straight character comparison int Compare (const char * lpsz) const; // compare ignoring case int CompareNoCase (const char * lpsz) const; // NLS aware comparison, case sensitive int Collate (const char * lpsz) const; // NLS aware comparison, case insensitive int CollateNoCase (const char * lpsz) const; // Returns the similarity between 2 strings float Similar (const char * lpsz) const; float Similar (const DString & str) const; // simple sub-string extraction // return nCount characters starting at zero-based nFirst DString Mid (int nFirst, int nCount) const; // return all characters starting at zero-based nFirst DString Mid (int nFirst) const; // return first nCount characters in string DString Left (int nCount) const; // return nCount characters from end of string DString Right (int nCount) const; // characters from beginning that are also in passed string DString SpanIncluding (const char * lpszCharSet) const; // characters from beginning that are not also in passed string DString SpanExcluding (const char * lpszCharSet) const; // upper/lower/reverse conversion // NLS aware conversion to uppercase void MakeUpper (); // NLS aware conversion to lowercase void MakeLower (); // reverse string right-to-left void MakeReverse (); // trimming whitespace (either side) // remove whitespace starting from right edge void TrimRight (); // remove whitespace starting from left side void TrimLeft (); // remove continuous occurrences of chTarget starting from right void TrimRight (char chTarget); // remove continuous occcurrences of characters in passed string, // starting from right void TrimRight (const char * lpszTargets); // remove continuous occurrences of chTarget starting from left void TrimLeft (char chTarget); // remove continuous occcurrences of characters in // passed string, starting from left void TrimLeft (const char * lpszTargets); // trimming anything (either side) DString Trim () const { DString copy = *this; copy.TrimRight (); copy.TrimLeft (); return copy; } // advanced manipulation // replace occurrences of chOld with chNew int Replace (char chOld, char chNew); // replace occurrences of substring lpszOld with lpszNew; // empty lpszNew removes instances of lpszOld int Replace (const char * lpszOld, const char * lpszNew); // replace, compare no case int NCReplace (const char * lpszOld, const char * lpszNew); // remove occurrences of lpszSub, just same as Replace (lpszSub, nullptr); int Remove (const char * lpszSub); // remove occurrences of chRemove int Remove (char chRemove); // remove space character int RemoveSpace (); // remove punctuation character int RemovePunctuation (); // remove control character int RemoveControl (); // remove occurrences of lpszSub, compare no case int NCRemove (const char * lpszSub); // remove occurrences of chRemove, compare no case int NCRemove (char chRemove); // replace tabs to space; int ReplaceTabs (int abstand); // insert character at zero-based index; concatenates // if index is past end of string int Insert (int nIndex, char ch); // insert substring at zero-based index; concatenates // if index is past end of string int Insert (int nIndex, const char * pstr); // delete nCount characters starting at zero-based index int Delete (int nIndex, int nCount = 1); // insert character n times void Repeat (char ch, int n); // insert string n times; void Repeat (const char * lpszStr, int n); // searching // find character starting at left, -1 if not found int Find (char ch) const; // find character starting at right int ReverseFind (char ch) const; // find character starting at zero-based index and going right int Find (char ch, int nStart) const; // find first instance of any character in passed string int FindOneOf (const char * lpszCharSet) const; // find first instance of substring int Find (const char * lpszSub) const; // find first instance of substring starting at zero-based index int Find (const char * lpszSub, int nStart) const; int NCFind (char ch) const; int NCFind (const char * lpszSub) const; // Cast public: // return pointer to const string operator const char * () const { return m_pchData; } const char * constBuffer (void) const { return m_pchData; } operator bool () const = delete; public: static DString From (const int i); static DString From (const long i); static DString From (const unsigned int u); static DString From (const unsigned long u); static DString From (const __int64 i); static DString From (const unsigned __int64 u); static DString From (const double d); // simple formatting static DString FromFormat (const char * szFormat, ...); // repeat a single character static DString FromRepeat (char ch, int nRepeat); protected: // make a guess at the maximum length of the resulting string static int __cdecl GetFormattedLength (const char * pszFormat, va_list argList); static int __cdecl VFormat (char * lpzBuffer, const char * pszFormat, va_list argList); public: // printf-like formatting using passed string void Format (const char * lpszFormat, ...); // printf-like formatting using referenced string resource void FormatV (const char * lpszFormat, va_list argList); // append with the formatted string void AppendFormat (const char * lpszFormat, ...); void AppendFormatV (const char * lpszFormat, va_list argList); void FormatMsg (unsigned long errcode, const char * fmt, ...); // Access to string implementation buffer as "C" character array // get pointer to modifiable buffer at least as long as nMinBufLength char * GetBuffer (int nMinBufLength); // release buffer, setting length to nNewLength (or to first nul if -1) void ReleaseBuffer (int nNewLength = -1); // get pointer to modifiable buffer exactly as long as nNewLength char * GetBufferSetLength (int nNewLength); //============================================================================== // Functions for Element-Strings //============================================================================== DString Elements (int start, int stop, char sep) const; DString Element (int i, char sep) const; int IndexOfElement (const char * lpszSuch, char sep) const; int IndexOfElement (double such, char sep) const; int IndexOfElement (int such, char sep) const; int IndexOfElement (char such, char sep) const; int IndexOfElement (bool such, char sep) const; // release memory allocated to but unused by string void FreeExtra (); // Use LockBuffer/UnlockBuffer to turn refcounting off // turn refcounting back on char * LockBuffer (); // turn refcounting off void UnlockBuffer (); // input and output friend InBuffer & operator >> (InBuffer & ib, DString& string); friend OutBuffer & operator << (OutBuffer & ob, const DString& string); // Implementation public: ~DString (); int GetAllocLength () const { return GetData ()->nAllocLength; } // The following code is stealed from CStringEx public: DString operator -- () { *this = Left (GetLength () - 1); return *this; } DString operator -- (int) { DString copy (*this); *this = Left (GetLength () - 1); return copy; } public: // 转换函数 double Double () const { return atof (m_pchData); } int Int () const { int i = atoi (m_pchData); if (i) return i; return strtol (m_pchData, nullptr, 16); } long Long () const { long l = atol (m_pchData); if (l) return l; return strtol (m_pchData, nullptr, 16); } char Char () const { return m_pchData[0]; } bool Bool () const; __int64 Int64 () const { __int64 i = _atoi64 (m_pchData); if (i) return i; return _strtoi64 (m_pchData, nullptr, 16); } template T To () const { } template <> int To () const { return Int (); } template <> double To () const { return Double (); } template <> float To () const { return (float) Double (); } template <> long To () const { return Long (); } template <> bool To () const { return Bool (); } template <> __int64 To () const { return Int64 (); } template <> unsigned int To () const { return Int (); } template <> unsigned __int64 To () const { return Int64 (); } template <> unsigned long To () const { return Long (); } public: // 判断整个字符串是否是某一类字符组成 bool IsDigit () const; bool IsAlNum () const; bool IsAlpha () const; bool IsUpper () const; bool IsLower () const; bool IsSpace () const; // 判断某个字符是否是某一类字符组成 bool IsDigit (int nPos) const; bool IsAlNum (int nPos) const; bool IsAlpha (int nPos) const; bool IsUpper (int nPos) const; bool IsLower (int nPos) const; bool IsSpace (int nPos) const; public: bool ToCharacterSet (unsigned int CodePage); bool FromCharacterSet (unsigned int CodePage); // End of stealed code protected: char * m_pchData; // pointer to ref counted string data // implementation helpers DStringData * DString::GetData() const { return ((DStringData *) m_pchData)-1; } void Init (); void AllocCopy (DString& dest, int nCopyLen, int nCopyIndex, int nExtraLen) const; void AllocBuffer (int nLen); void AssignCopy (int nSrcLen, const char * lpszSrcData); void ConcatCopy (int nSrc1Len, const char * lpszSrc1Data, int nSrc2Len, const char * lpszSrc2Data); void ConcatInPlace (int nSrcLen, const char * lpszSrcData); void CopyBeforeWrite (); void AllocBeforeWrite (int nLen); void MoveAssign (DString & Src); static void Release (DStringData * pData); static void FreeData (DStringData * pData); //----------------------------------------------------------------------------- // Token类用来对字符串进行标识符切分 //----------------------------------------------------------------------------- public: class DSTRING_API Token { public: Token (const DString & str, bool bSkipPunctuation = false) : m_Str (str), m_bSkipPunctuation (bSkipPunctuation) { // 在Restart之前先初始化这个变量,因为Restart之后需要立即调用Next, // 而Next函数需要这个变量 Restart (); } public: operator bool () const { return m_bContinue; }; operator DString () const { return Current (); }; public: // 定位到下一个标识符 bool Next (void); // 定位到下一个标识符,但是以出作为分割符 bool Next (char sep); // 定位到行尾,Current返回直到行尾的所有字符,但是不包括行尾的回车或换行 bool NextLine (void); DString Current (void) const; // 获得当前标识符,或者当前行 bool IsValid () const { return (m_nL <= m_nR); }; void Clear (void) { m_nL = 0; m_nR = -1; m_nNext = 0; m_bContinue = true; m_nStrLength = 0; } void Restart (void) // 重新开始 { m_szDoc = m_Str; Clear (); m_nStrLength = (int) strlen (m_szDoc); Next (); } bool SkipPunctuation (bool bSkipPunctuation) { bool tmp = m_bSkipPunctuation; m_bSkipPunctuation =bSkipPunctuation; return tmp; } void operator ++ () // ++Token; prevfix { Next (); } void operator ++ (int) // Token++; postfix { Next (); } DString operator () (void) const { return Current (); } protected: int FindWhitespace (int nChar) const; // 从nChar开始,定位到下一个非空字符,并返回这个位置的索引,如果找不到,返回-1 int FindChar (int nChar, char ch) const; // 从nChar开始,在字符串中寻找与ch相同的下一个ch,并返回这个位置的索引,如果找不到,返回-1 protected: const DString & m_Str; const char * m_szDoc; int m_nL; // 当前标识符的左边界 int m_nR; // 当前标识符的右边界 int m_nNext; // 下一个标识符的初始位置 bool m_bContinue; // 可用继续迭代吗? int m_nStrLength; // 字符串长度; bool m_bSkipPunctuation; // Next()时跳过标点符号,即Current()不会返回遇到的标点符号 }; #if 0 //----------------------------------------------------------------------------- // DFileName类用来对Windows的文件名进行切分和组合 //----------------------------------------------------------------------------- class DSTRING_API DFileName { public: DFileName (const char * FileName) { Init (FileName); } public: const char * FullFileName () const // 获得全文件名 { return m_szFullFileName; } const char * FileName () const // 获得文件名 { return m_szFileName; } const char * FileExt () const // 获得扩展名 { return m_ext; } const char * Drive () const // 获得驱动器名 { return m_drive; } const char * FilePath () const; // 获得全路径名 bool IsFile (const char * FileName) const; // 判断是否是某个文件,FileName必须是文件名,不能含有路径 void SetPath (const char * Path); // 将路径设置为Path protected: void Init (const char * FileName); protected: char m_szFileName [_MAX_PATH + _MAX_PATH]; char m_szFullFileName [_MAX_PATH + _MAX_PATH]; mutable char m_szFilePath [_MAX_PATH + _MAX_PATH]; char m_drive [_MAX_PATH]; char m_path [_MAX_PATH]; char m_filename [_MAX_PATH]; char m_ext [_MAX_PATH]; }; #endif }; // Compare helpers DSTRING_API inline bool __stdcall operator == (const DString& s1, const DString& s2) { return s1.Compare (s2) == 0; } DSTRING_API inline bool __stdcall operator == (const DString& s1, const char * s2) { return s1.Compare (s2) == 0; } DSTRING_API inline bool __stdcall operator == (const char * s1 , const DString& s2) { return s2.Compare (s1) == 0; } DSTRING_API inline bool __stdcall operator != (const DString& s1, const DString& s2) { return s1.Compare (s2) != 0; } DSTRING_API inline bool __stdcall operator != (const DString& s1, const char * s2) { return s1.Compare (s2) != 0; } DSTRING_API inline bool __stdcall operator != (const char * s1 , const DString& s2) { return s2.Compare (s1) != 0; } DSTRING_API inline bool __stdcall operator < (const DString& s1, const DString& s2) { return s1.Compare (s2) < 0; } DSTRING_API inline bool __stdcall operator < (const DString& s1, const char * s2) { return s1.Compare (s2) < 0; } DSTRING_API inline bool __stdcall operator < (const char * s1 , const DString& s2) { return s2.Compare (s1) > 0; } DSTRING_API inline bool __stdcall operator > (const DString& s1, const DString& s2) { return s1.Compare (s2) > 0; } DSTRING_API inline bool __stdcall operator > (const DString& s1, const char * s2) { return s1.Compare (s2) > 0; } DSTRING_API inline bool __stdcall operator > (const char * s1 , const DString& s2) { return s2.Compare (s1) < 0; } DSTRING_API inline bool __stdcall operator <= (const DString& s1, const DString& s2) { return s1.Compare (s2) <= 0; } DSTRING_API inline bool __stdcall operator <= (const DString& s1, const char * s2) { return s1.Compare (s2) <= 0; } DSTRING_API inline bool __stdcall operator <= (const char * s1 , const DString& s2) { return s2.Compare (s1) >= 0; } DSTRING_API inline bool __stdcall operator >= (const DString& s1, const DString& s2) { return s1.Compare (s2) >= 0; } DSTRING_API inline bool __stdcall operator >= (const DString& s1, const char * s2) { return s1.Compare (s2) >= 0; } DSTRING_API inline bool __stdcall operator >= (const char * s1 , const DString& s2) { return s2.Compare (s1) <= 0; }