1 /* 2 * Copyright (c) 2000 Apple Computer, 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 OSString::initWithString(const OSString *aString) 60 { 61 return initWithCString(aString->string); 62 } 63 64 bool OSString::initWithCString(const char *cString) 65 { 66 unsigned int newLength; 67 char * newString; 68 69 if (!cString || !super::init()) return false; 70 71 newLength = strnlen(cString, kMaxStringLength); 72 if (newLength >= kMaxStringLength) return false; 73 74 newLength++; 75 newString = (char *) kalloc_container(newLength); 76 if (!newString) return false; 77 78 bcopy(cString, newString, newLength); 79 80 if ( !(flags & kOSStringNoCopy) && string) { 81 kfree(string, (vm_size_t)length); 82 OSCONTAINER_ACCUMSIZE(-((size_t)length)); 83 } 84 string = newString; 85 length = newLength; 86 flags &= ~kOSStringNoCopy; 87 88 OSCONTAINER_ACCUMSIZE(length); 89 90 return true; 91 } 92 93 bool OSString::initWithStringOfLength(const char *cString, size_t inlength) 94 { 95 unsigned int newLength; 96 char * newString; 97 98 if (!cString || !super::init()) return false; 99 100 if (inlength >= kMaxStringLength) return false; 101 102 newLength = inlength + 1; 103 newString = (char *) kalloc_container(newLength); 104 if (!newString) return false; 105 106 bcopy(cString, newString, inlength); 107 newString[inlength] = 0; 108 109 if ( !(flags & kOSStringNoCopy) && string) { 110 kfree(string, (vm_size_t)length); 111 OSCONTAINER_ACCUMSIZE(-((size_t)length)); 112 } 113 114 string = newString; 115 length = newLength; 116 flags &= ~kOSStringNoCopy; 117 118 OSCONTAINER_ACCUMSIZE(length); 119 120 return true; 121 } 122 123 bool OSString::initWithCStringNoCopy(const char *cString) 124 { 125 if (!cString || !super::init()) 126 return false; 127 128 length = strnlen(cString, kMaxStringLength); 129 if (length >= kMaxStringLength) return false; 130 131 length++; 132 flags |= kOSStringNoCopy; 133 string = const_cast<char *>(cString); 134 135 return true; 136 } 137 138 OSString *OSString::withString(const OSString *aString) 139 { 140 OSString *me = new OSString; 141 142 if (me && !me->initWithString(aString)) { 143 me->release(); 144 return 0; 145 } 146 147 return me; 148 } 149 150 OSString *OSString::withCString(const char *cString) 151 { 152 OSString *me = new OSString; 153 154 if (me && !me->initWithCString(cString)) { 155 me->release(); 156 return 0; 157 } 158 159 return me; 160 } 161 162 OSString *OSString::withCStringNoCopy(const char *cString) 163 { 164 OSString *me = new OSString; 165 166 if (me && !me->initWithCStringNoCopy(cString)) { 167 me->release(); 168 return 0; 169 } 170 171 return me; 172 } 173 174 OSString *OSString::withStringOfLength(const char *cString, size_t length) 175 { 176 OSString *me = new OSString; 177 178 if (me && !me->initWithStringOfLength(cString, length)) { 179 me->release(); 180 return 0; 181 } 182 183 return me; 184 } 185 186 187 188 /* @@@ gvdl */ 189 #if 0 190 OSString *OSString::stringWithFormat(const char *format, ...) 191 { 192 #ifndef KERNEL // mach3xxx 193 OSString *me; 194 va_list argList; 195 196 if (!format) 197 return 0; 198 199 va_start(argList, format); 200 me = stringWithCapacity(256); 201 me->length = vsnprintf(me->string, 256, format, argList); 202 me->length++; // we include the null in the length 203 if (me->Length > 256) 204 me->Length = 256; 205 va_end (argList); 206 207 return me; 208 #else 209 return 0; 210 #endif 211 } 212 #endif /* 0 */ 213 214 void OSString::free() 215 { 216 if ( !(flags & kOSStringNoCopy) && string) { 217 kfree(string, (vm_size_t)length); 218 OSCONTAINER_ACCUMSIZE(-((size_t)length)); 219 } 220 221 super::free(); 222 } 223 224 unsigned int OSString::getLength() const { return length - 1; } 225 226 const char *OSString::getCStringNoCopy() const 227 { 228 return string; 229 } 230 231 bool OSString::setChar(char aChar, unsigned int index) 232 { 233 if ( !(flags & kOSStringNoCopy) && index < length - 1) { 234 string[index] = aChar; 235 236 return true; 237 } 238 else 239 return false; 240 } 241 242 char OSString::getChar(unsigned int index) const 243 { 244 if (index < length) 245 return string[index]; 246 else 247 return '\0'; 248 } 249 250 251 bool OSString::isEqualTo(const OSString *aString) const 252 { 253 if (length != aString->length) 254 return false; 255 else 256 return isEqualTo((const char *) aString->string); 257 } 258 259 bool OSString::isEqualTo(const char *aCString) const 260 { 261 return strncmp(string, aCString, length) == 0; 262 } 263 264 bool OSString::isEqualTo(const OSMetaClassBase *obj) const 265 { 266 OSString * str; 267 OSData * data; 268 269 if ((str = OSDynamicCast(OSString, obj))) 270 return isEqualTo(str); 271 else if ((data = OSDynamicCast (OSData, obj))) 272 return isEqualTo(data); 273 else 274 return false; 275 } 276 277 bool OSString::isEqualTo(const OSData *obj) const 278 { 279 if (NULL == obj) 280 return false; 281 282 unsigned int dataLen = obj->getLength ();; 283 const char * dataPtr = (const char *) obj->getBytesNoCopy (); 284 285 if (dataLen != length) { 286 287 // check for the fact that OSData may be a buffer that 288 // that includes a termination byte and will thus have 289 // a length of the actual string length PLUS 1. In this 290 // case we verify that the additional byte is a terminator 291 // and if so count the two lengths as being the same. 292 293 if ( (dataLen - length) == 1 ) { 294 if (dataPtr[dataLen-1] != 0) 295 return false; 296 dataLen--; 297 } 298 else 299 return false; 300 } 301 302 for ( unsigned int i=0; i < dataLen; i++ ) { 303 if ( *dataPtr++ != string[i] ) 304 return false; 305 } 306 307 return true; 308 } 309 310 bool OSString::serialize(OSSerialize *s) const 311 { 312 char *c = string; 313 314 if (s->previouslySerialized(this)) return true; 315 316 if (!s->addXMLStartTag(this, "string")) return false; 317 while (*c) { 318 if (*c == '<') { 319 if (!s->addString("<")) return false; 320 } else if (*c == '>') { 321 if (!s->addString(">")) return false; 322 } else if (*c == '&') { 323 if (!s->addString("&")) return false; 324 } else { 325 if (!s->addChar(*c)) return false; 326 } 327 c++; 328 } 329 330 return s->addXMLEndTag("string"); 331 } 332