|
ferencd@0
|
1 /*
|
|
ferencd@0
|
2 www.sourceforge.net/projects/tinyxml
|
|
ferencd@0
|
3
|
|
ferencd@0
|
4 This software is provided 'as-is', without any express or implied
|
|
ferencd@0
|
5 warranty. In no event will the authors be held liable for any
|
|
ferencd@0
|
6 damages arising from the use of this software.
|
|
ferencd@0
|
7
|
|
ferencd@0
|
8 Permission is granted to anyone to use this software for any
|
|
ferencd@0
|
9 purpose, including commercial applications, and to alter it and
|
|
ferencd@0
|
10 redistribute it freely, subject to the following restrictions:
|
|
ferencd@0
|
11
|
|
ferencd@0
|
12 1. The origin of this software must not be misrepresented; you must
|
|
ferencd@0
|
13 not claim that you wrote the original software. If you use this
|
|
ferencd@0
|
14 software in a product, an acknowledgment in the product documentation
|
|
ferencd@0
|
15 would be appreciated but is not required.
|
|
ferencd@0
|
16
|
|
ferencd@0
|
17 2. Altered source versions must be plainly marked as such, and
|
|
ferencd@0
|
18 must not be misrepresented as being the original software.
|
|
ferencd@0
|
19
|
|
ferencd@0
|
20 3. This notice may not be removed or altered from any source
|
|
ferencd@0
|
21 distribution.
|
|
ferencd@0
|
22 */
|
|
ferencd@0
|
23
|
|
ferencd@0
|
24
|
|
ferencd@0
|
25 #ifndef TIXML_USE_STL
|
|
ferencd@0
|
26
|
|
ferencd@0
|
27 #ifndef TIXML_STRING_INCLUDED
|
|
ferencd@0
|
28 #define TIXML_STRING_INCLUDED
|
|
ferencd@0
|
29
|
|
ferencd@0
|
30 #include <assert.h>
|
|
ferencd@0
|
31 #include <string.h>
|
|
ferencd@0
|
32
|
|
ferencd@0
|
33 /* The support for explicit isn't that universal, and it isn't really
|
|
ferencd@0
|
34 required - it is used to check that the TiXmlString class isn't incorrectly
|
|
ferencd@0
|
35 used. Be nice to old compilers and macro it here:
|
|
ferencd@0
|
36 */
|
|
ferencd@0
|
37 #if defined(_MSC_VER) && (_MSC_VER >= 1200 )
|
|
ferencd@0
|
38 // Microsoft visual studio, version 6 and higher.
|
|
ferencd@0
|
39 #define TIXML_EXPLICIT explicit
|
|
ferencd@0
|
40 #elif defined(__GNUC__) && (__GNUC__ >= 3 )
|
|
ferencd@0
|
41 // GCC version 3 and higher.s
|
|
ferencd@0
|
42 #define TIXML_EXPLICIT explicit
|
|
ferencd@0
|
43 #else
|
|
ferencd@0
|
44 #define TIXML_EXPLICIT
|
|
ferencd@0
|
45 #endif
|
|
ferencd@0
|
46
|
|
ferencd@0
|
47
|
|
ferencd@0
|
48 /*
|
|
ferencd@0
|
49 TiXmlString is an emulation of a subset of the std::string template.
|
|
ferencd@0
|
50 Its purpose is to allow compiling TinyXML on compilers with no or poor STL support.
|
|
ferencd@0
|
51 Only the member functions relevant to the TinyXML project have been implemented.
|
|
ferencd@0
|
52 The buffer allocation is made by a simplistic power of 2 like mechanism : if we increase
|
|
ferencd@0
|
53 a string and there's no more room, we allocate a buffer twice as big as we need.
|
|
ferencd@0
|
54 */
|
|
ferencd@0
|
55 class TiXmlString
|
|
ferencd@0
|
56 {
|
|
ferencd@0
|
57 public :
|
|
ferencd@0
|
58 // The size type used
|
|
ferencd@0
|
59 typedef size_t size_type;
|
|
ferencd@0
|
60
|
|
ferencd@0
|
61 // Error value for find primitive
|
|
ferencd@0
|
62 static const size_type npos; // = -1;
|
|
ferencd@0
|
63
|
|
ferencd@0
|
64
|
|
ferencd@0
|
65 // TiXmlString empty constructor
|
|
ferencd@0
|
66 TiXmlString () : rep_(&nullrep_)
|
|
ferencd@0
|
67 {
|
|
ferencd@0
|
68 }
|
|
ferencd@0
|
69
|
|
ferencd@0
|
70 // TiXmlString copy constructor
|
|
ferencd@0
|
71 TiXmlString ( const TiXmlString & copy) : rep_(0)
|
|
ferencd@0
|
72 {
|
|
ferencd@0
|
73 init(copy.length());
|
|
ferencd@0
|
74 memcpy(start(), copy.data(), length());
|
|
ferencd@0
|
75 }
|
|
ferencd@0
|
76
|
|
ferencd@0
|
77 // TiXmlString constructor, based on a string
|
|
ferencd@0
|
78 TIXML_EXPLICIT TiXmlString ( const char * copy) : rep_(0)
|
|
ferencd@0
|
79 {
|
|
ferencd@0
|
80 init( static_cast<size_type>( strlen(copy) ));
|
|
ferencd@0
|
81 memcpy(start(), copy, length());
|
|
ferencd@0
|
82 }
|
|
ferencd@0
|
83
|
|
ferencd@0
|
84 // TiXmlString constructor, based on a string
|
|
ferencd@0
|
85 TIXML_EXPLICIT TiXmlString ( const char * str, size_type len) : rep_(0)
|
|
ferencd@0
|
86 {
|
|
ferencd@0
|
87 init(len);
|
|
ferencd@0
|
88 memcpy(start(), str, len);
|
|
ferencd@0
|
89 }
|
|
ferencd@0
|
90
|
|
ferencd@0
|
91 // TiXmlString destructor
|
|
ferencd@0
|
92 ~TiXmlString ()
|
|
ferencd@0
|
93 {
|
|
ferencd@0
|
94 quit();
|
|
ferencd@0
|
95 }
|
|
ferencd@0
|
96
|
|
ferencd@0
|
97 TiXmlString& operator = (const char * copy)
|
|
ferencd@0
|
98 {
|
|
ferencd@0
|
99 return assign( copy, static_cast<size_type>(strlen(copy)));
|
|
ferencd@0
|
100 }
|
|
ferencd@0
|
101
|
|
ferencd@0
|
102 TiXmlString& operator = (const TiXmlString & copy)
|
|
ferencd@0
|
103 {
|
|
ferencd@0
|
104 return assign(copy.start(), copy.length());
|
|
ferencd@0
|
105 }
|
|
ferencd@0
|
106
|
|
ferencd@0
|
107
|
|
ferencd@0
|
108 // += operator. Maps to append
|
|
ferencd@0
|
109 TiXmlString& operator += (const char * suffix)
|
|
ferencd@0
|
110 {
|
|
ferencd@0
|
111 return append(suffix, static_cast<size_type>( strlen(suffix) ));
|
|
ferencd@0
|
112 }
|
|
ferencd@0
|
113
|
|
ferencd@0
|
114 // += operator. Maps to append
|
|
ferencd@0
|
115 TiXmlString& operator += (char single)
|
|
ferencd@0
|
116 {
|
|
ferencd@0
|
117 return append(&single, 1);
|
|
ferencd@0
|
118 }
|
|
ferencd@0
|
119
|
|
ferencd@0
|
120 // += operator. Maps to append
|
|
ferencd@0
|
121 TiXmlString& operator += (const TiXmlString & suffix)
|
|
ferencd@0
|
122 {
|
|
ferencd@0
|
123 return append(suffix.data(), suffix.length());
|
|
ferencd@0
|
124 }
|
|
ferencd@0
|
125
|
|
ferencd@0
|
126
|
|
ferencd@0
|
127 // Convert a TiXmlString into a null-terminated char *
|
|
ferencd@0
|
128 const char * c_str () const { return rep_->str; }
|
|
ferencd@0
|
129
|
|
ferencd@0
|
130 // Convert a TiXmlString into a char * (need not be null terminated).
|
|
ferencd@0
|
131 const char * data () const { return rep_->str; }
|
|
ferencd@0
|
132
|
|
ferencd@0
|
133 // Return the length of a TiXmlString
|
|
ferencd@0
|
134 size_type length () const { return rep_->size; }
|
|
ferencd@0
|
135
|
|
ferencd@0
|
136 // Alias for length()
|
|
ferencd@0
|
137 size_type size () const { return rep_->size; }
|
|
ferencd@0
|
138
|
|
ferencd@0
|
139 // Checks if a TiXmlString is empty
|
|
ferencd@0
|
140 bool empty () const { return rep_->size == 0; }
|
|
ferencd@0
|
141
|
|
ferencd@0
|
142 // Return capacity of string
|
|
ferencd@0
|
143 size_type capacity () const { return rep_->capacity; }
|
|
ferencd@0
|
144
|
|
ferencd@0
|
145
|
|
ferencd@0
|
146 // single char extraction
|
|
ferencd@0
|
147 const char& at (size_type index) const
|
|
ferencd@0
|
148 {
|
|
ferencd@0
|
149 assert( index < length() );
|
|
ferencd@0
|
150 return rep_->str[ index ];
|
|
ferencd@0
|
151 }
|
|
ferencd@0
|
152
|
|
ferencd@0
|
153 // [] operator
|
|
ferencd@0
|
154 char& operator [] (size_type index) const
|
|
ferencd@0
|
155 {
|
|
ferencd@0
|
156 assert( index < length() );
|
|
ferencd@0
|
157 return rep_->str[ index ];
|
|
ferencd@0
|
158 }
|
|
ferencd@0
|
159
|
|
ferencd@0
|
160 // find a char in a string. Return TiXmlString::npos if not found
|
|
ferencd@0
|
161 size_type find (char lookup) const
|
|
ferencd@0
|
162 {
|
|
ferencd@0
|
163 return find(lookup, 0);
|
|
ferencd@0
|
164 }
|
|
ferencd@0
|
165
|
|
ferencd@0
|
166 // find a char in a string from an offset. Return TiXmlString::npos if not found
|
|
ferencd@0
|
167 size_type find (char tofind, size_type offset) const
|
|
ferencd@0
|
168 {
|
|
ferencd@0
|
169 if (offset >= length()) return npos;
|
|
ferencd@0
|
170
|
|
ferencd@0
|
171 for (const char* p = c_str() + offset; *p != '\0'; ++p)
|
|
ferencd@0
|
172 {
|
|
ferencd@0
|
173 if (*p == tofind) return static_cast< size_type >( p - c_str() );
|
|
ferencd@0
|
174 }
|
|
ferencd@0
|
175 return npos;
|
|
ferencd@0
|
176 }
|
|
ferencd@0
|
177
|
|
ferencd@0
|
178 void clear ()
|
|
ferencd@0
|
179 {
|
|
ferencd@0
|
180 //Lee:
|
|
ferencd@0
|
181 //The original was just too strange, though correct:
|
|
ferencd@0
|
182 // TiXmlString().swap(*this);
|
|
ferencd@0
|
183 //Instead use the quit & re-init:
|
|
ferencd@0
|
184 quit();
|
|
ferencd@0
|
185 init(0,0);
|
|
ferencd@0
|
186 }
|
|
ferencd@0
|
187
|
|
ferencd@0
|
188 /* Function to reserve a big amount of data when we know we'll need it. Be aware that this
|
|
ferencd@0
|
189 function DOES NOT clear the content of the TiXmlString if any exists.
|
|
ferencd@0
|
190 */
|
|
ferencd@0
|
191 void reserve (size_type cap);
|
|
ferencd@0
|
192
|
|
ferencd@0
|
193 TiXmlString& assign (const char* str, size_type len);
|
|
ferencd@0
|
194
|
|
ferencd@0
|
195 TiXmlString& append (const char* str, size_type len);
|
|
ferencd@0
|
196
|
|
ferencd@0
|
197 void swap (TiXmlString& other)
|
|
ferencd@0
|
198 {
|
|
ferencd@0
|
199 Rep* r = rep_;
|
|
ferencd@0
|
200 rep_ = other.rep_;
|
|
ferencd@0
|
201 other.rep_ = r;
|
|
ferencd@0
|
202 }
|
|
ferencd@0
|
203
|
|
ferencd@0
|
204 private:
|
|
ferencd@0
|
205
|
|
ferencd@0
|
206 void init(size_type sz) { init(sz, sz); }
|
|
ferencd@0
|
207 void set_size(size_type sz) { rep_->str[ rep_->size = sz ] = '\0'; }
|
|
ferencd@0
|
208 char* start() const { return rep_->str; }
|
|
ferencd@0
|
209 char* finish() const { return rep_->str + rep_->size; }
|
|
ferencd@0
|
210
|
|
ferencd@0
|
211 struct Rep
|
|
ferencd@0
|
212 {
|
|
ferencd@0
|
213 size_type size, capacity;
|
|
ferencd@0
|
214 char str[1];
|
|
ferencd@0
|
215 };
|
|
ferencd@0
|
216
|
|
ferencd@0
|
217 void init(size_type sz, size_type cap)
|
|
ferencd@0
|
218 {
|
|
ferencd@0
|
219 if (cap)
|
|
ferencd@0
|
220 {
|
|
ferencd@0
|
221 // Lee: the original form:
|
|
ferencd@0
|
222 // rep_ = static_cast<Rep*>(operator new(sizeof(Rep) + cap));
|
|
ferencd@0
|
223 // doesn't work in some cases of new being overloaded. Switching
|
|
ferencd@0
|
224 // to the normal allocation, although use an 'int' for systems
|
|
ferencd@0
|
225 // that are overly picky about structure alignment.
|
|
ferencd@0
|
226 const size_type bytesNeeded = sizeof(Rep) + cap;
|
|
ferencd@0
|
227 const size_type intsNeeded = ( bytesNeeded + sizeof(int) - 1 ) / sizeof( int );
|
|
ferencd@0
|
228 rep_ = reinterpret_cast<Rep*>( new int[ intsNeeded ] );
|
|
ferencd@0
|
229
|
|
ferencd@0
|
230 rep_->str[ rep_->size = sz ] = '\0';
|
|
ferencd@0
|
231 rep_->capacity = cap;
|
|
ferencd@0
|
232 }
|
|
ferencd@0
|
233 else
|
|
ferencd@0
|
234 {
|
|
ferencd@0
|
235 rep_ = &nullrep_;
|
|
ferencd@0
|
236 }
|
|
ferencd@0
|
237 }
|
|
ferencd@0
|
238
|
|
ferencd@0
|
239 void quit()
|
|
ferencd@0
|
240 {
|
|
ferencd@0
|
241 if (rep_ != &nullrep_)
|
|
ferencd@0
|
242 {
|
|
ferencd@0
|
243 // The rep_ is really an array of ints. (see the allocator, above).
|
|
ferencd@0
|
244 // Cast it back before delete, so the compiler won't incorrectly call destructors.
|
|
ferencd@0
|
245 delete [] ( reinterpret_cast<int*>( rep_ ) );
|
|
ferencd@0
|
246 }
|
|
ferencd@0
|
247 }
|
|
ferencd@0
|
248
|
|
ferencd@0
|
249 Rep * rep_;
|
|
ferencd@0
|
250 static Rep nullrep_;
|
|
ferencd@0
|
251
|
|
ferencd@0
|
252 } ;
|
|
ferencd@0
|
253
|
|
ferencd@0
|
254
|
|
ferencd@0
|
255 inline bool operator == (const TiXmlString & a, const TiXmlString & b)
|
|
ferencd@0
|
256 {
|
|
ferencd@0
|
257 return ( a.length() == b.length() ) // optimization on some platforms
|
|
ferencd@0
|
258 && ( strcmp(a.c_str(), b.c_str()) == 0 ); // actual compare
|
|
ferencd@0
|
259 }
|
|
ferencd@0
|
260 inline bool operator < (const TiXmlString & a, const TiXmlString & b)
|
|
ferencd@0
|
261 {
|
|
ferencd@0
|
262 return strcmp(a.c_str(), b.c_str()) < 0;
|
|
ferencd@0
|
263 }
|
|
ferencd@0
|
264
|
|
ferencd@0
|
265 inline bool operator != (const TiXmlString & a, const TiXmlString & b) { return !(a == b); }
|
|
ferencd@0
|
266 inline bool operator > (const TiXmlString & a, const TiXmlString & b) { return b < a; }
|
|
ferencd@0
|
267 inline bool operator <= (const TiXmlString & a, const TiXmlString & b) { return !(b < a); }
|
|
ferencd@0
|
268 inline bool operator >= (const TiXmlString & a, const TiXmlString & b) { return !(a < b); }
|
|
ferencd@0
|
269
|
|
ferencd@0
|
270 inline bool operator == (const TiXmlString & a, const char* b) { return strcmp(a.c_str(), b) == 0; }
|
|
ferencd@0
|
271 inline bool operator == (const char* a, const TiXmlString & b) { return b == a; }
|
|
ferencd@0
|
272 inline bool operator != (const TiXmlString & a, const char* b) { return !(a == b); }
|
|
ferencd@0
|
273 inline bool operator != (const char* a, const TiXmlString & b) { return !(b == a); }
|
|
ferencd@0
|
274
|
|
ferencd@0
|
275 TiXmlString operator + (const TiXmlString & a, const TiXmlString & b);
|
|
ferencd@0
|
276 TiXmlString operator + (const TiXmlString & a, const char* b);
|
|
ferencd@0
|
277 TiXmlString operator + (const char* a, const TiXmlString & b);
|
|
ferencd@0
|
278
|
|
ferencd@0
|
279
|
|
ferencd@0
|
280 /*
|
|
ferencd@0
|
281 TiXmlOutStream is an emulation of std::ostream. It is based on TiXmlString.
|
|
ferencd@0
|
282 Only the operators that we need for TinyXML have been developped.
|
|
ferencd@0
|
283 */
|
|
ferencd@0
|
284 class TiXmlOutStream : public TiXmlString
|
|
ferencd@0
|
285 {
|
|
ferencd@0
|
286 public :
|
|
ferencd@0
|
287
|
|
ferencd@0
|
288 // TiXmlOutStream << operator.
|
|
ferencd@0
|
289 TiXmlOutStream & operator << (const TiXmlString & in)
|
|
ferencd@0
|
290 {
|
|
ferencd@0
|
291 *this += in;
|
|
ferencd@0
|
292 return *this;
|
|
ferencd@0
|
293 }
|
|
ferencd@0
|
294
|
|
ferencd@0
|
295 // TiXmlOutStream << operator.
|
|
ferencd@0
|
296 TiXmlOutStream & operator << (const char * in)
|
|
ferencd@0
|
297 {
|
|
ferencd@0
|
298 *this += in;
|
|
ferencd@0
|
299 return *this;
|
|
ferencd@0
|
300 }
|
|
ferencd@0
|
301
|
|
ferencd@0
|
302 } ;
|
|
ferencd@0
|
303
|
|
ferencd@0
|
304 #endif // TIXML_STRING_INCLUDED
|
|
ferencd@0
|
305 #endif // TIXML_USE_STL
|