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
41OSDefineMetaClassAndStructors(OSString, OSObject)
42OSMetaClassDefineReservedUnused(OSString,  0);
43OSMetaClassDefineReservedUnused(OSString,  1);
44OSMetaClassDefineReservedUnused(OSString,  2);
45OSMetaClassDefineReservedUnused(OSString,  3);
46OSMetaClassDefineReservedUnused(OSString,  4);
47OSMetaClassDefineReservedUnused(OSString,  5);
48OSMetaClassDefineReservedUnused(OSString,  6);
49OSMetaClassDefineReservedUnused(OSString,  7);
50OSMetaClassDefineReservedUnused(OSString,  8);
51OSMetaClassDefineReservedUnused(OSString,  9);
52OSMetaClassDefineReservedUnused(OSString, 10);
53OSMetaClassDefineReservedUnused(OSString, 11);
54OSMetaClassDefineReservedUnused(OSString, 12);
55OSMetaClassDefineReservedUnused(OSString, 13);
56OSMetaClassDefineReservedUnused(OSString, 14);
57OSMetaClassDefineReservedUnused(OSString, 15);
58
59#if OSALLOCDEBUG
60extern "C" {
61    extern int debug_container_malloc_size;
62};
63#define ACCUMSIZE(s) do { debug_container_malloc_size += (s); } while(0)
64#else
65#define ACCUMSIZE(s)
66#endif
67
68bool OSString::initWithString(const OSString *aString)
69{
70    return initWithCString(aString->string);
71}
72
73bool OSString::initWithCString(const char *cString)
74{
75    if (!cString || !super::init())
76        return false;
77
78    length = strlen(cString) + 1;
79    string = (char *) kalloc(length);
80    if (!string)
81        return false;
82
83    bcopy(cString, string, length);
84
85    ACCUMSIZE(length);
86
87    return true;
88}
89
90bool OSString::initWithCStringNoCopy(const char *cString)
91{
92    if (!cString || !super::init())
93        return false;
94
95    length = strlen(cString) + 1;
96    flags |= kOSStringNoCopy;
97    string = const_cast<char *>(cString);
98
99    return true;
100}
101
102OSString *OSString::withString(const OSString *aString)
103{
104    OSString *me = new OSString;
105
106    if (me && !me->initWithString(aString)) {
107        me->release();
108        return 0;
109    }
110
111    return me;
112}
113
114OSString *OSString::withCString(const char *cString)
115{
116    OSString *me = new OSString;
117
118    if (me && !me->initWithCString(cString)) {
119        me->release();
120        return 0;
121    }
122
123    return me;
124}
125
126OSString *OSString::withCStringNoCopy(const char *cString)
127{
128    OSString *me = new OSString;
129
130    if (me && !me->initWithCStringNoCopy(cString)) {
131        me->release();
132        return 0;
133    }
134
135    return me;
136}
137
138/* @@@ gvdl */
139#if 0
140OSString *OSString::stringWithFormat(const char *format, ...)
141{
142#ifndef KERNEL			// mach3xxx
143    OSString *me;
144    va_list argList;
145
146    if (!format)
147        return 0;
148
149    va_start(argList, format);
150    me = stringWithCapacity(256);
151    me->length = vsnprintf(me->string, 256, format, argList);
152    me->length++;	// we include the null in the length
153    if (me->Length > 256)
154        me->Length = 256;
155    va_end (argList);
156
157    return me;
158#else
159    return 0;
160#endif
161}
162#endif /* 0 */
163
164void OSString::free()
165{
166    if ( !(flags & kOSStringNoCopy) && string) {
167        kfree(string, (vm_size_t)length);
168        ACCUMSIZE(-length);
169    }
170
171    super::free();
172}
173
174unsigned int OSString::getLength()  const { return length - 1; }
175
176const char *OSString::getCStringNoCopy() const
177{
178    return string;
179}
180
181bool OSString::setChar(char aChar, unsigned int index)
182{
183    if ( !(flags & kOSStringNoCopy) && index < length - 1) {
184        string[index] = aChar;
185
186        return true;
187    }
188    else
189        return false;
190}
191
192char OSString::getChar(unsigned int index) const
193{
194    if (index < length)
195        return string[index];
196    else
197        return '\0';
198}
199
200
201bool OSString::isEqualTo(const OSString *aString) const
202{
203    if (length != aString->length)
204        return false;
205    else
206        return isEqualTo((const char *) aString->string);
207}
208
209bool OSString::isEqualTo(const char *aCString) const
210{
211    return strncmp(string, aCString, length) == 0;
212}
213
214bool OSString::isEqualTo(const OSMetaClassBase *obj) const
215{
216    OSString *	str;
217    OSData *    data;
218
219    if ((str = OSDynamicCast(OSString, obj)))
220        return isEqualTo(str);
221    else if ((data = OSDynamicCast (OSData, obj)))
222        return isEqualTo(data);
223    else
224        return false;
225}
226
227bool OSString::isEqualTo(const OSData *obj) const
228{
229    if (NULL == obj)
230      return false;
231
232    unsigned int dataLen = obj->getLength ();;
233    char * dataPtr = (char *) obj->getBytesNoCopy ();
234
235    if (dataLen != length) {
236
237      // check for the fact that OSData may be a buffer that
238      // that includes a termination byte and will thus have
239      // a length of the actual string length PLUS 1. In this
240      // case we verify that the additional byte is a terminator
241      // and if so count the two lengths as being the same.
242
243      if ( (dataLen - length) == 1 ) {
244	if (dataPtr[dataLen-1] != 0)
245	  return false;
246	dataLen--;
247      }
248      else
249	return false;
250    }
251
252    for ( unsigned int i=0; i < dataLen; i++ ) {
253      if ( *dataPtr++ != string[i] )
254        return false;
255    }
256
257    return true;
258}
259
260bool OSString::serialize(OSSerialize *s) const
261{
262    char *c = string;
263
264    if (s->previouslySerialized(this)) return true;
265
266    if (!s->addXMLStartTag(this, "string")) return false;
267    while (*c) {
268        if (*c == '<') {
269            if (!s->addString("&lt;")) return false;
270        } else if (*c == '>') {
271            if (!s->addString("&gt;")) return false;
272        } else if (*c == '&') {
273            if (!s->addString("&amp;")) return false;
274        } else {
275            if (!s->addChar(*c)) return false;
276        }
277        c++;
278    }
279
280    return s->addXMLEndTag("string");
281}
282