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("<")) { 372 return false; 373 } 374 } else if (*c == '>') { 375 if (!s->addString(">")) { 376 return false; 377 } 378 } else if (*c == '&') { 379 if (!s->addString("&")) { 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