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