|
Sierra Toolkit
Version of the Day
|
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