]> git.saurik.com Git - apple/xnu.git/blame - libkern/c++/OSString.cpp
xnu-4903.270.47.tar.gz
[apple/xnu.git] / libkern / c++ / OSString.cpp
CommitLineData
1c79356b 1/*
0a7de745 2 * Copyright (c) 2019 Apple Inc. All rights reserved.
1c79356b 3 *
2d21ac55 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
0a7de745 5 *
2d21ac55
A
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.
0a7de745 14 *
2d21ac55
A
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
0a7de745 17 *
2d21ac55
A
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
8f6c56a5
A
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
2d21ac55
A
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.
0a7de745 25 *
2d21ac55 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
1c79356b
A
27 */
28/* IOString.m created by rsulack on Wed 17-Sep-1997 */
29/* IOString.cpp converted to C++ on Tue 1998-9-22 */
30
9bccf70c 31#include <string.h>
1c79356b
A
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>
9bccf70c 37#include <string.h>
1c79356b
A
38
39#define super OSObject
40
41OSDefineMetaClassAndStructors(OSString, OSObject)
0a7de745
A
42OSMetaClassDefineReservedUnused(OSString, 0);
43OSMetaClassDefineReservedUnused(OSString, 1);
44OSMetaClassDefineReservedUnused(OSString, 2);
45OSMetaClassDefineReservedUnused(OSString, 3);
46OSMetaClassDefineReservedUnused(OSString, 4);
47OSMetaClassDefineReservedUnused(OSString, 5);
48OSMetaClassDefineReservedUnused(OSString, 6);
49OSMetaClassDefineReservedUnused(OSString, 7);
50OSMetaClassDefineReservedUnused(OSString, 8);
51OSMetaClassDefineReservedUnused(OSString, 9);
1c79356b
A
52OSMetaClassDefineReservedUnused(OSString, 10);
53OSMetaClassDefineReservedUnused(OSString, 11);
54OSMetaClassDefineReservedUnused(OSString, 12);
55OSMetaClassDefineReservedUnused(OSString, 13);
56OSMetaClassDefineReservedUnused(OSString, 14);
57OSMetaClassDefineReservedUnused(OSString, 15);
58
0a7de745
A
59bool
60OSString::initWithString(const OSString *aString)
1c79356b 61{
0a7de745 62 return initWithCString(aString->string);
1c79356b
A
63}
64
0a7de745
A
65bool
66OSString::initWithCString(const char *cString)
1c79356b 67{
0a7de745
A
68 unsigned int newLength;
69 char * newString;
1c79356b 70
0a7de745
A
71 if (!cString || !super::init()) {
72 return false;
73 }
3e170ce0 74
0a7de745
A
75 newLength = strnlen(cString, kMaxStringLength);
76 if (newLength >= kMaxStringLength) {
77 return false;
78 }
39037602 79
0a7de745
A
80 newLength++;
81 newString = (char *) kalloc_container(newLength);
82 if (!newString) {
83 return false;
84 }
1c79356b 85
0a7de745 86 bcopy(cString, newString, newLength);
1c79356b 87
0a7de745
A
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;
3e170ce0 95
0a7de745 96 OSCONTAINER_ACCUMSIZE(length);
1c79356b 97
0a7de745 98 return true;
1c79356b
A
99}
100
0a7de745
A
101bool
102OSString::initWithStringOfLength(const char *cString, size_t inlength)
fe8ab488 103{
0a7de745
A
104 unsigned int newLength;
105 char * newString;
fe8ab488 106
0a7de745
A
107 if (!cString || !super::init()) {
108 return false;
109 }
3e170ce0 110
0a7de745
A
111 if (inlength >= kMaxStringLength) {
112 return false;
113 }
39037602 114
0a7de745
A
115 if (strnlen(cString, inlength) < inlength) {
116 return false;
117 }
3e170ce0 118
0a7de745
A
119 newLength = inlength + 1;
120 newString = (char *) kalloc_container(newLength);
121 if (!newString) {
122 return false;
123 }
3e170ce0 124
0a7de745
A
125 bcopy(cString, newString, inlength);
126 newString[inlength] = 0;
fe8ab488 127
0a7de745
A
128 if (!(flags & kOSStringNoCopy) && string) {
129 kfree(string, (vm_size_t)length);
130 OSCONTAINER_ACCUMSIZE(-((size_t)length));
131 }
fe8ab488 132
0a7de745
A
133 string = newString;
134 length = newLength;
135 flags &= ~kOSStringNoCopy;
fe8ab488 136
0a7de745
A
137 OSCONTAINER_ACCUMSIZE(length);
138
139 return true;
fe8ab488
A
140}
141
0a7de745
A
142bool
143OSString::initWithCStringNoCopy(const char *cString)
1c79356b 144{
0a7de745
A
145 if (!cString || !super::init()) {
146 return false;
147 }
1c79356b 148
0a7de745
A
149 length = strnlen(cString, kMaxStringLength);
150 if (length >= kMaxStringLength) {
151 return false;
152 }
39037602 153
0a7de745
A
154 length++;
155 flags |= kOSStringNoCopy;
156 string = const_cast<char *>(cString);
1c79356b 157
0a7de745 158 return true;
1c79356b
A
159}
160
0a7de745
A
161OSString *
162OSString::withString(const OSString *aString)
1c79356b 163{
0a7de745 164 OSString *me = new OSString;
1c79356b 165
0a7de745
A
166 if (me && !me->initWithString(aString)) {
167 me->release();
168 return 0;
169 }
1c79356b 170
0a7de745 171 return me;
1c79356b
A
172}
173
0a7de745
A
174OSString *
175OSString::withCString(const char *cString)
1c79356b 176{
0a7de745 177 OSString *me = new OSString;
1c79356b 178
0a7de745
A
179 if (me && !me->initWithCString(cString)) {
180 me->release();
181 return 0;
182 }
1c79356b 183
0a7de745 184 return me;
1c79356b
A
185}
186
0a7de745
A
187OSString *
188OSString::withCStringNoCopy(const char *cString)
1c79356b 189{
0a7de745 190 OSString *me = new OSString;
1c79356b 191
0a7de745
A
192 if (me && !me->initWithCStringNoCopy(cString)) {
193 me->release();
194 return 0;
195 }
1c79356b 196
0a7de745 197 return me;
1c79356b
A
198}
199
0a7de745
A
200OSString *
201OSString::withStringOfLength(const char *cString, size_t length)
fe8ab488 202{
0a7de745 203 OSString *me = new OSString;
fe8ab488 204
0a7de745
A
205 if (me && !me->initWithStringOfLength(cString, length)) {
206 me->release();
207 return 0;
208 }
fe8ab488 209
0a7de745 210 return me;
fe8ab488
A
211}
212
213
214
1c79356b
A
215/* @@@ gvdl */
216#if 0
0a7de745
A
217OSString *
218OSString::stringWithFormat(const char *format, ...)
1c79356b 219{
0a7de745
A
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;
1c79356b 238#else
0a7de745 239 return 0;
1c79356b
A
240#endif
241}
242#endif /* 0 */
243
0a7de745
A
244void
245OSString::free()
1c79356b 246{
0a7de745
A
247 if (!(flags & kOSStringNoCopy) && string) {
248 kfree(string, (vm_size_t)length);
249 OSCONTAINER_ACCUMSIZE(-((size_t)length));
250 }
1c79356b 251
0a7de745 252 super::free();
1c79356b
A
253}
254
0a7de745
A
255unsigned int
256OSString::getLength() const
257{
258 return length - 1;
259}
1c79356b 260
0a7de745
A
261const char *
262OSString::getCStringNoCopy() const
1c79356b 263{
0a7de745 264 return string;
1c79356b
A
265}
266
0a7de745
A
267bool
268OSString::setChar(char aChar, unsigned int index)
1c79356b 269{
0a7de745
A
270 if (!(flags & kOSStringNoCopy) && index < length - 1) {
271 string[index] = aChar;
1c79356b 272
0a7de745
A
273 return true;
274 } else {
275 return false;
276 }
1c79356b
A
277}
278
0a7de745
A
279char
280OSString::getChar(unsigned int index) const
1c79356b 281{
0a7de745
A
282 if (index < length) {
283 return string[index];
284 } else {
285 return '\0';
286 }
1c79356b
A
287}
288
289
0a7de745
A
290bool
291OSString::isEqualTo(const OSString *aString) const
1c79356b 292{
0a7de745
A
293 if (length != aString->length) {
294 return false;
295 } else {
296 return isEqualTo((const char *) aString->string);
297 }
1c79356b
A
298}
299
0a7de745
A
300bool
301OSString::isEqualTo(const char *aCString) const
1c79356b 302{
0a7de745 303 return strncmp(string, aCString, length) == 0;
1c79356b
A
304}
305
0a7de745
A
306bool
307OSString::isEqualTo(const OSMetaClassBase *obj) const
1c79356b 308{
0a7de745
A
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 }
1c79356b
A
319}
320
0a7de745
A
321bool
322OSString::isEqualTo(const OSData *obj) const
1c79356b 323{
0a7de745
A
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;
1c79356b
A
355}
356
0a7de745
A
357bool
358OSString::serialize(OSSerialize *s) const
1c79356b 359{
0a7de745
A
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");
1c79356b 391}