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