1 mike 1.1 /*
2 **==============================================================================
3 **
4 ** Open Management Infrastructure (OMI)
5 **
6 ** Copyright (c) Microsoft Corporation
7 **
8 ** Licensed under the Apache License, Version 2.0 (the "License"); you may not
9 ** use this file except in compliance with the License. You may obtain a copy
10 ** of the License at
11 **
12 ** http://www.apache.org/licenses/LICENSE-2.0
13 **
14 ** THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 ** KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
16 ** WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
17 ** MERCHANTABLITY OR NON-INFRINGEMENT.
18 **
19 ** See the Apache 2 License for the specific language governing permissions
20 ** and limitations under the License.
21 **
22 mike 1.1 **==============================================================================
23 */
24
25 #include "string.h"
26 #include "memory.h"
27
28 #include <assert.h>
29 #include <new>
30 ////////////////////////////////////////////
31 // Utility and base classes
32 #include <common.h>
33
34 MI_BEGIN_NAMESPACE
35
36 // String
37
38 static size_t _Strlen(const MI_Char* p)
39 {
40 const MI_Char* start = p;
41 while (*p)
42 p++;
43 mike 1.1 return p - start;
44 }
45
46 String::String(const MI_Char* str)
47 {
48 m_data = 0;
49
50 if ( str )
51 {
52 int size = (int)_Strlen(str);
53 m_data = Allocate( size+1 );
54 memcpy(m_data,str,(size+1) * sizeof(MI_Char) );
55 GetHeader(m_data)->m_size = size;
56
57 AddRef();
58 }
59 }
60
61 String::String(const MI_Char* str, MI_Uint32 size)
62 {
63 m_data = 0;
64 mike 1.1
65 if ( str && size > 0 )
66 {
67 m_data = Allocate( size+1 );
68 memcpy(m_data,str,(size) * sizeof(MI_Char) );
69 m_data[size] = 0;
70 GetHeader(m_data)->m_size = size;
71
72 AddRef();
73 }
74 }
75
76 void String::Clear()
77 {
78 if (m_data)
79 {
80 GetHeader(m_data)->m_size = 0;
81 m_data[0] = '\0';
82 }
83 }
84
85 mike 1.1 String& String::operator = (const String& x)
86 {
87 if ( m_data != x.m_data )
88 {
89 Release();
90 m_data = x.m_data;
91 AddRef();
92 }
93 return *this;
94 }
95
96 bool String::Equal(const String& x) const
97 {
98 if ( x.m_data == m_data )
99 return true;
100
101 if ( GetSize() != x.GetSize() )
102 return false;
103
104 return memcmp(x.Str(), Str(), (GetSize()+1) * sizeof(MI_Char)) == 0;
105 }
106 mike 1.1
107 void String::Release()
108 {
109 if ( m_data &&
110 AtomicDec(GetHeader(m_data)->m_refCounter))
111 {
112 operator delete(GetHeader(m_data));
113 m_data = 0;
114 }
115 }
116
117 MI_Char* String::Allocate(int capacity)
118 {
119 capacity = AlignCapacity(capacity);
120
121 // allocate new buffer
122 Header* chunk = (Header*)operator new(
123 sizeof(Header) + capacity * sizeof(MI_Char));
124
125 chunk->m_capacity = capacity;
126 AtomicSet(chunk->m_refCounter, 0);
127 mike 1.1 chunk->m_size = 0;
128
129 return reinterpret_cast<MI_Char*>(chunk + 1);
130 }
131
132 String& String::operator += (const MI_Char* str)
133 {
134 // use assign instead
135 if ( !m_data )
136 return operator=(String(str));
137
138 if ( !str )
139 return *this;
140
141 int size = (int)_Strlen(str);
142
143
144 return StrCat(str,size);
145 }
146
147 void String::Append(const MI_Char* str, MI_Uint32 size)
148 mike 1.1 {
149 if (str)
150 {
151 if (!m_data)
152 {
153 operator=(String(str, size));
154 return;
155 }
156
157 StrCat(str, size);
158 }
159 }
160
161 MI_Char& String::operator[](MI_Uint32 index)
162 {
163 if (m_data && index < GetHeader(m_data)->m_size)
164 {
165 return m_data[index];
166 }
167 else
168 {
169 mike 1.1 static MI_Char dummy;
170 return dummy;
171 }
172 }
173
174 MI_Char String::operator[](MI_Uint32 index) const
175 {
176 if (m_data && index < GetHeader(m_data)->m_size)
177 return m_data[index];
178 else
179 return '\0';
180 }
181
182 String& String::operator+=(const MI_Char ch)
183 {
184 // ATTN: optimize this!
185 MI_Char buf[2];
186 buf[0] = ch;
187 buf[1] = '\0';
188 return operator+=(buf);
189 }
190 mike 1.1
191 String& String::StrCat(const MI_Char* str, MI_Uint32 size)
192 {
193 // nothing to change
194 if ( !size )
195 return *this;
196
197 if ( AtomicGet(GetHeader(m_data)->m_refCounter) != 1 ||
198 GetHeader(m_data)->m_capacity <= (size + GetHeader(m_data)->m_size)
199 )
200 { // have to allocate a new buffer
201 MI_Char* new_buf = Allocate( GetHeader(m_data)->m_size + size + 1 );
202
203 memcpy(new_buf,m_data,GetHeader(m_data)->m_size * sizeof(MI_Char) );
204 memcpy(new_buf+GetHeader(m_data)->m_size,str,(size+1) * sizeof(MI_Char) );
205 GetHeader(new_buf)->m_size = GetHeader(m_data)->m_size + size;
206
207 Release();
208 m_data = new_buf;
209 AddRef();
210 }
211 mike 1.1 else
212 {
213 memcpy(m_data+GetHeader(m_data)->m_size,str,(size+1) * sizeof(MI_Char) );
214 GetHeader(m_data)->m_size += size;
215 }
216
217 return *this;
218 }
219
220 MI_END_NAMESPACE
|