xref: /xnu-11215/libkern/c++/OSString.cpp (revision 0f3703ac)
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 = strlen(cString) + 1;
72     newString = (char *) kalloc_container(newLength);
73     if (!newString) return false;
74 
75     bcopy(cString, newString, newLength);
76 
77     if ( !(flags & kOSStringNoCopy) && string) {
78         kfree(string, (vm_size_t)length);
79         OSCONTAINER_ACCUMSIZE(-((size_t)length));
80     }
81     string = newString;
82     length = newLength;
83     flags &= ~kOSStringNoCopy;
84 
85     OSCONTAINER_ACCUMSIZE(length);
86 
87     return true;
88 }
89 
90 bool OSString::initWithStringOfLength(const char *cString, size_t inlength)
91 {
92     unsigned int   newLength;
93     char         * newString;
94 
95     if (!cString || !super::init()) return false;
96 
97     newLength = inlength + 1;
98     newString = (char *) kalloc_container(newLength);
99     if (!newString) return false;
100 
101     bcopy(cString, newString, inlength);
102     newString[inlength] = 0;
103 
104     if ( !(flags & kOSStringNoCopy) && string) {
105         kfree(string, (vm_size_t)length);
106         OSCONTAINER_ACCUMSIZE(-((size_t)length));
107     }
108 
109     string = newString;
110     length = newLength;
111     flags &= ~kOSStringNoCopy;
112 
113     OSCONTAINER_ACCUMSIZE(length);
114 
115     return true;
116 }
117 
118 bool OSString::initWithCStringNoCopy(const char *cString)
119 {
120     if (!cString || !super::init())
121         return false;
122 
123     length = strlen(cString) + 1;
124     flags |= kOSStringNoCopy;
125     string = const_cast<char *>(cString);
126 
127     return true;
128 }
129 
130 OSString *OSString::withString(const OSString *aString)
131 {
132     OSString *me = new OSString;
133 
134     if (me && !me->initWithString(aString)) {
135         me->release();
136         return 0;
137     }
138 
139     return me;
140 }
141 
142 OSString *OSString::withCString(const char *cString)
143 {
144     OSString *me = new OSString;
145 
146     if (me && !me->initWithCString(cString)) {
147         me->release();
148         return 0;
149     }
150 
151     return me;
152 }
153 
154 OSString *OSString::withCStringNoCopy(const char *cString)
155 {
156     OSString *me = new OSString;
157 
158     if (me && !me->initWithCStringNoCopy(cString)) {
159         me->release();
160         return 0;
161     }
162 
163     return me;
164 }
165 
166 OSString *OSString::withStringOfLength(const char *cString, size_t length)
167 {
168     OSString *me = new OSString;
169 
170     if (me && !me->initWithStringOfLength(cString, length)) {
171         me->release();
172         return 0;
173     }
174 
175     return me;
176 }
177 
178 
179 
180 /* @@@ gvdl */
181 #if 0
182 OSString *OSString::stringWithFormat(const char *format, ...)
183 {
184 #ifndef KERNEL			// mach3xxx
185     OSString *me;
186     va_list argList;
187 
188     if (!format)
189         return 0;
190 
191     va_start(argList, format);
192     me = stringWithCapacity(256);
193     me->length = vsnprintf(me->string, 256, format, argList);
194     me->length++;	// we include the null in the length
195     if (me->Length > 256)
196         me->Length = 256;
197     va_end (argList);
198 
199     return me;
200 #else
201     return 0;
202 #endif
203 }
204 #endif /* 0 */
205 
206 void OSString::free()
207 {
208     if ( !(flags & kOSStringNoCopy) && string) {
209         kfree(string, (vm_size_t)length);
210         OSCONTAINER_ACCUMSIZE(-((size_t)length));
211     }
212 
213     super::free();
214 }
215 
216 unsigned int OSString::getLength()  const { return length - 1; }
217 
218 const char *OSString::getCStringNoCopy() const
219 {
220     return string;
221 }
222 
223 bool OSString::setChar(char aChar, unsigned int index)
224 {
225     if ( !(flags & kOSStringNoCopy) && index < length - 1) {
226         string[index] = aChar;
227 
228         return true;
229     }
230     else
231         return false;
232 }
233 
234 char OSString::getChar(unsigned int index) const
235 {
236     if (index < length)
237         return string[index];
238     else
239         return '\0';
240 }
241 
242 
243 bool OSString::isEqualTo(const OSString *aString) const
244 {
245     if (length != aString->length)
246         return false;
247     else
248         return isEqualTo((const char *) aString->string);
249 }
250 
251 bool OSString::isEqualTo(const char *aCString) const
252 {
253     return strncmp(string, aCString, length) == 0;
254 }
255 
256 bool OSString::isEqualTo(const OSMetaClassBase *obj) const
257 {
258     OSString *	str;
259     OSData *    data;
260 
261     if ((str = OSDynamicCast(OSString, obj)))
262         return isEqualTo(str);
263     else if ((data = OSDynamicCast (OSData, obj)))
264         return isEqualTo(data);
265     else
266         return false;
267 }
268 
269 bool OSString::isEqualTo(const OSData *obj) const
270 {
271     if (NULL == obj)
272       return false;
273 
274     unsigned int dataLen = obj->getLength ();;
275     char * dataPtr = (char *) obj->getBytesNoCopy ();
276 
277     if (dataLen != length) {
278 
279       // check for the fact that OSData may be a buffer that
280       // that includes a termination byte and will thus have
281       // a length of the actual string length PLUS 1. In this
282       // case we verify that the additional byte is a terminator
283       // and if so count the two lengths as being the same.
284 
285       if ( (dataLen - length) == 1 ) {
286 	if (dataPtr[dataLen-1] != 0)
287 	  return false;
288 	dataLen--;
289       }
290       else
291 	return false;
292     }
293 
294     for ( unsigned int i=0; i < dataLen; i++ ) {
295       if ( *dataPtr++ != string[i] )
296         return false;
297     }
298 
299     return true;
300 }
301 
302 bool OSString::serialize(OSSerialize *s) const
303 {
304     char *c = string;
305 
306     if (s->previouslySerialized(this)) return true;
307 
308     if (!s->addXMLStartTag(this, "string")) return false;
309     while (*c) {
310         if (*c == '<') {
311             if (!s->addString("&lt;")) return false;
312         } else if (*c == '>') {
313             if (!s->addString("&gt;")) return false;
314         } else if (*c == '&') {
315             if (!s->addString("&amp;")) return false;
316         } else {
317             if (!s->addChar(*c)) return false;
318         }
319         c++;
320     }
321 
322     return s->addXMLEndTag("string");
323 }
324