Main Page   Namespace List   Class Hierarchy   Compound List   File List   Namespace Members   Compound Members   File Members  

/otk/ustring.cc

Go to the documentation of this file.
00001 // -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*-
00002 
00003 #ifdef    HAVE_CONFIG_H
00004 #  include "../config.h"
00005 #endif // HAVE_CONFIG_H
00006 
00007 #include "ustring.hh"
00008 
00009 extern "C" {
00010 #include <assert.h>
00011 }
00012 
00013 namespace otk {
00014 
00015 // helper functions
00016 
00017 // The number of bytes to skip to find the next character in the string
00018 static const char utf8_skip[256] = {
00019   1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
00020   1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
00021   1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
00022   1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
00023   1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
00024   1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
00025   2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
00026   3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,6,6,1,1
00027 };
00028 
00029 // takes a pointer into a utf8 string and returns a unicode character for the
00030 // first character at the pointer
00031 unichar utf8_get_char (const char *p)
00032 {
00033   unichar result = static_cast<unsigned char>(*p);
00034 
00035   // if its not a 7-bit ascii character
00036   if((result & 0x80) != 0) {
00037     // len is the number of bytes this character takes up in the string
00038     unsigned char len = utf8_skip[result];
00039     result &= 0x7F >> len;
00040 
00041     while(--len != 0) {
00042       result <<= 6;
00043       result |= static_cast<unsigned char>(*++p) & 0x3F;
00044     }
00045   }
00046     
00047   return result;
00048 }
00049   
00050 // takes a pointer into a string and finds its offset
00051 static ustring::size_type utf8_ptr_to_offset(const char *str, const char *pos)
00052 {
00053   ustring::size_type offset = 0;
00054 
00055   while (str < pos) {
00056     str += utf8_skip[static_cast<unsigned char>(*str)];
00057     offset++;
00058   }
00059 
00060   return offset;
00061 }
00062 
00063 // takes an offset into a string and returns a pointer to it
00064 const char *utf8_offset_to_ptr(const char *str, ustring::size_type offset)
00065 {
00066   while (offset--)
00067     str += utf8_skip[static_cast<unsigned char>(*str)];
00068   return str;
00069 }
00070 
00071 // First overload: stop on '\0' character.
00072 ustring::size_type utf8_byte_offset(const char* str, ustring::size_type offset)
00073 {
00074   if(offset == ustring::npos)
00075     return ustring::npos;
00076 
00077   const char* p = str;
00078 
00079   for(; offset != 0; --offset)
00080   {
00081     if(*p == '\0')
00082       return ustring::npos;
00083 
00084     p += utf8_skip[static_cast<unsigned char>(*p)];
00085   }
00086 
00087   return (p - str);
00088 }
00089 
00090 // Second overload: stop when reaching maxlen.
00091 ustring::size_type utf8_byte_offset(const char* str, ustring::size_type offset,
00092             ustring::size_type maxlen)
00093 {
00094   if(offset == ustring::npos)
00095     return ustring::npos;
00096 
00097   const char *const pend = str + maxlen;
00098   const char* p = str;
00099 
00100   for(; offset != 0; --offset)
00101   {
00102     if(p >= pend)
00103       return ustring::npos;
00104 
00105     p += utf8_skip[static_cast<unsigned char>(*p)];
00106   }
00107 
00108   return (p - str);
00109 }
00110 
00111 
00112 // ustring methods
00113 
00114 ustring::ustring(bool utf8)
00115   : _utf8(utf8)
00116 {
00117 }
00118 
00119 ustring::~ustring()
00120 {
00121 }
00122 
00123 ustring::ustring(const ustring& other)
00124   : _string(other._string), _utf8(other._utf8)
00125 {
00126 }
00127 
00128 ustring& ustring::operator=(const ustring& other)
00129 {
00130   _string = other._string;
00131   _utf8 = other._utf8;
00132   return *this;
00133 }
00134 
00135 ustring::ustring(const std::string& src, bool utf8)
00136   : _string(src), _utf8(utf8)
00137 {
00138 }
00139 
00140 ustring::ustring(const char* src, bool utf8)
00141   : _string(src), _utf8(utf8)
00142 {
00143 }
00144 
00145 ustring& ustring::operator+=(const ustring& src)
00146 {
00147   assert(_utf8 == src._utf8);
00148   _string += src._string;
00149   return *this;
00150 }
00151 
00152 ustring& ustring::operator+=(const char* src)
00153 {
00154   _string += src;
00155   return *this;
00156 }
00157 
00158 ustring& ustring::operator+=(char c)
00159 {
00160   _string += c;
00161   return *this;
00162 }
00163 
00164 ustring::size_type ustring::size() const
00165 {
00166   if (_utf8) {
00167     const char *const pdata = _string.data();
00168     return utf8_ptr_to_offset(pdata, pdata + _string.size());
00169   } else
00170     return _string.size();
00171 }
00172 
00173 ustring::size_type ustring::bytes() const
00174 {
00175   return _string.size();
00176 }
00177 
00178 ustring::size_type ustring::capacity() const
00179 {
00180   return _string.capacity();
00181 }
00182 
00183 ustring::size_type ustring::max_size() const
00184 {
00185   return _string.max_size();
00186 }
00187 
00188 bool ustring::empty() const
00189 {
00190   return _string.empty();
00191 }
00192 
00193 void ustring::clear()
00194 {
00195   _string.erase();
00196 }
00197 
00198 ustring& ustring::erase(ustring::size_type i, ustring::size_type n)
00199 {
00200   if (_utf8) {
00201     // find a proper offset
00202     size_type utf_i = utf8_byte_offset(_string.c_str(), i);
00203     if (utf_i != npos) {
00204       // if the offset is not npos, find a proper length for 'n'
00205       size_type utf_n = utf8_byte_offset(_string.data() + utf_i, n,
00206            _string.size() - utf_i);
00207       _string.erase(utf_i, utf_n);
00208     }
00209   } else
00210     _string.erase(i, n);
00211 
00212   return *this;
00213 }
00214 
00215 void ustring::resize(ustring::size_type n, char c)
00216 {
00217   if (_utf8) {
00218     const size_type size_now = size();
00219     if(n < size_now)
00220       erase(n, npos);
00221     else if(n > size_now)
00222       _string.append(n - size_now, c);
00223   } else
00224     _string.resize(n, c);
00225 }
00226 
00227 ustring::value_type ustring::operator[](ustring::size_type i) const
00228 {
00229   return utf8_get_char(utf8_offset_to_ptr(_string.data(), i));
00230 }
00231 
00232 bool ustring::operator==(const ustring &other) const
00233 {
00234   return _string == other._string && _utf8 == other._utf8;
00235 }
00236 
00237 bool ustring::operator==(const std::string &other) const
00238 {
00239   return _string == other;
00240 }
00241 
00242 bool ustring::operator==(const char *other) const
00243 {
00244   return _string == other;
00245 }
00246 
00247 const char* ustring::data() const
00248 {
00249   return _string.data();
00250 }
00251 
00252 const char* ustring::c_str() const
00253 {
00254   return _string.c_str();
00255 }
00256 
00257 bool ustring::utf8() const
00258 {
00259   return _utf8;
00260 }
00261 
00262 void ustring::setUtf8(bool utf8)
00263 {
00264   _utf8 = utf8;
00265 }
00266 
00267 }

Generated on Tue Feb 4 22:58:57 2003 for Openbox by doxygen1.3-rc2