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 krisbash 1.3 #include "micxx_string.h"
|
26 mike 1.1 #include "memory.h"
27
28 #include <assert.h>
29 #include <new>
|
30 krisbash 1.3 #include <pal/atomic.h>
|
31 mike 1.1 ////////////////////////////////////////////
32 // Utility and base classes
33 #include <common.h>
34
35 MI_BEGIN_NAMESPACE
36
37 // String
38
39 static size_t _Strlen(const MI_Char* p)
40 {
41 const MI_Char* start = p;
42 while (*p)
43 p++;
44 return p - start;
45 }
46
47 String::String(const MI_Char* str)
48 {
49 m_data = 0;
50
51 if ( str )
52 mike 1.1 {
53 int size = (int)_Strlen(str);
54 m_data = Allocate( size+1 );
55 memcpy(m_data,str,(size+1) * sizeof(MI_Char) );
56 GetHeader(m_data)->m_size = size;
57
58 AddRef();
59 }
60 }
61
62 String::String(const MI_Char* str, MI_Uint32 size)
63 {
64 m_data = 0;
65
66 if ( str && size > 0 )
67 {
68 m_data = Allocate( size+1 );
69 memcpy(m_data,str,(size) * sizeof(MI_Char) );
70 m_data[size] = 0;
71 GetHeader(m_data)->m_size = size;
72
73 mike 1.1 AddRef();
74 }
75 }
76
77 void String::Clear()
78 {
79 if (m_data)
80 {
81 GetHeader(m_data)->m_size = 0;
82 m_data[0] = '\0';
83 }
84 }
85
86 String& String::operator = (const String& x)
87 {
88 if ( m_data != x.m_data )
89 {
90 Release();
91 m_data = x.m_data;
92 AddRef();
93 }
94 mike 1.1 return *this;
95 }
96
97 bool String::Equal(const String& x) const
98 {
99 if ( x.m_data == m_data )
100 return true;
101
102 if ( GetSize() != x.GetSize() )
103 return false;
104
105 return memcmp(x.Str(), Str(), (GetSize()+1) * sizeof(MI_Char)) == 0;
106 }
107
108 void String::Release()
109 {
110 if ( m_data &&
111 AtomicDec(GetHeader(m_data)->m_refCounter))
112 {
113 operator delete(GetHeader(m_data));
114 m_data = 0;
115 mike 1.1 }
116 }
117
118 MI_Char* String::Allocate(int capacity)
119 {
120 capacity = AlignCapacity(capacity);
121
122 // allocate new buffer
123 Header* chunk = (Header*)operator new(
124 sizeof(Header) + capacity * sizeof(MI_Char));
125
126 chunk->m_capacity = capacity;
|
127 krisbash 1.3 Atomic_Swap((ptrdiff_t*)&chunk->m_refCounter.__opaque, 0);
|
128 mike 1.1 chunk->m_size = 0;
129
130 return reinterpret_cast<MI_Char*>(chunk + 1);
131 }
132
133 String& String::operator += (const MI_Char* str)
134 {
135 // use assign instead
136 if ( !m_data )
137 return operator=(String(str));
138
139 if ( !str )
140 return *this;
141
142 int size = (int)_Strlen(str);
143
144
145 return StrCat(str,size);
146 }
147
148 void String::Append(const MI_Char* str, MI_Uint32 size)
149 mike 1.1 {
150 if (str)
151 {
152 if (!m_data)
153 {
154 operator=(String(str, size));
155 return;
156 }
157
158 StrCat(str, size);
159 }
160 }
161
162 MI_Char& String::operator[](MI_Uint32 index)
163 {
164 if (m_data && index < GetHeader(m_data)->m_size)
165 {
166 return m_data[index];
167 }
168 else
169 {
170 mike 1.1 static MI_Char dummy;
171 return dummy;
172 }
173 }
174
175 MI_Char String::operator[](MI_Uint32 index) const
176 {
177 if (m_data && index < GetHeader(m_data)->m_size)
178 return m_data[index];
179 else
180 return '\0';
181 }
182
183 String& String::operator+=(const MI_Char ch)
184 {
185 // ATTN: optimize this!
186 MI_Char buf[2];
187 buf[0] = ch;
188 buf[1] = '\0';
189 return operator+=(buf);
190 }
191 mike 1.1
192 String& String::StrCat(const MI_Char* str, MI_Uint32 size)
193 {
194 // nothing to change
195 if ( !size )
196 return *this;
197
198 if ( AtomicGet(GetHeader(m_data)->m_refCounter) != 1 ||
199 GetHeader(m_data)->m_capacity <= (size + GetHeader(m_data)->m_size)
200 )
201 { // have to allocate a new buffer
202 MI_Char* new_buf = Allocate( GetHeader(m_data)->m_size + size + 1 );
203
204 memcpy(new_buf,m_data,GetHeader(m_data)->m_size * sizeof(MI_Char) );
205 memcpy(new_buf+GetHeader(m_data)->m_size,str,(size+1) * sizeof(MI_Char) );
206 GetHeader(new_buf)->m_size = GetHeader(m_data)->m_size + size;
207
208 Release();
209 m_data = new_buf;
210 AddRef();
211 }
212 mike 1.1 else
213 {
214 memcpy(m_data+GetHeader(m_data)->m_size,str,(size+1) * sizeof(MI_Char) );
215 GetHeader(m_data)->m_size += size;
216 }
217
218 return *this;
219 }
220
221 MI_END_NAMESPACE
|