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