xref: /xnu-11215/libkern/c++/OSString.cpp (revision bb611c8f)
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 }
392