|
1 /* $Id$ */ |
|
2 |
|
3 /** @file str.hpp */ |
|
4 |
|
5 #ifndef STR_HPP |
|
6 #define STR_HPP |
|
7 |
|
8 #include <errno.h> |
|
9 #include <stdarg.h> |
|
10 #include "strapi.hpp" |
|
11 |
|
12 /** Blob based string. */ |
|
13 template <typename Tchar, bool TcaseInsensitive> |
|
14 struct CStrT : public CBlobT<Tchar> |
|
15 { |
|
16 typedef CBlobT<Tchar> base; ///< base class |
|
17 typedef CStrApiT<Tchar, TcaseInsensitive> Api; ///< string API abstraction layer |
|
18 typedef typename base::bsize_t bsize_t; ///< size type inherited from blob |
|
19 typedef typename base::OnTransfer OnTransfer; ///< temporary 'transfer ownership' object type |
|
20 |
|
21 /** Construction from C zero ended string. */ |
|
22 FORCEINLINE CStrT(const Tchar* str = NULL) |
|
23 { |
|
24 AppendStr(str); |
|
25 } |
|
26 |
|
27 /** Construction from C string and given number of characters. */ |
|
28 FORCEINLINE CStrT(const Tchar* str, bsize_t num_chars) : base(str, num_chars) |
|
29 { |
|
30 base::FixTail(); |
|
31 } |
|
32 |
|
33 /** Construction from C string determined by 'begin' and 'end' pointers. */ |
|
34 FORCEINLINE CStrT(const Tchar* str, const Tchar* end) |
|
35 : base(str, end - str) |
|
36 { |
|
37 base::FixTail(); |
|
38 } |
|
39 |
|
40 /** Construction from blob contents. */ |
|
41 FORCEINLINE CStrT(const CBlobBaseSimple& src) |
|
42 : base(src) |
|
43 { |
|
44 base::FixTail(); |
|
45 } |
|
46 |
|
47 /** Copy constructor. */ |
|
48 FORCEINLINE CStrT(const CStrT& src) |
|
49 : base(src) |
|
50 { |
|
51 base::FixTail(); |
|
52 } |
|
53 |
|
54 /** Take over ownership constructor */ |
|
55 FORCEINLINE CStrT(const OnTransfer& ot) |
|
56 : base(ot) |
|
57 { |
|
58 } |
|
59 |
|
60 /** Grow the actual buffer and fix the trailing zero at the end. */ |
|
61 FORCEINLINE Tchar* GrowSizeNC(bsize_t count) |
|
62 { |
|
63 Tchar* ret = base::GrowSizeNC(count); |
|
64 base::FixTail(); |
|
65 return ret; |
|
66 } |
|
67 |
|
68 /** Append zero-ended C string. */ |
|
69 FORCEINLINE void AppendStr(const Tchar* str) |
|
70 { |
|
71 if (str != NULL && str[0] != '\0') { |
|
72 base::Append(str, (bsize_t)Api::StrLen(str)); |
|
73 base::FixTail(); |
|
74 } |
|
75 } |
|
76 |
|
77 /** Append another CStrT or blob. */ |
|
78 FORCEINLINE void Append(const CBlobBaseSimple& src) |
|
79 { |
|
80 if (src.RawSize() > 0) { |
|
81 base::AppendRaw(src); |
|
82 base::FixTail(); |
|
83 } |
|
84 } |
|
85 |
|
86 /** Assignment from C string. */ |
|
87 FORCEINLINE CStrT& operator = (const Tchar* src) |
|
88 { |
|
89 base::Clear(); |
|
90 AppendStr(src); |
|
91 return *this; |
|
92 } |
|
93 |
|
94 /** Assignment from another CStrT or blob. */ |
|
95 FORCEINLINE CStrT& operator = (const CBlobBaseSimple& src) |
|
96 { |
|
97 base::Clear(); |
|
98 base::AppendRaw(src); |
|
99 base::FixTail(); |
|
100 return *this; |
|
101 } |
|
102 |
|
103 /** Assignment from another CStrT or blob. */ |
|
104 FORCEINLINE CStrT& operator = (const CStrT& src) |
|
105 { |
|
106 base::Clear(); |
|
107 base::AppendRaw(src); |
|
108 base::FixTail(); |
|
109 return *this; |
|
110 } |
|
111 |
|
112 /** Lower-than operator (to support stl collections) */ |
|
113 FORCEINLINE bool operator < (const CStrT &other) const |
|
114 { |
|
115 return (Api::StrCmp(base::Data(), other.Data()) < 0); |
|
116 } |
|
117 |
|
118 /** Add formated string (like vsprintf) at the end of existing contents. */ |
|
119 int AddFormatL(const Tchar *format, va_list args) |
|
120 { |
|
121 bsize_t addSize = Api::StrLen(format); |
|
122 if (addSize < 16) addSize = 16; |
|
123 addSize += addSize / 2; |
|
124 int ret; |
|
125 int err = 0; |
|
126 for (;;) { |
|
127 Tchar *buf = MakeFreeSpace(addSize); |
|
128 ret = Api::SPrintFL(buf, base::GetReserve(), format, args); |
|
129 if (ret >= base::GetReserve()) { |
|
130 /* Greater return than given count means needed buffer size. */ |
|
131 addSize = ret + 1; |
|
132 continue; |
|
133 } |
|
134 if (ret >= 0) { |
|
135 /* success */ |
|
136 break; |
|
137 } |
|
138 err = errno; |
|
139 if (err != ERANGE && err != ENOENT && err != 0) { |
|
140 /* some strange failure */ |
|
141 break; |
|
142 } |
|
143 /* small buffer (M$ implementation) */ |
|
144 addSize *= 2; |
|
145 } |
|
146 if (ret > 0) { |
|
147 GrowSizeNC(ret); |
|
148 } else { |
|
149 base::FixTail(); |
|
150 } |
|
151 return ret; |
|
152 } |
|
153 |
|
154 /** Add formated string (like sprintf) at the end of existing contents. */ |
|
155 int AddFormat(const Tchar *format, ...) |
|
156 { |
|
157 va_list args; |
|
158 va_start(args, format); |
|
159 int ret = AddFormatL(format, args); |
|
160 va_end(args); |
|
161 return ret; |
|
162 } |
|
163 |
|
164 /** Assign formated string (like vsprintf). */ |
|
165 int FormatL(const Tchar *format, va_list args) |
|
166 { |
|
167 base::Free(); |
|
168 int ret = AddFormatL(format, args); |
|
169 return ret; |
|
170 } |
|
171 |
|
172 /** Assign formated string (like sprintf). */ |
|
173 int Format(const Tchar *format, ...) |
|
174 { |
|
175 base::Free(); |
|
176 va_list args; |
|
177 va_start(args, format); |
|
178 int ret = AddFormatL(format, args); |
|
179 va_end(args); |
|
180 return ret; |
|
181 } |
|
182 }; |
|
183 |
|
184 typedef CStrT<char , false> CStrA; ///< Case sensitive ANSI/UTF-8 string |
|
185 typedef CStrT<char , true > CStrCiA; ///< Case insensitive ANSI/UTF-8 string |
|
186 typedef CStrT<wchar_t, false> CStrW; ///< Case sensitive unicode string |
|
187 typedef CStrT<wchar_t, true > CStrCiW; ///< Case insensitive unicode string |
|
188 |
|
189 #endif /* STR_HPP */ |