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(newLength, 86 Z_VM_TAG_BT(Z_WAITOK, VM_KERN_MEMORY_LIBKERN)); 87 if (!newString) { 88 return false; 89 } 90 91 bcopy(cString, newString, 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(cString, 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(cString, newString, 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(cString, 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, 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((const char *) aString->string); 302 } 303 } 304 305 bool 306 OSString::isEqualTo(const char *aCString) const 307 { 308 return strncmp(string, aCString, 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(str); 319 } else if ((data = OSDynamicCast(OSData, obj))) { 320 return isEqualTo(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(this)) { 368 return true; 369 } 370 371 if (!s->addXMLStartTag(this, "string")) { 372 return false; 373 } 374 while (*c) { 375 if (*c == '<') { 376 if (!s->addString("<")) { 377 return false; 378 } 379 } else if (*c == '>') { 380 if (!s->addString(">")) { 381 return false; 382 } 383 } else if (*c == '&') { 384 if (!s->addString("&")) { 385 return false; 386 } 387 } else { 388 if (!s->addChar(*c)) { 389 return false; 390 } 391 } 392 c++; 393 } 394 395 return s->addXMLEndTag("string"); 396 } 397