Sierra Toolkit Version of the Day
String.cpp
00001 
00010 #include <iostream>
00011 #include <iomanip>
00012 #include <sstream>
00013 #include <stdexcept>
00014 
00015 #include <stk_util/diag/String.hpp>
00016 
00017 #include <cstddef>
00018 #include <cctype>
00019 #include <stdexcept>
00020 #include <iostream>
00021 
00022 //----------------------------------------------------------------------
00023 
00024 namespace sierra {
00025 
00026 namespace {
00027 
00028 static const char arraylower_t[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
00029                                     0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
00030                                     0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
00031                                     0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 
00032                                     0x40,  'a',  'b',  'c',  'd',  'e',  'f',  'g',  'h',  'i',  'j',  'k',  'l',  'm',  'n',  'o',
00033                                      'p',  'q',  'r',  's',  't',  'u',  'v',  'w',  'x',  'y',  'z', 0x5B, 0x5C, 0x5D, 0x5E, 0x5F,
00034                                     0x60,  'a',  'b',  'c',  'd',  'e',  'f',  'g',  'h',  'i',  'j',  'k',  'l',  'm',  'n',  'o',
00035                                      'p',  'q',  'r',  's',  't',  'u',  'v',  'w',  'x',  'y',  'z', 0x7B, 0x7C, 0x7D, 0x7E, 0x7F
00036 };
00037 
00038 inline int arraylower(int c) {
00039   return arraylower_t[c];
00040 }
00041 
00042 } // namespace <unnamed>
00043 
00044 int to_label( int c )
00045 {
00046   return isspace(c) ? '_' : c;
00047 }
00048 
00049 size_t char_simple_traits::length( const char * c1 )
00050 {
00051   const char * c = c1 ;
00052   if ( c ) while ( *c ) ++c ;
00053   return c - c1 ;
00054 }
00055 
00056 int char_simple_traits::compare( const char * c1 , const char * c2 )
00057 {
00058   for ( ; *c1 && arraylower(*c1) == arraylower(*c2); c1++, c2++)
00059     ;
00060 
00061   return arraylower(*c1) - arraylower(*c2);
00062 }
00063 
00064 size_t char_label_traits::length( const char * c1 )
00065 {
00066   const char * c = c1 ;
00067   if ( c ) while ( *c ) ++c ;
00068   return c - c1 ;
00069 }
00070 
00071 void char_label_traits::convert( char * c , size_t n )
00072 {
00073   for ( char * const e = c + n ; c != e ; ++c )
00074     *c = to_label(*c);
00075 }
00076 
00077 int char_label_traits::compare( const char * c1 , const char * c2 )
00078 {
00079   for ( ; *c1 && arraylower(to_label(*c1)) == arraylower(to_label(*c2)); c1++, c2++)
00080     ;
00081 
00082   return arraylower(to_label(*c1)) - arraylower(to_label(*c2));
00083 }
00084 
00085 } // namespace sierra
00086 
00087 //----------------------------------------------------------------------
00088 
00089 namespace sierra {
00090 
00091 namespace implementation {
00092 
00116 // Manage memory but do not invalidate current memory
00117 // until operation is complete.
00118 
00119 char * StringData::mem( const char * cs , size_t n )
00120 {
00121   enum { inc = 4 * sizeof(long) };
00122   static std::string::allocator_type a ;
00123 
00124   const bool is_allocated = small[ max_len ] == 1;
00125   const bool to_allocated = max_len < n ;
00126 
00127   size_t new_alloc = 0 ;
00128 
00129   if ( to_allocated && ( ! is_allocated || large.siz <= n ) ) {
00130     const size_t n_total = n + 1 ;
00131     new_alloc = n_total % inc ? n_total + inc - n_total % inc : n_total ;
00132     if ( new_alloc == 0 || new_alloc - 1 < n ) {
00133       throw std::runtime_error("FAILED MEMORY ALLOCATION SIZING in sierra::String");
00134     }
00135   }
00136 
00137   char * dst = NULL ;
00138   char * del_ptr = NULL ;
00139   size_t del_size = 0 ;
00140 
00141   if ( is_allocated && ( new_alloc || ! to_allocated ) ) {
00142     // Deallocate currently allocated memory after copying input,
00143     // input might be a subset of currently allocated memory.
00144     del_ptr  = large.ptr ;
00145     del_size = large.siz ;
00146   }
00147 
00148   if ( to_allocated ) {
00149     // Needs to be allocated to hold input
00150 
00151     if ( new_alloc ) {
00152       // New allocation or reallocation to increase size
00153 
00154       { //----------------------------------------
00155   // Verify memory layout
00156   static bool first_pass = true ;
00157 
00158   if ( first_pass ) {
00159     first_pass = false ;
00160 
00161     if ( buf_len % sizeof(long) ||
00162          sizeof(StringData) != buf_len ||
00163          small + max_len < (char*)(&(large)) + sizeof(Large) ) {
00164       throw std::logic_error("StringData memory layout error");
00165     }
00166   }
00167       } //----------------------------------------
00168 
00169       try {
00170   large.siz = new_alloc ;
00171   large.ptr = (char *) a.allocate( new_alloc );
00172 //  std::cout << "String allocated at " << (void *)large.ptr << " for " << new_alloc << std::endl;
00173       }
00174       catch (...) {
00175   throw std::runtime_error("FAILED MEMORY ALLOCATION in sierra::String");
00176       }
00177     }
00178 
00179     small[max_len] = 1 ;
00180     large.len      = n ;
00181     dst = large.ptr ;
00182   }
00183   else {
00184     small[max_len] = 0 ;
00185     small[off_len] = n ;
00186     dst = small ;
00187   }
00188 
00189   {
00190     const char * const cs_e = cs + n ;
00191     char * d = dst ;
00192     while ( cs != cs_e ) *d++ = *cs++ ;
00193     *d = 0 ;
00194   }
00195 
00196   if ( del_ptr != NULL ) {
00197     try {
00198 //      std::cout << "String deallocated at " << (void *)del_ptr << " for " << del_size << std::endl;
00199       a.deallocate( del_ptr , del_size );
00200     }
00201     catch (...) {
00202       throw std::runtime_error("FAILED MEMORY DEALLOCATION in sierra::String");
00203     }
00204   }
00205 
00206   return dst ;
00207 }
00208 
00209 StringData::~StringData()
00210 { mem(NULL, 0); }
00211 
00212 StringData::StringData()
00213 { small[ max_len ] = small[ off_len ] = small[ 0 ] = 0 ; }
00214 
00215 size_t StringData::len() const
00216 { return small[ max_len ] ? large.len : small[ off_len ] ; }
00217 
00218 char * StringData::c_str()
00219 { return small[ max_len ] ? large.ptr : small ; }
00220 
00221 const char * StringData::c_str() const
00222 { return small[ max_len ] ? large.ptr : small ; }
00223 
00224 } // namespace internal
00225 
00226 std::ostream &
00227 operator<<( std::ostream & os, const sierra::String & s)
00228 { return os << s.c_str(); }
00229 
00230 std::istream &
00231 operator>>( std::istream & is, sierra::String & s )
00232 { std::string tmp; is >> tmp; s.assign(tmp); return is; }
00233 
00234 std::ostream &
00235 operator<<( std::ostream & os, const sierra::Identifier &s)
00236 { return os << s.c_str(); }
00237 
00238 std::istream &
00239 operator>>( std::istream & is, sierra::Identifier &s )
00240 { std::string tmp; is >> tmp; s.assign(tmp); return is; }
00241 
00242 } // namespace sierra
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines