Changes to attempt to silence bcc64x
[ACE_TAO.git] / ACE / ace / String_Base.cpp
blob976e215d9dfe88da3d813b6e977e9d4af6154fa7
1 #ifndef ACE_STRING_BASE_CPP
2 #define ACE_STRING_BASE_CPP
4 #include "ace/ACE.h"
5 #include "ace/Malloc_Base.h"
6 #include "ace/String_Base.h"
7 #include "ace/OS_NS_string.h"
9 #include <algorithm> // For std::swap<>
11 #if !defined (__ACE_INLINE__)
12 #include "ace/String_Base.inl"
13 #endif /* __ACE_INLINE__ */
15 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
17 ACE_ALLOC_HOOK_DEFINE_Tc(ACE_String_Base)
19 template <class ACE_CHAR_T>
20 ACE_CHAR_T ACE_String_Base<ACE_CHAR_T>::NULL_String_ = 0;
22 // Default constructor.
24 template <class ACE_CHAR_T>
25 ACE_String_Base<ACE_CHAR_T>::ACE_String_Base (ACE_Allocator *the_allocator)
26 : allocator_ (the_allocator ? the_allocator : ACE_Allocator::instance ()),
27 len_ (0),
28 buf_len_ (0),
29 rep_ (&ACE_String_Base<ACE_CHAR_T>::NULL_String_),
30 release_ (false)
32 ACE_TRACE ("ACE_String_Base<ACE_CHAR_T>::ACE_String_Base");
35 // Constructor that actually copies memory.
37 template <class ACE_CHAR_T>
38 ACE_String_Base<ACE_CHAR_T>::ACE_String_Base (const ACE_CHAR_T *s,
39 ACE_Allocator *the_allocator,
40 bool release)
41 : allocator_ (the_allocator ? the_allocator : ACE_Allocator::instance ()),
42 len_ (0),
43 buf_len_ (0),
44 rep_ (0),
45 release_ (false)
47 ACE_TRACE ("ACE_String_Base<ACE_CHAR_T>::ACE_String_Base");
48 this->set (s, release);
51 template <class ACE_CHAR_T>
52 ACE_String_Base<ACE_CHAR_T>::ACE_String_Base (ACE_CHAR_T c,
53 ACE_Allocator *the_allocator)
54 : allocator_ (the_allocator ? the_allocator : ACE_Allocator::instance ()),
55 len_ (0),
56 buf_len_ (0),
57 rep_ (0),
58 release_ (false)
60 ACE_TRACE ("ACE_String_Base<ACE_CHAR_T>::ACE_String_Base");
62 this->set (&c, 1, true);
65 // Constructor that actually copies memory.
67 template <class ACE_CHAR_T>
68 ACE_String_Base<ACE_CHAR_T>::ACE_String_Base (
69 const ACE_CHAR_T *s,
70 typename ACE_String_Base<ACE_CHAR_T>::size_type len,
71 ACE_Allocator *the_allocator,
72 bool release)
73 : allocator_ (the_allocator ? the_allocator : ACE_Allocator::instance ()),
74 len_ (0),
75 buf_len_ (0),
76 rep_ (nullptr),
77 release_ (false)
79 ACE_TRACE ("ACE_String_Base<ACE_CHAR_T>::ACE_String_Base");
81 this->set (s, len, release);
84 // Copy constructor.
86 template <class ACE_CHAR_T>
87 ACE_String_Base<ACE_CHAR_T>::ACE_String_Base (const ACE_String_Base<ACE_CHAR_T> &s)
88 : allocator_ (s.allocator_ ? s.allocator_ : ACE_Allocator::instance ()),
89 len_ (0),
90 buf_len_ (0),
91 rep_ (nullptr),
92 release_ (false)
94 ACE_TRACE ("ACE_String_Base<ACE_CHAR_T>::ACE_String_Base");
96 this->set (s.rep_, s.len_, true);
99 template <class ACE_CHAR_T>
100 ACE_String_Base<ACE_CHAR_T>::ACE_String_Base (
101 typename ACE_String_Base<ACE_CHAR_T>::size_type len,
102 ACE_CHAR_T c,
103 ACE_Allocator *the_allocator)
104 : allocator_ (the_allocator ? the_allocator : ACE_Allocator::instance ()),
105 len_ (0),
106 buf_len_ (0),
107 rep_ (nullptr),
108 release_ (false)
110 ACE_TRACE ("ACE_String_Base<ACE_CHAR_T>::ACE_String_Base");
112 this->resize (len, c);
115 template <class ACE_CHAR_T>
116 ACE_String_Base<ACE_CHAR_T>::~ACE_String_Base ()
118 ACE_TRACE ("ACE_String_Base<ACE_CHAR_T>::~ACE_String_Base");
120 if (this->buf_len_ != 0 && this->release_)
121 this->allocator_->free (this->rep_);
124 // this method might benefit from a little restructuring.
125 template <class ACE_CHAR_T> void
126 ACE_String_Base<ACE_CHAR_T>::set (const ACE_CHAR_T *s,
127 typename ACE_String_Base<ACE_CHAR_T>::size_type len,
128 bool release)
130 // Case 1. Going from memory to more memory
131 size_type const new_buf_len = len + 1;
132 if (s != 0 && len != 0 && release && this->buf_len_ < new_buf_len)
134 ACE_CHAR_T *temp = nullptr;
135 ACE_ALLOCATOR (temp,
136 (ACE_CHAR_T *) this->allocator_->malloc (new_buf_len * sizeof (ACE_CHAR_T)));
138 if (this->buf_len_ != 0 && this->release_)
139 this->allocator_->free (this->rep_);
141 this->rep_ = temp;
142 this->buf_len_ = new_buf_len;
143 this->release_ = true;
144 this->len_ = len;
145 ACE_OS::memcpy (this->rep_, s, len * sizeof (ACE_CHAR_T));
146 this->rep_[len] = 0;
148 else // Case 2. No memory allocation is necessary.
150 // Free memory if necessary and figure out future ownership
151 if (!release || s == 0 || len == 0)
153 if (this->buf_len_ != 0 && this->release_)
155 this->allocator_->free (this->rep_);
156 this->release_ = false;
159 // Populate data.
160 if (s == 0 || len == 0)
162 this->buf_len_ = 0;
163 this->len_ = 0;
164 this->rep_ = &ACE_String_Base<ACE_CHAR_T>::NULL_String_;
165 this->release_ = false;
167 else if (!release) // Note: No guarantee that rep_ is null terminated.
169 this->buf_len_ = len;
170 this->len_ = len;
171 this->rep_ = const_cast <ACE_CHAR_T *> (s);
172 this->release_ = false;
174 else
176 ACE_OS::memcpy (this->rep_, s, len * sizeof (ACE_CHAR_T));
177 this->rep_[len] = 0;
178 this->len_ = len;
183 // Return substring.
184 template <class ACE_CHAR_T> ACE_String_Base<ACE_CHAR_T>
185 ACE_String_Base<ACE_CHAR_T>::substring (
186 typename ACE_String_Base<ACE_CHAR_T>::size_type offset,
187 typename ACE_String_Base<ACE_CHAR_T>::size_type length) const
189 ACE_String_Base<ACE_CHAR_T> nill;
190 size_type count = length;
192 // case 1. empty string
193 if (this->len_ == 0)
194 return nill;
196 // case 2. start pos past our end
197 if (offset >= this->len_)
198 return nill;
199 // No length == empty string.
200 else if (length == 0)
201 return nill;
202 // Get all remaining bytes.
203 else if (length == npos || count > (this->len_ - offset))
204 count = this->len_ - offset;
206 return ACE_String_Base<ACE_CHAR_T> (&this->rep_[offset], count, this->allocator_);
209 template <class ACE_CHAR_T> ACE_String_Base<ACE_CHAR_T> &
210 ACE_String_Base<ACE_CHAR_T>::append (const ACE_CHAR_T* s,
211 typename ACE_String_Base<ACE_CHAR_T>::size_type slen)
213 ACE_TRACE ("ACE_String_Base<ACE_CHAR_T>::append(const ACE_CHAR_T*, size_type)");
214 if (slen > 0 && slen != npos)
216 // case 1. No memory allocation needed.
217 if (this->buf_len_ >= this->len_ + slen + 1)
219 // Copy in data from new string.
220 ACE_OS::memcpy (this->rep_ + this->len_, s, slen * sizeof (ACE_CHAR_T));
222 else // case 2. Memory reallocation is needed
224 const size_type new_buf_len =
225 ace_max(this->len_ + slen + 1, this->buf_len_ + this->buf_len_ / 2);
227 ACE_CHAR_T *t = 0;
229 ACE_ALLOCATOR_RETURN (t,
230 (ACE_CHAR_T *) this->allocator_->malloc (new_buf_len * sizeof (ACE_CHAR_T)), *this);
232 // Copy memory from old string into new string.
233 ACE_OS::memcpy (t, this->rep_, this->len_ * sizeof (ACE_CHAR_T));
235 ACE_OS::memcpy (t + this->len_, s, slen * sizeof (ACE_CHAR_T));
237 if (this->buf_len_ != 0 && this->release_)
238 this->allocator_->free (this->rep_);
240 this->release_ = true;
241 this->rep_ = t;
242 this->buf_len_ = new_buf_len;
245 this->len_ += slen;
246 this->rep_[this->len_] = 0;
249 return *this;
252 template <class ACE_CHAR_T> u_long
253 ACE_String_Base<ACE_CHAR_T>::hash () const
255 return
256 ACE::hash_pjw (reinterpret_cast<char *> (
257 const_cast<ACE_CHAR_T *> (this->rep_)),
258 this->len_ * sizeof (ACE_CHAR_T));
261 template <class ACE_CHAR_T> void
262 ACE_String_Base<ACE_CHAR_T>::resize (typename ACE_String_Base<ACE_CHAR_T>::size_type len,
263 ACE_CHAR_T c)
265 ACE_TRACE ("ACE_String_Base<ACE_CHAR_T>::resize");
267 fast_resize(len);
268 ACE_OS::memset (this->rep_, c, this->buf_len_ * sizeof (ACE_CHAR_T));
271 template <class ACE_CHAR_T> void
272 ACE_String_Base<ACE_CHAR_T>::fast_resize (size_t len)
274 ACE_TRACE ("ACE_String_Base<ACE_CHAR_T>::fast_resize");
276 // Only reallocate if we don't have enough space...
277 if (this->buf_len_ <= len)
279 if (this->buf_len_ != 0 && this->release_)
280 this->allocator_->free (this->rep_);
282 this->rep_ = static_cast<ACE_CHAR_T*>
283 (this->allocator_->malloc ((len + 1) * sizeof (ACE_CHAR_T)));
284 this->buf_len_ = len + 1;
285 this->release_ = true;
287 this->len_ = 0;
288 if (len > 0)
289 this->rep_[0] = 0;
292 template <class ACE_CHAR_T> void
293 ACE_String_Base<ACE_CHAR_T>::clear (bool release)
295 // This can't use set(), because that would free memory if release=false
296 if (release)
298 if (this->buf_len_ != 0 && this->release_)
299 this->allocator_->free (this->rep_);
301 this->rep_ = &ACE_String_Base<ACE_CHAR_T>::NULL_String_;
302 this->len_ = 0;
303 this->buf_len_ = 0;
304 this->release_ = false;
306 else
308 this->fast_clear ();
312 // Assignment operator (does copy memory).
313 template <class ACE_CHAR_T> ACE_String_Base<ACE_CHAR_T> &
314 ACE_String_Base<ACE_CHAR_T>::operator= (const ACE_CHAR_T *s)
316 ACE_TRACE ("ACE_String_Base<ACE_CHAR_T>::operator=");
317 if (s != 0)
318 this->set (s, true);
319 return *this;
322 // Assignment operator (does copy memory).
323 template <class ACE_CHAR_T> ACE_String_Base<ACE_CHAR_T> &
324 ACE_String_Base<ACE_CHAR_T>::operator= (const ACE_String_Base<ACE_CHAR_T> &s)
326 ACE_TRACE ("ACE_String_Base<ACE_CHAR_T>::operator=");
328 // Check for self-assignment.
329 if (this != &s)
331 this->set (s.rep_, s.len_, true);
334 return *this;
337 template <class ACE_CHAR_T> void
338 ACE_String_Base<ACE_CHAR_T>::set (const ACE_CHAR_T *s, bool release)
340 size_t length = 0;
341 if (s != 0)
342 length = ACE_OS::strlen (s);
344 this->set (s, length, release);
347 template <class ACE_CHAR_T> void
348 ACE_String_Base<ACE_CHAR_T>::fast_clear ()
350 this->len_ = 0;
351 if (this->release_)
353 // String retains the original buffer.
354 if (this->rep_ != &ACE_String_Base<ACE_CHAR_T>::NULL_String_)
355 this->rep_[0] = 0;
357 else
359 // External buffer: string relinquishes control of it.
360 this->buf_len_ = 0;
361 this->rep_ = &ACE_String_Base<ACE_CHAR_T>::NULL_String_;
365 // Get a copy of the underlying representation.
367 template <class ACE_CHAR_T> ACE_CHAR_T *
368 ACE_String_Base<ACE_CHAR_T>::rep () const
370 ACE_TRACE ("ACE_String_Base<ACE_CHAR_T>::rep");
372 ACE_CHAR_T *new_string;
373 #if defined (ACE_HAS_ALLOC_HOOKS)
374 ACE_ALLOCATOR_RETURN (new_string, static_cast<ACE_CHAR_T*>(ACE_Allocator::instance()->malloc(sizeof(ACE_CHAR_T) * (this->len_ + 1))), 0);
375 #else
376 ACE_NEW_RETURN (new_string, ACE_CHAR_T[this->len_ + 1], 0);
377 #endif
378 ACE_OS::strsncpy (new_string, this->rep_, this->len_+1);
380 return new_string;
383 template <class ACE_CHAR_T> int
384 ACE_String_Base<ACE_CHAR_T>::compare (const ACE_String_Base<ACE_CHAR_T> &s) const
386 ACE_TRACE ("ACE_String_Base<ACE_CHAR_T>::compare");
388 if (this->rep_ == s.rep_)
389 return 0;
391 // Pick smaller of the two lengths and perform the comparison.
392 size_type smaller_length = ace_min (this->len_, s.len_);
394 int result = ACE_OS::memcmp (this->rep_,
395 s.rep_,
396 smaller_length * sizeof (ACE_CHAR_T));
398 if (result == 0 && this->len_ != s.len_)
399 result = this->len_ > s.len_ ? 1 : -1;
400 return result;
403 // Comparison operator.
405 template <class ACE_CHAR_T> bool
406 ACE_String_Base<ACE_CHAR_T>::operator== (const ACE_String_Base<ACE_CHAR_T> &s) const
408 return this->len_ == s.len_ &&
409 ACE_OS::memcmp (this->rep_,
410 s.rep_,
411 this->len_ * sizeof (ACE_CHAR_T)) == 0;
414 template <class ACE_CHAR_T> bool
415 ACE_String_Base<ACE_CHAR_T>::operator== (const ACE_CHAR_T *s) const
417 size_t len = ACE_OS::strlen (s);
418 return this->len_ == len &&
419 ACE_OS::memcmp (this->rep_,
421 len * sizeof (ACE_CHAR_T)) == 0;
424 template <class ACE_CHAR_T> typename ACE_String_Base<ACE_CHAR_T>::size_type
425 ACE_String_Base<ACE_CHAR_T>::find (
426 const ACE_CHAR_T *s,
427 typename ACE_String_Base<ACE_CHAR_T>::size_type pos) const
429 ACE_CHAR_T *substr = this->rep_ + pos;
430 size_t len = ACE_OS::strlen (s);
431 ACE_CHAR_T *pointer = ACE_OS::strnstr (substr, s, len);
432 if (pointer == 0)
433 return ACE_String_Base<ACE_CHAR_T>::npos;
434 else
435 return pointer - this->rep_;
438 template <class ACE_CHAR_T> typename ACE_String_Base<ACE_CHAR_T>::size_type
439 ACE_String_Base<ACE_CHAR_T>::find (
440 ACE_CHAR_T c,
441 typename ACE_String_Base<ACE_CHAR_T>::size_type pos) const
443 ACE_CHAR_T *substr = this->rep_ + pos;
444 ACE_CHAR_T *pointer = ACE_OS::strnchr (substr, c, this->len_ - pos);
445 if (pointer == 0)
446 return ACE_String_Base<ACE_CHAR_T>::npos;
447 else
448 return pointer - this->rep_;
451 template <class ACE_CHAR_T> typename ACE_String_Base<ACE_CHAR_T>::size_type
452 ACE_String_Base<ACE_CHAR_T>::rfind (
453 ACE_CHAR_T c,
454 typename ACE_String_Base<ACE_CHAR_T>::size_type pos) const
456 if (pos == npos || pos > this->len_)
457 pos = this->len_;
459 // Do not change to prefix operator! Proper operation of this loop
460 // depends on postfix decrement behavior.
461 for (size_type i = pos; i-- != 0; )
462 if (this->rep_[i] == c)
463 return i;
465 return ACE_String_Base<ACE_CHAR_T>::npos;
468 template <class ACE_CHAR_T> void
469 ACE_String_Base<ACE_CHAR_T>::swap (ACE_String_Base<ACE_CHAR_T> & str)
471 std::swap (this->allocator_ , str.allocator_);
472 std::swap (this->len_ , str.len_);
473 std::swap (this->buf_len_ , str.buf_len_);
474 std::swap (this->rep_ , str.rep_);
475 std::swap (this->release_ , str.release_);
478 // ----------------------------------------------
480 template <class ACE_CHAR_T>
481 int ACE_String_Base_Iterator <ACE_CHAR_T>::next (ACE_CHAR_T * & ch) const
483 ACE_TRACE ("ACE_String_Base_Iterator<ACE_CHAR_T>::next");
485 if (0 == this->done ())
487 ch = &this->str_->rep_[this->index_];
488 return 1;
490 else
492 ch = 0;
493 return 0;
497 template <class ACE_CHAR_T>
498 int ACE_String_Base_Iterator <ACE_CHAR_T>::advance ()
500 ACE_TRACE ("ACE_String_Base_Iterator<ACE_CHAR_T>::advance");
502 if (this->index_ < this->str_->length ())
504 ++ this->index_;
505 return 1;
507 else
509 return 0;
513 template <class ACE_CHAR_T>
514 const ACE_String_Base_Iterator <ACE_CHAR_T> &
515 ACE_String_Base_Iterator <ACE_CHAR_T>::
516 operator = (const ACE_String_Base_Iterator <ACE_CHAR_T> & rhs)
518 ACE_TRACE ("ACE_String_Base_Iterator<ACE_CHAR_T>::operator =");
520 if (this == &rhs)
521 return *this;
523 this->str_ = rhs.str_;
524 this->index_ = rhs.index_;
525 return *this;
528 // ----------------------------------------------
530 template <class ACE_CHAR_T>
531 int ACE_String_Base_Const_Iterator <ACE_CHAR_T>::next (const ACE_CHAR_T * & ch) const
533 ACE_TRACE ("ACE_String_Base_Const_Iterator<ACE_CHAR_T>::next");
535 if (0 == this->done ())
537 ch = &this->str_->rep_[this->index_];
538 return 1;
540 else
542 ch = 0;
543 return 0;
547 template <class ACE_CHAR_T>
548 int ACE_String_Base_Const_Iterator <ACE_CHAR_T>::advance ()
550 ACE_TRACE ("ACE_String_Base_Const_Iterator<ACE_CHAR_T>::advance");
552 if (this->index_ < this->str_->length ())
554 ++ this->index_;
555 return 1;
557 else
559 return 0;
563 template <class ACE_CHAR_T>
564 const ACE_String_Base_Const_Iterator <ACE_CHAR_T> &
565 ACE_String_Base_Const_Iterator <ACE_CHAR_T>::
566 operator = (const ACE_String_Base_Const_Iterator <ACE_CHAR_T> & rhs)
568 ACE_TRACE ("ACE_String_Base_Const_Iterator<ACE_CHAR_T>::operator =");
570 if (this == &rhs)
571 return *this;
573 this->str_ = rhs.str_;
574 this->index_ = rhs.index_;
575 return *this;
578 // ----------------------------------------------
580 template <class ACE_CHAR_T> ACE_String_Base<ACE_CHAR_T>
581 operator+ (const ACE_String_Base<ACE_CHAR_T> &s, const ACE_String_Base<ACE_CHAR_T> &t)
583 ACE_String_Base<ACE_CHAR_T> temp (s.length () + t.length ());
584 temp += s;
585 temp += t;
586 return temp;
589 template <class ACE_CHAR_T> ACE_String_Base<ACE_CHAR_T>
590 operator+ (const ACE_CHAR_T *s, const ACE_String_Base<ACE_CHAR_T> &t)
592 size_t slen = 0;
593 if (s != 0)
594 slen = ACE_OS::strlen (s);
595 ACE_String_Base<ACE_CHAR_T> temp (slen + t.length ());
596 if (slen > 0)
597 temp.append (s, slen);
598 temp += t;
599 return temp;
602 template <class ACE_CHAR_T> ACE_String_Base<ACE_CHAR_T>
603 operator+ (const ACE_String_Base<ACE_CHAR_T> &s, const ACE_CHAR_T *t)
605 size_t tlen = 0;
606 if (t != 0)
607 tlen = ACE_OS::strlen (t);
608 ACE_String_Base<ACE_CHAR_T> temp (s.length () + tlen);
609 temp += s;
610 if (tlen > 0)
611 temp.append (t, tlen);
612 return temp;
615 template <class ACE_CHAR_T> ACE_String_Base<ACE_CHAR_T>
616 operator + (const ACE_String_Base<ACE_CHAR_T> &t,
617 const ACE_CHAR_T c)
619 ACE_String_Base<ACE_CHAR_T> temp (t.length () + 1);
620 temp += t;
621 temp += c;
622 return temp;
625 template <class ACE_CHAR_T> ACE_String_Base<ACE_CHAR_T>
626 operator + (const ACE_CHAR_T c,
627 const ACE_String_Base<ACE_CHAR_T> &t)
629 ACE_String_Base<ACE_CHAR_T> temp (t.length () + 1);
630 temp += c;
631 temp += t;
632 return temp;
635 template <class ACE_CHAR_T>
636 ACE_String_Base<ACE_CHAR_T> &
637 ACE_String_Base<ACE_CHAR_T>::operator+= (const ACE_CHAR_T* s)
639 size_t slen = 0;
640 if (s != 0)
641 slen = ACE_OS::strlen (s);
642 return this->append (s, slen);
645 template <class ACE_CHAR_T>
646 ACE_String_Base<ACE_CHAR_T> &
647 ACE_String_Base<ACE_CHAR_T>::operator+= (const ACE_String_Base<ACE_CHAR_T> &s)
649 ACE_TRACE ("ACE_String_Base<ACE_CHAR_T>::operator+=(const ACE_String_Base<ACE_CHAR_T> &)");
650 return this->append (s.rep_, s.len_);
653 template <class ACE_CHAR_T>
654 ACE_String_Base<ACE_CHAR_T> &
655 ACE_String_Base<ACE_CHAR_T>::operator+= (const ACE_CHAR_T c)
657 ACE_TRACE ("ACE_String_Base<ACE_CHAR_T>::operator+=(const ACE_CHAR_T)");
658 const size_type slen = 1;
659 // This temp is silly but it quiets an optimizer warning in IBM XL C++ 10.
660 ACE_String_Base<ACE_CHAR_T>& r = this->append (&c, slen);
661 return r;
664 ACE_END_VERSIONED_NAMESPACE_DECL
666 #endif /* ACE_STRING_BASE_CPP */