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