xref: /xnu-11215/libkern/c++/OSString.cpp (revision cc9a6355)
1 /*
2  * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3  *
4  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5  *
6  * This file contains Original Code and/or Modifications of Original Code
7  * as defined in and that are subject to the Apple Public Source License
8  * Version 2.0 (the 'License'). You may not use this file except in
9  * compliance with the License. The rights granted to you under the License
10  * may not be used to create, or enable the creation or redistribution of,
11  * unlawful or unlicensed copies of an Apple operating system, or to
12  * circumvent, violate, or enable the circumvention or violation of, any
13  * terms of an Apple operating system software license agreement.
14  *
15  * Please obtain a copy of the License at
16  * http://www.opensource.apple.com/apsl/ and read it before using this file.
17  *
18  * The Original Code and all software distributed under the License are
19  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23  * Please see the License for the specific language governing rights and
24  * limitations under the License.
25  *
26  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27  */
28 /* IOString.m created by rsulack on Wed 17-Sep-1997 */
29 /* IOString.cpp converted to C++ on Tue 1998-9-22 */
30 
31 #include <string.h>
32 
33 #include <libkern/c++/OSString.h>
34 #include <libkern/c++/OSSerialize.h>
35 #include <libkern/c++/OSLib.h>
36 #include <libkern/c++/OSData.h>
37 #include <string.h>
38 
39 #define super OSObject
40 
41 OSDefineMetaClassAndStructors(OSString, OSObject)
42 OSMetaClassDefineReservedUnused(OSString,  0);
43 OSMetaClassDefineReservedUnused(OSString,  1);
44 OSMetaClassDefineReservedUnused(OSString,  2);
45 OSMetaClassDefineReservedUnused(OSString,  3);
46 OSMetaClassDefineReservedUnused(OSString,  4);
47 OSMetaClassDefineReservedUnused(OSString,  5);
48 OSMetaClassDefineReservedUnused(OSString,  6);
49 OSMetaClassDefineReservedUnused(OSString,  7);
50 OSMetaClassDefineReservedUnused(OSString,  8);
51 OSMetaClassDefineReservedUnused(OSString,  9);
52 OSMetaClassDefineReservedUnused(OSString, 10);
53 OSMetaClassDefineReservedUnused(OSString, 11);
54 OSMetaClassDefineReservedUnused(OSString, 12);
55 OSMetaClassDefineReservedUnused(OSString, 13);
56 OSMetaClassDefineReservedUnused(OSString, 14);
57 OSMetaClassDefineReservedUnused(OSString, 15);
58 
59 bool OSString::initWithString(const OSString *aString)
60 {
61     return initWithCString(aString->string);
62 }
63 
64 bool OSString::initWithCString(const char *cString)
65 {
66     unsigned int   newLength;
67     char         * newString;
68 
69     if (!cString || !super::init()) return false;
70 
71     newLength = strnlen(cString, kMaxStringLength);
72     if (newLength >= kMaxStringLength) return false;
73 
74     newLength++;
75     newString = (char *) kalloc_container(newLength);
76     if (!newString) return false;
77 
78     bcopy(cString, newString, newLength);
79 
80     if ( !(flags & kOSStringNoCopy) && string) {
81         kfree(string, (vm_size_t)length);
82         OSCONTAINER_ACCUMSIZE(-((size_t)length));
83     }
84     string = newString;
85     length = newLength;
86     flags &= ~kOSStringNoCopy;
87 
88     OSCONTAINER_ACCUMSIZE(length);
89 
90     return true;
91 }
92 
93 bool OSString::initWithStringOfLength(const char *cString, size_t inlength)
94 {
95     unsigned int   newLength;
96     char         * newString;
97 
98     if (!cString || !super::init()) return false;
99 
100     if (inlength >= kMaxStringLength) return false;
101 
102     newLength = inlength + 1;
103     newString = (char *) kalloc_container(newLength);
104     if (!newString) return false;
105 
106     bcopy(cString, newString, inlength);
107     newString[inlength] = 0;
108 
109     if ( !(flags & kOSStringNoCopy) && string) {
110         kfree(string, (vm_size_t)length);
111         OSCONTAINER_ACCUMSIZE(-((size_t)length));
112     }
113 
114     string = newString;
115     length = newLength;
116     flags &= ~kOSStringNoCopy;
117 
118     OSCONTAINER_ACCUMSIZE(length);
119 
120     return true;
121 }
122 
123 bool OSString::initWithCStringNoCopy(const char *cString)
124 {
125     if (!cString || !super::init())
126         return false;
127 
128     length = strnlen(cString, kMaxStringLength);
129     if (length >= kMaxStringLength) return false;
130 
131     length++;
132     flags |= kOSStringNoCopy;
133     string = const_cast<char *>(cString);
134 
135     return true;
136 }
137 
138 OSString *OSString::withString(const OSString *aString)
139 {
140     OSString *me = new OSString;
141 
142     if (me && !me->initWithString(aString)) {
143         me->release();
144         return 0;
145     }
146 
147     return me;
148 }
149 
150 OSString *OSString::withCString(const char *cString)
151 {
152     OSString *me = new OSString;
153 
154     if (me && !me->initWithCString(cString)) {
155         me->release();
156         return 0;
157     }
158 
159     return me;
160 }
161 
162 OSString *OSString::withCStringNoCopy(const char *cString)
163 {
164     OSString *me = new OSString;
165 
166     if (me && !me->initWithCStringNoCopy(cString)) {
167         me->release();
168         return 0;
169     }
170 
171     return me;
172 }
173 
174 OSString *OSString::withStringOfLength(const char *cString, size_t length)
175 {
176     OSString *me = new OSString;
177 
178     if (me && !me->initWithStringOfLength(cString, length)) {
179         me->release();
180         return 0;
181     }
182 
183     return me;
184 }
185 
186 
187 
188 /* @@@ gvdl */
189 #if 0
190 OSString *OSString::stringWithFormat(const char *format, ...)
191 {
192 #ifndef KERNEL			// mach3xxx
193     OSString *me;
194     va_list argList;
195 
196     if (!format)
197         return 0;
198 
199     va_start(argList, format);
200     me = stringWithCapacity(256);
201     me->length = vsnprintf(me->string, 256, format, argList);
202     me->length++;	// we include the null in the length
203     if (me->Length > 256)
204         me->Length = 256;
205     va_end (argList);
206 
207     return me;
208 #else
209     return 0;
210 #endif
211 }
212 #endif /* 0 */
213 
214 void OSString::free()
215 {
216     if ( !(flags & kOSStringNoCopy) && string) {
217         kfree(string, (vm_size_t)length);
218         OSCONTAINER_ACCUMSIZE(-((size_t)length));
219     }
220 
221     super::free();
222 }
223 
224 unsigned int OSString::getLength()  const { return length - 1; }
225 
226 const char *OSString::getCStringNoCopy() const
227 {
228     return string;
229 }
230 
231 bool OSString::setChar(char aChar, unsigned int index)
232 {
233     if ( !(flags & kOSStringNoCopy) && index < length - 1) {
234         string[index] = aChar;
235 
236         return true;
237     }
238     else
239         return false;
240 }
241 
242 char OSString::getChar(unsigned int index) const
243 {
244     if (index < length)
245         return string[index];
246     else
247         return '\0';
248 }
249 
250 
251 bool OSString::isEqualTo(const OSString *aString) const
252 {
253     if (length != aString->length)
254         return false;
255     else
256         return isEqualTo((const char *) aString->string);
257 }
258 
259 bool OSString::isEqualTo(const char *aCString) const
260 {
261     return strncmp(string, aCString, length) == 0;
262 }
263 
264 bool OSString::isEqualTo(const OSMetaClassBase *obj) const
265 {
266     OSString *	str;
267     OSData *    data;
268 
269     if ((str = OSDynamicCast(OSString, obj)))
270         return isEqualTo(str);
271     else if ((data = OSDynamicCast (OSData, obj)))
272         return isEqualTo(data);
273     else
274         return false;
275 }
276 
277 bool OSString::isEqualTo(const OSData *obj) const
278 {
279     if (NULL == obj)
280       return false;
281 
282     unsigned int dataLen = obj->getLength ();;
283     const char * dataPtr = (const char *) obj->getBytesNoCopy ();
284 
285     if (dataLen != length) {
286 
287       // check for the fact that OSData may be a buffer that
288       // that includes a termination byte and will thus have
289       // a length of the actual string length PLUS 1. In this
290       // case we verify that the additional byte is a terminator
291       // and if so count the two lengths as being the same.
292 
293       if ( (dataLen - length) == 1 ) {
294 	if (dataPtr[dataLen-1] != 0)
295 	  return false;
296 	dataLen--;
297       }
298       else
299 	return false;
300     }
301 
302     for ( unsigned int i=0; i < dataLen; i++ ) {
303       if ( *dataPtr++ != string[i] )
304         return false;
305     }
306 
307     return true;
308 }
309 
310 bool OSString::serialize(OSSerialize *s) const
311 {
312     char *c = string;
313 
314     if (s->previouslySerialized(this)) return true;
315 
316     if (!s->addXMLStartTag(this, "string")) return false;
317     while (*c) {
318         if (*c == '<') {
319             if (!s->addString("&lt;")) return false;
320         } else if (*c == '>') {
321             if (!s->addString("&gt;")) return false;
322         } else if (*c == '&') {
323             if (!s->addString("&amp;")) return false;
324         } else {
325             if (!s->addChar(*c)) return false;
326         }
327         c++;
328     }
329 
330     return s->addXMLEndTag("string");
331 }
332