String_Base.cpp

Go to the documentation of this file.
00001 // $Id: String_Base.cpp 81138 2008-03-28 09:18:15Z johnnyw $
00002 
00003 #ifndef ACE_STRING_BASE_CPP
00004 #define ACE_STRING_BASE_CPP
00005 
00006 #include "ace/ACE.h"
00007 #include "ace/Malloc_Base.h"
00008 #include "ace/String_Base.h"
00009 #include "ace/Auto_Ptr.h"
00010 #include "ace/OS_NS_string.h"
00011 
00012 #include <algorithm>  // For std::swap<>
00013 
00014 #if !defined (__ACE_INLINE__)
00015 #include "ace/String_Base.inl"
00016 #endif /* __ACE_INLINE__ */
00017 
00018 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
00019 
00020 ACE_ALLOC_HOOK_DEFINE(ACE_String_Base)
00021 
00022 template <class CHAR>
00023 CHAR ACE_String_Base<CHAR>::NULL_String_ = 0;
00024 
00025 // Default constructor.
00026 
00027 template <class CHAR>
00028 ACE_String_Base<CHAR>::ACE_String_Base (ACE_Allocator *the_allocator)
00029   : allocator_ (the_allocator ? the_allocator : ACE_Allocator::instance ()),
00030     len_ (0),
00031     buf_len_ (0),
00032     rep_ (&ACE_String_Base<CHAR>::NULL_String_),
00033     release_ (false)
00034 {
00035   ACE_TRACE ("ACE_String_Base<CHAR>::ACE_String_Base");
00036 }
00037 
00038 // Constructor that actually copies memory.
00039 
00040 template <class CHAR>
00041 ACE_String_Base<CHAR>::ACE_String_Base (const CHAR *s,
00042                                         ACE_Allocator *the_allocator,
00043                                         bool release)
00044   : allocator_ (the_allocator ? the_allocator : ACE_Allocator::instance ()),
00045     len_ (0),
00046     buf_len_ (0),
00047     rep_ (0),
00048     release_ (false)
00049 {
00050   ACE_TRACE ("ACE_String_Base<CHAR>::ACE_String_Base");
00051   this->set (s, release);
00052 }
00053 
00054 template <class CHAR>
00055 ACE_String_Base<CHAR>::ACE_String_Base (CHAR c,
00056                                         ACE_Allocator *the_allocator)
00057   : allocator_ (the_allocator ? the_allocator : ACE_Allocator::instance ()),
00058     len_ (0),
00059     buf_len_ (0),
00060     rep_ (0),
00061     release_ (false)
00062 {
00063   ACE_TRACE ("ACE_String_Base<CHAR>::ACE_String_Base");
00064 
00065   this->set (&c, 1, true);
00066 }
00067 
00068 // Constructor that actually copies memory.
00069 
00070 template <class CHAR>
00071 ACE_String_Base<CHAR>::ACE_String_Base (
00072   const CHAR *s,
00073   typename ACE_String_Base<CHAR>::size_type  len,
00074   ACE_Allocator *the_allocator,
00075   bool release)
00076   : allocator_ (the_allocator ? the_allocator : ACE_Allocator::instance ()),
00077     len_ (0),
00078     buf_len_ (0),
00079     rep_ (0),
00080     release_ (false)
00081 {
00082   ACE_TRACE ("ACE_String_Base<CHAR>::ACE_String_Base");
00083 
00084   this->set (s, len, release);
00085 }
00086 
00087 // Copy constructor.
00088 
00089 template <class CHAR>
00090 ACE_String_Base<CHAR>::ACE_String_Base (const ACE_String_Base<CHAR> &s)
00091   : allocator_ (s.allocator_ ? s.allocator_ : ACE_Allocator::instance ()),
00092     len_ (0),
00093     buf_len_ (0),
00094     rep_ (0),
00095     release_ (false)
00096 {
00097   ACE_TRACE ("ACE_String_Base<CHAR>::ACE_String_Base");
00098 
00099   this->set (s.rep_, s.len_, true);
00100 }
00101 
00102 template <class CHAR>
00103 ACE_String_Base<CHAR>::ACE_String_Base (
00104   typename ACE_String_Base<CHAR>::size_type len,
00105   CHAR c,
00106   ACE_Allocator *the_allocator)
00107   : allocator_ (the_allocator ? the_allocator : ACE_Allocator::instance ()),
00108     len_ (0),
00109     buf_len_ (0),
00110     rep_ (0),
00111     release_ (false)
00112 {
00113   ACE_TRACE ("ACE_String_Base<CHAR>::ACE_String_Base");
00114 
00115   this->resize (len, c);
00116 }
00117 
00118 template <class CHAR>
00119 ACE_String_Base<CHAR>::~ACE_String_Base (void)
00120 {
00121   ACE_TRACE ("ACE_String_Base<CHAR>::~ACE_String_Base");
00122 
00123   if (this->buf_len_ != 0 && this->release_)
00124       this->allocator_->free (this->rep_);
00125 }
00126 
00127 // this method might benefit from a little restructuring.
00128 template <class CHAR> void
00129 ACE_String_Base<CHAR>::set (const CHAR *s,
00130                             typename ACE_String_Base<CHAR>::size_type len,
00131                             bool release)
00132 {
00133   // Case 1. Going from memory to more memory
00134   size_type new_buf_len = len + 1;
00135   if (s != 0 && len != 0 && release && this->buf_len_ < new_buf_len)
00136     {
00137       CHAR *temp = 0;
00138       ACE_ALLOCATOR (temp,
00139                      (CHAR *) this->allocator_->malloc (new_buf_len * sizeof (CHAR)));
00140 
00141       if (this->buf_len_ != 0 && this->release_)
00142         this->allocator_->free (this->rep_);
00143 
00144       this->rep_ = temp;
00145       this->buf_len_ = new_buf_len;
00146       this->release_ = true;
00147       this->len_ = len;
00148       ACE_OS::memcpy (this->rep_, s, len * sizeof (CHAR));
00149       this->rep_[len] = 0;
00150     }
00151   else // Case 2. No memory allocation is necessary.
00152     {
00153       // Free memory if necessary and figure out future ownership
00154       if (!release || s == 0 || len == 0)
00155         {
00156           if (this->buf_len_ != 0 && this->release_)
00157             {
00158               this->allocator_->free (this->rep_);
00159               this->release_ = false;
00160             }
00161         }
00162       // Populate data.
00163       if (s == 0 || len == 0)
00164         {
00165           this->buf_len_ = 0;
00166           this->len_ = 0;
00167           this->rep_ = &ACE_String_Base<CHAR>::NULL_String_;
00168           this->release_ = false;
00169         }
00170       else if (!release) // Note: No guarantee that rep_ is null terminated.
00171         {
00172           this->buf_len_ = len;
00173           this->len_ = len;
00174           this->rep_ = const_cast <CHAR *> (s);
00175           this->release_ = false;
00176         }
00177       else
00178         {
00179           ACE_OS::memcpy (this->rep_, s, len * sizeof (CHAR));
00180           this->rep_[len] = 0;
00181           this->len_ = len;
00182         }
00183     }
00184 }
00185 
00186 // Return substring.
00187 template <class CHAR> ACE_String_Base<CHAR>
00188 ACE_String_Base<CHAR>::substring (
00189   typename ACE_String_Base<CHAR>::size_type offset,
00190   typename ACE_String_Base<CHAR>::size_type length) const
00191 {
00192   ACE_String_Base<CHAR> nill;
00193   size_type count = length;
00194 
00195   // case 1. empty string
00196   if (this->len_ == 0)
00197     return nill;
00198 
00199   // case 2. start pos past our end
00200   if (offset >= this->len_)
00201     return nill;
00202   // No length == empty string.
00203   else if (length == 0)
00204     return nill;
00205   // Get all remaining bytes.
00206   else if (length == npos || count > (this->len_ - offset))
00207     count = this->len_ - offset;
00208 
00209   return ACE_String_Base<CHAR> (&this->rep_[offset], count, this->allocator_);
00210 }
00211 
00212 template <class CHAR> ACE_String_Base<CHAR> &
00213 ACE_String_Base<CHAR>::append (const CHAR* s,
00214                                typename ACE_String_Base<CHAR>::size_type slen)
00215 {
00216   ACE_TRACE ("ACE_String_Base<CHAR>::append(const CHAR*, size_type)");
00217   if (slen > 0 && slen != npos)
00218   {
00219     // case 1. No memory allocation needed.
00220     if (this->buf_len_ >= this->len_ + slen + 1)
00221     {
00222       // Copy in data from new string.
00223       ACE_OS::memcpy (this->rep_ + this->len_, s, slen * sizeof (CHAR));
00224     }
00225     else // case 2. Memory reallocation is needed
00226     {
00227       const size_type new_buf_len =
00228         ace_max(this->len_ + slen + 1, this->buf_len_ + this->buf_len_ / 2);
00229 
00230       CHAR *t = 0;
00231 
00232       ACE_ALLOCATOR_RETURN (t,
00233         (CHAR *) this->allocator_->malloc (new_buf_len * sizeof (CHAR)), *this);
00234 
00235       // Copy memory from old string into new string.
00236       ACE_OS::memcpy (t, this->rep_, this->len_ * sizeof (CHAR));
00237 
00238       ACE_OS::memcpy (t + this->len_, s, slen * sizeof (CHAR));
00239 
00240       if (this->buf_len_ != 0 && this->release_)
00241         this->allocator_->free (this->rep_);
00242 
00243       this->release_ = true;
00244       this->rep_ = t;
00245       this->buf_len_ = new_buf_len;
00246     }
00247 
00248     this->len_ += slen;
00249     this->rep_[this->len_] = 0;
00250   }
00251 
00252   return *this;
00253 }
00254 
00255 template <class CHAR> u_long
00256 ACE_String_Base<CHAR>::hash (void) const
00257 {
00258   return
00259     ACE::hash_pjw (reinterpret_cast<char *> (
00260                       const_cast<CHAR *> (this->rep_)),
00261                    this->len_ * sizeof (CHAR));
00262 }
00263 
00264 template <class CHAR> void
00265 ACE_String_Base<CHAR>::resize (typename ACE_String_Base<CHAR>::size_type len,
00266                                CHAR c)
00267 {
00268   ACE_TRACE ("ACE_String_Base<CHAR>::resize");
00269 
00270   fast_resize(len);
00271   ACE_OS::memset (this->rep_, c, this->buf_len_ * sizeof (CHAR));
00272 }
00273 
00274 template <class CHAR> void
00275 ACE_String_Base<CHAR>::fast_resize (size_t len)
00276 {
00277   ACE_TRACE ("ACE_String_Base<CHAR>::fast_resize");
00278 
00279   // Only reallocate if we don't have enough space...
00280   if (this->buf_len_ <= len)
00281     {
00282       if (this->buf_len_ != 0 && this->release_)
00283         this->allocator_->free (this->rep_);
00284 
00285       this->rep_ = static_cast<CHAR*>
00286                      (this->allocator_->malloc ((len + 1) * sizeof (CHAR)));
00287       this->buf_len_ = len + 1;
00288       this->release_ = true;
00289     }
00290   this->len_ = 0;
00291   if (len > 0)
00292     this->rep_[0] = 0;
00293 }
00294 
00295 template <class CHAR> void
00296 ACE_String_Base<CHAR>::clear (bool release)
00297 {
00298   // This can't use set(), because that would free memory if release=false
00299   if (release)
00300   {
00301     if (this->buf_len_ != 0 && this->release_)
00302       this->allocator_->free (this->rep_);
00303 
00304     this->rep_ = &ACE_String_Base<CHAR>::NULL_String_;
00305     this->len_ = 0;
00306     this->buf_len_ = 0;
00307     this->release_ = false;
00308   }
00309   else
00310     {
00311       this->fast_clear ();
00312     }
00313 }
00314 
00315 // Assignment operator (does copy memory).
00316 template <class CHAR> ACE_String_Base<CHAR> &
00317 ACE_String_Base<CHAR>::operator= (const CHAR *s)
00318 {
00319   ACE_TRACE ("ACE_String_Base<CHAR>::operator=");
00320   if (s != 0)
00321     this->set (s, true);
00322   return *this;
00323 }
00324 
00325 // Assignment operator (does copy memory).
00326 template <class CHAR> ACE_String_Base<CHAR> &
00327 ACE_String_Base<CHAR>::operator= (const ACE_String_Base<CHAR> &s)
00328 {
00329   ACE_TRACE ("ACE_String_Base<CHAR>::operator=");
00330 
00331   // Check for self-assignment.
00332   if (this != &s)
00333     {
00334       this->set (s.rep_, s.len_, true);
00335     }
00336 
00337   return *this;
00338 }
00339 
00340 template <class CHAR> void
00341 ACE_String_Base<CHAR>::set (const CHAR *s, bool release)
00342 {
00343   size_t length = 0;
00344   if (s != 0)
00345     length = ACE_OS::strlen (s);
00346 
00347   this->set (s, length, release);
00348 }
00349 
00350 template <class CHAR> void
00351 ACE_String_Base<CHAR>::fast_clear (void)
00352 {
00353   this->len_ = 0;
00354   if (this->release_)
00355     {
00356       // String retains the original buffer.
00357       if (this->rep_ != &ACE_String_Base<CHAR>::NULL_String_)
00358         this->rep_[0] = 0;
00359     }
00360   else
00361     {
00362       // External buffer: string relinquishes control of it.
00363       this->buf_len_ = 0;
00364       this->rep_ = &ACE_String_Base<CHAR>::NULL_String_;
00365     }
00366 }
00367 
00368 // Get a copy of the underlying representation.
00369 
00370 template <class CHAR> CHAR *
00371 ACE_String_Base<CHAR>::rep (void) const
00372 {
00373   ACE_TRACE ("ACE_String_Base<CHAR>::rep");
00374 
00375   CHAR *new_string;
00376   ACE_NEW_RETURN (new_string, CHAR[this->len_ + 1], 0);
00377   ACE_OS::strsncpy (new_string, this->rep_, this->len_+1);
00378 
00379   return new_string;
00380 }
00381 
00382 template <class CHAR> int
00383 ACE_String_Base<CHAR>::compare (const ACE_String_Base<CHAR> &s) const
00384 {
00385   ACE_TRACE ("ACE_String_Base<CHAR>::compare");
00386 
00387   if (this->rep_ == s.rep_)
00388     return 0;
00389 
00390   // Pick smaller of the two lengths and perform the comparison.
00391   size_type smaller_length = ace_min (this->len_, s.len_);
00392 
00393   int result = ACE_OS::memcmp (this->rep_,
00394                                s.rep_,
00395                                smaller_length * sizeof (CHAR));
00396 
00397   if (!result)
00398     result = static_cast<int> (this->len_ - s.len_);
00399   return result;
00400 }
00401 
00402 // Comparison operator.
00403 
00404 template <class CHAR> bool
00405 ACE_String_Base<CHAR>::operator== (const ACE_String_Base<CHAR> &s) const
00406 {
00407   return this->len_ == s.len_ &&
00408          ACE_OS::memcmp (this->rep_,
00409                          s.rep_,
00410                          this->len_ * sizeof (CHAR)) == 0;
00411 }
00412 
00413 template <class CHAR> bool
00414 ACE_String_Base<CHAR>::operator== (const CHAR *s) const
00415 {
00416   size_t len = ACE_OS::strlen (s);
00417   return this->len_ == len &&
00418          ACE_OS::memcmp (this->rep_,
00419                          s,
00420                          len * sizeof (CHAR)) == 0;
00421 }
00422 
00423 template <class CHAR> typename ACE_String_Base<CHAR>::size_type
00424 ACE_String_Base<CHAR>::find (
00425   const CHAR *s,
00426   typename ACE_String_Base<CHAR>::size_type pos) const
00427 {
00428   CHAR *substr = this->rep_ + pos;
00429   size_t len = ACE_OS::strlen (s);
00430   CHAR *pointer = ACE_OS::strnstr (substr, s, len);
00431   if (pointer == 0)
00432     return ACE_String_Base<CHAR>::npos;
00433   else
00434     return pointer - this->rep_;
00435 }
00436 
00437 template <class CHAR> typename ACE_String_Base<CHAR>::size_type
00438 ACE_String_Base<CHAR>::find (
00439   CHAR c,
00440   typename ACE_String_Base<CHAR>::size_type pos) const
00441 {
00442   CHAR *substr = this->rep_ + pos;
00443   CHAR *pointer = ACE_OS::strnchr (substr, c, this->len_ - pos);
00444   if (pointer == 0)
00445     return ACE_String_Base<CHAR>::npos;
00446   else
00447     return pointer - this->rep_;
00448 }
00449 
00450 template <class CHAR> typename ACE_String_Base<CHAR>::size_type
00451 ACE_String_Base<CHAR>::rfind (
00452   CHAR c,
00453   typename ACE_String_Base<CHAR>::size_type pos) const
00454 {
00455   if (pos == npos || pos > this->len_)
00456     pos = this->len_;
00457 
00458   // Do not change to prefix operator!  Proper operation of this loop
00459   // depends on postfix decrement behavior.
00460   for (size_type i = pos; i-- != 0; )
00461     if (this->rep_[i] == c)
00462       return i;
00463 
00464   return ACE_String_Base<CHAR>::npos;
00465 }
00466 
00467 template <class CHAR> void
00468 ACE_String_Base<CHAR>::swap (ACE_String_Base<CHAR> & str)
00469 {
00470   std::swap (this->allocator_ , str.allocator_);
00471   std::swap (this->len_       , str.len_);
00472   std::swap (this->buf_len_   , str.buf_len_);
00473   std::swap (this->rep_       , str.rep_);
00474   std::swap (this->release_   , str.release_);
00475 }
00476 
00477 // ----------------------------------------------
00478 
00479 template <class CHAR> ACE_String_Base<CHAR>
00480 operator+ (const ACE_String_Base<CHAR> &s, const ACE_String_Base<CHAR> &t)
00481 {
00482   ACE_String_Base<CHAR> temp (s.length () + t.length ());
00483   temp += s;
00484   temp += t;
00485   return temp;
00486 }
00487 
00488 template <class CHAR> ACE_String_Base<CHAR>
00489 operator+ (const CHAR *s, const ACE_String_Base<CHAR> &t)
00490 {
00491   size_t slen = 0;
00492   if (s != 0)
00493     slen = ACE_OS::strlen (s);
00494   ACE_String_Base<CHAR> temp (slen + t.length ());
00495   if (slen > 0)
00496     temp.append (s, slen);
00497   temp += t;
00498   return temp;
00499 }
00500 
00501 template <class CHAR> ACE_String_Base<CHAR>
00502 operator+ (const ACE_String_Base<CHAR> &s, const CHAR *t)
00503 {
00504   size_t tlen = 0;
00505   if (t != 0)
00506     tlen = ACE_OS::strlen (t);
00507   ACE_String_Base<CHAR> temp (s.length () + tlen);
00508   temp += s;
00509   if (tlen > 0)
00510     temp.append (t, tlen);
00511   return temp;
00512 }
00513 
00514 template <class CHAR> ACE_String_Base<CHAR>
00515 operator + (const ACE_String_Base<CHAR> &t,
00516             const CHAR c)
00517 {
00518   ACE_String_Base<CHAR> temp (t.length () + 1);
00519   temp += t;
00520   temp += c;
00521   return temp;
00522 }
00523 
00524 template <class CHAR> ACE_String_Base<CHAR>
00525 operator + (const CHAR c,
00526             const ACE_String_Base<CHAR> &t)
00527 {
00528   ACE_String_Base<CHAR> temp (t.length () + 1);
00529   temp += c;
00530   temp += t;
00531   return temp;
00532 }
00533 
00534 template <class CHAR>
00535 ACE_String_Base<CHAR> &
00536 ACE_String_Base<CHAR>::operator+= (const CHAR* s)
00537 {
00538   size_t slen = 0;
00539   if (s != 0)
00540     slen = ACE_OS::strlen (s);
00541   return this->append (s, slen);
00542 }
00543 
00544 template <class CHAR>
00545 ACE_String_Base<CHAR> &
00546 ACE_String_Base<CHAR>::operator+= (const ACE_String_Base<CHAR> &s)
00547 {
00548   ACE_TRACE ("ACE_String_Base<CHAR>::operator+=(const ACE_String_Base<CHAR> &)");
00549   return this->append (s.rep_, s.len_);
00550 }
00551 
00552 template <class CHAR>
00553 ACE_String_Base<CHAR> &
00554 ACE_String_Base<CHAR>::operator+= (const CHAR c)
00555 {
00556   ACE_TRACE ("ACE_String_Base<CHAR>::operator+=(const CHAR)");
00557   const size_type slen = 1;
00558   return this->append (&c, slen);
00559 }
00560 
00561 ACE_END_VERSIONED_NAMESPACE_DECL
00562 
00563 #endif  /* ACE_STRING_BASE_CPP */

Generated on Tue Feb 2 17:18:43 2010 for ACE by  doxygen 1.4.7