KUDr@7116: /* $Id$ */ KUDr@7116: KUDr@7116: /** @file str.hpp */ KUDr@7116: KUDr@7116: #ifndef STR_HPP KUDr@7116: #define STR_HPP KUDr@7116: KUDr@7116: #include KUDr@7116: #include KUDr@7116: #include "strapi.hpp" KUDr@7116: KUDr@7116: /** Blob based string. */ KUDr@7116: template KUDr@7116: struct CStrT : public CBlobT KUDr@7116: { KUDr@7116: typedef CBlobT base; ///< base class KUDr@7116: typedef CStrApiT Api; ///< string API abstraction layer KUDr@7116: typedef typename base::bsize_t bsize_t; ///< size type inherited from blob KUDr@7116: typedef typename base::OnTransfer OnTransfer; ///< temporary 'transfer ownership' object type KUDr@7116: KUDr@7116: /** Construction from C zero ended string. */ KUDr@7116: FORCEINLINE CStrT(const Tchar* str = NULL) KUDr@7116: { KUDr@7116: AppendStr(str); KUDr@7116: } KUDr@7116: KUDr@7116: /** Construction from C string and given number of characters. */ KUDr@7116: FORCEINLINE CStrT(const Tchar* str, bsize_t num_chars) : base(str, num_chars) KUDr@7116: { KUDr@7116: base::FixTail(); KUDr@7116: } KUDr@7116: KUDr@7116: /** Construction from C string determined by 'begin' and 'end' pointers. */ KUDr@7116: FORCEINLINE CStrT(const Tchar* str, const Tchar* end) KUDr@7116: : base(str, end - str) KUDr@7116: { KUDr@7116: base::FixTail(); KUDr@7116: } KUDr@7116: KUDr@7116: /** Construction from blob contents. */ KUDr@7116: FORCEINLINE CStrT(const CBlobBaseSimple& src) KUDr@7116: : base(src) KUDr@7116: { KUDr@7116: base::FixTail(); KUDr@7116: } KUDr@7116: KUDr@7116: /** Copy constructor. */ KUDr@7116: FORCEINLINE CStrT(const CStrT& src) KUDr@7116: : base(src) KUDr@7116: { KUDr@7116: base::FixTail(); KUDr@7116: } KUDr@7116: KUDr@7116: /** Take over ownership constructor */ KUDr@7116: FORCEINLINE CStrT(const OnTransfer& ot) KUDr@7116: : base(ot) KUDr@7116: { KUDr@7116: } KUDr@7116: KUDr@7116: /** Grow the actual buffer and fix the trailing zero at the end. */ KUDr@7116: FORCEINLINE Tchar* GrowSizeNC(bsize_t count) KUDr@7116: { KUDr@7116: Tchar* ret = base::GrowSizeNC(count); KUDr@7116: base::FixTail(); KUDr@7116: return ret; KUDr@7116: } KUDr@7116: KUDr@7116: /** Append zero-ended C string. */ KUDr@7116: FORCEINLINE void AppendStr(const Tchar* str) KUDr@7116: { KUDr@7116: if (str != NULL && str[0] != '\0') { KUDr@7116: base::Append(str, (bsize_t)Api::StrLen(str)); KUDr@7116: base::FixTail(); KUDr@7116: } KUDr@7116: } KUDr@7116: KUDr@7116: /** Append another CStrT or blob. */ KUDr@7116: FORCEINLINE void Append(const CBlobBaseSimple& src) KUDr@7116: { KUDr@7116: if (src.RawSize() > 0) { KUDr@7116: base::AppendRaw(src); KUDr@7116: base::FixTail(); KUDr@7116: } KUDr@7116: } KUDr@7116: KUDr@7116: /** Assignment from C string. */ KUDr@7116: FORCEINLINE CStrT& operator = (const Tchar* src) KUDr@7116: { KUDr@7116: base::Clear(); KUDr@7116: AppendStr(src); KUDr@7116: return *this; KUDr@7116: } KUDr@7116: KUDr@7116: /** Assignment from another CStrT or blob. */ KUDr@7116: FORCEINLINE CStrT& operator = (const CBlobBaseSimple& src) KUDr@7116: { KUDr@7116: base::Clear(); KUDr@7116: base::AppendRaw(src); KUDr@7116: base::FixTail(); KUDr@7116: return *this; KUDr@7116: } KUDr@7116: KUDr@7116: /** Assignment from another CStrT or blob. */ KUDr@7116: FORCEINLINE CStrT& operator = (const CStrT& src) KUDr@7116: { KUDr@7116: base::Clear(); KUDr@7116: base::AppendRaw(src); KUDr@7116: base::FixTail(); KUDr@7116: return *this; KUDr@7116: } KUDr@7116: KUDr@7116: /** Lower-than operator (to support stl collections) */ KUDr@7116: FORCEINLINE bool operator < (const CStrT &other) const KUDr@7116: { KUDr@7116: return (Api::StrCmp(base::Data(), other.Data()) < 0); KUDr@7116: } KUDr@7116: KUDr@7116: /** Add formated string (like vsprintf) at the end of existing contents. */ KUDr@7116: int AddFormatL(const Tchar *format, va_list args) KUDr@7116: { KUDr@7116: bsize_t addSize = Api::StrLen(format); KUDr@7116: if (addSize < 16) addSize = 16; KUDr@7153: addSize += addSize / 2; KUDr@7153: int ret; KUDr@7153: int err = 0; KUDr@7153: for (;;) { KUDr@7116: Tchar *buf = MakeFreeSpace(addSize); KUDr@7116: ret = Api::SPrintFL(buf, base::GetReserve(), format, args); KUDr@7153: if (ret >= base::GetReserve()) { KUDr@7153: /* Greater return than given count means needed buffer size. */ KUDr@7153: addSize = ret + 1; KUDr@7153: continue; KUDr@7153: } KUDr@7153: if (ret >= 0) { KUDr@7153: /* success */ KUDr@7153: break; KUDr@7153: } KUDr@7153: err = errno; KUDr@7153: if (err != ERANGE && err != ENOENT && err != 0) { KUDr@7153: /* some strange failure */ KUDr@7153: break; KUDr@7153: } KUDr@7153: /* small buffer (M$ implementation) */ KUDr@7116: addSize *= 2; KUDr@7153: } KUDr@7116: if (ret > 0) { KUDr@7116: GrowSizeNC(ret); KUDr@7116: } else { KUDr@7116: base::FixTail(); KUDr@7116: } KUDr@7116: return ret; KUDr@7116: } KUDr@7116: KUDr@7116: /** Add formated string (like sprintf) at the end of existing contents. */ KUDr@7116: int AddFormat(const Tchar *format, ...) KUDr@7116: { KUDr@7116: va_list args; KUDr@7116: va_start(args, format); KUDr@7116: int ret = AddFormatL(format, args); KUDr@7116: va_end(args); KUDr@7116: return ret; KUDr@7116: } KUDr@7116: KUDr@7116: /** Assign formated string (like vsprintf). */ KUDr@7116: int FormatL(const Tchar *format, va_list args) KUDr@7116: { KUDr@7116: base::Free(); KUDr@7116: int ret = AddFormatL(format, args); KUDr@7116: return ret; KUDr@7116: } KUDr@7116: KUDr@7116: /** Assign formated string (like sprintf). */ KUDr@7116: int Format(const Tchar *format, ...) KUDr@7116: { KUDr@7116: base::Free(); KUDr@7116: va_list args; KUDr@7116: va_start(args, format); KUDr@7116: int ret = AddFormatL(format, args); KUDr@7116: va_end(args); KUDr@7116: return ret; KUDr@7116: } KUDr@7116: }; KUDr@7116: KUDr@7116: typedef CStrT CStrA; ///< Case sensitive ANSI/UTF-8 string KUDr@7116: typedef CStrT CStrCiA; ///< Case insensitive ANSI/UTF-8 string rubidium@7255: #if defined(HAS_WCHAR) KUDr@7116: typedef CStrT CStrW; ///< Case sensitive unicode string KUDr@7116: typedef CStrT CStrCiW; ///< Case insensitive unicode string rubidium@7255: #endif /* HAS_WCHAR */ KUDr@7116: KUDr@7116: #endif /* STR_HPP */