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 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 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> 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> 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> 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> 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 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 259 OSString::getLength() const 260 { 261 return length - 1; 262 } 263 264 const char * 265 OSString::getCStringNoCopy() const 266 { 267 return string; 268 } 269 270 bool 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 283 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 294 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 304 OSString::isEqualTo(const char *aCString) const 305 { 306 return strncmp(string, aCString, length) == 0; 307 } 308 309 bool 310 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 325 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 361 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