http://www.developer.com/ws/brew/article.php/2229051/String-in-BREW-Revisitedmdasha-BrewString-Generalization.htm
This article details a String implementation that freely uses both char and AECHAR data types. This is actually a generalization of BrewString that allows strings, wide strings, char and AECHAR arrays to be mixed together, such as: AECHAR is the wide string data type in BREW, defined as: and as written in the Brew Guidelines: This has two implications: On the other hand, char is a basic type, widely used and many libraries are based on it or use it extensively. This means that the answer to the above question has to be: "AECHAR and char." A simple solution might be to take a char-based string implementation and specialize it for AECHAR. This is fast but not very rewarding—all the AECHAR/char/wide string/string conversions have to be done manually by the end user. It would be nice to hide all the complexities between a unique façade and give the end user the ability to freely mix strings/wide strings/char and AECHAR arrays. This was actually one of the goals of BrewString1 but on a different scale—char only. Enlarging the scope of BrewString, by supporting AECHAR directly, looks like a natural and useful addition. The actual process of transforming BrewString is rather delicate; the automatic conversions from one type to the other make things complicated. A simple is not enough. What's needed is: Point 1 was implemented in and its AECHAR specialization: Class function members are mainly wrappers around AEEStdLib.h functionality used internally by BrewString; for example: There are cases when, due to a nonstandard implementation, the wrappers become adapters: In one case, STRSTR, the wide string counterpart is missing from AEEStdLib.h so that it was implemented from scratch. Point 2 is less obvious. For example, a constructor such as might take any type as input and we have to differentiate and act accordingly. On top of this, there is an additional problem: Conversion from one type to the other requests memory to be allocated and, more important, released—definitely not the end user's responsibility. The answer is a private internal class that acts like a proxy/auto pointer: At creation time, Wrapper simply takes a type, does some "type laundering" if needed, and establishes whether there is any memory to be owned and released at destruction time. Its use is based on the "resource acquisition is initialization" idiom, such as: Please note the minimal impact on BrewString: rhs is "wrapped" and p functor is used instead of rhs—very mechanical. String is defined as: and WString as: We can write now code like this: Another goal of this implementation was to support both old and new compilers. This influenced some design decisions and added a certain "roughness"—especially in automatic type conversions. The creation of temporaries is, as usual, reduced to a minimum. As p() calls are typically inlined for the trivial, case efficiency shouldn't be affected. This release contains some previously unpublished run-time allocation safety features (see setBuffer(), increaseBuffer(), etc.). Please consider this as an example only as different strategies are possible in this area. For example the new gcc compiler support for exceptions (and implicitly for throwing new) might change this radically. Download the application -- 211 Kb. 1 Utility Libraries for BREW—A String Class Radu Braniste is Director of Technology at Epicad. He can be contacted at rbraniste@epicad.com # # #
String in BREW Revisited-a BrewString Generalization
June 27, 2003
Preamble
WString w("br");w += "ew";const AECHAR* ae = w.toCharArray();String d ( w);d += ae;AECHAR or Char?
typedef uint16 AECHAR;
"BREW is Unicode (wide string) compliant only (no ISOLATIN1/ANSI) except for file names, which are ISOLATIN1/ANSI. Always use AECHAR instead of "char". Use string services provided in AEEStdLib.h for string manipulation."
A Flexible Implementation
typedef BrewString<AECHAR> WString;
template <typename T >struct BrewStringPolicy;
template <>struct BrewStringPolicy <AECHAR>;
static int T_STRLEN(const T* s){ return STRLEN(s);}static int T_STRLEN(const AECHAR* s){ return WSTRLEN(s);}static T* T_STRLOWER( T* s){ return STRLOWER(s);}static AECHAR* T_STRLOWER( AECHAR* s){ WSTRLOWER(s); return s;}template <class U> BrewString( const U& rhs , UINT sz = 0);
class Wrapper{public: template <typename U> Wrapper(U* t) : t_(getArray(t)) {} template <typename U, typename R> Wrapper(const BrewString<U,R>< t) : t_(getArray(t)) {} ~Wrapper() { if (owns_) { delete[] t_; } } const T* operator()() const { return t_; }private: template <typename U> T* getArray(const U* c) { owns_ = true; return P::createBuffer(c); } T* getArray(const T* u) { owns_ = false; return const_cast<T*>(u); } template <typename U, typename R> T* getArray(const BrewString<U,R>& u) { owns_ = false; return getArray(u.toCharArray()); } T* getArray(const BrewString<T,P>& u) { owns_ = false; return const_cast<T*>(u.toCharArray()); }private: T* t_; bool owns_;};template <class U>BrewString( const U& rhs , UINT sz = 0): pData_(0){ Wrapper p(rhs); CopyCtorImpl(p(), sz);}typedef BrewString<char, BrewStringPolicy<char> > String;
typedef BrewString<AECHAR, BrewStringPolicy<AECHAR> > WString;
WString w("br");w += "ew";const AECHAR* ae = w.toCharArray();String d ( w);d += ae;String y;y.ensureCapacity(20);y = "mybrew";WString tst(y);bool b = y.equals("brew");b = y.startsWith("my");Final Remarks
Resources
References
http://www.developer.com/ws/brew/article.php/1755971About the Author