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