bufstr_t.hpp

Go to the documentation of this file.
00001 #ifndef GLIM_BUFSTR_T_HPP_
00002 #define GLIM_BUFSTR_T_HPP_
00003 
00004 /// Stack-allocated string buffer.
00005 /// @file
00006 
00007 #include <stdexcept>
00008 #include <limits>
00009 #include <utility> // pair
00010 #include <string>
00011 #include "config.h"
00012 #if defined HAS_stpncpy
00013 # include <string.h>
00014 #endif
00015 #include "c_func.hpp"
00016 
00017 namespace glim {
00018 
00019 /**
00020  * Stack-allocated string buffer.
00021  * Based on str_t and safestr_t classes from libaga, of the same author,
00022  * which were made back in 1999, but without C++ templating and exceptions.\n\n
00023  * Operations that would overflow will either throw the std::out_of_range error
00024  * (if the THROW template parameter is true, which it is by default),
00025  * or silently ignored.\n\n
00026  * See also http://www.codeproject.com/string/Allocdynstringsonstack.asp
00027  */
00028 template <int SIZE, bool THROW = true>
00029 struct bufstr_t {
00030   /**
00031    * The buffer (stack-allocated, if the containing instance is).
00032    * The size of the buffer is SIZE + 1, so that we always have a space to zero-terminate the string.
00033    */
00034   char buf[SIZE+1];
00035   /** The current length of the string. */
00036   int len;
00037 
00038   /**
00039    * This default constructor is sufficient to use the buffer.
00040    */
00041   bufstr_t(): len(0) {}
00042 
00043   /**
00044    * Access the buffer as null-terminated C string.
00045    * This method will terminate the buffer with zero.
00046    */
00047   char* c() {
00048     buf[len] = 0;
00049     return buf;
00050   }
00051 
00052   /**
00053    * Access the buffer as null-terminated C string.
00054    * This method will terminate the buffer with zero.
00055    */
00056   char* c_str() {
00057     buf[len] = 0;
00058     return buf;
00059   }
00060 
00061   /**
00062    * Returns a pointer to the end of the contained string.
00063    * bufstr.end() is a shorthand to (bufstr.buf + bufstr.len).
00064    */
00065   char* end() const {
00066     return (char*) buf + len;
00067   }
00068 
00069   /**
00070    * Access the buffer as std::pair.
00071    * The pair consists of a pointer to the beginning and the length of the contained string.
00072    */
00073   std::pair<char const*, int> pair() const {
00074     return std::pair<char const*, int> (buf, len);
00075   }
00076 
00077   /**
00078    * Set the length counter back to 0, so that the buffer can be reused.
00079    */
00080   bufstr_t& reset() {
00081     len = 0;
00082     return *this;
00083   }
00084 
00085   /**
00086    * Append another buffer.
00087    */
00088   template <int C_SIZE, bool C_THROW>
00089   bufstr_t& operator << (const bufstr_t<C_SIZE, C_THROW>& ab) {
00090     return appendString(ab.buf, ab.len); }
00091 
00092   /**
00093    * Append a string whose length is known.
00094    */
00095   bufstr_t& operator << (std::pair<char const*, int> str) {
00096     return appendString(str.first, str.second); }
00097 
00098   /**
00099    * Append a null-terminated character string.
00100    */
00101   bufstr_t& operator << (char const* cs) {
00102     return appendString(cs); }
00103 
00104   /// Append a C++ string into the buffer.
00105   bufstr_t& operator << (const std::string& str) {
00106     return appendString (str.c_str(), str.length()); }
00107 
00108   /**
00109    * Append a signed integer to the buffer, converting it to decimal form.
00110    */
00111   template <typename INT>
00112   bufstr_t& appendInt (INT integer) {
00113     if (SIZE - len < std::numeric_limits<INT>::digits10 + 2) {
00114       if (THROW) throw std::out_of_range("bufstr_t");
00115       else return *this;
00116     }
00117     char* end = buf + len;
00118     len += glim::itoa(end, integer) - end;
00119     return *this; }
00120 
00121   /**
00122    * Append a string whose length is known.
00123    */
00124   bufstr_t& appendString (char const* str, int strLen) {
00125     if (strLen > 0) {
00126       if (strLen + len > SIZE) {
00127         if (THROW) throw std::out_of_range("bufstr_t");
00128         else return *this;
00129       } else {
00130         memcpy(buf+len, str, strLen);
00131         len += strLen;
00132     } }
00133     return *this; }
00134 
00135   /**
00136    * Append a null-terminated character string.
00137    */
00138   bufstr_t& appendString (char const* cs) {
00139     if (cs) {
00140       char* end = buf + len;
00141       #if defined HAS_stpncpy
00142         len += ::stpncpy(end, cs, SIZE - len) - end;
00143       #else
00144         len += glim::stpncpy(end, cs, SIZE - len) - end;
00145       #endif
00146       if(THROW && len == SIZE) throw std::out_of_range("bufstr_t");
00147     }
00148     return *this; }
00149 
00150   /// Append a C++ string into the buffer.
00151   bufstr_t& appendString (const std::string& str) {
00152     return appendString (str.c_str(), str.length()); }
00153 
00154   /// Append an int to the buffer, converting it to decimal form.
00155   bufstr_t& operator << (int integer) {
00156     return appendInt(integer); }
00157 
00158   /// Append a long long to the buffer, converting it to decimal form.
00159   bufstr_t& operator << (long long integer) {
00160     return appendInt(integer); }
00161 
00162   /**
00163    * Append a single character to the buffer.
00164    */
00165   bufstr_t& operator << (char ch) {
00166     if (len >= SIZE) {
00167       if (THROW) throw std::out_of_range("bufstr_t");
00168       else return *this;
00169     }
00170     buf[len++] = ch;
00171     return *this;
00172   }
00173 };
00174 
00175 } // namespace glim
00176 
00177 #endif // GLIM_BUFSTR_T_HPP_

Generated on Fri Nov 24 20:57:37 2006 for libglim by  doxygen 1.4.6