(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 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

ViewCVS 0.9.2