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