(file) Return to string.cpp CVS log (file) (dir) Up to [OMI] / omi / micxx

  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

ViewCVS 0.9.2