1 /*
2 www.sourceforge.net/projects/tinyxml
3 Original file by Yves Berquin.
4 
5 This software is provided 'as-is', without any express or implied
6 warranty. In no event will the authors be held liable for any
7 damages arising from the use of this software.
8 
9 Permission is granted to anyone to use this software for any
10 purpose, including commercial applications, and to alter it and
11 redistribute it freely, subject to the following restrictions:
12 
13 1. The origin of this software must not be misrepresented; you must
14 not claim that you wrote the original software. If you use this
15 software in a product, an acknowledgment in the product documentation
16 would be appreciated but is not required.
17 
18 2. Altered source versions must be plainly marked as such, and
19 must not be misrepresented as being the original software.
20 
21 3. This notice may not be removed or altered from any source
22 distribution.
23 */
24 
25 #include "tinyxml.h"
26 
27 #ifndef TIXML_USE_STL
28 
29 
30 #include <stdlib.h>
31 #include <string.h>
32 #include <ctype.h>
33 
34 #include "TinyStr.h"
35 
36 // TiXmlString constructor, based on a C string
TiXmlString(const char * instring)37 TiXmlString::TiXmlString (const char* instring)
38 {
39     unsigned newlen;
40     char * newstring;
41 
42     if (!instring)
43     {
44         allocated = 0;
45         cstring = NULL;
46         current_length = 0;
47         return;
48     }
49     newlen = strlen (instring) + 1;
50     newstring = new char [newlen];
51     memcpy (newstring, instring, newlen);
52     // strcpy (newstring, instring);
53     allocated = newlen;
54     cstring = newstring;
55     current_length = newlen - 1;
56 }
57 
58 // TiXmlString copy constructor
TiXmlString(const TiXmlString & copy)59 TiXmlString::TiXmlString (const TiXmlString& copy)
60 {
61     unsigned newlen;
62     char * newstring;
63 
64 	// Prevent copy to self!
65 	if ( &copy == this )
66 		return;
67 
68     if (! copy . allocated)
69     {
70         allocated = 0;
71         cstring = NULL;
72         current_length = 0;
73         return;
74     }
75     newlen = copy . length () + 1;
76     newstring = new char [newlen];
77     // strcpy (newstring, copy . cstring);
78     memcpy (newstring, copy . cstring, newlen);
79     allocated = newlen;
80     cstring = newstring;
81     current_length = newlen - 1;
82 }
83 
84 // TiXmlString = operator. Safe when assign own content
operator =(const char * content)85 void TiXmlString ::operator = (const char * content)
86 {
87     unsigned newlen;
88     char * newstring;
89 
90     if (! content)
91     {
92         empty_it ();
93         return;
94     }
95     newlen = strlen (content) + 1;
96     newstring = new char [newlen];
97     // strcpy (newstring, content);
98     memcpy (newstring, content, newlen);
99     empty_it ();
100     allocated = newlen;
101     cstring = newstring;
102     current_length = newlen - 1;
103 }
104 
105 // = operator. Safe when assign own content
operator =(const TiXmlString & copy)106 void TiXmlString ::operator = (const TiXmlString & copy)
107 {
108     unsigned newlen;
109     char * newstring;
110 
111     if (! copy . length ())
112     {
113         empty_it ();
114         return;
115     }
116     newlen = copy . length () + 1;
117     newstring = new char [newlen];
118     // strcpy (newstring, copy . c_str ());
119     memcpy (newstring, copy . c_str (), newlen);
120     empty_it ();
121     allocated = newlen;
122     cstring = newstring;
123     current_length = newlen - 1;
124 }
125 
126 
127 // append a const char * to an existing TiXmlString
append(const char * str,int len)128 void TiXmlString::append( const char* str, int len )
129 {
130     char * new_string;
131     unsigned new_alloc, new_size, size_suffix;
132 
133 	// don't use strlen - it can overrun the len passed in!
134 	const char* p = str;
135 	size_suffix = 0;
136 
137 	while ( *p && size_suffix < (unsigned)len )
138 	{
139 		++p;
140 		++size_suffix;
141 	}
142     if ( !size_suffix)
143         return;
144 
145     new_size = length () + size_suffix + 1;
146     // check if we need to expand
147     if (new_size > allocated)
148     {
149         // compute new size
150         new_alloc = assign_new_size (new_size);
151 
152         // allocate new buffer
153         new_string = new char [new_alloc];
154         new_string [0] = 0;
155 
156         // copy the previous allocated buffer into this one
157         if (allocated && cstring)
158             // strcpy (new_string, cstring);
159             memcpy (new_string, cstring, length ());
160 
161         // append the suffix. It does exist, otherwize we wouldn't be expanding
162         // strncat (new_string, str, len);
163         memcpy (new_string + length (),
164                 str,
165                 size_suffix);
166 
167         // return previsously allocated buffer if any
168         if (allocated && cstring)
169             delete [] cstring;
170 
171         // update member variables
172         cstring = new_string;
173         allocated = new_alloc;
174     }
175     else
176     {
177         // we know we can safely append the new string
178         // strncat (cstring, str, len);
179         memcpy (cstring + length (),
180                 str,
181                 size_suffix);
182     }
183     current_length = new_size - 1;
184     cstring [current_length] = 0;
185 }
186 
187 
188 // append a const char * to an existing TiXmlString
append(const char * suffix)189 void TiXmlString::append( const char * suffix )
190 {
191     char * new_string;
192     unsigned new_alloc, new_size;
193 
194     new_size = length () + strlen (suffix) + 1;
195     // check if we need to expand
196     if (new_size > allocated)
197     {
198         // compute new size
199         new_alloc = assign_new_size (new_size);
200 
201         // allocate new buffer
202         new_string = new char [new_alloc];
203         new_string [0] = 0;
204 
205         // copy the previous allocated buffer into this one
206         if (allocated && cstring)
207             memcpy (new_string, cstring, 1 + length ());
208             // strcpy (new_string, cstring);
209 
210         // append the suffix. It does exist, otherwize we wouldn't be expanding
211         // strcat (new_string, suffix);
212         memcpy (new_string + length (),
213                 suffix,
214                 strlen (suffix) + 1);
215 
216         // return previsously allocated buffer if any
217         if (allocated && cstring)
218             delete [] cstring;
219 
220         // update member variables
221         cstring = new_string;
222         allocated = new_alloc;
223     }
224     else
225     {
226         // we know we can safely append the new string
227         // strcat (cstring, suffix);
228         memcpy (cstring + length (),
229                 suffix,
230                 strlen (suffix) + 1);
231     }
232     current_length = new_size - 1;
233 }
234 
235 // Check for TiXmlString equuivalence
236 //bool TiXmlString::operator == (const TiXmlString & compare) const
237 //{
238 //    return (! strcmp (c_str (), compare . c_str ()));
239 //}
240 
241 //unsigned TiXmlString::length () const
242 //{
243 //    if (allocated)
244 //        // return strlen (cstring);
245 //        return current_length;
246 //    return 0;
247 //}
248 
249 
find(char tofind,unsigned offset) const250 unsigned TiXmlString::find (char tofind, unsigned offset) const
251 {
252     char * lookup;
253 
254     if (offset >= length ())
255         return (unsigned) notfound;
256     for (lookup = cstring + offset; * lookup; lookup++)
257         if (* lookup == tofind)
258             return lookup - cstring;
259     return (unsigned) notfound;
260 }
261 
262 
operator ==(const TiXmlString & compare) const263 bool TiXmlString::operator == (const TiXmlString & compare) const
264 {
265 	if ( allocated && compare.allocated )
266 	{
267 		assert( cstring );
268 		assert( compare.cstring );
269 		return ( strcmp( cstring, compare.cstring ) == 0 );
270  	}
271 	return false;
272 }
273 
274 
operator <(const TiXmlString & compare) const275 bool TiXmlString::operator < (const TiXmlString & compare) const
276 {
277 	if ( allocated && compare.allocated )
278 	{
279 		assert( cstring );
280 		assert( compare.cstring );
281 		return ( strcmp( cstring, compare.cstring ) > 0 );
282  	}
283 	return false;
284 }
285 
286 
operator >(const TiXmlString & compare) const287 bool TiXmlString::operator > (const TiXmlString & compare) const
288 {
289 	if ( allocated && compare.allocated )
290 	{
291 		assert( cstring );
292 		assert( compare.cstring );
293 		return ( strcmp( cstring, compare.cstring ) < 0 );
294  	}
295 	return false;
296 }
297 
298 
299 #endif	// TIXML_USE_STL
300