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