]> git.saurik.com Git - apple/xnu.git/blob - libkern/c++/OSString.cpp
xnu-7195.50.7.100.1.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 #define IOKIT_ENABLE_SHARED_PTR
32
33 #include <string.h>
34
35 #include <libkern/c++/OSString.h>
36 #include <libkern/c++/OSSerialize.h>
37 #include <libkern/c++/OSSharedPtr.h>
38 #include <libkern/c++/OSLib.h>
39 #include <libkern/c++/OSData.h>
40 #include <string.h>
41
42 #define super OSObject
43
44 OSDefineMetaClassAndStructorsWithZone(OSString, OSObject,
45 (zone_create_flags_t) (ZC_CACHING | ZC_ZFREE_CLEARMEM))
46 OSMetaClassDefineReservedUnused(OSString, 0);
47 OSMetaClassDefineReservedUnused(OSString, 1);
48 OSMetaClassDefineReservedUnused(OSString, 2);
49 OSMetaClassDefineReservedUnused(OSString, 3);
50 OSMetaClassDefineReservedUnused(OSString, 4);
51 OSMetaClassDefineReservedUnused(OSString, 5);
52 OSMetaClassDefineReservedUnused(OSString, 6);
53 OSMetaClassDefineReservedUnused(OSString, 7);
54 OSMetaClassDefineReservedUnused(OSString, 8);
55 OSMetaClassDefineReservedUnused(OSString, 9);
56 OSMetaClassDefineReservedUnused(OSString, 10);
57 OSMetaClassDefineReservedUnused(OSString, 11);
58 OSMetaClassDefineReservedUnused(OSString, 12);
59 OSMetaClassDefineReservedUnused(OSString, 13);
60 OSMetaClassDefineReservedUnused(OSString, 14);
61 OSMetaClassDefineReservedUnused(OSString, 15);
62
63 bool
64 OSString::initWithString(const OSString *aString)
65 {
66 return initWithCString(aString->string);
67 }
68
69 bool
70 OSString::initWithCString(const char *cString)
71 {
72 unsigned int newLength;
73 char * newString;
74
75 if (!cString || !super::init()) {
76 return false;
77 }
78
79 newLength = (unsigned int) strnlen(cString, kMaxStringLength);
80 if (newLength >= kMaxStringLength) {
81 return false;
82 }
83
84 newLength++;
85 newString = (char *)kalloc_data_container(newLength, Z_WAITOK);
86 if (!newString) {
87 return false;
88 }
89
90 bcopy(cString, newString, newLength);
91
92 if (!(flags & kOSStringNoCopy) && string) {
93 kfree_data_container(string, length);
94 OSCONTAINER_ACCUMSIZE(-((size_t)length));
95 }
96 string = newString;
97 length = newLength;
98 flags &= ~kOSStringNoCopy;
99
100 OSCONTAINER_ACCUMSIZE(length);
101
102 return true;
103 }
104
105 bool
106 OSString::initWithStringOfLength(const char *cString, size_t inlength)
107 {
108 unsigned int newLength;
109 char * newString;
110
111 if (!cString || !super::init()) {
112 return false;
113 }
114
115 if (inlength >= kMaxStringLength) {
116 return false;
117 }
118
119 if (strnlen(cString, inlength) < inlength) {
120 return false;
121 }
122
123 newLength = (unsigned int) (inlength + 1);
124 newString = (char *)kalloc_data_container(newLength, Z_WAITOK);
125 if (!newString) {
126 return false;
127 }
128
129 bcopy(cString, newString, inlength);
130 newString[inlength] = 0;
131
132 if (!(flags & kOSStringNoCopy) && string) {
133 kfree_data_container(string, length);
134 OSCONTAINER_ACCUMSIZE(-((size_t)length));
135 }
136
137 string = newString;
138 length = newLength;
139 flags &= ~kOSStringNoCopy;
140
141 OSCONTAINER_ACCUMSIZE(length);
142
143 return true;
144 }
145
146 bool
147 OSString::initWithCStringNoCopy(const char *cString)
148 {
149 if (!cString || !super::init()) {
150 return false;
151 }
152
153 length = (unsigned int) strnlen(cString, kMaxStringLength);
154 if (length >= kMaxStringLength) {
155 return false;
156 }
157
158 length++;
159 flags |= kOSStringNoCopy;
160 string = const_cast<char *>(cString);
161
162 return true;
163 }
164
165 OSSharedPtr<OSString>
166 OSString::withString(const OSString *aString)
167 {
168 OSSharedPtr<OSString> me = OSMakeShared<OSString>();
169
170 if (me && !me->initWithString(aString)) {
171 return nullptr;
172 }
173
174 return me;
175 }
176
177 OSSharedPtr<OSString>
178 OSString::withCString(const char *cString)
179 {
180 OSSharedPtr<OSString> me = OSMakeShared<OSString>();
181
182 if (me && !me->initWithCString(cString)) {
183 return nullptr;
184 }
185
186 return me;
187 }
188
189 OSSharedPtr<OSString>
190 OSString::withCStringNoCopy(const char *cString)
191 {
192 OSSharedPtr<OSString> me = OSMakeShared<OSString>();
193
194 if (me && !me->initWithCStringNoCopy(cString)) {
195 return nullptr;
196 }
197
198 return me;
199 }
200
201 OSSharedPtr<OSString>
202 OSString::withStringOfLength(const char *cString, size_t length)
203 {
204 OSSharedPtr<OSString> me = OSMakeShared<OSString>();
205
206 if (me && !me->initWithStringOfLength(cString, length)) {
207 return nullptr;
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_data_container(string, 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 }