00001 /** @file rutz/fstring.h ref-counted string type that allows much 00002 faster compile times than std::string */ 00003 00004 /////////////////////////////////////////////////////////////////////// 00005 // 00006 // Copyright (c) 2000-2004 California Institute of Technology 00007 // Copyright (c) 2004-2007 University of Southern California 00008 // Rob Peters <rjpeters at usc dot edu> 00009 // 00010 // created: Fri Oct 15 15:40:18 2004 00011 // commit: $Id: fstring.h 8249 2007-04-12 06:03:40Z rjpeters $ 00012 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/rutz/fstring.h $ 00013 // 00014 // -------------------------------------------------------------------- 00015 // 00016 // This file is part of GroovX. 00017 // [http://ilab.usc.edu/rjpeters/groovx/] 00018 // 00019 // GroovX is free software; you can redistribute it and/or modify it 00020 // under the terms of the GNU General Public License as published by 00021 // the Free Software Foundation; either version 2 of the License, or 00022 // (at your option) any later version. 00023 // 00024 // GroovX is distributed in the hope that it will be useful, but 00025 // WITHOUT ANY WARRANTY; without even the implied warranty of 00026 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00027 // General Public License for more details. 00028 // 00029 // You should have received a copy of the GNU General Public License 00030 // along with GroovX; if not, write to the Free Software Foundation, 00031 // Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. 00032 // 00033 /////////////////////////////////////////////////////////////////////// 00034 00035 #ifndef GROOVX_RUTZ_FSTRING_H_UTC20050626084021_DEFINED 00036 #define GROOVX_RUTZ_FSTRING_H_UTC20050626084021_DEFINED 00037 00038 #include "rutz/atomic.h" 00039 00040 #include <cstddef> 00041 #include <cstring> 00042 #include <iosfwd> 00043 00044 namespace rutz 00045 { 00046 /////////////////////////////////////////////////////////// 00047 /** 00048 * 00049 * \c string_rep is a helper class for fstring that handles memory 00050 * management and reference-counting. \c string_rep should not be 00051 * used by public clients. 00052 * 00053 **/ 00054 /////////////////////////////////////////////////////////// 00055 00056 class string_rep 00057 { 00058 public: 00059 static string_rep* make(std::size_t length, const char* text, 00060 std::size_t capacity=0); 00061 00062 static string_rep* read_from_stream(std::istream& is); 00063 00064 static string_rep* readsome_from_stream(std::istream& is, unsigned int count); 00065 00066 static string_rep* readline_from_stream(std::istream& is, char eol = '\n'); 00067 00068 void incr_ref_count() throw() { m_refcount.atomic_incr(); } 00069 00070 int decr_ref_count() throw() 00071 { 00072 const int c = m_refcount.atomic_decr_return(); 00073 if (c <= 0) 00074 delete this; 00075 return c; 00076 } 00077 00078 std::size_t length() const throw() { return m_length; } 00079 std::size_t capacity() const throw() { return m_capacity; } 00080 const char* text() const throw() { return m_text; } 00081 00082 void debug_dump() const throw(); 00083 00084 private: 00085 // Class-specific operator new. 00086 void* operator new(std::size_t bytes); 00087 00088 // Class-specific operator delete. 00089 void operator delete(void* space); 00090 00091 // Constructor builds a string_rep with ref-count 0. 'length' here 00092 // does NOT need to "+1" for a null-terminator 00093 string_rep(std::size_t length, const char* text, std::size_t capacity=0); 00094 00095 ~string_rep() throw(); 00096 00097 // To be called once via pthread_once() 00098 static void initialize_empty_rep(); 00099 00100 // Member functions whose names are prefixed with "uniq_" require 00101 // as a precondition that the string_rep object be unshared. In 00102 // order to ensure thread safety, such mutating calls are private 00103 // and can be made only during the process of construction of a 00104 // string_rep object. 00105 00106 void uniq_append_no_terminate(char c); 00107 void add_terminator() throw(); 00108 void uniq_set_length(std::size_t length) throw(); 00109 void uniq_append(std::size_t length, const char* text); 00110 void uniq_realloc(std::size_t capacity); 00111 00112 string_rep(const string_rep& other); // not implemented 00113 string_rep& operator=(const string_rep& other); // not implemented 00114 00115 rutz::atomic_int_t m_refcount; 00116 00117 std::size_t m_capacity; 00118 std::size_t m_length; 00119 char* m_text; 00120 }; 00121 00122 struct char_range 00123 { 00124 char_range(const char* t, unsigned int n) : text(t), len(n) {} 00125 00126 // default copy, dtor, assignment OK 00127 00128 const char* const text; 00129 unsigned int const len; 00130 }; 00131 00132 /////////////////////////////////////////////////////////// 00133 /** 00134 * 00135 * \c fstring is a simple string class that holds a pointer to a 00136 * dynamically-allocated char array. The initializer does not have 00137 * to reside in permanent storage, since a copy is made when the \c 00138 * fstring is constructed. Assignment is allowed, with copy 00139 * semantics. Also, a \c swap() operation is provided. The internal 00140 * implementation uses reference counting to allow for efficient 00141 * copies; however, to allow safe multi-threaded access to fstring, 00142 * fstring's interface is read-only, except for a few functions 00143 * (assignment operator, swap(), clear() read(), readline(), 00144 * readsome()) which safely replace the entire string. 00145 * 00146 **/ 00147 /////////////////////////////////////////////////////////// 00148 00149 class fstring 00150 { 00151 public: 00152 /// Construct an empty string. 00153 fstring(); 00154 00155 /// Copy constructor. 00156 fstring(const fstring& other) throw(); 00157 00158 /// Destructory. 00159 ~fstring() throw(); 00160 00161 /// Construct by copying from a C-style null-terminated char array. 00162 fstring(const char* s) : 00163 m_rep(0) 00164 { 00165 init_range(char_range(s, s ? strlen(s) : 0)); 00166 } 00167 00168 /// Construct from a character range (pointer plus length). 00169 explicit fstring(char_range r) : 00170 m_rep(0) 00171 { 00172 init_range(r); 00173 } 00174 00175 /// Swap contents with another fstring object. 00176 void swap(fstring& other) throw(); 00177 00178 /// Assign from a C-style null-terminated char array. 00179 fstring& operator=(const char* text); 00180 00181 /// Assignment operator. 00182 fstring& operator=(const fstring& other) throw(); 00183 00184 /// Get a pointer to the const underlying data array. 00185 const char* c_str() const throw() { return m_rep->text(); } 00186 00187 /// Get the number of characters in the string (NOT INCLUDING the null terminator). 00188 std::size_t length() const throw() { return m_rep->length(); } 00189 00190 /// Query whether the length of the string is 0. 00191 bool is_empty() const throw() { return (length() == 0); } 00192 00193 /// Same as is_empty(); for compatibility with std::string interface. 00194 bool empty() const throw() { return is_empty(); } 00195 00196 /// Return the character at position i. 00197 char operator[](unsigned int i) const { return m_rep->text()[i]; } 00198 00199 /// Reset to an empty string. 00200 void clear(); 00201 00202 // 00203 // Substring operations 00204 // 00205 00206 /// Query whether the terminal substring matches the given string. 00207 bool ends_with(const fstring& ext) const throw(); 00208 00209 // 00210 // Comparison operators 00211 // 00212 00213 /// Query for equality with a C-style string. 00214 bool equals(const char* other) const throw(); 00215 /// Query for equality with another fstring object. 00216 bool equals(const fstring& other) const throw(); 00217 00218 /// Query if string is lexicographically less-than another string. 00219 bool operator<(const char* other) const throw(); 00220 00221 /// Query if string is lexicographically less-than another string. 00222 template <class string_type> 00223 bool operator<(const string_type& other) const throw() 00224 { 00225 return operator<(other.c_str()); 00226 } 00227 00228 /// Query if string is lexicographically greater-than another string. 00229 bool operator>(const char* other) const throw(); 00230 00231 /// Query if string is lexicographically greater-than another string. 00232 template <class string_type> 00233 bool operator>(const string_type& other) const throw() 00234 { 00235 return operator>(other.c_str()); 00236 } 00237 00238 // 00239 // Input/Output 00240 // 00241 00242 /// Set the string by reading consecutive non-whitespace characters. 00243 void read(std::istream& is); 00244 00245 /// Set the string by reading exactly count characters. 00246 void readsome(std::istream& is, unsigned int count); 00247 00248 /// Write the string's contents to the ostream. 00249 void write(std::ostream& os) const; 00250 00251 /// Set the string by reading characters up until newline or EOF. 00252 void readline(std::istream& is, char eol = '\n'); 00253 00254 // 00255 // Operators 00256 // 00257 00258 /// Equality operator. 00259 bool operator==(const char* rhs) const throw() { return equals(rhs); } 00260 /// Equality operator. 00261 bool operator==(const fstring& rhs) const throw() { return equals(rhs); } 00262 00263 /// Inequality operator. 00264 bool operator!=(const char* rhs) const throw() { return !equals(rhs); } 00265 /// Inequality operator. 00266 bool operator!=(const fstring& rhs) const throw() { return !equals(rhs); } 00267 00268 /// Dump contents for debugging. 00269 void debug_dump() const throw(); 00270 00271 private: 00272 void init_empty(); 00273 00274 void init_range(char_range r); 00275 00276 /// Construct from an existing string_rep object 00277 /** The string_rep should have refcount==0 on entry. */ 00278 fstring(string_rep* r); 00279 00280 string_rep* m_rep; 00281 }; 00282 00283 00284 fstring sconvert(char x); ///< Convert char -> fstring 00285 fstring sconvert(const char* x); ///< Convert c string -> fstring 00286 fstring sconvert(const fstring& x); ///< Convert fstring -> fstring 00287 00288 fstring sconvert(bool x); ///< Convert bool -> fstring 00289 fstring sconvert(int x); ///< Convert int -> fstring 00290 fstring sconvert(unsigned int x); ///< Convert uint -> fstring 00291 fstring sconvert(long x); ///< Convert long -> fstring 00292 fstring sconvert(unsigned long x); ///< Convert ulong -> fstring 00293 fstring sconvert(double x); ///< Convert double -> fstring 00294 00295 00296 /////////////////////////////////////////////////////////// 00297 // 00298 // Overloaded operators 00299 // 00300 /////////////////////////////////////////////////////////// 00301 00302 // operator == 00303 00304 inline bool operator==(const char* lhs, const fstring& rhs) throw() 00305 { return rhs.equals(lhs); } 00306 00307 // operator != 00308 00309 inline bool operator!=(const char* lhs, const fstring& rhs) throw() 00310 { return !rhs.equals(lhs); } 00311 00312 /////////////////////////////////////////////////////////// 00313 // 00314 // Input/Output functions 00315 // 00316 /////////////////////////////////////////////////////////// 00317 00318 inline std::istream& operator>>(std::istream& is, fstring& str) 00319 { 00320 str.read(is); return is; 00321 } 00322 00323 inline std::ostream& operator<<(std::ostream& os, const fstring& str) 00324 { 00325 str.write(os); return os; 00326 } 00327 00328 inline std::istream& getline(std::istream& is, fstring& str) 00329 { 00330 str.readline(is); return is; 00331 } 00332 00333 inline std::istream& getline(std::istream& is, fstring& str, char eol) 00334 { 00335 str.readline(is, eol); return is; 00336 } 00337 00338 /////////////////////////////////////////////////////////// 00339 // 00340 // Overload of rutz::debug::eval() (used in dbg_eval macros) 00341 // 00342 /////////////////////////////////////////////////////////// 00343 00344 namespace debug 00345 { 00346 inline void eval (const char* what, int level, const char* where, 00347 int line_no, bool nl, rutz::fstring expr) throw() 00348 { 00349 eval(what, level, where, line_no, nl, expr.c_str()); 00350 } 00351 } 00352 00353 } // end namespace rutz 00354 00355 static const char __attribute__((used)) vcid_groovx_rutz_fstring_h_utc20050626084021[] = "$Id: fstring.h 8249 2007-04-12 06:03:40Z rjpeters $ $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/rutz/fstring.h $"; 00356 #endif // !GROOVX_RUTZ_FSTRING_H_UTC20050626084021_DEFINED