00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00031
00032 #ifndef header_xml_writer_generic
00033 #define header_xml_writer_generic
00034
00035 #if _MSC_VER > 1000
00036 #pragma once
00037 #endif
00038
00039 #include <string>
00040 #include <algorithm>
00041 #include <vector>
00042
00043
00044
00045
00046 class CL_XMLTokenString
00047 {
00048 public:
00049 CL_XMLTokenString();
00050
00051 CL_XMLTokenString(char const * pointer, int len, bool is_need_escape);
00052
00053 CL_XMLTokenString(char * pointer, int len, bool is_need_escape);
00054
00055 CL_XMLTokenString(const CL_XMLTokenString & copy);
00056
00057 CL_XMLTokenString & operator=(const CL_XMLTokenString & copy);
00058
00059 public:
00060 char * ptr();
00061
00062 char const * ptr() const;
00063
00064 int length() const;
00065
00066 char operator[](int i) const;
00067
00068 char & operator[](int i);
00069
00070 std::string to_string() const;
00071
00072 bool empty() const;
00073
00074 bool need_escape() const;
00075
00076 char * begin();
00077
00078 char * end();
00079
00080 char * begin() const;
00081
00082 char * end() const;
00083
00084 private:
00085 char * pointer;
00086
00087 int len;
00088
00089 bool is_need_escape;
00090 };
00091
00092
00093 inline CL_XMLTokenString::CL_XMLTokenString()
00094 : pointer(0)
00095 , len(0)
00096 , is_need_escape(false)
00097 {
00098 }
00099
00100 inline CL_XMLTokenString::CL_XMLTokenString(char * pointer, int len, bool is_need_escape)
00101 : pointer(pointer)
00102 , len(len)
00103 , is_need_escape(is_need_escape)
00104 {
00105 }
00106
00107
00108 inline CL_XMLTokenString::CL_XMLTokenString(char const * pointer, int len, bool is_need_escape)
00109 : pointer(const_cast<char*>(pointer))
00110 , len(len)
00111 , is_need_escape(is_need_escape)
00112 {
00113 }
00114
00115 inline CL_XMLTokenString::CL_XMLTokenString(const CL_XMLTokenString & copy)
00116 : pointer(copy.pointer)
00117 , len(copy.len)
00118 , is_need_escape(copy.is_need_escape)
00119 {
00120 }
00121
00122 inline CL_XMLTokenString & CL_XMLTokenString::operator=(const CL_XMLTokenString & copy)
00123 {
00124 if (this == ©)
00125 return *this;
00126
00127 pointer = copy.pointer;
00128 len = copy.len;
00129 is_need_escape = copy.is_need_escape;
00130
00131 return *this;
00132 }
00133
00134 inline char * CL_XMLTokenString::ptr()
00135 {
00136 return pointer;
00137 }
00138
00139 inline char const * CL_XMLTokenString::ptr() const
00140 {
00141 return pointer;
00142 }
00143
00144 inline int CL_XMLTokenString::length() const
00145 {
00146 return len;
00147 }
00148
00149 inline bool CL_XMLTokenString::empty() const
00150 {
00151 return len == 0;
00152 }
00153
00154 inline char * CL_XMLTokenString::begin()
00155 {
00156 return pointer;
00157 }
00158
00159 inline char * CL_XMLTokenString::end()
00160 {
00161 return pointer + len;
00162 }
00163
00164 inline char * CL_XMLTokenString::begin() const
00165 {
00166 return pointer;
00167 }
00168
00169 inline char * CL_XMLTokenString::end() const
00170 {
00171 return pointer + len;
00172 }
00173
00174 inline bool CL_XMLTokenString::need_escape() const
00175 {
00176 return is_need_escape;
00177 }
00178
00179 inline bool operator==(CL_XMLTokenString const & lhs, CL_XMLTokenString const & rhs)
00180 {
00181 return lhs.length() == rhs.length() && !memcmp(lhs.ptr(), rhs.ptr(), lhs.length());
00182 }
00183
00184 inline char CL_XMLTokenString::operator[](int i) const
00185 {
00186 return pointer[i];
00187 }
00188
00189 inline char & CL_XMLTokenString::operator[](int i)
00190 {
00191 return pointer[i];
00192 }
00193
00194 template <typename Container, typename Iter>
00195 inline bool append_escape(Container & buff, size_t & buff_size, Iter & begin, Iter end, std::string const & escape, char escape_char)
00196 {
00197 if ((int)escape.size() <= (end - begin))
00198 if (std::equal(escape.begin(), escape.end(), begin))
00199 {
00200 buff[buff_size] = escape_char;
00201 buff_size += 1;
00202 begin += escape.size();
00203 return true;
00204 }
00205 return false;
00206 }
00207
00208 inline std::string replace_escapes_fast(CL_XMLTokenString const & token_string)
00209 {
00210 static std::string const amp("&");
00211 static std::string const quot(""");
00212 static std::string const apos("'");
00213 static std::string const lt("<");
00214 static std::string const gt(">");
00215
00216 char const * begin = token_string.begin();
00217 char const * end = token_string.end();
00218
00219 std::string::size_type size = token_string.length();
00220
00221 static std::vector<char> buff;
00222 if (buff.size() < size)
00223 buff.resize(size);
00224
00225 size_t buff_size = 0;
00226
00227 while(begin != end)
00228 {
00229 char const * pos = std::find(begin, end, '&');
00230 std::copy(begin, pos, buff.begin() + buff_size);
00231 buff_size += std::distance(begin, pos);
00232
00233 if (pos == end)
00234 break;
00235
00236 begin = pos;
00237 if ( append_escape(buff, buff_size, begin, end, amp, '&')
00238 || append_escape(buff, buff_size, begin, end, quot, '\"')
00239 || append_escape(buff, buff_size, begin, end, apos, '\'')
00240 || append_escape(buff, buff_size, begin, end, gt, '>')
00241 || append_escape(buff, buff_size, begin, end, lt, '<'))
00242 {
00243 }
00244 else
00245 {
00246 buff[buff_size] = '&';
00247 buff_size += 1;
00248 ++begin;
00249 }
00250 }
00251 return std::string(&buff[0], buff_size);
00252 }
00253
00254 inline std::string CL_XMLTokenString::to_string() const
00255 {
00256 if (!is_need_escape)
00257 return std::string(pointer, len);
00258
00259 return replace_escapes_fast(*this);
00260 }
00261
00262 inline CL_XMLTokenString trim_whitespace(CL_XMLTokenString const & str)
00263 {
00264 if (str.empty())
00265 return str;
00266
00267 char const * begin = str.begin();
00268 char const * end = str.end();
00269
00270 while(begin != end)
00271 {
00272 char ch = *begin;
00273 if ( ch != ' '
00274 && ch != '\t'
00275 && ch != '\r'
00276 && ch != '\n')
00277 {
00278 break;
00279 }
00280 ++begin;
00281 }
00282
00283 while(end != begin)
00284 {
00285 char const * old_end = end--;
00286
00287 char ch = *end;
00288 if ( ch != ' '
00289 && ch != '\t'
00290 && ch != '\r'
00291 && ch != '\n')
00292 {
00293 end = old_end;
00294 break;
00295 }
00296 --end;
00297 }
00298
00299 return CL_XMLTokenString(begin, (int) std::distance(begin, end), str.need_escape());
00300 }
00301
00302 #endif