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