1 #ifndef ACE_STRING_BASE_CPP
2 #define ACE_STRING_BASE_CPP
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 ()),
29 rep_ (&ACE_String_Base
<ACE_CHAR_T
>::NULL_String_
),
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
,
41 : allocator_ (the_allocator
? the_allocator
: ACE_Allocator::instance ()),
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 ()),
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 (
70 typename ACE_String_Base
<ACE_CHAR_T
>::size_type len
,
71 ACE_Allocator
*the_allocator
,
73 : allocator_ (the_allocator
? the_allocator
: ACE_Allocator::instance ()),
79 ACE_TRACE ("ACE_String_Base<ACE_CHAR_T>::ACE_String_Base");
81 this->set (s
, len
, release
);
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 ()),
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
,
103 ACE_Allocator
*the_allocator
)
104 : allocator_ (the_allocator
? the_allocator
: ACE_Allocator::instance ()),
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
,
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;
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_
);
142 this->buf_len_
= new_buf_len
;
143 this->release_
= true;
145 ACE_OS::memcpy (this->rep_
, s
, len
* sizeof (ACE_CHAR_T
));
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;
160 if (s
== 0 || 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
;
171 this->rep_
= const_cast <ACE_CHAR_T
*> (s
);
172 this->release_
= false;
176 ACE_OS::memcpy (this->rep_
, s
, len
* sizeof (ACE_CHAR_T
));
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
196 // case 2. start pos past our end
197 if (offset
>= this->len_
)
199 // No length == empty string.
200 else if (length
== 0)
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);
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;
242 this->buf_len_
= new_buf_len
;
246 this->rep_
[this->len_
] = 0;
252 template <class ACE_CHAR_T
> u_long
253 ACE_String_Base
<ACE_CHAR_T
>::hash () const
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
,
265 ACE_TRACE ("ACE_String_Base<ACE_CHAR_T>::resize");
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;
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
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_
;
304 this->release_
= false;
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=");
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.
331 this->set (s
.rep_
, s
.len_
, true);
337 template <class ACE_CHAR_T
> void
338 ACE_String_Base
<ACE_CHAR_T
>::set (const ACE_CHAR_T
*s
, bool release
)
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 ()
353 // String retains the original buffer.
354 if (this->rep_
!= &ACE_String_Base
<ACE_CHAR_T
>::NULL_String_
)
359 // External buffer: string relinquishes control of it.
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);
376 ACE_NEW_RETURN (new_string
, ACE_CHAR_T
[this->len_
+ 1], 0);
378 ACE_OS::strsncpy (new_string
, this->rep_
, this->len_
+1);
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_
)
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_
,
396 smaller_length
* sizeof (ACE_CHAR_T
));
398 if (result
== 0 && this->len_
!= s
.len_
)
399 result
= this->len_
> s
.len_
? 1 : -1;
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_
,
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 (
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
);
433 return ACE_String_Base
<ACE_CHAR_T
>::npos
;
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 (
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
);
446 return ACE_String_Base
<ACE_CHAR_T
>::npos
;
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 (
454 typename ACE_String_Base
<ACE_CHAR_T
>::size_type pos
) const
456 if (pos
== npos
|| 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
)
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_
];
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 ())
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 =");
523 this->str_
= rhs
.str_
;
524 this->index_
= rhs
.index_
;
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_
];
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 ())
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 =");
573 this->str_
= rhs
.str_
;
574 this->index_
= rhs
.index_
;
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 ());
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
)
594 slen
= ACE_OS::strlen (s
);
595 ACE_String_Base
<ACE_CHAR_T
> temp (slen
+ t
.length ());
597 temp
.append (s
, slen
);
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
)
607 tlen
= ACE_OS::strlen (t
);
608 ACE_String_Base
<ACE_CHAR_T
> temp (s
.length () + tlen
);
611 temp
.append (t
, tlen
);
615 template <class ACE_CHAR_T
> ACE_String_Base
<ACE_CHAR_T
>
616 operator + (const ACE_String_Base
<ACE_CHAR_T
> &t
,
619 ACE_String_Base
<ACE_CHAR_T
> temp (t
.length () + 1);
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);
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
)
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
);
664 ACE_END_VERSIONED_NAMESPACE_DECL
666 #endif /* ACE_STRING_BASE_CPP */