├── LICENSE.md ├── README.md ├── hprose ├── client.hpp ├── client │ ├── CookieManager.hpp │ ├── HproseClient.hpp │ ├── HproseHTTPClient.hpp │ └── asio │ │ └── HproseHTTPClient.hpp ├── common.hpp ├── common │ ├── Any.hpp │ ├── HproseException.hpp │ ├── IntUtil.hpp │ └── UTF8Util.hpp ├── config.hpp ├── ext │ ├── BigInteger.hpp │ └── CTime.hpp ├── io.hpp └── io │ ├── ClassManager.hpp │ ├── HproseFormatter.hpp │ ├── HproseReader.hpp │ ├── HproseTags.hpp │ ├── HproseTypes.hpp │ └── HproseWriter.hpp └── tests └── main.cpp /LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2008-2016 http://hprose.com 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Hprose for C++ 2 | 3 | [![Join the chat at https://gitter.im/hprose/hprose-cpp](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/hprose/hprose-cpp?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) 4 | 5 | *Hprose* is a High Performance Remote Object Service Engine. 6 | 7 | It is a modern, lightweight, cross-language, cross-platform, object-oriented, high performance, remote dynamic communication middleware. It is not only easy to use, but powerful. You just need a little time to learn, then you can use it to easily construct cross language cross platform distributed application system. 8 | 9 | *Hprose* supports many programming languages, for example: 10 | 11 | * AAuto Quicker 12 | * ActionScript 13 | * ASP 14 | * C++ 15 | * Dart 16 | * Delphi/Free Pascal 17 | * dotNET(C#, Visual Basic...) 18 | * Golang 19 | * Java 20 | * JavaScript 21 | * Node.js 22 | * Objective-C 23 | * Perl 24 | * PHP 25 | * Python 26 | * Ruby 27 | * ... 28 | 29 | Through *Hprose*, You can conveniently and efficiently intercommunicate between those programming languages. 30 | 31 | This project is the implementation of Hprose for C++. 32 | -------------------------------------------------------------------------------- /hprose/client.hpp: -------------------------------------------------------------------------------- 1 | /**********************************************************\ 2 | | | 3 | | hprose | 4 | | | 5 | | Official WebSite: http://www.hprose.com/ | 6 | | http://www.hprose.org/ | 7 | | | 8 | \**********************************************************/ 9 | /**********************************************************\ 10 | * * 11 | * client.hpp * 12 | * * 13 | * hprose client unit for Cpp. * 14 | * * 15 | * LastModified: Jun 15, 2014 * 16 | * Author: Chen fei * 17 | * * 18 | \**********************************************************/ 19 | 20 | #ifndef HPROSE_CLIENT_HPP 21 | #define HPROSE_CLIENT_HPP 22 | 23 | #if defined(_MSC_VER) && (_MSC_VER >= 1020) 24 | #pragma once 25 | #endif 26 | 27 | #include 28 | 29 | #endif // HPROSE_CLIENT_HPP 30 | -------------------------------------------------------------------------------- /hprose/client/CookieManager.hpp: -------------------------------------------------------------------------------- 1 | /**********************************************************\ 2 | | | 3 | | hprose | 4 | | | 5 | | Official WebSite: http://www.hprose.com/ | 6 | | http://www.hprose.net/ | 7 | | http://www.hprose.org/ | 8 | | | 9 | \**********************************************************/ 10 | 11 | /**********************************************************\ 12 | * * 13 | * CookieManager.hpp * 14 | * * 15 | * hprose cookie manager unit for cpp. * 16 | * * 17 | * LastModified: May 29, 2014 * 18 | * Author: Chen fei * 19 | * * 20 | \**********************************************************/ 21 | 22 | #ifndef HPROSE_CLIENT_COOKIE_MANAGER_HPP 23 | #define HPROSE_CLIENT_COOKIE_MANAGER_HPP 24 | 25 | #if defined(_MSC_VER) && (_MSC_VER >= 1020) 26 | #pragma once 27 | #endif 28 | 29 | #include 30 | 31 | #include 32 | #include 33 | 34 | #include 35 | #include 36 | #include 37 | #include 38 | 39 | namespace hprose { 40 | 41 | const char MonthNames[12][4] = { 42 | "JAN", "FEB", "MAR", "APR", "MAY", "JUN", // 1-6 43 | "JUL", "AUG", "SEP", "OCT", "NOV", "DEC" // 7-12 44 | }; 45 | 46 | const int TimeZoneCount[26] = { 47 | 1, 1, 4, 2, 2, 2, 2, 2, 2, 1, 1, 2, 4, // -12-0 48 | 5, 6, 1, 1, 1, 1, 1, 2, 1, 1, 1, 3, 1 // 1-13 49 | }; 50 | 51 | const char TimeZoneNames[26][6][5] = { 52 | { "IDLW" }, // -12 53 | { "NT" }, // -11 54 | { "AHST", "CAT", "HST", "AHST" }, // -10 55 | { "YST", "HDT" }, // -9 56 | { "PST", "YDT" }, // -8 57 | { "MST", "PDT" }, // -7 58 | { "CST", "MDT" }, // -6 59 | { "EST", "CDT" }, // -5 60 | { "AST", "EDT" }, // -4 61 | { "ADT" }, // -3 62 | { "AT" }, // -2 63 | { "WAT", "BST" }, // -1 64 | { "UT", "UTC", "GMT", "WET" }, // 0 65 | { "CET", "FWT", "MET", "MEWT", "SWT" }, // 1 66 | { "EET", "MEST", "MESZ", "SST", "FST", "CEST" }, // 2 67 | { "BT" }, // 3 68 | { "ZP4" }, // 4 69 | { "ZP5" }, // 5 70 | { "ZP6" }, // 6 71 | { "WAST" }, // 7 72 | { "CCT", "WADT" }, // 8 73 | { "JST" }, // 9 74 | { "GST" }, // 10 75 | { "EADT" }, // 11 76 | { "IDLE", "NZST", "NZT" }, // 12 77 | { "NZDT" } // 13 78 | }; 79 | 80 | struct cookie { 81 | cookie() 82 | : expiry(0), secure(false) { 83 | } 84 | 85 | inline bool expired() const { 86 | return expiry && (expiry < time(0)); 87 | }; 88 | 89 | inline bool good() const { 90 | return !value.empty(); 91 | }; 92 | 93 | inline std::string rawform() const { 94 | return name + "=" + value; 95 | }; 96 | 97 | std::string name; 98 | std::string value; 99 | std::string domain; 100 | std::string path; 101 | std::time_t expiry; 102 | bool secure; 103 | }; 104 | 105 | class CookieManager { 106 | public: 107 | 108 | inline static CookieManager * SharedInstance() { 109 | static CookieManager cookieManager; 110 | return &cookieManager; 111 | } 112 | 113 | public: 114 | 115 | std::string GetCookie(const std::string & host, const std::string & path, bool secure = false) { 116 | boost::upgrade_lock lock(mutex); 117 | std::string ret; 118 | for (AllCookies::iterator iter1 = container.begin(); iter1 != container.end(); ++iter1) { 119 | if (host.find(iter1->first) != std::string::npos) { 120 | std::vector names; 121 | DomainCookies & map = iter1->second; 122 | for (DomainCookies::iterator iter2 = map.begin(); iter2 != map.end(); ++iter2) { 123 | cookie & c = iter2->second; 124 | if (path.find(c.path) == 0) { 125 | if (c.expired()) { 126 | names.push_back(c.name); 127 | } else if (((!c.secure) || (secure && c.secure)) && c.good()) { 128 | ret += ret.empty() ? c.rawform() : ("; " + c.rawform()); 129 | } 130 | } 131 | } 132 | if (!names.empty()) { 133 | // boost::upgrade_to_unique_lock doesn't compile on C++0x mode(#2501) 134 | // boost::upgrade_to_unique_lock unique_lock(lock); 135 | mutex.unlock_upgrade_and_lock(); 136 | for (size_t i = 0; i < names.size(); i++) { 137 | map.erase(names[i]); 138 | } 139 | mutex.unlock_and_lock_upgrade(); 140 | } 141 | } 142 | } 143 | return ret; 144 | }; 145 | 146 | void SetCookie(const std::string & host, std::string content) { 147 | std::string::size_type pos = content.find(';'); 148 | if (pos != std::string::npos) { 149 | cookie c; 150 | std::string s = content.substr(0, pos); 151 | content.erase(0, pos + 2); 152 | pos = s.find('='); 153 | if (pos != std::string::npos) { 154 | c.name = s.substr(0, pos); 155 | c.value = s.substr(pos + 1); 156 | std::string key, value; 157 | while (true) { 158 | bool eof = false; 159 | pos = content.find(';'); 160 | if (pos == std::string::npos) { 161 | eof = true; 162 | s = content; 163 | } else { 164 | s = content.substr(0, pos); 165 | content.erase(0, pos + 2); 166 | } 167 | pos = s.find('='); 168 | if (pos != std::string::npos) { 169 | key = s.substr(0, pos); 170 | value = s.substr(pos + 1); 171 | } else { 172 | if (_strcmpi(s.c_str(), "secure") == 0) { 173 | c.secure = true; 174 | } 175 | continue; 176 | } 177 | if (_strcmpi(key.c_str(), "path") == 0) { 178 | if (!value.empty()) { 179 | if (*value.begin() == '"') { 180 | value.erase(0, 1); 181 | } 182 | if (*value.rbegin() == '"') { 183 | value.erase(value.size() - 1); 184 | } 185 | c.path = value.empty() ? std::string("/") : value; 186 | } 187 | } else if (_strcmpi(key.c_str(), "domain") == 0) { 188 | if (!value.empty()) { 189 | std::transform(value.begin(), value.end(), value.begin(), tolower); 190 | c.domain = value; 191 | } 192 | } else if (_strcmpi(key.c_str(), "expires") == 0) { 193 | if (!value.empty()) { 194 | c.expiry = parseRFCDatetime(value); 195 | } 196 | } 197 | if (eof) break; 198 | } 199 | if (c.path.empty()) { 200 | c.path = "/"; 201 | } 202 | if (c.domain.empty()) { 203 | c.domain = host; 204 | } 205 | boost::unique_lock lock(mutex); 206 | container[c.domain][c.name] = c; 207 | } 208 | } 209 | }; 210 | 211 | private: 212 | bool parseMonth(const std::string & value, int & month) { 213 | for (int i = 0; i < 12; i++) { 214 | if (MonthNames[i] == value) { 215 | month = i; 216 | return true; 217 | } 218 | } 219 | return false; 220 | } 221 | 222 | bool parseTimezone(const std::string & value, long & zone) { 223 | if ((value[0] == '+') || (value[0] == '-')) { 224 | if (value == "-0000") { 225 | zone = CTime::TimeZone(); 226 | } else if (value.size() > 4) { 227 | int zh = atoi(value.substr(1, 2).c_str()); 228 | int zm = atoi(value.substr(3, 2).c_str()); 229 | zone = zh * 3600 + zm * 60; 230 | if (value[0] == '-') { 231 | zone = zone * (-1); 232 | } 233 | } 234 | return true; 235 | } else { 236 | for (int i = 0; i < 26; i++) { 237 | for (int j = 0; j < TimeZoneCount[i]; j++) { 238 | if (TimeZoneNames[i][j] == value) { 239 | zone = (i - 12) * 3600; 240 | return true; 241 | } 242 | } 243 | } 244 | } 245 | return false; 246 | } 247 | 248 | std::time_t parseRFCDatetime(std::string value) { 249 | boost::replace_all(value, " -", " #"); 250 | std::replace(value.begin(), value.end(), '-', ' '); 251 | boost::replace_all(value, " #", " -"); 252 | std::tm t; 253 | memset(&t, 0, sizeof(std::tm)); 254 | int x; 255 | long zone = 0; 256 | std::string s; 257 | std::string::size_type pos; 258 | while (!value.empty()) { 259 | pos = value.find(' '); 260 | if (pos != std::string::npos) { 261 | s = value.substr(0, pos); 262 | value.erase(0, pos + 1); 263 | } else { 264 | s = value; 265 | value.clear(); 266 | } 267 | std::transform(s.begin(), s.end(), s.begin(), toupper); 268 | if (parseTimezone(s, zone)) continue; 269 | if ((x = atoi(s.c_str())) > 0) { 270 | if ((x < 32) && (!t.tm_mday)) { 271 | t.tm_mday = x; 272 | continue; 273 | } else { 274 | if ((!t.tm_year) && (t.tm_mon || (x > 12))) { 275 | if (x < 32) { 276 | t.tm_year = x + 100; 277 | } else if (x < 1000) { 278 | t.tm_year = x; 279 | } else { 280 | t.tm_year = x - 1900; 281 | } 282 | continue; 283 | } 284 | } 285 | } 286 | std::string::size_type first, last; 287 | if ((first = s.find_first_of(':')) < (last = s.find_last_of(':'))) { 288 | t.tm_hour = atoi(s.substr(0, first).c_str()); 289 | t.tm_min = atoi(s.substr(first + 1, last).c_str()); 290 | t.tm_sec = atoi(s.substr(last + 1).c_str()); 291 | continue; 292 | } 293 | if (s == "DST") { 294 | t.tm_isdst = true; 295 | continue; 296 | } 297 | if (parseMonth(s, x) && (!t.tm_mon)) { 298 | t.tm_mon = x; 299 | } 300 | } 301 | if (!t.tm_year) { 302 | t.tm_year = 80; 303 | } 304 | if (t.tm_mon > 11) { 305 | t.tm_mon = 11; 306 | } 307 | if (!t.tm_mday) { 308 | t.tm_mday = 1; 309 | } 310 | t.tm_sec -= (zone + CTime::TimeZone()); 311 | return mktime(&t); 312 | } 313 | 314 | private: 315 | 316 | typedef std::tr1::unordered_map DomainCookies; 317 | typedef std::tr1::unordered_map AllCookies; 318 | 319 | AllCookies container; 320 | boost::shared_mutex mutex; // read-write lock for containers 321 | 322 | }; // class CookieManager 323 | 324 | } // namespace hprose 325 | 326 | #endif // HPROSE_CLIENT_COOKIE_MANAGER_HPP 327 | -------------------------------------------------------------------------------- /hprose/client/HproseClient.hpp: -------------------------------------------------------------------------------- 1 | /**********************************************************\ 2 | | | 3 | | hprose | 4 | | | 5 | | Official WebSite: http://www.hprose.com/ | 6 | | http://www.hprose.net/ | 7 | | http://www.hprose.org/ | 8 | | | 9 | \**********************************************************/ 10 | /**********************************************************\ 11 | * * 12 | * HproseClient.hpp * 13 | * * 14 | * hprose client class for Cpp. * 15 | * * 16 | * LastModified: Jul 7, 2015 * 17 | * Author: Chen fei * 18 | * * 19 | \**********************************************************/ 20 | 21 | #ifndef HPROSE_CLIENT_HPROSE_CLIENT_HPP 22 | #define HPROSE_CLIENT_HPROSE_CLIENT_HPP 23 | 24 | #if defined(_MSC_VER) && (_MSC_VER >= 1020) 25 | #pragma once 26 | #endif 27 | 28 | #include 29 | #include 30 | 31 | namespace hprose { 32 | 33 | namespace HproseTags { 34 | 35 | const char ResultTags[4] = { TagResult, TagArgument, TagError, TagEnd }; // Todo: Remove 36 | 37 | } // namespace HproseTags 38 | 39 | class HproseClient { 40 | protected: // structors 41 | 42 | HproseClient() { 43 | } 44 | 45 | HproseClient(const std::string & uri) { 46 | UseService(uri); 47 | } 48 | 49 | virtual ~HproseClient() { 50 | } 51 | 52 | protected: 53 | 54 | virtual void * GetInvokeContext() = 0; 55 | 56 | virtual void SendData(void * context) = 0; 57 | 58 | virtual void EndInvoke(void * context) = 0; 59 | 60 | virtual std::ostream & GetOutputStream(void * context) = 0; 61 | 62 | virtual std::istream & GetInputStream(void * context) = 0; 63 | 64 | public: 65 | 66 | virtual void UseService(const std::string & uri) { 67 | this->uri = uri; 68 | } 69 | 70 | template 71 | inline ReturnType Invoke(const std::string & name) { 72 | std::vector args; 73 | return Invoke(name, args); 74 | } 75 | 76 | template 77 | inline void Invoke(ReturnType & ret, const std::string & name) { 78 | std::vector args; 79 | Invoke(ret, name, args); 80 | } 81 | 82 | #ifndef BOOST_NO_INITIALIZER_LISTS 83 | template 84 | inline ReturnType Invoke(const std::string & name, const std::initializer_list & args) { 85 | return Invoke(name, args, false); 86 | } 87 | 88 | template 89 | inline void Invoke(ReturnType & ret, const std::string & name, const std::initializer_list & args) { 90 | Invoke(ret, name, args, false); 91 | } 92 | #endif 93 | 94 | template 95 | inline ReturnType Invoke(const std::string & name, ArgsType & args, bool ref = false) { 96 | ReturnType ret = ReturnType(); 97 | Invoke(ret, name, args, ref); 98 | return ret; 99 | } 100 | 101 | template 102 | void Invoke(ReturnType & ret, const std::string & name, ArgsType & args, bool ref = false) { 103 | std::string error; 104 | void * context = 0; 105 | context = GetInvokeContext(); 106 | try { 107 | DoOutput(name, args, ref, GetOutputStream(context)); 108 | SendData(context); 109 | DoInput(ret, args, error, GetInputStream(context)); 110 | } 111 | catch (...) { 112 | } 113 | EndInvoke(context); 114 | if (!error.empty()) { 115 | HPROSE_THROW_EXCEPTION(error); 116 | } 117 | } 118 | 119 | template 120 | inline void AsyncInvoke(const std::string & name, Functor func) { 121 | static std::vector args; 122 | AsyncInvoke(name, args, func, false); 123 | } 124 | 125 | template 126 | inline void AsyncInvoke(const std::string & name, const ArgsType & args, Functor func, bool ref = false) { 127 | boost::thread thread(Async(*this, name, args, func, ref)); 128 | } 129 | 130 | template 131 | inline void AsyncInvoke(const std::string & name, const ArgsType (&args)[ArraySize], Functor func, bool ref = false) { 132 | std::vector newArgs(ArraySize); 133 | for (int i = 0; i < ArraySize; ++i) { 134 | newArgs[i] = args[i]; 135 | } 136 | AsyncInvoke(name, newArgs, func, ref); 137 | } 138 | 139 | private: 140 | 141 | template 142 | class Async { 143 | public: 144 | 145 | Async(HproseClient & client, const std::string & name, ArgsType args, Functor func, bool ref) 146 | : client(client), name(name), args(args), func(func), ref(ref) { 147 | } 148 | 149 | public: 150 | 151 | inline void operator()() { 152 | ReturnType ret = ReturnType(); 153 | client.Invoke(ret, name, args, ref); 154 | func(ret, args); 155 | } 156 | 157 | private: 158 | 159 | HproseClient & client; 160 | std::string name; 161 | ArgsType args; 162 | Functor func; 163 | bool ref; 164 | 165 | }; // class Async 166 | 167 | private: 168 | 169 | template 170 | void DoInput(ReturnType & ret, ArgsType & args, std::string & error, std::istream & stream) { 171 | HproseReader reader(stream); 172 | while (true) { 173 | switch (reader.CheckTags(HproseTags::ResultTags)) { 174 | case HproseTags::TagResult: 175 | ret = reader.Unserialize(); 176 | break; 177 | case HproseTags::TagArgument: 178 | //args = reader.ReadList(); 179 | break; 180 | case HproseTags::TagError: 181 | error = reader.ReadString(); 182 | return; 183 | case HproseTags::TagEnd: 184 | return; 185 | } 186 | } 187 | } 188 | 189 | template 190 | void DoOutput(const std::string & name, ArgsType & args, bool ref, std::ostream & stream) { 191 | HproseWriter writer(stream); 192 | stream << HproseTags::TagCall; 193 | writer.WriteString(name, false); 194 | if (!args.empty()) { 195 | writer.WriteList(args, false); 196 | if (ref) { 197 | writer.WriteBool(true); 198 | } 199 | } 200 | 201 | stream << HproseTags::TagEnd; 202 | } 203 | 204 | template 205 | void DoOutput(const std::string & name, ArgsType (&args)[ArraySize], bool ref, std::ostream & stream) { 206 | HproseWriter writer(stream); 207 | stream << HproseTags::TagCall; 208 | writer.WriteString(name, false); 209 | if (ArraySize > 0) { 210 | writer.WriteList(args, false); 211 | if (ref) { 212 | writer.WriteBool(true); 213 | } 214 | } 215 | 216 | stream << HproseTags::TagEnd; 217 | } 218 | 219 | protected: 220 | 221 | std::string uri; 222 | 223 | }; // class HproseClient 224 | 225 | } // namespace hprose 226 | 227 | #endif // HPROSE_CLIENT_HPROSE_CLIENT_HPP 228 | -------------------------------------------------------------------------------- /hprose/client/HproseHTTPClient.hpp: -------------------------------------------------------------------------------- 1 | /**********************************************************\ 2 | | | 3 | | hprose | 4 | | | 5 | | Official WebSite: http://www.hprose.com/ | 6 | | http://www.hprose.net/ | 7 | | http://www.hprose.org/ | 8 | | | 9 | \**********************************************************/ 10 | /**********************************************************\ 11 | * * 12 | * HproseHTTPClient.hpp * 13 | * * 14 | * hprose default http client unit for Cpp. * 15 | * * 16 | * LastModified: Mar 2, 2014 * 17 | * Author: Chen fei * 18 | * * 19 | \**********************************************************/ 20 | 21 | #ifndef HPROSE_CLIENT_HPROSE_HTTPCLIENT_HPP 22 | #define HPROSE_CLIENT_HPROSE_HTTPCLIENT_HPP 23 | 24 | #if defined(_MSC_VER) && (_MSC_VER >= 1020) 25 | #pragma once 26 | #endif 27 | 28 | #include 29 | 30 | namespace hprose { 31 | using asio::HproseHTTPClient; 32 | } 33 | 34 | #endif // HPROSE_CLIENT_HPROSE_HTTPCLIENT_HPP 35 | -------------------------------------------------------------------------------- /hprose/client/asio/HproseHTTPClient.hpp: -------------------------------------------------------------------------------- 1 | /**********************************************************\ 2 | | | 3 | | hprose | 4 | | | 5 | | Official WebSite: http://www.hprose.com/ | 6 | | http://www.hprose.org/ | 7 | | | 8 | \**********************************************************/ 9 | /**********************************************************\ 10 | * * 11 | * HproseHTTPClient.hpp * 12 | * * 13 | * hprose asio http client class unit for Cpp. * 14 | * * 15 | * LastModified: Mar 2, 2014 * 16 | * Author: Chen fei * 17 | * * 18 | \**********************************************************/ 19 | 20 | #ifndef HPROSE_CLIENT_ASIO_HPROSE_HTTPCLIENT_HPP 21 | #define HPROSE_CLIENT_ASIO_HPROSE_HTTPCLIENT_HPP 22 | 23 | #if defined(_MSC_VER) && (_MSC_VER >= 1020) 24 | #pragma once 25 | #endif 26 | 27 | #include 28 | #include 29 | 30 | #include 31 | #ifndef HPROSE_NO_OPENSSL 32 | #include 33 | #endif 34 | #include 35 | 36 | namespace hprose { namespace asio { 37 | 38 | using boost::asio::ip::tcp; 39 | 40 | class HproseHTTPClient : public HproseClient { 41 | public: 42 | 43 | HproseHTTPClient(const std::string & uri = "http://localhost/") { 44 | UseService(uri); 45 | SetKeepAlive(true); 46 | SetHeader("Content-Type", "application/hprose"); 47 | SetUserAgent("Hprose Http Client for Cpp (asio)"); 48 | }; 49 | 50 | virtual ~HproseHTTPClient() { 51 | boost::mutex::scoped_lock lock(mutex); 52 | while (!pool.empty()) { 53 | HTTPContext * context = pool.top(); 54 | pool.pop(); 55 | delete context; 56 | } 57 | }; 58 | 59 | public: 60 | 61 | virtual void UseService(const std::string & uri) { 62 | HproseClient::UseService(uri); 63 | ParseURI(); 64 | }; 65 | 66 | inline void SetHeader(const std::string & key, const std::string & value) { 67 | headers[key] = value; 68 | }; 69 | 70 | void SetKeepAlive(bool keepAlive, int timeout = 300) { 71 | if (keepAlive) { 72 | std::ostringstream stream; 73 | stream << "keep-alive\r\nKeep-Alive: " << timeout; 74 | SetHeader("Connection", stream.str()); 75 | } else { 76 | SetHeader("Connection", "close"); 77 | } 78 | }; 79 | 80 | inline void SetUserAgent(const std::string & userAgent) { 81 | headers["User-Agent"] = userAgent; 82 | }; 83 | 84 | protected: 85 | 86 | virtual void * GetInvokeContext() { 87 | boost::mutex::scoped_lock lock(mutex); 88 | if (pool.size() > 0) { 89 | HTTPContext * ctx = pool.top(); 90 | pool.pop(); 91 | return ctx; 92 | } else { 93 | return new HTTPContext(ios); 94 | } 95 | }; 96 | 97 | virtual void SendData(void * context) { 98 | if (context) { 99 | HTTPContext & ctx = *static_cast(context); 100 | ctx.Post(host, port, path, headers, protocol == "https"); 101 | } 102 | }; 103 | 104 | virtual void EndInvoke(void * context) { 105 | if (context) { 106 | boost::mutex::scoped_lock lock(mutex); 107 | HTTPContext * ctx = static_cast(context); 108 | pool.push(ctx); 109 | } 110 | }; 111 | 112 | virtual std::ostream & GetOutputStream(void * context) { 113 | if (context) { 114 | return (static_cast(context))->requestStream; 115 | } else { 116 | HPROSE_THROW_EXCEPTION("Can''t get output stream."); 117 | } 118 | }; 119 | 120 | virtual std::istream & GetInputStream(void * context) { 121 | if (context) { 122 | return (static_cast(context))->responseStream; 123 | } else { 124 | HPROSE_THROW_EXCEPTION("Can''t get input stream."); 125 | } 126 | }; 127 | 128 | private: 129 | 130 | void ParseURI() { 131 | std::string surl; 132 | std::string::size_type x, y; 133 | protocol = "http"; 134 | user = ""; 135 | password = ""; 136 | port = "80"; 137 | x = uri.find("://"); 138 | if (x != std::string::npos) { 139 | protocol = uri.substr(0, x); 140 | surl = uri.substr(x + 3); 141 | } else { 142 | surl = uri; 143 | } 144 | std::transform(protocol.begin(), protocol.end(), protocol.begin(), tolower); 145 | if (protocol == "https") { 146 | port = "443"; 147 | } 148 | x = surl.find('@'); 149 | y = surl.find('/'); 150 | if ((x != std::string::npos) && ((x < y) || (y == std::string::npos))) { 151 | user = surl.substr(0, x); 152 | surl.erase(0, x + 1); 153 | x = user.find(':'); 154 | if (x != std::string::npos) { 155 | password = user.substr(x + 1); 156 | user.erase(x); 157 | } 158 | } 159 | x = surl.find('/'); 160 | if (x != std::string::npos) { 161 | host = surl.substr(0, x); 162 | surl.erase(0, x + 1); 163 | } else { 164 | host = surl; 165 | surl = ""; 166 | } 167 | bool ipv6 = host[0] == '['; 168 | if (ipv6) { 169 | x = host.find(']'); 170 | if ((x + 1 < host.size()) && (host[x + 1] == ':')) { 171 | port = host.substr(x + 2); 172 | } 173 | host = host.substr(1, x - 1); 174 | } else { 175 | x = host.find(':'); 176 | if (x != std::string::npos) { 177 | port = host.substr(x + 1); 178 | host.erase(x); 179 | } 180 | } 181 | SetHeader("Host", (ipv6 ? ('[' + host + ']') : host) + ((port == "80") ? std::string() : (':' + port))); 182 | 183 | path = '/' + surl; 184 | 185 | if (host == "") { 186 | host = "localhost"; 187 | } 188 | }; 189 | 190 | private: 191 | 192 | class HTTPContext { 193 | public: // structors 194 | 195 | HTTPContext(boost::asio::io_service & ios) 196 | : resolver(ios), 197 | socket(ios), 198 | #ifndef HPROSE_NO_OPENSSL 199 | sslContext(ios, boost::asio::ssl::context::sslv23), 200 | sslSocket(ios, sslContext), 201 | #endif 202 | requestStream(&request), 203 | responseStream(&response) { 204 | }; 205 | 206 | public: 207 | 208 | void Post(const std::string & host, const std::string & port, const std::string & path, const std::map & headers, bool secure) { 209 | if (!Connect( 210 | #ifndef HPROSE_NO_OPENSSL 211 | secure ? 212 | sslSocket.next_layer() : 213 | #endif 214 | socket, host, port, secure)) return; 215 | boost::system::error_code error = boost::asio::error::host_not_found; 216 | boost::asio::streambuf header; 217 | std::iostream headerStream(&header); 218 | headerStream << "POST " << ((path == "/*") ? std::string("*") : path) << " HTTP/1.1\r\n";; 219 | for (std::map::const_iterator iter = headers.begin(); iter != headers.end(); iter++) { 220 | headerStream << iter->first << ": " << iter->second << "\r\n"; 221 | } 222 | std::string cookie = CookieManager::SharedInstance()->GetCookie(aliveHost, path, secure); 223 | if (!cookie.empty()) { 224 | headerStream << "Cookie: " << cookie << "\r\n"; 225 | } 226 | headerStream << "Content-Length: " << request.size() << "\r\n\r\n"; 227 | if (request.size() >= 64 * 1024) { 228 | Write(header, secure); 229 | Write(request, secure); 230 | } else { 231 | headerStream << &request; 232 | Write(header, secure); 233 | } 234 | if (response.size()) { 235 | response.consume(response.size()); 236 | } 237 | std::string s; 238 | size_t bytes = 0, len = 0; 239 | bool toclose = false, chunked = false; 240 | while ((bytes = ReadLine(header, secure)) > 2) { 241 | headerStream >> s; 242 | if (_strcmpi(s.c_str(), "Content-Length:") == 0) { 243 | headerStream >> len; 244 | } else if (_strcmpi(s.c_str(), "Connection:") == 0) { 245 | headerStream >> s; 246 | if (_strcmpi(s.c_str(), "close") == 0) { 247 | toclose = true; 248 | } 249 | } else if (_strcmpi(s.c_str(), "Keep-Alive:") == 0) { 250 | std::getline(headerStream, s, '='); 251 | if (_strcmpi(s.c_str(), " timeout") == 0) { 252 | clock_t timeout; 253 | headerStream >> timeout; 254 | aliveTime = clock() + timeout * CLOCKS_PER_SEC; 255 | } 256 | } else if (_strcmpi(s.c_str(), "Transfer-Encoding:") == 0) { 257 | headerStream >> s; 258 | if (_strcmpi(s.c_str(), "chunked") == 0) { 259 | chunked = true; 260 | } 261 | } else if ((_strcmpi(s.c_str(), "Set-Cookie:") == 0) || (_strcmpi(s.c_str(), "Set-Cookie2:") == 0)) { 262 | std::getline(headerStream, s); 263 | CookieManager::SharedInstance()->SetCookie(aliveHost, s.substr(1, s.size() - 2)); 264 | continue; 265 | } 266 | headerStream.ignore((std::numeric_limits::max)(), '\n'); 267 | } 268 | header.consume(2); 269 | if (chunked) { 270 | while (true) { 271 | size_t chunk_size = 0; 272 | ReadLine(header, secure); 273 | headerStream >> std::hex >> chunk_size >> std::dec; 274 | header.consume(2); 275 | if (chunk_size) { 276 | bytes = 0; 277 | while (true) { 278 | bytes += ReadLine(header, secure); 279 | if (bytes > chunk_size) { 280 | for (size_t i = 0; i < chunk_size; i++) { 281 | responseStream << (char)headerStream.get(); 282 | }; 283 | header.consume(2); 284 | break; 285 | } 286 | } 287 | } else { 288 | header.consume(2); 289 | break; 290 | } 291 | } 292 | } else { 293 | bool nosize = !len; 294 | size_t n = std::min(len, header.size()); 295 | for (size_t i = 0; i < n; ++i, --len) { 296 | responseStream << (char)headerStream.get(); 297 | }; 298 | if (nosize) { 299 | len = (std::numeric_limits::max)(); 300 | } 301 | if (len) { 302 | char buf[1024]; 303 | while (len) { 304 | size_t n = 305 | #ifndef HPROSE_NO_OPENSSL 306 | secure ? 307 | sslSocket.read_some(boost::asio::buffer(buf), error) : 308 | #endif 309 | socket.read_some(boost::asio::buffer(buf), error); 310 | if (error) break; 311 | responseStream.write(buf, n); 312 | len -= n; 313 | } 314 | } 315 | } 316 | if (toclose) { 317 | ( 318 | #ifndef HPROSE_NO_OPENSSL 319 | secure ? 320 | sslSocket.next_layer() : 321 | #endif 322 | socket).close(); 323 | Clear(); 324 | } 325 | }; 326 | 327 | private: 328 | 329 | inline void Clear() { 330 | aliveHost.clear(); 331 | alivePort.clear(); 332 | aliveTime = 0; 333 | }; 334 | 335 | bool Connect(tcp::socket & socket, const std::string & host, const std::string & port, bool secure) { 336 | if (socket.is_open() && (aliveHost == host) && (alivePort == port) && (clock() < aliveTime)) { 337 | return true; 338 | } 339 | tcp::resolver::query query(host, port); 340 | tcp::resolver::iterator endpoint_iterator = resolver.resolve(query); 341 | tcp::resolver::iterator end; 342 | boost::system::error_code error = boost::asio::error::host_not_found; 343 | while (error && endpoint_iterator != end) { 344 | socket.close(); 345 | socket.connect(*endpoint_iterator++, error); 346 | } 347 | if (error) { 348 | Clear(); 349 | return false; 350 | } else { 351 | #ifndef HPROSE_NO_OPENSSL 352 | if (secure) { 353 | sslSocket.handshake(boost::asio::ssl::stream_base::client, error); 354 | if (error) { 355 | socket.close(); 356 | return false; 357 | } 358 | } 359 | #endif 360 | aliveHost = host; 361 | alivePort = port; 362 | return true; 363 | } 364 | }; 365 | 366 | void Write(boost::asio::streambuf & buf, bool secure) { 367 | #ifndef HPROSE_NO_OPENSSL 368 | if (secure) { 369 | boost::asio::write(sslSocket, buf); 370 | } else { 371 | #endif 372 | boost::asio::write(socket, buf); 373 | #ifndef HPROSE_NO_OPENSSL 374 | } 375 | #endif 376 | }; 377 | 378 | size_t ReadLine(boost::asio::streambuf & buf, bool secure) { 379 | return 380 | #ifndef HPROSE_NO_OPENSSL 381 | secure ? 382 | boost::asio::read_until(sslSocket, buf, "\r\n") : 383 | #endif 384 | boost::asio::read_until(socket, buf, std::string("\r\n")); 385 | }; 386 | 387 | private: 388 | 389 | std::string aliveHost; 390 | std::string alivePort; 391 | clock_t aliveTime; 392 | 393 | tcp::resolver resolver; 394 | tcp::socket socket; 395 | 396 | #ifndef HPROSE_NO_OPENSSL 397 | boost::asio::ssl::context sslContext; 398 | boost::asio::ssl::stream sslSocket; 399 | #endif 400 | 401 | boost::asio::streambuf request; 402 | boost::asio::streambuf response; 403 | 404 | public: 405 | 406 | std::iostream requestStream; 407 | std::iostream responseStream; 408 | 409 | }; 410 | 411 | private: 412 | 413 | std::string protocol; 414 | std::string user; 415 | std::string password; 416 | std::string host; 417 | std::string port; 418 | std::string path; 419 | 420 | std::map headers; 421 | std::stack pool; 422 | boost::mutex mutex; 423 | boost::asio::io_service ios; 424 | 425 | }; // class HproseHTTPClient 426 | 427 | } } // namespaces 428 | 429 | #endif 430 | -------------------------------------------------------------------------------- /hprose/common.hpp: -------------------------------------------------------------------------------- 1 | /**********************************************************\ 2 | | | 3 | | hprose | 4 | | | 5 | | Official WebSite: http://www.hprose.com/ | 6 | | http://www.hprose.org/ | 7 | | | 8 | \**********************************************************/ 9 | 10 | /**********************************************************\ 11 | * * 12 | * common.hpp * 13 | * * 14 | * hprose common unit for cpp. * 15 | * * 16 | * LastModified: Apr 27, 2015 * 17 | * Author: Chen fei * 18 | * * 19 | \**********************************************************/ 20 | 21 | #ifndef HPROSE_COMMON_HPP 22 | #define HPROSE_COMMON_HPP 23 | 24 | #if defined(_MSC_VER) && (_MSC_VER >= 1020) 25 | #pragma once 26 | #endif 27 | 28 | #include 29 | #include 30 | #include 31 | 32 | #endif // HPROSE_COMMON_HPP 33 | -------------------------------------------------------------------------------- /hprose/common/Any.hpp: -------------------------------------------------------------------------------- 1 | /**********************************************************\ 2 | | | 3 | | hprose | 4 | | | 5 | | Official WebSite: http://www.hprose.com/ | 6 | | http://www.hprose.org/ | 7 | | | 8 | \**********************************************************/ 9 | 10 | /**********************************************************\ 11 | * * 12 | * Any.hpp * 13 | * * 14 | * hprose any unit for cpp. * 15 | * * 16 | * LastModified: Sep 20, 2016 * 17 | * Author: Chen fei * 18 | * * 19 | \**********************************************************/ 20 | 21 | #ifndef HPROSE_COMMON_ANY_HPP 22 | #define HPROSE_COMMON_ANY_HPP 23 | 24 | #if defined(_MSC_VER) && (_MSC_VER >= 1020) 25 | #pragma once 26 | #endif 27 | 28 | #include 29 | 30 | #if (defined(__GNUC__) && __GNUC__ >= 3) \ 31 | || defined(_AIX) \ 32 | || (defined(__sgi) && defined(__host_mips)) \ 33 | || (defined(__hpux) && defined(__HP_aCC)) \ 34 | || (defined(linux) && defined(__INTEL_COMPILER) && defined(__ICC)) 35 | #define BOOST_AUX_ANY_TYPE_ID_NAME 36 | #include 37 | #endif 38 | 39 | namespace hprose { 40 | 41 | template 42 | struct is_const 43 | : public std::is_const { 44 | }; 45 | 46 | template 47 | struct is_const 48 | : public is_const { 49 | }; 50 | 51 | template 52 | struct remove_member_pointer { 53 | typedef MemberType type; 54 | }; 55 | 56 | template 57 | struct remove_member_pointer { 58 | typedef MemberType type; 59 | }; 60 | 61 | template 62 | class BasicAny { 63 | public: // structors 64 | 65 | BasicAny() 66 | : content(0) { 67 | } 68 | 69 | template 70 | BasicAny(const ValueType & value) 71 | : content(new holder(value)) { 72 | } 73 | 74 | template 75 | BasicAny(ValueType ClassType::*value) 76 | : content(new holder(value)) { 77 | } 78 | 79 | BasicAny(const BasicAny & other) 80 | : content(other.content ? other.content->clone() : 0) { 81 | } 82 | 83 | ~BasicAny() { 84 | delete content; 85 | } 86 | 87 | public: // modifies 88 | 89 | BasicAny & swap(BasicAny & rhs) { 90 | std::swap(content, rhs.content); 91 | return *this; 92 | } 93 | 94 | template 95 | BasicAny & operator=(const T & rhs) { 96 | BasicAny(rhs).swap(*this); 97 | return *this; 98 | } 99 | 100 | BasicAny & operator=(BasicAny rhs) { 101 | rhs.swap(*this); 102 | return *this; 103 | } 104 | 105 | public: // queries 106 | 107 | bool empty() const { 108 | return !content; 109 | } 110 | 111 | const std::type_info & type() const { 112 | return content ? content->type() : typeid(void); 113 | } 114 | 115 | public: // Serialize 116 | 117 | inline void Unserialize(Reader & r) { 118 | if (content) { 119 | content->Unserialize(r); 120 | } else { 121 | r.Unserialize(*this); 122 | } 123 | } 124 | 125 | template 126 | inline void Unserialize(Reader & r, Object & object) { 127 | if (content) { 128 | content->Unserialize(r, &object); 129 | } else { 130 | // r.Unserialize(*this); 131 | } 132 | } 133 | 134 | inline void Serialize(Writer & w) const { 135 | if (content) { 136 | content->Serialize(w); 137 | } else { 138 | w.WriteNull(); 139 | } 140 | } 141 | 142 | template 143 | inline void Serialize(Writer & w, const Object & object) const { 144 | if (content) { 145 | content->Serialize(w, &object); 146 | } else { 147 | w.WriteNull(); 148 | } 149 | } 150 | 151 | private: // types 152 | 153 | class placeholder { 154 | public: // structors 155 | 156 | virtual ~placeholder() { 157 | } 158 | 159 | public: // queries 160 | 161 | virtual const std::type_info & type() const = 0; 162 | 163 | virtual placeholder * clone() const = 0; 164 | 165 | virtual void Unserialize(Reader & r) = 0; 166 | 167 | virtual void Unserialize(Reader & r, void * o) = 0; 168 | 169 | virtual void Serialize(Writer & w) const = 0; 170 | 171 | virtual void Serialize(Writer & w, const void * o) const = 0; 172 | 173 | }; 174 | 175 | template 176 | class holder : public placeholder { 177 | public: // structors 178 | 179 | holder(const ValueType & value) 180 | : held(value) { 181 | } 182 | 183 | public: // queries 184 | 185 | virtual const std::type_info & type() const { 186 | return typeid(ValueType); 187 | } 188 | 189 | virtual placeholder * clone() const { 190 | return new holder(held); 191 | } 192 | 193 | virtual void Unserialize(Reader & r) { 194 | Unserialize(r, is_const()); 195 | } 196 | 197 | virtual void Unserialize(Reader & r, void * o) { 198 | Unserialize(r, o, std::is_member_pointer()); 199 | } 200 | 201 | virtual void Serialize(Writer & w) const { 202 | w.Serialize(held); 203 | } 204 | 205 | virtual void Serialize(Writer & w, const void * o) const { 206 | Serialize(w, o, std::is_member_pointer()); 207 | } 208 | 209 | private: 210 | 211 | inline void Serialize(Writer & w, const void * o, const std::true_type &) const { 212 | const ClassType * p = static_cast(o); 213 | w.Serialize(p->*held); 214 | } 215 | 216 | inline void Serialize(Writer & w, const void * o, const std::false_type &) const { 217 | HPROSE_THROW_EXCEPTION("Can't Serialize none member pointer"); 218 | } 219 | 220 | inline void Unserialize(Reader & r, const std::true_type &) { 221 | HPROSE_THROW_EXCEPTION("Constant value can't be Unserialized"); 222 | } 223 | 224 | inline void Unserialize(Reader & r, const std::false_type &) { 225 | held = r.template Unserialize(); 226 | } 227 | 228 | inline void Unserialize(Reader & r, void * o, const std::true_type &) { 229 | ClassType * p = static_cast(o); 230 | p->*held = r.template Unserialize::type >(); 231 | } 232 | 233 | inline void Unserialize(Reader & w, void * o, const std::false_type &) { 234 | HPROSE_THROW_EXCEPTION("Can't Unserialize none member pointer"); 235 | } 236 | 237 | public: // representation 238 | 239 | ValueType held; 240 | 241 | private: // intentionally left unimplemented 242 | 243 | holder & operator=(const holder &); 244 | 245 | }; 246 | 247 | public: 248 | 249 | template 250 | static ValueType * cast(BasicAny * operand) { 251 | return operand && 252 | #ifdef BOOST_AUX_ANY_TYPE_ID_NAME 253 | std::strcmp(operand->type().name(), typeid(ValueType).name()) == 0 254 | #else 255 | operand->type() == typeid(ValueType) 256 | #endif 257 | ? &static_cast::BOOST_NESTED_TEMPLATE holder *>(operand->content)->held 258 | : 0; 259 | } 260 | 261 | template 262 | inline static const ValueType * cast(const BasicAny * operand) { 263 | return cast(const_cast *>(operand)); 264 | } 265 | 266 | template 267 | static ValueType cast(BasicAny & operand) { 268 | typedef BOOST_DEDUCED_TYPENAME std::remove_reference::type nonref; 269 | #ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION 270 | BOOST_STATIC_ASSERT(!is_reference::value); 271 | #endif 272 | nonref * result = cast(&operand); 273 | if (!result) { 274 | HPROSE_THROW_EXCEPTION("Failed conversion using hprose::Any::cast"); 275 | } 276 | return *result; 277 | } 278 | 279 | template 280 | inline static ValueType cast(const BasicAny & operand) { 281 | typedef BOOST_DEDUCED_TYPENAME std::remove_reference::type nonref; 282 | #ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION 283 | BOOST_STATIC_ASSERT(!is_reference::value); 284 | #endif 285 | return cast(const_cast &>(operand)); 286 | } 287 | 288 | template 289 | inline static ValueType * unsafe_cast(BasicAny * operand) { 290 | return &static_cast::BOOST_NESTED_TEMPLATE holder *>(operand->content)->held; 291 | } 292 | 293 | template 294 | inline static const ValueType * unsafe_cast(const BasicAny * operand) { 295 | return unsafe_cast(const_cast *>(operand)); 296 | } 297 | 298 | private: // representation 299 | 300 | placeholder * content; 301 | 302 | }; 303 | 304 | class HproseReader; 305 | class HproseWriter; 306 | 307 | typedef BasicAny Any; 308 | 309 | template 310 | int vector_index_of(const std::vector & container, ValueType & value) { 311 | std::vector::const_iterator iter = container.begin(); 312 | while (iter != container.end()) { 313 | if ((*iter).type() == typeid(ValueType)) { 314 | if (Any::cast(*iter) == value) { 315 | return (int)(iter - container.begin()); 316 | } 317 | } 318 | iter++; 319 | } 320 | return -1; 321 | } 322 | 323 | struct type_info_less { 324 | bool operator()(const std::type_info * left, const std::type_info * right) const { 325 | return left->before(*right) != 0; 326 | } 327 | }; 328 | 329 | } // namespace hprose 330 | 331 | #endif // HPROSE_COMMON_ANY_HPP 332 | -------------------------------------------------------------------------------- /hprose/common/HproseException.hpp: -------------------------------------------------------------------------------- 1 | /**********************************************************\ 2 | | | 3 | | hprose | 4 | | | 5 | | Official WebSite: http://www.hprose.com/ | 6 | | http://www.hprose.org/ | 7 | | | 8 | \**********************************************************/ 9 | 10 | /**********************************************************\ 11 | * * 12 | * HproseException.hpp * 13 | * * 14 | * hprose exception unit for cpp. * 15 | * * 16 | * LastModified: Jun 15, 2014 * 17 | * Author: Chen fei * 18 | * * 19 | \**********************************************************/ 20 | 21 | #ifndef HPROSE_COMMON_HPROSE_EXCEPTION_HPP 22 | #define HPROSE_COMMON_HPROSE_EXCEPTION_HPP 23 | 24 | #if defined(_MSC_VER) && (_MSC_VER >= 1020) 25 | #pragma once 26 | #endif 27 | 28 | #include 29 | 30 | #include 31 | 32 | #ifdef HPROSE_DEBUG_MODE 33 | #define HPROSE_EXCEPTION(s) hprose::HproseException(s, __FILE__, __LINE__) 34 | #else 35 | #define HPROSE_EXCEPTION(s) hprose::HproseException(s) 36 | #endif 37 | 38 | // HPROSE_THROW_EXCEPTION(s) = boost::throw_exception(hprose::HproseException(s)) 39 | // Use HPROSE_THROW_EXCEPTION instead of boost::throw_exception can avoid some warnings 40 | #ifndef BOOST_EXCEPTION_DISABLE 41 | #define HPROSE_THROW_EXCEPTION(s) throw boost::enable_current_exception(boost::enable_error_info(HPROSE_EXCEPTION(s))) 42 | #else 43 | #define HPROSE_THROW_EXCEPTION(s) throw HPROSE_EXCEPTION(s) 44 | #endif 45 | 46 | namespace hprose { 47 | 48 | class HproseException : public std::exception { 49 | public: 50 | 51 | #ifdef HPROSE_DEBUG_MODE 52 | HproseException(const std::string & message, const char * file, unsigned int line) throw() { 53 | std::ostringstream stream; 54 | stream << "[" << file << ":" << line << "] " << message; 55 | this->message = stream.str(); 56 | } 57 | #endif 58 | 59 | HproseException(const std::string & message) throw() 60 | : message(message) { 61 | } 62 | 63 | virtual ~HproseException() throw() { 64 | } 65 | 66 | virtual const char * what() const throw() { 67 | return message.c_str(); 68 | } 69 | 70 | private: 71 | 72 | std::string message; 73 | 74 | }; // class HproseException 75 | 76 | } // namespace hprose 77 | 78 | #endif // HPROSE_COMMON_HPROSE_EXCEPTION_HPP 79 | -------------------------------------------------------------------------------- /hprose/common/IntUtil.hpp: -------------------------------------------------------------------------------- 1 | /**********************************************************\ 2 | | | 3 | | hprose | 4 | | | 5 | | Official WebSite: http://www.hprose.com/ | 6 | | http://www.hprose.org/ | 7 | | | 8 | \**********************************************************/ 9 | 10 | /**********************************************************\ 11 | * * 12 | * IntUtil.hpp * 13 | * * 14 | * hprose int util unit for cpp. * 15 | * * 16 | * LastModified: Apr 27, 2015 * 17 | * Author: Chen fei * 18 | * * 19 | \**********************************************************/ 20 | 21 | #ifndef HPROSE_COMMON_INT_UTIL_HPP 22 | #define HPROSE_COMMON_INT_UTIL_HPP 23 | 24 | #if defined(_MSC_VER) && (_MSC_VER >= 1020) 25 | #pragma once 26 | #endif 27 | 28 | namespace hprose { 29 | 30 | typedef std::true_type SignedType; 31 | typedef std::false_type UnignedType; 32 | 33 | const std::size_t radix = 10; 34 | const std::size_t radixSqr = radix * radix; 35 | const std::size_t radixCube = radix * radix * radix; 36 | 37 | const unsigned char Digit3Table[] = { 38 | "000001002003004005006007008009010011012013014015016017018019020021022023024" 39 | "025026027028029030031032033034035036037038039040041042043044045046047048049" 40 | "050051052053054055056057058059060061062063064065066067068069070071072073074" 41 | "075076077078079080081082083084085086087088089090091092093094095096097098099" 42 | "100101102103104105106107108109110111112113114115116117118119120121122123124" 43 | "125126127128129130131132133134135136137138139140141142143144145146147148149" 44 | "150151152153154155156157158159160161162163164165166167168169170171172173174" 45 | "175176177178179180181182183184185186187188189190191192193194195196197198199" 46 | "200201202203204205206207208209210211212213214215216217218219220221222223224" 47 | "225226227228229230231232233234235236237238239240241242243244245246247248249" 48 | "250251252253254255256257258259260261262263264265266267268269270271272273274" 49 | "275276277278279280281282283284285286287288289290291292293294295296297298299" 50 | "300301302303304305306307308309310311312313314315316317318319320321322323324" 51 | "325326327328329330331332333334335336337338339340341342343344345346347348349" 52 | "350351352353354355356357358359360361362363364365366367368369370371372373374" 53 | "375376377378379380381382383384385386387388389390391392393394395396397398399" 54 | "400401402403404405406407408409410411412413414415416417418419420421422423424" 55 | "425426427428429430431432433434435436437438439440441442443444445446447448449" 56 | "450451452453454455456457458459460461462463464465466467468469470471472473474" 57 | "475476477478479480481482483484485486487488489490491492493494495496497498499" 58 | "500501502503504505506507508509510511512513514515516517518519520521522523524" 59 | "525526527528529530531532533534535536537538539540541542543544545546547548549" 60 | "550551552553554555556557558559560561562563564565566567568569570571572573574" 61 | "575576577578579580581582583584585586587588589590591592593594595596597598599" 62 | "600601602603604605606607608609610611612613614615616617618619620621622623624" 63 | "625626627628629630631632633634635636637638639640641642643644645646647648649" 64 | "650651652653654655656657658659660661662663664665666667668669670671672673674" 65 | "675676677678679680681682683684685686687688689690691692693694695696697698699" 66 | "700701702703704705706707708709710711712713714715716717718719720721722723724" 67 | "725726727728729730731732733734735736737738739740741742743744745746747748749" 68 | "750751752753754755756757758759760761762763764765766767768769770771772773774" 69 | "775776777778779780781782783784785786787788789790791792793794795796797798799" 70 | "800801802803804805806807808809810811812813814815816817818819820821822823824" 71 | "825826827828829830831832833834835836837838839840841842843844845846847848849" 72 | "850851852853854855856857858859860861862863864865866867868869870871872873874" 73 | "875876877878879880881882883884885886887888889890891892893894895896897898899" 74 | "900901902903904905906907908909910911912913914915916917918919920921922923924" 75 | "925926927928929930931932933934935936937938939940941942943944945946947948949" 76 | "950951952953954955956957958959960961962963964965966967968969970971972973974" 77 | "975976977978979980981982983984985986987988989990991992993994995996997998999" 78 | }; 79 | 80 | const unsigned char Digit2Table[] = { 81 | "0001020304050607080910111213141516171819" 82 | "2021222324252627282930313233343536373839" 83 | "4041424344454647484950515253545556575859" 84 | "6061626364656667686970717273747576777879" 85 | "8081828384858687888990919293949596979899" 86 | }; 87 | 88 | template 89 | struct UnsignedType {}; 90 | 91 | #define define_unsigned_type(Type,ReType) \ 92 | template <> \ 93 | struct UnsignedType \ 94 | { \ 95 | typedef ReType type; \ 96 | }; \ 97 | 98 | define_unsigned_type(char ,unsigned char ) 99 | define_unsigned_type(signed char,unsigned char ) 100 | define_unsigned_type(short ,unsigned short ) 101 | define_unsigned_type(int ,unsigned int ) 102 | define_unsigned_type(long ,unsigned long ) 103 | define_unsigned_type(long long ,unsigned long long) 104 | 105 | #undef define_unsigned_type 106 | 107 | template 108 | void WriteIntFast(T i, std::ostream & os, const SignedType &) { 109 | char buf[32]; 110 | bool negative = (i < 0); 111 | typedef BOOST_DEDUCED_TYPENAME UnsignedType::type TT; 112 | TT value = (negative) ? -i : i; 113 | 114 | char *itr = &buf[32]; 115 | if (value) { 116 | while (value >= static_cast(radixSqr)) { 117 | itr -= 3; 118 | T tempV = value / radixCube; 119 | memcpy(itr, &Digit3Table[3 * (value - (tempV * radixCube))], 3); 120 | value = tempV; 121 | } 122 | while (value >= static_cast(radix)) { 123 | itr -= 2; 124 | T tempV = value / radixSqr; 125 | memcpy(itr, &Digit2Table[2 * (value - (tempV * radixSqr))], 2); 126 | value = tempV; 127 | } 128 | if (value) { 129 | *(--itr) = static_cast('0' + value); 130 | } 131 | if (negative) { 132 | *(--itr) = '-'; 133 | } 134 | } else { 135 | *(--itr) = '0'; 136 | } 137 | os.write(itr, &buf[32] - itr); 138 | } 139 | 140 | template 141 | void WriteIntFast(T value, std::ostream & os, const UnignedType &) { 142 | char buf[32]; 143 | char *itr = &buf[32]; 144 | if (value) { 145 | while (value >= static_cast(radixSqr)) { 146 | itr -= 3; 147 | T tempV = value / radixCube; 148 | memcpy(itr, &Digit3Table[3 * (value - (tempV * radixCube))], 3); 149 | value = tempV; 150 | } 151 | while (value >= static_cast(radix)) { 152 | itr -= 2; 153 | T tempV = value / radixSqr; 154 | memcpy(itr, &Digit2Table[2 * (value - (tempV * radixSqr))], 2); 155 | value = tempV; 156 | } 157 | if (value) { 158 | *(--itr) = static_cast('0' + value); 159 | } 160 | } else { 161 | *(--itr) = '0'; 162 | } 163 | os.write(itr, &buf[32] - itr); 164 | } 165 | 166 | template 167 | inline void WriteIntFast(T i, std::ostream & os) { 168 | WriteIntFast(i, os, std::is_signed()); 169 | } 170 | 171 | } // namespace hprose 172 | 173 | #endif // HPROSE_COMMON_INT_UTIL_HPP 174 | -------------------------------------------------------------------------------- /hprose/common/UTF8Util.hpp: -------------------------------------------------------------------------------- 1 | /**********************************************************\ 2 | | | 3 | | hprose | 4 | | | 5 | | Official WebSite: http://www.hprose.com/ | 6 | | http://www.hprose.org/ | 7 | | | 8 | \**********************************************************/ 9 | 10 | /**********************************************************\ 11 | * * 12 | * UTF8Util.hpp * 13 | * * 14 | * hprose utf8 util unit for cpp. * 15 | * * 16 | * LastModified: Jun 15, 2014 * 17 | * Author: Chen fei * 18 | * * 19 | \**********************************************************/ 20 | 21 | #ifndef HPROSE_COMMON_UTF8_UTIL_HPP 22 | #define HPROSE_COMMON_UTF8_UTIL_HPP 23 | 24 | #if defined(_MSC_VER) && (_MSC_VER >= 1020) 25 | #pragma once 26 | #endif 27 | 28 | #include 29 | 30 | #ifdef BOOST_WINDOWS 31 | #ifndef _WINDOWS_ 32 | 33 | // Don't include winsock.h 34 | #ifndef _WINSOCKAPI_ 35 | #define _WINSOCKAPI_ 36 | #else 37 | #define _WINSOCKAPI_EXIST 38 | #endif 39 | 40 | #include 41 | 42 | #ifndef _WINSOCKAPI_EXIST 43 | #undef _WINSOCKAPI_ 44 | #endif 45 | 46 | #endif 47 | #endif 48 | 49 | namespace hprose { 50 | 51 | template 52 | struct CharSize { 53 | BOOST_STATIC_CONSTANT(int, value = v); 54 | }; 55 | 56 | typedef CharSize<1> Char8Type; 57 | typedef CharSize<2> Char16Type; 58 | typedef CharSize<4> Char32Type; 59 | 60 | inline bool is_ascii(char c) { return (c & 0x80) == 0x00; } 61 | 62 | inline bool is_inseq(char c) { return (c & 0xc0) == 0x80; } 63 | 64 | inline bool is_2byte(char c) { return (c & 0xe0) == 0xc0; } 65 | 66 | inline bool is_3byte(char c) { return (c & 0xf0) == 0xe0; } 67 | 68 | inline bool is_4byte(char c) { return (c & 0xf8) == 0xf0; } 69 | 70 | inline bool is_5byte(char c) { return (c & 0xFC) == 0xF8; } 71 | 72 | inline bool is_6byte(char c) { return (c & 0xFE) == 0xFC; } 73 | 74 | template 75 | size_t UTF8Size(InputIterator first, InputIterator last, Char16Type) { 76 | size_t len = 0; 77 | for (; first < last; ++first) { 78 | unsigned int c = *first; 79 | if (c < 0x80) { // U+0000 - U+007F 80 | len += 1; 81 | } else if (c < 0x0800) { // U+0100 - U+07FF 82 | len += 2; 83 | } else if (0xd800 != (0xf800 & c)) { // U+0800 - U+D7FF, U+E000 - U+FFFF 84 | len += 3; 85 | } else if (c < 0xdc00) { // U+D800 - U+DBFF 86 | ++first; 87 | if (first == last) { 88 | HPROSE_THROW_EXCEPTION("Surrogate pair split between fragments"); 89 | } 90 | c = *first; 91 | if (0xdc00 == (0xfc00 & c)) { 92 | len += 4; 93 | } else { 94 | HPROSE_THROW_EXCEPTION("Got a high Surrogate but no low surrogate"); 95 | } 96 | } else { // U+DC00 - U+DFFF 97 | HPROSE_THROW_EXCEPTION("got a low Surrogate but no high surrogate"); 98 | } 99 | } 100 | return len; 101 | } 102 | 103 | template 104 | size_t UTF8Size(InputIterator first, InputIterator last, Char32Type) { 105 | size_t len = 0; 106 | for (; first < last; ++first) { 107 | unsigned int c = *first; 108 | if (c < 0x80) { // U+0000 - U+007F 109 | len += 1; 110 | } else if (c < 0x0800) { // U+0100 - U+07FF 111 | len += 2; 112 | } else if (c < 0xd800) { // U+0800 - U+D7FF 113 | len += 3; 114 | } else if (c < 0xe000) { // U+D800 - U+DFFF 115 | HPROSE_THROW_EXCEPTION("Surrogate values are illegal"); 116 | } else if (c < 0x10000) { // U+E000 - U+FFFF 117 | len += 3; 118 | } else if (c < 0x0010ffff) { 119 | len += 4; 120 | } else { 121 | HPROSE_THROW_EXCEPTION("Not a UTF-32 string"); 122 | } 123 | } 124 | return len; 125 | } 126 | 127 | template 128 | inline size_t UTF8Size(const std::basic_string & data) { 129 | HPROSE_STATIC_ASSERT((sizeof(Element) == 2) || (sizeof(Element) == 4), "Require Unicode String"); 130 | return UTF8Size(data.begin(), data.end(), CharSize()); 131 | } 132 | 133 | template 134 | size_t UTF8Length(InputIterator first, InputIterator last, Char16Type) { 135 | size_t len = 0; 136 | for (; first < last; ++len) { 137 | if (is_ascii(*first)) { 138 | first += 1; 139 | } else if (is_2byte(*first)) { 140 | first+= 2; 141 | } else if (is_3byte(*first)) { 142 | first += 3; 143 | } else if (is_4byte(*first)) { 144 | first += 4; 145 | ++len; 146 | } else if (is_5byte(*first)) { 147 | first += 5; 148 | } else if (is_6byte(*first)) { 149 | first += 6; 150 | } else { 151 | break; 152 | } 153 | } 154 | if (first != last) { 155 | HPROSE_THROW_EXCEPTION("Not a UTF-8 string"); 156 | } 157 | return len; 158 | } 159 | 160 | template 161 | size_t UTF8Length(InputIterator first, InputIterator last, Char32Type) { 162 | size_t len = 0; 163 | for (; first < last; ++len) { 164 | if (is_ascii(*first)) { 165 | first += 1; 166 | } else if (is_2byte(*first)) { 167 | first+= 2; 168 | } else if (is_3byte(*first)) { 169 | first += 3; 170 | } else if (is_4byte(*first)) { 171 | first += 4; 172 | } else if (is_5byte(*first)) { 173 | first += 5; 174 | } else if (is_6byte(*first)) { 175 | first += 6; 176 | } else { 177 | break; 178 | } 179 | } 180 | if (first != last) { 181 | HPROSE_THROW_EXCEPTION("Not a UTF-8 string"); 182 | } 183 | return len; 184 | } 185 | 186 | template 187 | inline size_t UTF8Encode(ValueType c, OutputIterator dest, Char16Type) { 188 | OutputIterator start = dest; 189 | if (c < 0x80) // U+0000 - U+007F 190 | { 191 | *dest++ = (char)c; 192 | } else if (c < 0x0800) // U+0100 - U+07FF 193 | { 194 | *dest++ = 0xc0 | (char)(c >> 6); 195 | *dest++ = 0x80 | (char)(c & 0x3f); 196 | } else if (0xd800 != (0xf800 & c)) // U+0800 - U+D7FF, U+E000 - U+FFFF 197 | { 198 | *dest++ = 0xe0 | (char)(c >> 12); 199 | *dest++ = 0x80 | (char)(0x3f & (c >> 6)); 200 | *dest++ = 0x80 | (char)(0x3f & c); 201 | } 202 | return dest - start; 203 | } 204 | 205 | template 206 | inline size_t UTF8Encode(ValueType c, OutputIterator dest, Char32Type) { 207 | OutputIterator start = dest; 208 | if (c < 0x80) { // U+0000 - U+007F 209 | *dest++ = (char)c; 210 | } else if (c < 0x0800) { // U+0100 - U+07FF 211 | *dest++ = 0xc0 | (char)(c >> 6); 212 | *dest++ = 0x80 | (char)(c & 0x3f); 213 | } else if (c < 0xd800 || (c >= 0xe000 && c <=0xffff)) { // U+0800 - U+D7FF, U+E000 - U+FFFF 214 | *dest++ = 0xe0 | (char)(c >> 12); 215 | *dest++ = 0x80 | (char)(0x3f & (c >> 6)); 216 | *dest++ = 0x80 | (char)(0x3f & c); 217 | } else if (c > 0xffff && c < 0x0010ffff) { // 0001 0000-001F FFFF 218 | *dest++ = 0xf0 | (char)(c >> 18); 219 | *dest++ = 0x80 | (char)(0x3f & (c >> 12)); 220 | *dest++ = 0x80 | (char)(0x3f & (c >> 6)); 221 | *dest++ = 0x80 | (char)(0x3f & c); 222 | } 223 | return dest - start; 224 | } 225 | 226 | template 227 | void UTF8Encode(InputIterator first, InputIterator last, OutputIterator dest, Char16Type) { 228 | while (first != last) { 229 | unsigned int c = *first++; 230 | if (size_t len = UTF8Encode(c, dest, Char16Type())) { 231 | dest += len; 232 | continue; 233 | } 234 | if (c < 0xdc00) { // U+D800 - U+DBFF 235 | if (first != last) { 236 | unsigned int ucs4 = 0x10000 + ((0x03ff & c) << 10); 237 | c = *first++; 238 | if (0xdc00 == (0xfc00 & c)) { // 0001 0000-001F FFFF 239 | ucs4 |= (0x03ff & c); 240 | *dest++ = 0xf0 | (char)(ucs4 >> 18); 241 | *dest++ = 0x80 | (char)(0x3f & (ucs4 >> 12)); 242 | *dest++ = 0x80 | (char)(0x3f & (ucs4 >> 6)); 243 | *dest++ = 0x80 | (char)(0x3f & ucs4); 244 | } else { 245 | HPROSE_THROW_EXCEPTION("Got a high surrogate but no low surrogate"); 246 | } 247 | } else { 248 | HPROSE_THROW_EXCEPTION("Surrogate pair split between fragments"); 249 | } 250 | } else { // U+DC00 - U+DFFF 251 | HPROSE_THROW_EXCEPTION("Got a low surrogate but no high surrogate"); 252 | } 253 | } 254 | } 255 | 256 | template 257 | void UTF8Encode(InputIterator first, InputIterator last, OutputIterator dest, Char32Type) { 258 | while (first != last) { 259 | unsigned int c = *first++; 260 | if (size_t len = UTF8Encode(c, dest, Char32Type())) { 261 | dest += len; 262 | continue; 263 | } 264 | if (c >= 0xd800 && c <= 0xdfff) { // U+D800 - U+DFFF 265 | HPROSE_THROW_EXCEPTION("Surrogate values are illegal"); 266 | } else { 267 | HPROSE_THROW_EXCEPTION("Not a UTF-32 string"); 268 | } 269 | } 270 | } 271 | 272 | template 273 | inline std::string UTF8Encode(const std::basic_string & data) { 274 | HPROSE_STATIC_ASSERT((sizeof(Element) == 2) || (sizeof(Element) == 4), "Require Unicode String"); 275 | std::string ret; 276 | ret.resize(UTF8Size(data)); 277 | UTF8Encode(data.begin(), data.end(), ret.begin(), CharSize()); 278 | return ret; 279 | } 280 | 281 | template 282 | unsigned short UTF8Decode(InputIterator & first, Char16Type) { 283 | char c = *first++; 284 | if (is_ascii(c)) { 285 | return c; 286 | } 287 | unsigned int ucs4, min_ucs4; 288 | unsigned int state = 0; 289 | if (is_2byte(c)) { 290 | ucs4 = ((unsigned int)c << 6) & 0x000007c0L; 291 | state = 1; 292 | min_ucs4 = 0x00000080; 293 | } else if (is_3byte(c)) { 294 | ucs4 = ((unsigned int)c << 12) & 0x0000f000L; 295 | state = 2; 296 | min_ucs4 = 0x00000800; 297 | } else if (is_4byte(c)) { 298 | ucs4 = ((unsigned int)c << 18) & 0x001f0000L; 299 | state = 3; 300 | min_ucs4 = 0x00010000; 301 | } else if (is_5byte(c)) { 302 | ucs4 = ((unsigned int)c << 24) & 0x03000000L; 303 | state = 4; 304 | min_ucs4 = 0x00200000; 305 | } else if (is_6byte(c)) { 306 | ucs4 = ((unsigned int)c << 30) & 0x40000000L; 307 | state = 5; 308 | min_ucs4 = 0x04000000; 309 | } else { 310 | HPROSE_THROW_EXCEPTION("Not a UTF-8 char"); 311 | } 312 | while (state--) { 313 | c = *first++; 314 | if (is_inseq(c)) { 315 | unsigned int shift = state * 6; 316 | ucs4 |= ((unsigned int)c & 0x3f) << shift; 317 | } else { 318 | HPROSE_THROW_EXCEPTION("Not a UTF-8 char"); 319 | } 320 | } 321 | if (ucs4 < min_ucs4) { 322 | return 0xfffd; 323 | } else if (ucs4 <= 0xd7ff) { 324 | return ucs4; 325 | } else if (ucs4 <= 0xdfff) { 326 | return 0xfffd; 327 | } else if (ucs4 == 0xfffe || ucs4 == 0xffff) { 328 | return 0xfffd; 329 | } else if (ucs4 >= 0x00010000) { 330 | return 0xfffd; 331 | } else { 332 | return ucs4; 333 | } 334 | } 335 | 336 | template 337 | unsigned int UTF8Decode(InputIterator & first, Char32Type) { 338 | char c = *first++; 339 | if (is_ascii(c)) { 340 | return c; 341 | } 342 | unsigned int ucs4, min_ucs4; 343 | unsigned int state = 0; 344 | if (is_2byte(c)) { 345 | ucs4 = ((unsigned int)c << 6) & 0x000007c0L; 346 | state = 1; 347 | min_ucs4 = 0x00000080; 348 | } else if (is_3byte(c)) { 349 | ucs4 = ((unsigned int)c << 12) & 0x0000f000L; 350 | state = 2; 351 | min_ucs4 = 0x00000800; 352 | } else if (is_4byte(c)) { 353 | ucs4 = ((unsigned int)c << 18) & 0x001f0000L; 354 | state = 3; 355 | min_ucs4 = 0x00010000; 356 | } else if (is_5byte(c)) { 357 | ucs4 = ((unsigned int)c << 24) & 0x03000000L; 358 | state = 4; 359 | min_ucs4 = 0x00200000; 360 | } else if (is_6byte(c)) { 361 | ucs4 = ((unsigned int)c << 30) & 0x40000000L; 362 | state = 5; 363 | min_ucs4 = 0x04000000; 364 | } else { 365 | HPROSE_THROW_EXCEPTION("Not a UTF-8 char"); 366 | } 367 | while (state--) { 368 | c = *first++; 369 | if (is_inseq(c)) { 370 | unsigned int shift = state * 6; 371 | ucs4 |= ((unsigned int)c & 0x3f) << shift; 372 | } else { 373 | HPROSE_THROW_EXCEPTION("Not a UTF-8 char"); 374 | } 375 | } 376 | if (ucs4 < min_ucs4) { 377 | return 0xfffd; 378 | } else if (ucs4 <= 0xd7ff) { 379 | return ucs4; 380 | } else if (ucs4 <= 0xdfff) { 381 | return 0xfffd; 382 | } else if (ucs4 == 0xfffe || ucs4 == 0xffff) { 383 | return 0xfffd; 384 | } else if (ucs4 >= 0x00110000) { 385 | return 0xfffd; 386 | } else { 387 | return ucs4; 388 | } 389 | } 390 | 391 | template 392 | void UTF8Decode(InputIterator first, InputIterator last, OutputIterator dest, Char16Type) { 393 | while (first != last) { 394 | char c = *first++; 395 | if (is_ascii(c)) { 396 | *dest++ = c; 397 | continue; 398 | } 399 | unsigned int ucs4, min_ucs4; 400 | unsigned int state = 0; 401 | if (is_2byte(c)) { 402 | ucs4 = ((unsigned int)c << 6) & 0x000007c0L; 403 | state = 1; 404 | min_ucs4 = 0x00000080; 405 | } else if (is_3byte(c)) { 406 | ucs4 = ((unsigned int)c << 12) & 0x0000f000L; 407 | state = 2; 408 | min_ucs4 = 0x00000800; 409 | } else if (is_4byte(c)) { 410 | ucs4 = ((unsigned int)c << 18) & 0x001f0000L; 411 | state = 3; 412 | min_ucs4 = 0x00010000; 413 | } else if (is_5byte(c)) { 414 | ucs4 = ((unsigned int)c << 24) & 0x03000000L; 415 | state = 4; 416 | min_ucs4 = 0x00200000; 417 | } else if (is_6byte(c)) { 418 | ucs4 = ((unsigned int)c << 30) & 0x40000000L; 419 | state = 5; 420 | min_ucs4 = 0x04000000; 421 | } else { 422 | HPROSE_THROW_EXCEPTION("Not a UTF-8 char"); 423 | } 424 | while (state--) { 425 | c = *first++; 426 | if (is_inseq(c)) { 427 | unsigned int shift = state * 6; 428 | ucs4 |= ((unsigned int)c & 0x3f) << shift; 429 | } else { 430 | HPROSE_THROW_EXCEPTION("Not a UTF-8 char"); 431 | } 432 | } 433 | if (ucs4 < min_ucs4) { 434 | *dest++ = 0xfffd; 435 | } else if (ucs4 <= 0xd7ff) { 436 | *dest++ = ucs4; 437 | } else if (ucs4 <= 0xdfff) { 438 | *dest++ = 0xfffd; 439 | } else if (ucs4 == 0xfffe || ucs4 == 0xffff) { 440 | *dest++ = 0xfffd; 441 | } else if (ucs4 >= 0x00010000) { 442 | if (ucs4 >= 0x00110000) { 443 | *dest++ = 0xfffd; 444 | } else { 445 | ucs4 -= 0x00010000; 446 | *dest++ = (ucs4 >> 10) | 0xd800u; 447 | *dest++ = (ucs4 & 0x3ff) | 0xdc00u; 448 | } 449 | } else { 450 | *dest++ = ucs4; 451 | } 452 | } 453 | } 454 | 455 | template 456 | inline void UTF8Decode(InputIterator first, InputIterator last, OutputIterator dest, Char32Type) { 457 | while (first != last) { 458 | *dest++ = UTF8Decode(first, Char32Type()); 459 | } 460 | } 461 | 462 | template 463 | inline size_t UTF16Size(InputIterator first, InputIterator last, Char16Type) { 464 | return last - first; 465 | } 466 | 467 | template 468 | inline size_t UTF16Size(InputIterator first, InputIterator last, Char32Type) { 469 | size_t size = 0; 470 | for (; first < last; ++size, ++first) { 471 | if (*first >= 0x10000 && *first < 0x110000) { 472 | ++size; 473 | } 474 | } 475 | return size; 476 | } 477 | 478 | template 479 | inline size_t UTF16Size(const std::basic_string & data) { 480 | HPROSE_STATIC_ASSERT((sizeof(Element) == 2) || (sizeof(Element) == 4), "Require Unicode String"); 481 | return UTF16Size(data.begin(), data.end(), CharSize()); 482 | } 483 | 484 | #ifdef BOOST_WINDOWS 485 | inline wchar_t * AnsiToUnicode(const char * src, size_t src_len, wchar_t * dest) { 486 | if (!dest) { 487 | dest = (wchar_t *)calloc(src_len, sizeof(wchar_t)); 488 | } 489 | if (dest) { 490 | MultiByteToWideChar(CP_ACP, 0, src, (int)src_len, dest, (int)src_len); 491 | } 492 | return dest; 493 | } 494 | 495 | inline char * UnicodeToAnsi(const wchar_t * src, size_t src_len, char * dest) { 496 | if (!dest) { 497 | dest = (char *)calloc(src_len * 2, sizeof(char)); 498 | } 499 | if (dest) { 500 | WideCharToMultiByte(CP_ACP, 0, src, -1, dest, (int)src_len * 2, NULL, NULL); 501 | } 502 | return dest; 503 | } 504 | 505 | inline std::wstring AnsiToUnicode(const std::string & data) { 506 | if (data.empty()) { 507 | return L""; 508 | } 509 | wchar_t buf[256]; 510 | size_t len = data.size() + 1; 511 | wchar_t * s = AnsiToUnicode(data.c_str(), len, (len > 256) ? 0 : buf); 512 | std::wstring ret(s); 513 | if (s != buf) { 514 | free(s); 515 | }; 516 | return ret; 517 | } 518 | 519 | inline std::string UnicodeToAnsi(const std::wstring & data) { 520 | if (data.empty()) { 521 | return ""; 522 | } 523 | char buf[512]; 524 | size_t len = data.size() + 1; 525 | char * s = UnicodeToAnsi(data.c_str(), len, (len > 256) ? 0 : buf); 526 | std::string ret(s); 527 | if (s != buf) { 528 | free(s); 529 | }; 530 | return ret; 531 | } 532 | 533 | inline wchar_t AnsiToUnicode(char c) { 534 | wchar_t ret[2]; 535 | AnsiToUnicode(&c, 1, ret); 536 | return ret[0]; 537 | } 538 | 539 | inline char UnicodeToAnsi(wchar_t c) { 540 | char ret[3]; 541 | UnicodeToAnsi(&c, 1, ret); 542 | return ret[0]; 543 | } 544 | #endif 545 | 546 | } // namespace hprose 547 | 548 | #endif // HPROSE_COMMON_UTF8_UTIL_HPP 549 | -------------------------------------------------------------------------------- /hprose/config.hpp: -------------------------------------------------------------------------------- 1 | /**********************************************************\ 2 | | | 3 | | hprose | 4 | | | 5 | | Official WebSite: http://www.hprose.com/ | 6 | | http://www.hprose.org/ | 7 | | | 8 | \**********************************************************/ 9 | 10 | /**********************************************************\ 11 | * * 12 | * config.hpp * 13 | * * 14 | * hprose config unit for cpp. * 15 | * * 16 | * LastModified: Jun 15, 2014 * 17 | * Author: Chen fei * 18 | * * 19 | \**********************************************************/ 20 | 21 | #ifndef HPROSE_CONFIG_HPP 22 | #define HPROSE_CONFIG_HPP 23 | 24 | #if defined(_MSC_VER) && (_MSC_VER >= 1020) 25 | #pragma once 26 | #endif 27 | 28 | #include 29 | #include 30 | 31 | #include 32 | #include 33 | #include 34 | #include 35 | 36 | #include 37 | #include 38 | 39 | //#include 40 | 41 | #define BOOST_MAJOR_VERSION (BOOST_VERSION / 100000) 42 | #define BOOST_MINOR_VERSION (BOOST_VERSION / 100 % 1000) 43 | 44 | #if BOOST_MAJOR_VERSION == 1 45 | # if BOOST_MINOR_VERSION < 36 46 | # error Boost version requires >= 1.36 // Asio requires >= 1.35, Unordered requires >= 1.36 47 | # elif BOOST_MINOR_VERSION < 44 48 | # if BOOST_MINOR_VERSION < 40 49 | # define BOOST_NO_AUTO_DECLARATIONS 50 | # define BOOST_NO_LAMBDAS 51 | # define BOOST_NO_NULLPTR 52 | # endif 53 | # if BOOST_MINOR_VERSION < 38 54 | # define BOOST_NO_INITIALIZER_LISTS 55 | # endif 56 | # ifndef BOOST_NO_STATIC_ASSERT 57 | # ifndef BOOST_HAS_STATIC_ASSERT 58 | # define BOOST_HAS_STATIC_ASSERT // Used in BOOST_STATIC_ASSERT 59 | # endif 60 | # endif 61 | # endif 62 | #endif 63 | 64 | #ifndef BOOST_NO_CXX11_HDR_ARRAY 65 | #ifdef BOOST_NO_0X_HDR_ARRAY 66 | #define BOOST_NO_CXX11_HDR_ARRAY 67 | #endif 68 | #endif 69 | 70 | #ifndef BOOST_NO_CXX11_CHAR16_T 71 | #ifdef BOOST_NO_CHAR16_T 72 | #define BOOST_NO_CXX11_CHAR16_T 73 | #endif 74 | #endif 75 | 76 | #ifndef BOOST_NO_CXX11_CHAR32_T 77 | #ifdef BOOST_NO_CHAR32_T 78 | #define BOOST_NO_CXX11_CHAR32_T 79 | #endif 80 | #endif 81 | 82 | #ifndef BOOST_NO_CXX11_NULLPTR 83 | #ifdef BOOST_NO_NULLPTR 84 | #define BOOST_NO_CXX11_NULLPTR 85 | #endif 86 | #endif 87 | 88 | #ifndef BOOST_NO_CXX11_VARIADIC_TEMPLATES 89 | #ifdef BOOST_NO_VARIADIC_TEMPLATES 90 | #define BOOST_NO_CXX11_VARIADIC_TEMPLATES 91 | #endif 92 | #endif 93 | 94 | #ifndef BOOST_NO_CXX11_VARIADIC_MACROS 95 | #ifdef BOOST_NO_VARIADIC_MACROS 96 | #define BOOST_NO_CXX11_VARIADIC_MACROS 97 | #endif 98 | #endif 99 | 100 | #define HPROSE_NO_UNIQUE_PTR 101 | 102 | #if defined(_MSC_VER) && (_MSC_VER >= 1600) // decltype supported by vc2010 103 | # ifdef BOOST_NO_DECLTYPE 104 | # undef BOOST_NO_DECLTYPE 105 | # endif 106 | # ifdef BOOST_NO_NULLPTR 107 | # undef BOOST_NO_NULLPTR 108 | # endif 109 | # undef HPROSE_NO_UNIQUE_PTR 110 | #endif 111 | 112 | #if (__GNUC__ == 4 && __GNUC_MINOR__ >= 4) && defined(__GXX_EXPERIMENTAL_CXX0X__) 113 | #undef HPROSE_NO_UNIQUE_PTR 114 | #endif 115 | 116 | #if defined(_MSC_VER) && defined(_DEBUG) 117 | #define HPROSE_DEBUG_MODE 118 | #elif defined(__BORLANDC__) && (__BORLANDC__ > 0x561) 119 | #pragma defineonoption HPROSE_DEBUG_MODE -v 120 | #endif 121 | 122 | #include 123 | 124 | #ifndef BOOST_NO_STATIC_ASSERT 125 | #define HPROSE_STATIC_ASSERT(Exp, Msg) static_assert(Exp, Msg) 126 | #else 127 | #define HPROSE_STATIC_ASSERT(Exp, Msg) BOOST_STATIC_ASSERT(Exp) 128 | #endif 129 | 130 | #ifdef BOOST_WINDOWS 131 | # ifdef __BORLANDC__ 132 | # define _strcmpi strcmpi 133 | # define timezone _timezone 134 | # endif 135 | #else 136 | # define _strcmpi strcasecmp 137 | # define _tzset tzset 138 | #endif 139 | 140 | #define HPROSE_STATIC_MEMBER(Type, Name) Type & Get##Name() { static Type Name; return Name; } 141 | 142 | #endif // HPROSE_CONFIG_HPP 143 | -------------------------------------------------------------------------------- /hprose/ext/BigInteger.hpp: -------------------------------------------------------------------------------- 1 | /**********************************************************\ 2 | | | 3 | | hprose | 4 | | | 5 | | Official WebSite: http://www.hprose.com/ | 6 | | http://www.hprose.net/ | 7 | | http://www.hprose.org/ | 8 | | | 9 | \**********************************************************/ 10 | 11 | /**********************************************************\ 12 | * * 13 | * BigInteger.hpp * 14 | * * 15 | * hprose big integer unit for cpp. * 16 | * * 17 | * LastModified: May 26, 2014 * 18 | * Author: Chen fei * 19 | * * 20 | \**********************************************************/ 21 | 22 | #ifndef HPROSE_COMMON_BIGINTEGER_HPP 23 | #define HPROSE_COMMON_BIGINTEGER_HPP 24 | 25 | #if defined(_MSC_VER) && (_MSC_VER >= 1020) 26 | #pragma once 27 | #endif 28 | 29 | #include 30 | 31 | namespace hprose { 32 | 33 | class BigInteger { 34 | public: // structors 35 | 36 | BigInteger() { 37 | } 38 | 39 | BigInteger(const unsigned int x) { 40 | data.push_back(x); 41 | } 42 | 43 | BigInteger(const std::string & s) { 44 | data.push_back(0); 45 | unsigned int i; 46 | for (i = 0; i < s.size(); i++) { 47 | if (!isdigit(s[i])) { 48 | HPROSE_THROW_EXCEPTION("string contains non-decimal digit"); 49 | } 50 | } 51 | std::string dec("0123456789"); 52 | for (i = 0; i < s.size(); i++) { 53 | *this = (*this) * 10; 54 | BigInteger t((unsigned int)dec.find(s[i])); 55 | *this = (*this) + t; 56 | } 57 | } 58 | 59 | BigInteger(const BigInteger & x) { 60 | data = x.data; 61 | } 62 | 63 | public: 64 | 65 | static BigInteger divide(BigInteger dividend, BigInteger divisor, BigInteger * rem) { 66 | BigInteger zero(0); 67 | int count = 0; 68 | if (divisor == zero) { 69 | HPROSE_THROW_EXCEPTION("divisor == zero"); 70 | } 71 | BigInteger quot(0); 72 | quot.resize(dividend.length()); 73 | if (rem) rem->resize(dividend.length()); 74 | while (divisor < dividend) { 75 | divisor <<= 1; 76 | count++; 77 | } 78 | if (divisor > dividend) { 79 | divisor >>= 1; 80 | count--; 81 | } 82 | if (count >= 0) { 83 | for(int i = 0; i <= count; i++) { 84 | if (divisor <= dividend) { 85 | dividend -= divisor; 86 | divisor >>= 1; 87 | quot <<= 1; 88 | quot++; 89 | } else { 90 | divisor >>= 1; 91 | quot <<= 1; 92 | } 93 | } 94 | } 95 | if (rem) { 96 | *rem = dividend; 97 | rem->fixlen(); 98 | } 99 | quot.fixlen(); 100 | return quot; 101 | } 102 | 103 | static BigInteger powmod(BigInteger x, BigInteger y, BigInteger z) { 104 | BigInteger r(1); 105 | unsigned int tmp; 106 | size_t n = y.length(); 107 | for (unsigned int i = 0; i < n - 1; i++) { 108 | tmp = y.data[i]; 109 | 110 | for (unsigned int j = 0; j < 16; j++) { 111 | if (tmp & 1) r = r * x % z; 112 | tmp >>= 1; 113 | x = x * x % z; 114 | } 115 | } 116 | tmp = y.data[n - 1]; 117 | while (tmp) { 118 | if (tmp & 1) r = r * x % z; 119 | tmp >>= 1; 120 | x = x * x % z; 121 | } 122 | return r; 123 | } 124 | 125 | public: 126 | 127 | std::string to_bin() const { 128 | std::string retval; 129 | size_t n = length(); 130 | retval.resize(n * 4); 131 | for (unsigned int i = 0; i < n; i++) { 132 | retval[(n - i) * 4 - 1] = (char)(data[i] & 0xff); 133 | retval[(n - i) * 4 - 2] = (char)((data[i] >> 8) & 0xff); 134 | retval[(n - i) * 4 - 3] = (char)((data[i] >> 16) & 0xff); 135 | retval[(n - i - 1) * 4] = (char)((data[i] >> 24) & 0xff); 136 | } 137 | return retval; 138 | } 139 | 140 | std::string to_string() const { 141 | std::string retval; 142 | BigInteger zero(0), one(1); 143 | if (*this == zero) { 144 | retval = "0"; 145 | } else if (*this == one) { 146 | retval = "1"; 147 | } else { 148 | std::string dec("0123456789"); 149 | BigInteger t(*this); 150 | BigInteger r; 151 | while (t != zero) { 152 | t = divide(t, BigInteger(10), &r); 153 | retval.insert(retval.begin(), dec[r.data[0]]); 154 | } 155 | } 156 | return retval; 157 | } 158 | 159 | friend std::ostream & operator<<(std::ostream & os, const BigInteger & x) { 160 | return os << x.to_string(); 161 | } 162 | 163 | public: // operators 164 | 165 | bool operator<(const BigInteger & x) const { 166 | if (length() < x.length()) return true; 167 | if (x.length() < length()) return false; 168 | for (size_t i = length() - 1; i > 0; i--) { 169 | if (data[i] < x.data[i]) return true; 170 | if (x.data[i] < data[i]) return false; 171 | } 172 | return (data[0] < x.data[0]); 173 | } 174 | 175 | bool operator<=(const BigInteger & x) const { 176 | return (*this < x) || (*this == x); 177 | } 178 | 179 | bool operator>(const BigInteger & x) const { 180 | return !(*this <= x); 181 | } 182 | 183 | bool operator>=(const BigInteger & x) const { 184 | return !(*this < x); 185 | } 186 | 187 | bool operator==(const BigInteger & x) const { 188 | return !((*this < x) || (x < *this)); 189 | } 190 | 191 | bool operator!=(const BigInteger & x) const { 192 | return !(*this == x); 193 | } 194 | 195 | BigInteger operator+(BigInteger & x) { 196 | BigInteger r; 197 | unsigned int carry = 0; 198 | const size_t & max_size = std::max(length(), x.length()); 199 | resize(max_size + 1); 200 | x.resize(max_size + 1); 201 | r.resize(max_size + 1); 202 | for (unsigned int i = 0; i < length(); i++) { 203 | r.data[i] = data[i] + x.data[i] + carry; 204 | if (carry == 0) { 205 | carry = ((r.data[i] < data[i] || r.data[i] < x.data[i]) ? 1 : 0); 206 | } else { 207 | carry = ((r.data[i] <= data[i] || r.data[i] <= x.data[i]) ? 1 : 0); 208 | } 209 | } 210 | fixlen(); 211 | x.fixlen(); 212 | r.fixlen(); 213 | return r; 214 | } 215 | 216 | BigInteger operator+(unsigned int i) { 217 | BigInteger t(i); 218 | return *this + t; 219 | } 220 | 221 | BigInteger & operator+=(BigInteger & x) { 222 | unsigned int carry = 0; 223 | unsigned int prevdigit; 224 | const size_t & max_size = std::max(length(), x.length()); 225 | resize(max_size + 1); 226 | x.resize(max_size + 1); 227 | for (unsigned int i = 0; i < length(); i++) { 228 | prevdigit = data[i]; 229 | data[i] = data[i] + x.data[i] + carry; 230 | if (carry == 0) { 231 | carry = ((data[i] < prevdigit || data[i] < x.data[i]) ? 1 : 0); 232 | } else { 233 | carry = ((data[i] <= prevdigit || data[i] <=x.data[i]) ? 1 : 0); 234 | } 235 | } 236 | fixlen(); 237 | x.fixlen(); 238 | return *this; 239 | } 240 | 241 | BigInteger & operator++() { 242 | data.push_back(0); 243 | data.front()++; 244 | for (unsigned int i = 1; i < length(); i++) { 245 | if (data[i-1]) break; 246 | data[i]++; 247 | } 248 | fixlen(); 249 | return *this; 250 | } 251 | 252 | BigInteger operator++(int) { 253 | BigInteger t(*this); 254 | ++*this; 255 | return t; 256 | } 257 | 258 | BigInteger operator-(BigInteger & x) { 259 | BigInteger r(0); 260 | unsigned int borrow = 0; 261 | const size_t & max_size = std::max(length(), x.length()); 262 | resize(max_size + 1); 263 | x.resize(max_size + 1); 264 | r.resize(max_size + 1); 265 | if (*this < x) { 266 | HPROSE_THROW_EXCEPTION("minuend < subtracter"); 267 | } 268 | for (unsigned int i = 0; i < length(); i++) { 269 | r.data[i] = data[i] - x.data[i] - borrow; 270 | 271 | if (borrow == 0) { 272 | borrow = (data[i] < x.data[i]) ? 1 : 0; 273 | } else { 274 | borrow = (data[i] <= x.data[i]) ? 1 : 0; 275 | } 276 | } 277 | fixlen(); 278 | x.fixlen(); 279 | r.fixlen(); 280 | return r; 281 | } 282 | 283 | BigInteger & operator-=(BigInteger & x) { 284 | unsigned int borrow = 0; 285 | unsigned int prevdigit; 286 | const size_t & max_size = std::max(length(), x.length()); 287 | resize(max_size + 1); 288 | x.resize(max_size + 1); 289 | if (*this < x) { 290 | HPROSE_THROW_EXCEPTION("minuend < subtracter"); 291 | } 292 | for (unsigned int i = 0; i < length(); i++) { 293 | prevdigit = data[i]; 294 | data[i] = data[i] - x.data[i] - borrow; 295 | 296 | if (borrow == 0) { 297 | borrow = (prevdigit < x.data[i]) ? 1 : 0; 298 | } else { 299 | borrow = (prevdigit <= x.data[i]) ? 1 : 0; 300 | } 301 | } 302 | fixlen(); 303 | x.fixlen(); 304 | return *this; 305 | } 306 | 307 | BigInteger & operator--() { 308 | data.front()--; 309 | for (unsigned int i = 1; i < length(); i++) { 310 | if (data[i-1] != 0x80000000) break; 311 | data[i]--; 312 | } 313 | fixlen(); 314 | return *this; 315 | } 316 | 317 | BigInteger operator--(int) { 318 | BigInteger t(*this); 319 | --*this; 320 | return t; 321 | } 322 | 323 | BigInteger operator*(BigInteger x) const { 324 | BigInteger t(*this); 325 | BigInteger r(0), zero(0); 326 | do { 327 | if ((x.data.front() & 1) != 0) r += t; 328 | x >>= 1; 329 | t <<= 1; 330 | } while (x != zero); 331 | r.fixlen(); 332 | return r; 333 | } 334 | 335 | BigInteger operator*(unsigned int i) const { 336 | return (*this) * BigInteger(i); 337 | } 338 | 339 | BigInteger operator/(const BigInteger & x) const { 340 | return divide(*this, x, NULL); 341 | } 342 | 343 | BigInteger operator%(const BigInteger & x) const { 344 | BigInteger r; 345 | divide(*this, x, &r); 346 | return r; 347 | } 348 | 349 | BigInteger & operator>>=(unsigned int bit) { 350 | unsigned int carry; 351 | data.push_back(0); 352 | for (unsigned int i = 0; i < bit; i++) { 353 | carry = data.back() & 1; 354 | data.back() >>= 1; 355 | for (int j = (int)length() - 1; j >= 0; j--) { 356 | if (carry) { 357 | carry = data[j] & 1; 358 | data[j] >>= 1; 359 | data[j] |= 0x80000000; 360 | } else { 361 | carry = data[j] & 1; 362 | data[j] >>= 1; 363 | } 364 | } 365 | } 366 | fixlen(); 367 | return *this; 368 | } 369 | 370 | BigInteger & operator<<=(unsigned int bit) { 371 | unsigned int carry; 372 | unsigned int push_back_size = bit/32 + 1; 373 | unsigned int i; 374 | for (i = 0; i < push_back_size + 1; i++) { 375 | data.push_back(0); 376 | } 377 | for (i = 0; i < bit; i++) { 378 | carry = data.front() & 0x80000000; 379 | data.front() <<= 1; 380 | for (unsigned int j = 1; j < length(); j++) { 381 | if (carry) { 382 | carry = data[j] & 0x80000000; 383 | data[j] <<= 1; 384 | data[j] |= 1; 385 | } else { 386 | carry = data[j] & 0x80000000; 387 | data[j] <<= 1; 388 | } 389 | } 390 | } 391 | fixlen(); 392 | return *this; 393 | } 394 | 395 | private: 396 | 397 | inline bool empty() const { 398 | return data.empty(); 399 | } 400 | 401 | inline size_t length() const { 402 | return data.size(); 403 | } 404 | 405 | inline void resize(size_t size) { 406 | data.resize(size); 407 | } 408 | 409 | void fixlen() { 410 | while ((data.size() > 1) && (data.back() == 0)) { 411 | data.pop_back(); 412 | } 413 | } 414 | 415 | private: 416 | 417 | std::vector data; 418 | 419 | }; // class BigInteger 420 | 421 | } // namespace hprose 422 | 423 | #endif // HPROSE_COMMON_BIGINTEGER_HPP 424 | -------------------------------------------------------------------------------- /hprose/ext/CTime.hpp: -------------------------------------------------------------------------------- 1 | /**********************************************************\ 2 | | | 3 | | hprose | 4 | | | 5 | | Official WebSite: http://www.hprose.com/ | 6 | | http://www.hprose.net/ | 7 | | http://www.hprose.org/ | 8 | | | 9 | \**********************************************************/ 10 | 11 | /**********************************************************\ 12 | * * 13 | * CTime.hpp * 14 | * * 15 | * hprose c time unit for cpp. * 16 | * * 17 | * LastModified: May 29, 2014 * 18 | * Author: Chen fei * 19 | * * 20 | \**********************************************************/ 21 | 22 | #ifndef HPROSE_COMMON_CTIME_HPP 23 | #define HPROSE_COMMON_CTIME_HPP 24 | 25 | #if defined(_MSC_VER) && (_MSC_VER >= 1020) 26 | #pragma once 27 | #endif 28 | 29 | #include 30 | 31 | namespace hprose { 32 | 33 | class CTime { 34 | public: // structors 35 | 36 | CTime() throw() 37 | : time(0) { 38 | } 39 | 40 | CTime(time_t time) throw() 41 | : time(time) { 42 | } 43 | 44 | CTime(int year, int month, int day, int hour, int min, int sec, int dst = -1) { 45 | tm t; 46 | t.tm_year = year - 1900; 47 | t.tm_mon = month - 1; 48 | t.tm_mday = day; 49 | t.tm_hour = hour; 50 | t.tm_min = min; 51 | t.tm_sec = sec; 52 | t.tm_isdst = dst; 53 | time = mktime(&t); 54 | } 55 | 56 | public: // operators 57 | 58 | inline CTime & operator=(time_t time) throw() { 59 | this->time = time; 60 | return (*this); 61 | } 62 | 63 | inline CTime & operator+=(time_t span) throw() { 64 | time += span; 65 | return (*this); 66 | } 67 | 68 | inline CTime & operator-=(time_t span) throw() { 69 | time -= span; 70 | return (*this); 71 | } 72 | 73 | inline CTime operator+(time_t span) const throw() { 74 | return CTime(time + span); 75 | } 76 | 77 | inline CTime operator-(time_t span) const throw() { 78 | return CTime(time - span); 79 | } 80 | 81 | inline time_t operator-(CTime time) const throw() { 82 | return this->time - time.time; 83 | } 84 | 85 | inline bool operator==(CTime time) const throw() { 86 | return this->time == time.time; 87 | } 88 | 89 | inline bool operator!=(CTime time) const throw() { 90 | return this->time != time.time; 91 | } 92 | 93 | inline bool operator>(CTime time) const throw() { 94 | return this->time > time.time; 95 | } 96 | 97 | inline bool operator<(CTime time) const throw() { 98 | return this->time < time.time; 99 | } 100 | 101 | inline bool operator>=(CTime time) const throw() { 102 | return this->time >= time.time; 103 | } 104 | 105 | inline bool operator<=(CTime time) const throw() { 106 | return this->time <= time.time; 107 | } 108 | 109 | public: // apis 110 | 111 | inline static CTime Now() throw() { 112 | return CTime(::time(0)); 113 | } 114 | 115 | static long TimeZone() { 116 | static bool set; 117 | if (!set) { 118 | _tzset(); 119 | set = true; 120 | } 121 | #if defined(_MSC_VER) && (_MSC_VER >= 1600) 122 | long timezone; 123 | _get_timezone(&timezone); 124 | return timezone; 125 | #else 126 | return ::timezone; 127 | #endif 128 | } 129 | 130 | inline time_t GetTime() const throw() { 131 | return time; 132 | } 133 | 134 | tm * GetGmtTm(tm * ptm = NULL) const { 135 | #ifdef BOOST_WINDOWS 136 | #ifdef __STDC_WANT_SECURE_LIB__ 137 | gmtime_s(ptm, &time); 138 | #else 139 | *ptm = *gmtime(&time); 140 | #endif 141 | #else 142 | gmtime_r(&time, ptm); 143 | #endif 144 | return ptm; 145 | } 146 | 147 | tm * GetLocalTm(tm * ptm = NULL) const { 148 | #ifdef BOOST_WINDOWS 149 | #ifdef __STDC_WANT_SECURE_LIB__ 150 | localtime_s(ptm, &time); 151 | #else 152 | *ptm = *localtime(&time); 153 | #endif 154 | #else 155 | localtime_r(&time, ptm); 156 | #endif 157 | return ptm; 158 | } 159 | 160 | std::string ToString() { // ToDo 161 | #ifdef BOOST_WINDOWS 162 | #ifdef __STDC_WANT_SECURE_LIB__ 163 | char buf[30]; 164 | ctime_s(buf, 30, &time); 165 | return buf; 166 | #else 167 | return ctime(&t); 168 | #endif 169 | #else 170 | char buf[30]; 171 | return ctime_r(&time, buf); 172 | #endif 173 | } 174 | 175 | private: 176 | 177 | time_t time; 178 | 179 | }; // CTime 180 | 181 | } // namespace hprose 182 | 183 | #endif // HPROSE_COMMON_CTIME_HPP 184 | -------------------------------------------------------------------------------- /hprose/io.hpp: -------------------------------------------------------------------------------- 1 | /**********************************************************\ 2 | | | 3 | | hprose | 4 | | | 5 | | Official WebSite: http://www.hprose.com/ | 6 | | http://www.hprose.org/ | 7 | | | 8 | \**********************************************************/ 9 | 10 | /**********************************************************\ 11 | * * 12 | * io.hpp * 13 | * * 14 | * hprose io unit for cpp. * 15 | * * 16 | * LastModified: Jun 15, 2014 * 17 | * Author: Chen fei * 18 | * * 19 | \**********************************************************/ 20 | 21 | #ifndef HPROSE_IO_HPP 22 | #define HPROSE_IO_HPP 23 | 24 | #if defined(_MSC_VER) && (_MSC_VER >= 1020) 25 | #pragma once 26 | #endif 27 | 28 | #include 29 | 30 | #endif // HPROSE_IO_HPP 31 | -------------------------------------------------------------------------------- /hprose/io/ClassManager.hpp: -------------------------------------------------------------------------------- 1 | /**********************************************************\ 2 | | | 3 | | hprose | 4 | | | 5 | | Official WebSite: http://www.hprose.com/ | 6 | | http://www.hprose.org/ | 7 | | | 8 | \**********************************************************/ 9 | 10 | /**********************************************************\ 11 | * * 12 | * ClassManager.hpp * 13 | * * 14 | * hprose class manager unit for cpp. * 15 | * * 16 | * LastModified: Jun 15, 2014 * 17 | * Author: Chen fei * 18 | * * 19 | \**********************************************************/ 20 | 21 | #ifndef HPROSE_IO_CLASS_MANAGER_HPP 22 | #define HPROSE_IO_CLASS_MANAGER_HPP 23 | 24 | #if defined(_MSC_VER) && (_MSC_VER >= 1020) 25 | #pragma once 26 | #endif 27 | 28 | #include 29 | 30 | #include 31 | #include 32 | #include 33 | 34 | #define HPROSE_REG_CLASS(Class) \ 35 | hprose::ClassManager::SharedInstance()->RegisterClass(&typeid(Class), #Class) 36 | #define HPROSE_REG_CLASS_EX(Class, Alias) \ 37 | hprose::ClassManager::SharedInstance()->RegisterClass(&typeid(Class), Alias) 38 | #define HPROSE_REG_PROPERTY(Class, Property) \ 39 | hprose::ClassManager::SharedInstance()->RegisterProperty(&typeid(Class), #Property, &Class::Property) 40 | #define HPROSE_REG_PROPERTY_EX(Class, Property, Alias) \ 41 | hprose::ClassManager::SharedInstance()->RegisterProperty(&typeid(Class), Alias, &Class::Property) 42 | 43 | #define HproseRegClass HPROSE_REG_CLASS 44 | #define HproseRegClassEx HPROSE_REG_CLASS_EX 45 | #define HproseRegProperty HPROSE_REG_PROPERTY 46 | #define HproseRegPropertyEx HPROSE_REG_PROPERTY_EX 47 | 48 | #ifndef BOOST_NO_CXX11_VARIADIC_MACROS 49 | #ifndef BOOST_NO_CXX11_VARIADIC_TEMPLATES 50 | #define HPROSE_REGISTER(Class, ...) \ 51 | hprose::ClassManager::SharedInstance()->RegisterClass(&typeid(Class), #Class, __VA_ARGS__) 52 | 53 | #define HproseRegister HPROSE_REGISTER 54 | #endif 55 | #endif 56 | 57 | namespace hprose { 58 | 59 | class ClassManager { 60 | public: 61 | 62 | typedef std::tr1::unordered_map ClassProperty; 63 | 64 | public: 65 | 66 | inline static ClassManager * SharedInstance() { 67 | static ClassManager classManager; 68 | return &classManager; 69 | } 70 | 71 | public: 72 | 73 | #ifndef BOOST_NO_CXX11_VARIADIC_TEMPLATES 74 | template 75 | inline void RegisterClass(const std::type_info * type, const std::string & alias, const ValueTypes &... values) { 76 | if (type && (!alias.empty())) { 77 | RegisterClass(type, alias); 78 | RegisterProperty(alias, values...); 79 | } 80 | } 81 | #endif 82 | 83 | inline void RegisterClass(const std::type_info * type, const std::string & alias) { 84 | if (type && (!alias.empty())) { 85 | #ifdef HPROSE_THREAD_SAFE_REG 86 | boost::unique_lock lock(mutex); 87 | #endif 88 | classAliases[type] = alias; 89 | classes[alias] = type; 90 | } 91 | } 92 | 93 | #ifndef BOOST_NO_CXX11_VARIADIC_TEMPLATES 94 | template 95 | inline void RegisterProperty(const std::string & alias, const std::string & name, const ValueType & value, const ValueTypes &... values) { 96 | if ((!alias.empty()) && (!name.empty())) { 97 | #ifdef HPROSE_THREAD_SAFE_REG 98 | boost::unique_lock lock(propertyMutex); 99 | #endif 100 | properties[alias][name] = value; 101 | } 102 | RegisterProperty(alias, values...); 103 | } 104 | #endif 105 | 106 | template 107 | inline void RegisterProperty(const std::string & alias, const std::string & name, ValueType value) { 108 | if ((!alias.empty()) && (!name.empty())) { 109 | #ifdef HPROSE_THREAD_SAFE_REG 110 | boost::unique_lock lock(propertyMutex); 111 | #endif 112 | properties[alias][name] = value; 113 | } 114 | } 115 | 116 | template 117 | inline void RegisterProperty(const std::type_info * type, const std::string & name, ValueType value) { 118 | if (type) { 119 | std::string alias = GetClassAlias(type); 120 | RegisterProperty(alias, name, value); 121 | } 122 | } 123 | 124 | inline std::string GetClassAlias(const std::type_info * type) { 125 | if (type) { 126 | #ifdef HPROSE_THREAD_SAFE_REG 127 | boost::shared_lock lock(mutex); 128 | #endif 129 | return classAliases[type]; 130 | } else { 131 | return ""; 132 | } 133 | } 134 | 135 | inline const std::type_info * GetClass(const std::string & alias) { 136 | if (!alias.empty()) { 137 | #ifdef HPROSE_THREAD_SAFE_REG 138 | boost::shared_lock lock(mutex); 139 | #endif 140 | Classes::const_iterator itr = classes.find(alias); 141 | return (itr != classes.end()) ? itr->second : NULL; 142 | } else { 143 | return NULL; 144 | } 145 | } 146 | 147 | inline ClassProperty * GetClassProperty(const std::string & alias) { 148 | if (!alias.empty()) { 149 | #ifdef HPROSE_THREAD_SAFE_REG 150 | boost::shared_lock lock(propertyMutex); 151 | #endif 152 | ClassProperties::iterator itr = properties.find(alias); 153 | return (itr != properties.end()) ? &itr->second : NULL; 154 | } else { 155 | return NULL; 156 | } 157 | } 158 | 159 | inline ClassProperty * GetClassProperty(const std::type_info * type) { 160 | if (type) { 161 | std::string alias = GetClassAlias(type); 162 | return GetClassProperty(alias); 163 | } else { 164 | return NULL; 165 | } 166 | } 167 | 168 | private: 169 | 170 | typedef std::tr1::unordered_map ClassAliases; 171 | typedef std::tr1::unordered_map Classes; 172 | typedef std::tr1::unordered_map ClassProperties; 173 | 174 | private: 175 | 176 | ClassAliases classAliases; 177 | Classes classes; 178 | ClassProperties properties; 179 | 180 | #ifdef HPROSE_THREAD_SAFE_REG 181 | boost::shared_mutex mutex; // read-write lock for classAliases and classes; 182 | boost::shared_mutex propertyMutex; // read-write lock for properties; 183 | #endif 184 | 185 | }; // class ClassManager 186 | 187 | } // namespace hprose 188 | 189 | #endif // HPROSE_IO_CLASS_MANAGER_HPP 190 | -------------------------------------------------------------------------------- /hprose/io/HproseFormatter.hpp: -------------------------------------------------------------------------------- 1 | /**********************************************************\ 2 | | | 3 | | hprose | 4 | | | 5 | | Official WebSite: http://www.hprose.com/ | 6 | | http://www.hprose.org/ | 7 | | | 8 | \**********************************************************/ 9 | 10 | /**********************************************************\ 11 | * * 12 | * HproseFormatter.hpp * 13 | * * 14 | * hprose formatter unit for cpp. * 15 | * * 16 | * LastModified: Jun 15, 2014 * 17 | * Author: Chen fei * 18 | * * 19 | \**********************************************************/ 20 | 21 | #ifndef HPROSE_IO_HPROSE_FORMATTER_HPP 22 | #define HPROSE_IO_HPROSE_FORMATTER_HPP 23 | 24 | #if defined(_MSC_VER) && (_MSC_VER >= 1020) 25 | #pragma once 26 | #endif 27 | 28 | #include 29 | #include 30 | 31 | namespace hprose { 32 | 33 | class HproseFormatter { 34 | public: 35 | 36 | template 37 | inline static void Serialize(const ValueType & value, std::ostream & stream, bool simple = false) { 38 | HproseWriter writer(stream, simple); 39 | writer.Serialize(value); 40 | } 41 | 42 | template 43 | inline static std::string Serialize(const ValueType & value, bool simple = false) { 44 | std::ostringstream stream; 45 | HproseWriter writer(stream, simple); 46 | writer.Serialize(value); 47 | return stream.str(); 48 | } 49 | 50 | #ifndef BOOST_NO_INITIALIZER_LISTS 51 | template 52 | inline static void Serialize(const std::initializer_list & value, std::ostream & stream, bool simple = false) { 53 | HproseWriter writer(stream, simple); 54 | writer.Serialize(value); 55 | } 56 | 57 | template 58 | inline static std::string Serialize(const std::initializer_list & value, bool simple = false) { 59 | std::ostringstream stream; 60 | HproseWriter writer(stream, simple); 61 | writer.Serialize(value); 62 | return stream.str(); 63 | } 64 | #endif 65 | 66 | template 67 | inline static ReturnType Unserialize(std::istream & stream, bool simple = false) { 68 | HproseReader reader(stream, simple); 69 | return reader.Unserialize(); 70 | } 71 | 72 | inline static Any Unserialize(std::istream & stream, bool simple = false) { 73 | return Unserialize(stream, simple); 74 | } 75 | 76 | template 77 | inline static ReturnType Unserialize(const std::string & data, bool simple = false) { 78 | std::istringstream stream(data); 79 | return Unserialize(stream, simple); 80 | } 81 | 82 | inline static Any Unserialize(const std::string & data, bool simple = false) { 83 | return Unserialize(data, simple); 84 | } 85 | 86 | }; // class HproseFormatter 87 | 88 | } // namespace hprose 89 | 90 | #endif // HPROSE_IO_HPROSE_FORMATTER_HPP 91 | -------------------------------------------------------------------------------- /hprose/io/HproseReader.hpp: -------------------------------------------------------------------------------- 1 | /**********************************************************\ 2 | | | 3 | | hprose | 4 | | | 5 | | Official WebSite: http://www.hprose.com/ | 6 | | http://www.hprose.org/ | 7 | | | 8 | \**********************************************************/ 9 | 10 | /**********************************************************\ 11 | * * 12 | * HproseReader.hpp * 13 | * * 14 | * hprose reader unit for cpp. * 15 | * * 16 | * LastModified: Oct 28, 2016 * 17 | * Author: Chen fei * 18 | * * 19 | \**********************************************************/ 20 | 21 | #ifndef HPROSE_IO_HPROSE_READER_HPP 22 | #define HPROSE_IO_HPROSE_READER_HPP 23 | 24 | #if defined(_MSC_VER) && (_MSC_VER >= 1020) 25 | #pragma once 26 | #endif 27 | 28 | #include 29 | 30 | #include 31 | #include 32 | #include 33 | 34 | namespace hprose { 35 | 36 | class HproseReader { 37 | public: 38 | 39 | HproseReader(std::istream & stream, bool simple = false) 40 | : stream(stream), simple(simple) { 41 | } 42 | 43 | public: 44 | 45 | template 46 | inline ReturnType Unserialize() { 47 | return Unserialize(NonCVType()); // Don't need remove_cv. 48 | } 49 | 50 | inline Any Unserialize() { 51 | return Unserialize(); 52 | } 53 | 54 | public: 55 | 56 | bool ReadBool() { 57 | switch (int tag = stream.get()) { 58 | case '0': return false; 59 | case '1': 60 | case '2': 61 | case '3': 62 | case '4': 63 | case '5': 64 | case '6': 65 | case '7': 66 | case '8': 67 | case '9': return true; 68 | case HproseTags::TagInteger: return ReadIntWithoutTag() != 0; 69 | case HproseTags::TagLong: return ReadUntil(HproseTags::TagSemicolon).str() != "0"; 70 | case HproseTags::TagDouble: return ReadDoubleWithoutTag() != 0.0; 71 | case HproseTags::TagNull: 72 | case HproseTags::TagEmpty: return false; 73 | case HproseTags::TagTrue: return true; 74 | case HproseTags::TagFalse: return false; 75 | case HproseTags::TagNaN: return true; 76 | case HproseTags::TagInfinity: stream.get(); return true; 77 | case HproseTags::TagUTF8Char: return std::wstring(L"\00").find(ReadUTF8CharAsChar()) == std::wstring::npos; 78 | case HproseTags::TagString: return ReadStringWithoutTag() == "true"; 79 | case HproseTags::TagRef: return ReadStringRef() == "true"; 80 | default: HPROSE_THROW_EXCEPTION(CastError(tag)); 81 | } 82 | } 83 | 84 | template 85 | ReturnType ReadChar() { 86 | HPROSE_STATIC_ASSERT(NonCVType::value == CharType::value, "Require CharType"); 87 | switch (int tag = stream.get()) { 88 | case '0': 89 | case '1': 90 | case '2': 91 | case '3': 92 | case '4': 93 | case '5': 94 | case '6': 95 | case '7': 96 | case '8': 97 | case '9': return tag; 98 | case HproseTags::TagInteger: 99 | case HproseTags::TagLong: return ReadIntWithoutTag(); 100 | case HproseTags::TagDouble: return static_cast(ReadDoubleWithoutTag()); 101 | case HproseTags::TagNull: return 0; 102 | case HproseTags::TagUTF8Char: return ReadUTF8CharAsChar(); 103 | case HproseTags::TagString: return ReadStringWithoutTag >().at(0); 104 | case HproseTags::TagRef: return ReadStringRef >().at(0); 105 | default: HPROSE_THROW_EXCEPTION(CastError(tag)); 106 | } 107 | } 108 | 109 | inline char_type ReadChar() { 110 | return ReadChar(); 111 | } 112 | 113 | template 114 | ReturnType ReadInt() { 115 | switch (int tag = stream.get()) { 116 | case '0': return 0; 117 | case '1': return 1; 118 | case '2': return 2; 119 | case '3': return 3; 120 | case '4': return 4; 121 | case '5': return 5; 122 | case '6': return 6; 123 | case '7': return 7; 124 | case '8': return 8; 125 | case '9': return 9; 126 | case HproseTags::TagInteger: 127 | case HproseTags::TagLong: return ReadIntWithoutTag(); 128 | case HproseTags::TagDouble: return static_cast(ReadDoubleWithoutTag()); 129 | case HproseTags::TagNull: 130 | case HproseTags::TagEmpty: return 0; 131 | case HproseTags::TagTrue: return 1; 132 | case HproseTags::TagFalse: return 0; 133 | case HproseTags::TagDate: return static_cast(ReadDateWithoutTag()); 134 | case HproseTags::TagTime: return static_cast(ReadTimeWithoutTag()); 135 | case HproseTags::TagUTF8Char: return ReadUTF8CharAsChar(); 136 | case HproseTags::TagString: return ParseNumeric(ReadStringWithoutTag()); 137 | case HproseTags::TagRef: return ParseNumeric(ReadStringRef()); 138 | default: HPROSE_THROW_EXCEPTION(CastError(tag)); 139 | } 140 | } 141 | 142 | inline int ReadInt() { 143 | return ReadInt(); 144 | } 145 | 146 | inline long_type ReadLong() { 147 | return ReadInt(); 148 | } 149 | 150 | template 151 | ReturnType ReadDouble() { 152 | switch (int tag = stream.get()) { 153 | case '0': return 0; 154 | case '1': return 1; 155 | case '2': return 2; 156 | case '3': return 3; 157 | case '4': return 4; 158 | case '5': return 5; 159 | case '6': return 6; 160 | case '7': return 7; 161 | case '8': return 8; 162 | case '9': return 9; 163 | case HproseTags::TagInteger: 164 | case HproseTags::TagLong: return ReadIntWithoutTag(); 165 | case HproseTags::TagDouble: return ReadDoubleWithoutTag(); 166 | case HproseTags::TagNull: 167 | case HproseTags::TagEmpty: return 0; 168 | case HproseTags::TagTrue: return 1; 169 | case HproseTags::TagFalse: return 0; 170 | case HproseTags::TagNaN: return std::numeric_limits::quiet_NaN(); 171 | case HproseTags::TagInfinity: return ReadInfinityWithoutTag(); 172 | case HproseTags::TagUTF8Char: return static_cast(ReadUTF8CharAsChar()); 173 | case HproseTags::TagString: return ParseNumeric(ReadStringWithoutTag()); 174 | case HproseTags::TagRef: return ParseNumeric(ReadStringRef()); 175 | default: HPROSE_THROW_EXCEPTION(CastError(tag)); 176 | } 177 | } 178 | 179 | inline double ReadDouble() { 180 | return ReadDouble(); 181 | } 182 | 183 | time_t ReadDateTime() { 184 | switch (int tag = stream.get()) { 185 | case '0': return 0; 186 | case '1': return 1; 187 | case '2': return 2; 188 | case '3': return 3; 189 | case '4': return 4; 190 | case '5': return 5; 191 | case '6': return 6; 192 | case '7': return 7; 193 | case '8': return 8; 194 | case '9': return 9; 195 | case HproseTags::TagInteger: 196 | case HproseTags::TagLong: return ReadIntWithoutTag(); 197 | case HproseTags::TagDouble: return static_cast(ReadDoubleWithoutTag()); 198 | case HproseTags::TagNull: 199 | case HproseTags::TagEmpty: return 0; 200 | case HproseTags::TagDate: return ReadDateWithoutTag(); 201 | case HproseTags::TagTime: return ReadTimeWithoutTag(); 202 | case HproseTags::TagRef: return ReadRef(); 203 | default: HPROSE_THROW_EXCEPTION(CastError(tag)); 204 | } 205 | } 206 | 207 | template 208 | ReturnType ReadBytes() { 209 | typedef BOOST_DEDUCED_TYPENAME NonCVElementType::type element; 210 | switch (int tag = stream.get()) { 211 | case HproseTags::TagNull: 212 | case HproseTags::TagEmpty: return ReturnType(); 213 | case HproseTags::TagUTF8Char: { 214 | std::string s = ReadUTF8CharAsUTF8String(); 215 | return ReturnType(s.begin(), s.end()); 216 | } 217 | case HproseTags::TagString: { 218 | std::string s = ReadCharsAsUTF8String(); 219 | return ReturnType(s.begin(), s.end()); 220 | } 221 | case HproseTags::TagGuid: { 222 | #ifdef BOOST_WINDOWS 223 | GUID g = ReadGUIDWithoutTag(); 224 | element *first = reinterpret_cast(&g); 225 | return ReturnType(first, first + sizeof(GUID)); 226 | #else 227 | //Todo: uuid_t 228 | #endif 229 | } 230 | case HproseTags::TagBytes: return ReadBytesWithoutTag(); 231 | case HproseTags::TagList: { 232 | int count = ReadInt(HproseTags::TagOpenbrace); 233 | ReturnType a; 234 | a.resize(count); 235 | for (int i = 0; i < count; i++) { 236 | a[i] = ReadInt(); 237 | } 238 | stream.get(); 239 | references.push_back(a); 240 | return a; 241 | } 242 | //case HproseTags::TagRef: { 243 | // object obj = ReadRef(); 244 | // if (obj is byte[]) return (byte[])obj; 245 | // if (obj is Guid) return ((Guid)obj).ToByteArray(); 246 | // if (obj is MemoryStream) return ((MemoryStream)obj).ToArray(); 247 | // throw CastError(obj, HproseHelper.typeofByteArray); 248 | //} 249 | default: HPROSE_THROW_EXCEPTION(CastError(tag)); 250 | } 251 | } 252 | 253 | template 254 | ReturnType ReadString() { 255 | switch (int tag = stream.get()) { 256 | case '0': return Stringify("0"); 257 | case '1': return Stringify("1"); 258 | case '2': return Stringify("2"); 259 | case '3': return Stringify("3"); 260 | case '4': return Stringify("4"); 261 | case '5': return Stringify("5"); 262 | case '6': return Stringify("6"); 263 | case '7': return Stringify("7"); 264 | case '8': return Stringify("8"); 265 | case '9': return Stringify("9"); 266 | case HproseTags::TagInteger: 267 | case HproseTags::TagLong: 268 | case HproseTags::TagDouble: return Stringify(ReadUntil(HproseTags::TagSemicolon).str()); 269 | case HproseTags::TagNull: 270 | case HproseTags::TagEmpty: return ReturnType(); 271 | case HproseTags::TagTrue: return Stringify("true"); 272 | case HproseTags::TagFalse: return Stringify("false"); 273 | case HproseTags::TagNaN: return Stringify("NaN"); 274 | case HproseTags::TagInfinity: return (stream.get() == HproseTags::TagPos) ? Stringify("Infinity") : Stringify("-Infinity"); 275 | // case HproseTags::TagDate: return ReadDateWithoutTag().ToString(); 276 | // case HproseTags::TagTime: return ReadTimeWithoutTag().ToString(); 277 | case HproseTags::TagUTF8Char: return ReadUTF8CharWithoutTag(); 278 | case HproseTags::TagString: return ReadStringWithoutTag(); 279 | // case HproseTags::TagGuid: // return readUUIDWithoutTag().toString(); 280 | // case HproseTags::TagList: // return readListWithoutTag().toString(); 281 | // case HproseTags::TagMap: // return readMapWithoutTag().toString(); 282 | // case HproseTags::TagClass: // readClass(); return readObject(null).toString(); 283 | // case HproseTags::TagObject: // return readObjectWithoutTag(null).toString(); 284 | case HproseTags::TagRef: return ReadRef(); 285 | default: HPROSE_THROW_EXCEPTION(CastError(tag)); 286 | } 287 | } 288 | 289 | inline std::string ReadString() { 290 | return ReadString(); 291 | } 292 | 293 | #ifdef BOOST_WINDOWS 294 | GUID ReadGUID() { 295 | switch (char tag = stream.get()) { 296 | // case HproseTags::TagBytes: return new Guid(ReadBytesWithoutTag()); 297 | case HproseTags::TagGuid: return ReadGUIDWithoutTag(); 298 | // case HproseTags::TagString: return new Guid(ReadStringWithoutTag()); 299 | //case HproseTags::TagRef: { 300 | // object obj = ReadRef(); 301 | // if (obj is Guid) return (Guid)obj; 302 | // if (obj is byte[]) return new Guid((byte[])obj); 303 | // if (obj is string) return new Guid((string)obj); 304 | // if (obj is char[]) return new Guid(new string((char[])obj)); 305 | // throw CastError(obj, HproseHelper.typeofGuid); 306 | //} 307 | default: HPROSE_THROW_EXCEPTION(CastError(tag)); 308 | } 309 | } 310 | #endif 311 | 312 | template 313 | ReturnType ReadList() { 314 | switch (int tag = stream.get()) { 315 | case HproseTags::TagNull: return ReturnType(); 316 | case HproseTags::TagList: return ReadListWithoutTag(); 317 | // case HproseTags.TagRef: return (List)ReadRef(); 318 | default: HPROSE_THROW_EXCEPTION(CastError(tag)); 319 | } 320 | } 321 | 322 | template 323 | ReturnType ReadMap() { 324 | switch (int tag = stream.get()) { 325 | case HproseTags::TagNull: return ReturnType(); 326 | // case HproseTags::TagList: return ReadListAsMap(); 327 | case HproseTags::TagMap: return ReadMapWithoutTag(); 328 | // case HproseTags::TagClass: readClass(); return readMap(cls, type); 329 | // case HproseTags::TagObject: return readObjectAsMap((Map)HproseHelper.newInstance(cls)); 330 | case HproseTags::TagRef: return ReadRef(); 331 | default: HPROSE_THROW_EXCEPTION(CastError(tag)); 332 | } 333 | } 334 | 335 | template 336 | ReturnType ReadObject() { 337 | switch (int tag = stream.get()) { 338 | // case HproseTags::TagNull: return null; 339 | // case HproseTags::TagMap: return readMapAsObject(type); 340 | case HproseTags::TagClass: ReadClass(); return ReadObject(); 341 | case HproseTags::TagObject: return ReadObjectWithoutTag(); 342 | // case HproseTags::TagRef: return readRef(type); 343 | default: HPROSE_THROW_EXCEPTION(CastError(tag)); 344 | } 345 | } 346 | 347 | public: 348 | 349 | inline void CheckTag(char expected, char found) { 350 | if (found != expected) { 351 | HPROSE_THROW_EXCEPTION(std::string("HproseTags::Tag '") + expected + "' expected, but '" + found + "' found in stream"); 352 | } 353 | } 354 | 355 | inline void CheckTag(char expected) { 356 | CheckTag(expected, stream.get()); 357 | } 358 | 359 | template 360 | inline char CheckTags(const char (&expected)[ArraySize], char found) { 361 | bool ok = false; 362 | for (size_t i = 0; i < ArraySize; i++) { 363 | if (expected[i] == found) { 364 | ok = true; 365 | break; 366 | } 367 | } 368 | if (!ok) { 369 | HPROSE_THROW_EXCEPTION(std::string("HproseTags::Tag '") + std::string(expected, expected + ArraySize) + "' expected, but '" + found + "' found in stream"); 370 | } 371 | return found; 372 | } 373 | 374 | template 375 | inline char CheckTags(const char (&expected)[ArraySize]) { 376 | return CheckTags(expected, stream.get()); 377 | } 378 | 379 | private: 380 | 381 | template 382 | inline ReturnType Unserialize(UnknownType) { 383 | HPROSE_THROW_EXCEPTION(CastError(stream.get())); 384 | } 385 | 386 | template 387 | inline ReturnType Unserialize(AutoPtrType) { 388 | return Unserialize(UnknownType()); 389 | } 390 | 391 | template 392 | inline ReturnType Unserialize(PointerType) { 393 | return Unserialize(UnknownType()); 394 | } 395 | 396 | template 397 | ReturnType Unserialize(AnyType) { 398 | switch (int tag = stream.get()) { 399 | case '0': return 0; 400 | case '1': return 1; 401 | case '2': return 2; 402 | case '3': return 3; 403 | case '4': return 4; 404 | case '5': return 5; 405 | case '6': return 6; 406 | case '7': return 7; 407 | case '8': return 8; 408 | case '9': return 9; 409 | case HproseTags::TagInteger: return ReadIntWithoutTag(); 410 | case HproseTags::TagLong: return ReadLongWithoutTag(); // Todo: BigInteger 411 | case HproseTags::TagDouble: return ReadDoubleWithoutTag(); 412 | case HproseTags::TagNaN: return std::numeric_limits::quiet_NaN(); 413 | case HproseTags::TagInfinity: return ReadInfinityWithoutTag(); 414 | case HproseTags::TagNull: return Any(); 415 | case HproseTags::TagEmpty: return std::string(); 416 | case HproseTags::TagTrue: return true; 417 | case HproseTags::TagFalse: return false; 418 | case HproseTags::TagDate: return ReadDateWithoutTag(); 419 | case HproseTags::TagTime: return ReadTimeWithoutTag(); 420 | case HproseTags::TagBytes: return ReadBytesWithoutTag(); 421 | case HproseTags::TagUTF8Char: return ReadUTF8CharWithoutTag(); 422 | case HproseTags::TagString: return ReadStringWithoutTag(); 423 | case HproseTags::TagList: return ReadListWithoutTag(); 424 | case HproseTags::TagMap: return ReadMapWithoutTag(); 425 | case HproseTags::TagClass: ReadClass(); return Unserialize(); 426 | //case HproseTags::TagObject: return ReadObjectWithoutTag(); 427 | case HproseTags::TagRef: return references[ReadInt(HproseTags::TagSemicolon)]; 428 | case HproseTags::TagError: HPROSE_THROW_EXCEPTION(ReadString()); 429 | default: HPROSE_THROW_EXCEPTION(UnexpectedTag(tag)); 430 | } 431 | } 432 | 433 | template 434 | inline ReturnType Unserialize(BoolType) { 435 | return ReadBool(); 436 | } 437 | 438 | template 439 | inline ReturnType Unserialize(ByteType) { 440 | return ReadInt(); 441 | } 442 | 443 | template 444 | inline ReturnType Unserialize(CharType) { 445 | return ReadChar(); 446 | } 447 | 448 | template 449 | inline ReturnType Unserialize(EnumType) { 450 | return static_cast(ReadInt()); 451 | } 452 | 453 | template 454 | inline ReturnType Unserialize(IntegerType) { 455 | return ReadInt(); 456 | } 457 | 458 | template 459 | inline ReturnType Unserialize(LongType) { 460 | return ReadLong(); // Todo: BigInteger 461 | } 462 | 463 | template 464 | inline ReturnType Unserialize(DoubleType) { 465 | return ReadDouble(); 466 | } 467 | 468 | template 469 | inline ReturnType Unserialize(TimeType) { 470 | return ReadDateTime(); 471 | } 472 | 473 | template 474 | inline ReturnType Unserialize(BytesType) { 475 | return ReadBytes(); 476 | } 477 | 478 | template 479 | inline ReturnType Unserialize(StringType) { 480 | return ReadString(); 481 | } 482 | 483 | template 484 | inline ReturnType Unserialize(GuidType) { 485 | #ifdef BOOST_WINDOWS 486 | return ReadGUID(); 487 | #else 488 | // Todo: uuid_t 489 | #endif 490 | } 491 | 492 | template 493 | inline ReturnType Unserialize(ListType) { 494 | return ReadList(); 495 | } 496 | 497 | template 498 | inline ReturnType Unserialize(MapType) { 499 | return ReadMap(); 500 | } 501 | 502 | template 503 | inline ReturnType Unserialize(ObjectType) { 504 | return ReadObject(); 505 | } 506 | 507 | private: 508 | 509 | std::stringstream ReadUntil(char tag) { 510 | std::stringstream ss; 511 | char c = stream.get(); 512 | while ((c != tag) && (c != -1)) { 513 | ss << c; 514 | c = stream.get(); 515 | } 516 | return ss; 517 | } 518 | 519 | template 520 | ReturnType ReadInt(char tag) { 521 | ReturnType result = 0; 522 | char c = stream.get(); 523 | if (c == tag) { 524 | return result; 525 | } 526 | ReturnType sign = 1; 527 | switch (c) { 528 | case '-': sign = -1; // no break 529 | case '+': c = stream.get(); 530 | } 531 | while (c != tag && c != -1) { 532 | result *= 10; 533 | result += (c - '0') * sign; 534 | c = stream.get(); 535 | } 536 | return result; 537 | } 538 | 539 | inline int ReadInt(char tag) { 540 | return ReadInt(tag); 541 | } 542 | 543 | template 544 | inline ReturnType ParseNumeric(std::stringstream ss) { 545 | ReturnType result; 546 | ss >> result; 547 | return result; 548 | } 549 | 550 | template 551 | inline ReturnType ParseNumeric(std::string s) { 552 | return ParseNumeric(std::stringstream(s)); 553 | } 554 | 555 | void ReadDate(struct tm * ptm) { 556 | int year = stream.get() - '0'; 557 | year = year * 10 + stream.get() - '0'; 558 | year = year * 10 + stream.get() - '0'; 559 | year = year * 10 + stream.get() - '0'; 560 | int month = stream.get() - '0'; 561 | month = month * 10 + stream.get() - '0'; 562 | int day = stream.get() - '0'; 563 | day = day * 10 + stream.get() - '0'; 564 | ptm->tm_year = year - 1900; 565 | ptm->tm_mon = month - 1; 566 | ptm->tm_mday = day; 567 | } 568 | 569 | void ReadTime(struct tm * ptm) { 570 | int hour = stream.get() - '0'; 571 | hour = hour * 10 + stream.get() - '0'; 572 | int min = stream.get() - '0'; 573 | min = min * 10 + stream.get() - '0'; 574 | int sec = stream.get() - '0'; 575 | sec = sec * 10 + stream.get() - '0'; 576 | char tag = stream.get(); 577 | if (tag == HproseTags::TagPoint) { // ignore millisec 578 | do { 579 | tag = stream.get(); 580 | } while ((tag >= '0') && (tag <= '9')); 581 | } 582 | if (tag == HproseTags::TagUTC) { 583 | sec -= CTime::TimeZone(); 584 | } 585 | ptm->tm_hour = hour; 586 | ptm->tm_min = min; 587 | ptm->tm_sec = sec; 588 | } 589 | 590 | template 591 | inline ReturnType ReadUTF8CharAsChar() { 592 | return static_cast(ReadUTF8CharAsChar()); 593 | } 594 | 595 | char_type ReadUTF8CharAsChar() { 596 | char_type u; 597 | int c = stream.get(); 598 | switch (c >> 4) { 599 | case 0: 600 | case 1: 601 | case 2: 602 | case 3: 603 | case 4: 604 | case 5: 605 | case 6: 606 | case 7: { // 0xxx xxxx 607 | u = (char_type)c; 608 | break; 609 | } 610 | case 12: 611 | case 13: { // 110x xxxx 10xx xxxx 612 | int c2 = stream.get(); 613 | u = (char_type)(((c & 0x1f) << 6) | (c2 & 0x3f)); 614 | break; 615 | } 616 | case 14: { // 1110 xxxx 10xx xxxx 10xx xxxx 617 | int c2 = stream.get(); 618 | int c3 = stream.get(); 619 | u = (char_type)(((c & 0x0f) << 12) | ((c2 & 0x3f) << 6) | (c3 & 0x3f)); 620 | break; 621 | } 622 | default: 623 | HPROSE_THROW_EXCEPTION("bad utf-8 encoding"); //Todo: at 624 | } 625 | return u; 626 | } 627 | 628 | std::basic_string ReadChars() { 629 | std::basic_string buf; 630 | int count = ReadInt(HproseTags::TagQuote); 631 | buf.resize(count); 632 | for (int i = 0; i < count; i++) { 633 | int c = stream.get(); 634 | switch (c >> 4) { 635 | case 0: 636 | case 1: 637 | case 2: 638 | case 3: 639 | case 4: 640 | case 5: 641 | case 6: 642 | case 7: { // 0xxx xxxx 643 | buf[i] = (char_type)c; 644 | break; 645 | } 646 | case 12: 647 | case 13: { // 110x xxxx 10xx xxxx 648 | char c2 = stream.get(); 649 | buf[i] = (char_type)(((c & 0x1f) << 6) | (c2 & 0x3f)); 650 | break; 651 | } 652 | case 14: { // 1110 xxxx 10xx xxxx 10xx xxxx 653 | char c2 = stream.get(); 654 | char c3 = stream.get(); 655 | buf[i] = (char_type)(((c & 0x0f) << 12) | ((c2 & 0x3f) << 6) | (c3 & 0x3f)); 656 | break; 657 | } 658 | case 15: { // 1111 0xxx 10xx xxxx 10xx xxxx 10xx xxxx 659 | if ((c & 0xf) <= 4) { 660 | char c2 = stream.get(); 661 | char c3 = stream.get(); 662 | char c4 = stream.get(); 663 | int s = ((c & 0x07) << 18) | ((c2 & 0x3f) << 12) | ((c3 & 0x3f) << 6) | (c4 & 0x3f) - 0x10000; 664 | if (0 <= s && s <= 0xfffff) { 665 | buf[i++] = (char_type)(((s >> 10) & 0x03ff) | 0xd800); 666 | buf[i] = (char_type)((s & 0x03ff) | 0xdc00); 667 | break; 668 | } 669 | } 670 | // no break here!! here need throw exception. 671 | } 672 | default: 673 | HPROSE_THROW_EXCEPTION("bad utf-8 encoding");//Todo: at 674 | }; 675 | } 676 | stream.get(); 677 | return buf; 678 | } 679 | 680 | template 681 | ReturnType ReadCharsAsString(const std::basic_string & chars, Char8Type) { 682 | #if defined(BOOST_WINDOWS) && (!defined(HPROSE_CHARSET_UTF8)) 683 | return UnicodeToAnsi(chars); 684 | #else 685 | std::string s; 686 | s.resize(UTF8Size(chars.begin(), chars.end(), Char16Type())); 687 | UTF8Encode(chars.begin(), chars.end(), s.begin(), Char16Type()); 688 | return s; 689 | #endif 690 | } 691 | 692 | template 693 | inline ReturnType ReadCharsAsString(const std::basic_string & chars, Char16Type) { 694 | return ReturnType(chars.begin(), chars.end()); 695 | } 696 | 697 | template 698 | inline ReturnType ReadCharsAsString(const std::basic_string & chars, Char32Type) { 699 | return ReturnType(chars.begin(), chars.end()); 700 | } 701 | 702 | std::string ReadUTF8CharAsUTF8String() { 703 | std::string s; 704 | int c = stream.get(); 705 | switch (c >> 4) { 706 | case 0: 707 | case 1: 708 | case 2: 709 | case 3: 710 | case 4: 711 | case 5: 712 | case 6: 713 | case 7: { 714 | s.push_back(c); 715 | break; 716 | } 717 | case 12: 718 | case 13: { 719 | char c2 = stream.get(); 720 | s.push_back(c); 721 | s.push_back(c2); 722 | break; 723 | } 724 | case 14: { 725 | char c2 = stream.get(); 726 | char c3 = stream.get(); 727 | s.push_back(c); 728 | s.push_back(c2); 729 | s.push_back(c3); 730 | break; 731 | } 732 | default: 733 | HPROSE_THROW_EXCEPTION("bad utf-8 encoding");//Todo: at 734 | } 735 | return s; 736 | } 737 | 738 | std::string ReadCharsAsUTF8String() { 739 | int count = ReadInt(HproseTags::TagQuote); 740 | std::string s; 741 | s.reserve(count * 3); 742 | for (int i = 0; i < count; i++) { 743 | int c = stream.get(); 744 | switch (c >> 4) { 745 | case 0: 746 | case 1: 747 | case 2: 748 | case 3: 749 | case 4: 750 | case 5: 751 | case 6: 752 | case 7: { 753 | s.push_back(c); 754 | break; 755 | } 756 | case 12: 757 | case 13: { 758 | char c2 = stream.get(); 759 | s.push_back(c); 760 | s.push_back(c2); 761 | break; 762 | } 763 | case 14: { 764 | char c2 = stream.get(); 765 | char c3 = stream.get(); 766 | s.push_back(c); 767 | s.push_back(c2); 768 | s.push_back(c3); 769 | break; 770 | } 771 | case 15: { // 1111 0xxx 10xx xxxx 10xx xxxx 10xx xxxx 772 | if ((c & 0xf) <= 4) { 773 | char c2 = stream.get(); 774 | char c3 = stream.get(); 775 | char c4 = stream.get(); 776 | int c32 = ((c & 0x07) << 18) | ((c2 & 0x3f) << 12) | ((c3 & 0x3f) << 6) | (c4 & 0x3f) - 0x10000; 777 | if (0 <= c32 && c32 <= 0xfffff) { 778 | s.push_back(c); 779 | s.push_back(c2); 780 | s.push_back(c3); 781 | s.push_back(c4); 782 | break; 783 | } 784 | } 785 | // no break here!! here need throw exception. 786 | } 787 | default: 788 | HPROSE_THROW_EXCEPTION("bad utf-8 encoding");//Todo: at 789 | } 790 | } 791 | stream.get(); 792 | references.push_back(s); 793 | return s; 794 | } 795 | 796 | template 797 | inline ReturnType Stringify(const std::string & s) { 798 | return ReturnType(s.begin(), s.end()); 799 | } 800 | 801 | template 802 | inline ReturnType Stringify(const char (&value)[ArraySize]) { 803 | size_t len = value[ArraySize - 1] == 0 ? (ArraySize - 1) : ArraySize; 804 | return ReturnType(value, &value[len - 1]); 805 | } 806 | 807 | private: 808 | 809 | template 810 | inline ReturnType ReadIntWithoutTag() { 811 | return ReadInt(HproseTags::TagSemicolon); 812 | } 813 | 814 | inline int ReadIntWithoutTag() { 815 | return ReadIntWithoutTag(); 816 | } 817 | 818 | inline long_type ReadLongWithoutTag() { 819 | return ReadIntWithoutTag(); 820 | } 821 | 822 | template 823 | inline ReturnType ReadDoubleWithoutTag() { 824 | return ParseNumeric(ReadUntil(HproseTags::TagSemicolon)); 825 | } 826 | 827 | inline double ReadDoubleWithoutTag() { 828 | return ReadDoubleWithoutTag(); 829 | } 830 | 831 | template 832 | inline ReturnType ReadInfinityWithoutTag() { 833 | return ((stream.get() == HproseTags::TagPos) 834 | ? std::numeric_limits::infinity() 835 | : -std::numeric_limits::infinity()); 836 | } 837 | 838 | inline double ReadInfinityWithoutTag() { 839 | return ReadInfinityWithoutTag(); 840 | } 841 | 842 | time_t ReadDateWithoutTag() { 843 | tm t; 844 | t.tm_isdst = -1; 845 | ReadDate(&t); 846 | char tag = stream.get(); 847 | if (tag == HproseTags::TagTime) { 848 | ReadTime(&t); 849 | } else { 850 | t.tm_hour = 0; 851 | t.tm_min = 0; 852 | if (tag == HproseTags::TagUTC) { 853 | t.tm_sec = static_cast(-CTime::TimeZone()); 854 | } else { 855 | t.tm_sec = 0; 856 | } 857 | } 858 | time_t result = mktime(&t); 859 | references.push_back(result); 860 | return result; 861 | } 862 | 863 | time_t ReadTimeWithoutTag() { 864 | tm t; 865 | t.tm_year = 70; // 1970 - 1900 866 | t.tm_mon = 0; 867 | t.tm_mday = 1; 868 | t.tm_isdst = -1; 869 | ReadTime(&t); 870 | time_t result = mktime(&t); 871 | references.push_back(result); 872 | return result; 873 | } 874 | 875 | std::vector ReadBytesWithoutTag() { 876 | int count = ReadInt(HproseTags::TagQuote); 877 | std::vector b; 878 | b.resize(count); 879 | stream.read(reinterpret_cast(b.data()), count); 880 | stream.get(); 881 | references.push_back(b); 882 | return b; 883 | } 884 | 885 | template 886 | ReturnType ReadUTF8CharWithoutTag(Char8Type) { 887 | char_type c = ReadUTF8CharAsChar(); 888 | #if defined(BOOST_WINDOWS) && (!defined(HPROSE_CHARSET_UTF8)) 889 | return UnicodeToAnsi(std::wstring(1, c)); 890 | #else 891 | std::string s; 892 | s.resize(UTF8Size(&c, &c + 1, Char16Type())); 893 | UTF8Encode(&c, &c + 1, s.begin(), Char16Type()); 894 | return s; 895 | #endif 896 | } 897 | 898 | template 899 | inline ReturnType ReadUTF8CharWithoutTag(Char16Type) { 900 | return ReturnType(1, ReadUTF8CharAsChar()); 901 | } 902 | 903 | template 904 | inline ReturnType ReadUTF8CharWithoutTag(Char32Type) { 905 | return ReadUTF8CharWithoutTag(Char16Type()); 906 | } 907 | 908 | template 909 | inline ReturnType ReadUTF8CharWithoutTag() { 910 | typedef BOOST_DEDUCED_TYPENAME NonCVElementType::type element; 911 | return ReadUTF8CharWithoutTag(CharSize()); 912 | } 913 | 914 | inline std::string ReadUTF8CharWithoutTag() { 915 | return ReadUTF8CharWithoutTag(); 916 | } 917 | 918 | template 919 | ReturnType ReadStringWithoutTag() { 920 | typedef BOOST_DEDUCED_TYPENAME NonCVElementType::type element; 921 | std::basic_string chars = ReadChars(); 922 | references.push_back(chars); 923 | return ReadCharsAsString(chars, CharSize()); 924 | } 925 | 926 | inline std::string ReadStringWithoutTag() { 927 | return ReadStringWithoutTag(); 928 | } 929 | 930 | #ifdef BOOST_WINDOWS 931 | GUID ReadGUIDWithoutTag() { 932 | char buf[39]; 933 | for (int i = 0; i < 38; i++) { 934 | buf[i] = stream.get(); 935 | } 936 | buf[38] = 0; 937 | char temp[19]; // 16 + (4 - 1) 938 | GUID *g = (GUID *)&temp[0]; 939 | #ifdef __STDC_WANT_SECURE_LIB__ 940 | sscanf_s(buf, 941 | #else 942 | sscanf(buf, 943 | #endif 944 | "{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}", 945 | &g->Data1, &g->Data2, &g->Data3, &g->Data4[0], &g->Data4[1], &g->Data4[2], 946 | &g->Data4[3], &g->Data4[4], &g->Data4[5], &g->Data4[6], &g->Data4[7]); 947 | references.push_back(*g); 948 | return *g; 949 | } 950 | #endif 951 | 952 | template 953 | ReturnType ReadListWithoutTag() { 954 | typedef BOOST_DEDUCED_TYPENAME NonCVElementType::type element; 955 | int count = ReadInt(HproseTags::TagOpenbrace); 956 | ReturnType a; 957 | a.resize(count); 958 | for (int i = 0; i < count; i++) { 959 | a[i] = Unserialize(); 960 | } 961 | stream.get(); 962 | references.push_back(a); 963 | return a; 964 | } 965 | 966 | inline std::vector ReadListWithoutTag() { 967 | return ReadListWithoutTag >(); 968 | } 969 | 970 | template 971 | ReturnType ReadMapWithoutTag() { 972 | typedef BOOST_DEDUCED_TYPENAME NonCVKeyType::type key; 973 | typedef BOOST_DEDUCED_TYPENAME NonCVValueType::type value; 974 | int count = ReadInt(HproseTags::TagOpenbrace); 975 | ReturnType map; 976 | for (int i = 0; i < count; i++) { 977 | key k = Unserialize(); 978 | value v = Unserialize(); 979 | map[k] = v; 980 | } 981 | stream.get(); 982 | references.push_back(map); 983 | return map; 984 | } 985 | 986 | inline std::tr1::unordered_map ReadMapWithoutTag() { 987 | return ReadMapWithoutTag >(); 988 | } 989 | 990 | void ReadClass() { 991 | std::string name = ReadStringWithoutTag(); 992 | int count = ReadInt(HproseTags::TagOpenbrace); 993 | std::vector attrs; 994 | attrs.reserve(count); 995 | for (int i = 0; i < count; i++) { 996 | attrs.push_back(ReadString()); 997 | } 998 | CheckTag(HproseTags::TagClosebrace); 999 | const std::type_info * type = ClassManager::SharedInstance()->GetClass(name); 1000 | if (type) { 1001 | classRef.push_back(type); 1002 | attrsRef[type] = attrs; 1003 | } 1004 | } 1005 | 1006 | template 1007 | ReturnType ReadObjectWithoutTag() { 1008 | const std::type_info * type = classRef[ReadInt(HproseTags::TagOpenbrace)]; 1009 | std::vector & attrs = attrsRef[type]; 1010 | std::string alias = ClassManager::SharedInstance()->GetClassAlias(type); 1011 | ClassManager::ClassProperty * m = ClassManager::SharedInstance()->GetClassProperty(alias); 1012 | ReturnType o; 1013 | references.push_back(&o); 1014 | for (size_t i = 0; i < attrs.size(); i++) { 1015 | (*m)[attrs[i]].Unserialize(*this, o); 1016 | } 1017 | CheckTag(HproseTags::TagClosebrace); 1018 | return o; 1019 | } 1020 | 1021 | template 1022 | ReturnType ReadRef() { 1023 | if (simple) { 1024 | HPROSE_THROW_EXCEPTION("Not supported yet."); 1025 | } 1026 | Any a = references[ReadIntWithoutTag()]; 1027 | try { 1028 | return Any::cast(a); 1029 | } catch (...) { 1030 | HPROSE_THROW_EXCEPTION(CastError(a.type().name(), typeid(ReturnType).name())); 1031 | } 1032 | } 1033 | 1034 | template 1035 | inline ReturnType ReadStringRef() { 1036 | typedef BOOST_DEDUCED_TYPENAME NonCVElementType::type element; 1037 | std::basic_string chars = ReadRef >(); 1038 | return ReadCharsAsString(chars, CharSize()); 1039 | } 1040 | 1041 | inline std::string ReadStringRef() { 1042 | return ReadStringRef(); 1043 | } 1044 | 1045 | private: 1046 | 1047 | inline std::string UnexpectedTag(char tag) { 1048 | if (tag == -1) { 1049 | return "No byte found in stream"; 1050 | } else { 1051 | return std::string("Unexpected serialize tag '") + tag + "' in stream"; 1052 | } 1053 | } 1054 | 1055 | inline std::string CastError(const std::string & srctype, const std::string & desttype) { 1056 | return srctype + " can't change to " + desttype; 1057 | } 1058 | 1059 | template 1060 | inline std::string CastError(char tag) { 1061 | return CastError(TagToString(tag), typeid(DestType).name()); 1062 | } 1063 | 1064 | std::string TagToString(char tag) { 1065 | switch (tag) { 1066 | case '0': 1067 | case '1': 1068 | case '2': 1069 | case '3': 1070 | case '4': 1071 | case '5': 1072 | case '6': 1073 | case '7': 1074 | case '8': 1075 | case '9': 1076 | case HproseTags::TagInteger: return "Integer"; 1077 | case HproseTags::TagLong: return "Long"; 1078 | case HproseTags::TagDouble: return "Double"; 1079 | case HproseTags::TagNull: return "Null"; 1080 | case HproseTags::TagEmpty: return "Empty String"; 1081 | case HproseTags::TagTrue: return "Boolean True"; 1082 | case HproseTags::TagFalse: return "Boolean False"; 1083 | case HproseTags::TagNaN: return "NaN"; 1084 | case HproseTags::TagInfinity: return "Infinity"; 1085 | case HproseTags::TagDate: return "DateTime"; 1086 | case HproseTags::TagTime: return "DateTime"; 1087 | case HproseTags::TagBytes: return "Bytes"; 1088 | case HproseTags::TagUTF8Char: return "Char"; 1089 | case HproseTags::TagString: return "String"; 1090 | case HproseTags::TagGuid: return "Guid"; 1091 | case HproseTags::TagList: return "List"; 1092 | case HproseTags::TagMap: return "Map"; 1093 | case HproseTags::TagClass: return "Class"; 1094 | case HproseTags::TagObject: return "Object"; 1095 | case HproseTags::TagRef: return "Object Reference"; 1096 | case HproseTags::TagError: HPROSE_THROW_EXCEPTION(ReadString()); 1097 | default: HPROSE_THROW_EXCEPTION(UnexpectedTag(tag)); 1098 | } 1099 | } 1100 | 1101 | private: 1102 | 1103 | std::istream & stream; 1104 | bool simple; 1105 | 1106 | std::vector references; 1107 | std::vector classRef; 1108 | std::tr1::unordered_map > attrsRef; 1109 | 1110 | }; // class HproseReader 1111 | 1112 | } // namespace hprose 1113 | 1114 | #endif // HPROSE_IO_HPROSE_READER_HPP 1115 | -------------------------------------------------------------------------------- /hprose/io/HproseTags.hpp: -------------------------------------------------------------------------------- 1 | /**********************************************************\ 2 | | | 3 | | hprose | 4 | | | 5 | | Official WebSite: http://www.hprose.com/ | 6 | | http://www.hprose.org/ | 7 | | | 8 | \**********************************************************/ 9 | 10 | /**********************************************************\ 11 | * * 12 | * HproseTags.hpp * 13 | * * 14 | * hprose tags unit for cpp. * 15 | * * 16 | * LastModified: Jun 15, 2014 * 17 | * Author: Chen fei * 18 | * * 19 | \**********************************************************/ 20 | 21 | #ifndef HPROSE_IO_HPROSE_TAGS_HPP 22 | #define HPROSE_IO_HPROSE_TAGS_HPP 23 | 24 | #if defined(_MSC_VER) && (_MSC_VER >= 1020) 25 | #pragma once 26 | #endif 27 | 28 | namespace hprose { namespace HproseTags { 29 | 30 | /* Serialize Tags */ 31 | const char TagInteger = 'i'; 32 | const char TagLong = 'l'; 33 | const char TagDouble = 'd'; 34 | const char TagNull = 'n'; 35 | const char TagEmpty = 'e'; 36 | const char TagTrue = 't'; 37 | const char TagFalse = 'f'; 38 | const char TagNaN = 'N'; 39 | const char TagInfinity = 'I'; 40 | const char TagDate = 'D'; 41 | const char TagTime = 'T'; 42 | const char TagUTC = 'Z'; 43 | const char TagBytes = 'b'; 44 | const char TagUTF8Char = 'u'; 45 | const char TagString = 's'; 46 | const char TagGuid = 'g'; 47 | const char TagList = 'a'; 48 | const char TagMap = 'm'; 49 | const char TagClass = 'c'; 50 | const char TagObject = 'o'; 51 | const char TagRef = 'r'; 52 | /* Serialize Marks */ 53 | const char TagPos = '+'; 54 | const char TagNeg = '-'; 55 | const char TagSemicolon = ';'; 56 | const char TagOpenbrace = '{'; 57 | const char TagClosebrace = '}'; 58 | const char TagQuote = '"'; 59 | const char TagPoint = '.'; 60 | /* Protocol Tags */ 61 | const char TagFunctions = 'F'; 62 | const char TagCall = 'C'; 63 | const char TagResult = 'R'; 64 | const char TagArgument = 'A'; 65 | const char TagError = 'E'; 66 | const char TagEnd = 'z'; 67 | 68 | } } // namespaces 69 | 70 | #endif // HPROSE_IO_HPROSE_TAGS_HPP 71 | -------------------------------------------------------------------------------- /hprose/io/HproseTypes.hpp: -------------------------------------------------------------------------------- 1 | /**********************************************************\ 2 | | | 3 | | hprose | 4 | | | 5 | | Official WebSite: http://www.hprose.com/ | 6 | | http://www.hprose.org/ | 7 | | | 8 | \**********************************************************/ 9 | 10 | /**********************************************************\ 11 | * * 12 | * HproseTypes.hpp * 13 | * * 14 | * hprose types unit for cpp. * 15 | * * 16 | * LastModified: Jun 15, 2014 * 17 | * Author: Chen fei * 18 | * * 19 | \**********************************************************/ 20 | 21 | #ifndef HPROSE_IO_HPROSE_TYPES_HPP 22 | #define HPROSE_IO_HPROSE_TYPES_HPP 23 | 24 | #if defined(_MSC_VER) && (_MSC_VER >= 1020) 25 | #pragma once 26 | #endif 27 | 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | 36 | //#ifdef BOOST_NO_CXX11_HDR_ARRAY 37 | //#include 38 | //#endif 39 | //#ifdef BOOST_NO_CXX11_SMART_PTR 40 | //#include 41 | //#endif 42 | #include 43 | #include 44 | #include 45 | #include 46 | #include 47 | #include 48 | 49 | namespace hprose { 50 | 51 | #if !defined(BOOST_NO_CXX11_CHAR16_T) 52 | typedef char16_t char_type; 53 | #elif WCHAR_MAX == USHRT_MAX 54 | typedef wchar_t char_type; 55 | #else 56 | typedef unsigned short char_type; 57 | #endif 58 | 59 | #if !defined(BOOST_NO_LONG_LONG) 60 | typedef long long long_type; 61 | #elif defined(BOOST_HAS_MS_INT64) 62 | typedef __int64 long_type; 63 | #else 64 | typedef long long_type; 65 | #endif 66 | 67 | template 68 | struct IntToType { 69 | BOOST_STATIC_CONSTANT(int, value = v); 70 | }; 71 | 72 | // Special Types 73 | typedef IntToType<-4> UnknownType; 74 | #ifndef BOOST_NO_CXX11_NULLPTR 75 | typedef IntToType<-3> NullPtrType; // c++0x std::nullptr_t 76 | #endif 77 | typedef IntToType<-2> AutoPtrType; 78 | typedef IntToType<-1> PointerType; // std::tr1::is_pointer 79 | typedef IntToType< 0> AnyType; 80 | // Native and STL Types 81 | typedef IntToType< 1> BoolType; 82 | typedef IntToType< 2> ByteType; 83 | typedef IntToType< 3> CharType; 84 | typedef IntToType< 4> EnumType; // std::tr1::is_enum 85 | typedef IntToType< 5> IntegerType; 86 | typedef IntToType< 6> LongType; 87 | typedef IntToType< 7> DoubleType; 88 | typedef IntToType< 8> TimeType; 89 | typedef IntToType< 9> BytesType; 90 | typedef IntToType<10> StringType; 91 | typedef IntToType<11> GuidType; 92 | typedef IntToType<12> ListType; 93 | typedef IntToType<13> MapType; 94 | typedef IntToType<14> ObjectType; // std::tr1::is_class 95 | 96 | template 97 | struct TypeToType { 98 | typedef BOOST_DEDUCED_TYPENAME std::is_pointer is_pointer; 99 | typedef BOOST_DEDUCED_TYPENAME std::is_enum is_enum; 100 | typedef BOOST_DEDUCED_TYPENAME std::is_class is_class; 101 | typedef IntToType< 102 | is_pointer::value 103 | ? PointerType::value 104 | : (is_enum::value 105 | ? EnumType::value 106 | : (is_class::value 107 | ? ObjectType::value 108 | : UnknownType::value))> type; 109 | }; 110 | 111 | #ifndef BOOST_NO_CXX11_NULLPTR 112 | template<> 113 | struct TypeToType { 114 | typedef NullPtrType type; 115 | }; 116 | #endif 117 | 118 | #ifndef BOOST_NO_AUTO_PTR 119 | template 120 | struct TypeToType > { // departed in c++0x 121 | typedef AutoPtrType type; 122 | typedef Type element; 123 | }; 124 | #endif 125 | 126 | #ifndef BOOST_NO_CXX11_SMART_PTR 127 | template 128 | struct TypeToType > { 129 | typedef AutoPtrType type; 130 | typedef Type element; 131 | }; 132 | 133 | template 134 | struct TypeToType > { 135 | typedef AutoPtrType type; 136 | typedef Type element; 137 | }; 138 | #endif 139 | 140 | //template 141 | //struct TypeToType > { 142 | // typedef AutoPtrType type; 143 | // typedef Type element; 144 | //}; 145 | // 146 | //template 147 | //struct TypeToType > { 148 | // typedef AutoPtrType type; 149 | // typedef Type element; 150 | //}; 151 | 152 | template<> 153 | struct TypeToType { 154 | typedef AnyType type; 155 | }; 156 | 157 | template<> 158 | struct TypeToType { 159 | typedef BoolType type; 160 | }; 161 | 162 | template<> 163 | struct TypeToType { 164 | typedef CharType type; 165 | }; 166 | 167 | template<> 168 | struct TypeToType { 169 | typedef CharType type; 170 | }; 171 | 172 | #ifndef BOOST_NO_CXX11_CHAR16_T 173 | template<> 174 | struct TypeToType { 175 | typedef CharType type; 176 | }; 177 | #endif 178 | 179 | #ifndef BOOST_NO_CXX11_CHAR32_T 180 | template<> 181 | struct TypeToType { 182 | typedef CharType type; 183 | }; 184 | #endif 185 | 186 | template<> 187 | struct TypeToType { 188 | typedef ByteType type; 189 | }; 190 | 191 | template<> 192 | struct TypeToType { 193 | typedef ByteType type; 194 | }; 195 | 196 | template<> 197 | struct TypeToType { 198 | typedef IntegerType type; 199 | }; 200 | 201 | template<> 202 | struct TypeToType { 203 | typedef IntegerType type; 204 | }; 205 | 206 | template<> 207 | struct TypeToType { 208 | typedef IntegerType type; 209 | }; 210 | 211 | template<> 212 | struct TypeToType { 213 | typedef LongType type; 214 | }; 215 | 216 | template<> 217 | struct TypeToType { 218 | #if LONG_MAX == INT_MAX 219 | typedef IntegerType type; 220 | #else 221 | typedef LongType type; 222 | #endif 223 | }; 224 | 225 | template<> 226 | struct TypeToType { 227 | typedef LongType type; 228 | }; 229 | 230 | #if !defined(BOOST_NO_LONG_LONG) 231 | template<> 232 | struct TypeToType { 233 | typedef LongType type; 234 | }; 235 | 236 | template<> 237 | struct TypeToType { 238 | typedef LongType type; 239 | }; 240 | #elif defined(BOOST_HAS_MS_INT64) 241 | template<> 242 | struct TypeToType<__int64> { 243 | typedef LongType type; 244 | }; 245 | 246 | template<> 247 | struct TypeToType { 248 | typedef LongType type; 249 | }; 250 | #endif 251 | 252 | #ifdef BOOST_HAS_INT128 253 | template<> 254 | struct TypeToType<__int128> { 255 | typedef LongType type; 256 | }; 257 | 258 | template<> 259 | struct TypeToType { 260 | typedef LongType type; 261 | }; 262 | #endif 263 | 264 | //template<> 265 | //struct TypeToType { 266 | // typedef LongType type; 267 | //}; 268 | 269 | template<> 270 | struct TypeToType { 271 | typedef DoubleType type; 272 | }; 273 | 274 | template<> 275 | struct TypeToType { 276 | typedef DoubleType type; 277 | }; 278 | 279 | template<> 280 | struct TypeToType { 281 | typedef DoubleType type; 282 | }; 283 | 284 | //template<> 285 | //struct TypeToType { 286 | // typedef TimeType type; 287 | //}; 288 | 289 | template<> 290 | struct TypeToType { 291 | typedef StringType type; 292 | typedef char element; 293 | }; 294 | 295 | template<> 296 | struct TypeToType { 297 | typedef StringType type; 298 | typedef char element; 299 | }; 300 | 301 | template<> 302 | struct TypeToType { 303 | typedef StringType type; 304 | typedef wchar_t element; 305 | }; 306 | 307 | template<> 308 | struct TypeToType { 309 | typedef StringType type; 310 | typedef wchar_t element; 311 | }; 312 | 313 | #ifndef BOOST_NO_CXX11_CHAR16_T 314 | template<> 315 | struct TypeToType { 316 | typedef StringType type; 317 | typedef char16_t element; 318 | }; 319 | 320 | template<> 321 | struct TypeToType { 322 | typedef StringType type; 323 | typedef char16_t element; 324 | }; 325 | #endif 326 | 327 | #ifndef BOOST_NO_CXX11_CHAR32_T 328 | template<> 329 | struct TypeToType { 330 | typedef StringType type; 331 | typedef char32_t element; 332 | }; 333 | 334 | template<> 335 | struct TypeToType { 336 | typedef StringType type; 337 | typedef char32_t element; 338 | }; 339 | #endif 340 | 341 | template 342 | struct TypeToType > { 343 | typedef StringType type; 344 | typedef Element element; 345 | }; 346 | 347 | template 348 | struct TypeToType > { 349 | typedef StringType type; 350 | }; 351 | 352 | template 353 | struct TypeToType > { 354 | typedef StringType type; 355 | }; 356 | 357 | template 358 | struct TypeToType > { 359 | typedef StringType type; 360 | }; 361 | 362 | #ifdef BOOST_WINDOWS 363 | template<> 364 | struct TypeToType { 365 | typedef GuidType type; 366 | }; 367 | #else 368 | //template<> 369 | //struct TypeToType { 370 | // typedef GuidType type; 371 | //}; 372 | #endif 373 | 374 | template 375 | struct ContainerType { 376 | typedef ListType type; 377 | }; 378 | 379 | template<> 380 | struct ContainerType { 381 | typedef BytesType type; 382 | }; 383 | 384 | template<> 385 | struct ContainerType { 386 | typedef BytesType type; 387 | }; 388 | 389 | template<> 390 | struct ContainerType { 391 | typedef BytesType type; 392 | }; 393 | 394 | template 395 | struct StaticArrayType { 396 | typedef ListType type; 397 | }; 398 | 399 | template<> 400 | struct StaticArrayType { 401 | typedef BytesType type; 402 | }; 403 | 404 | template<> 405 | struct StaticArrayType { 406 | typedef BytesType type; 407 | }; 408 | 409 | template<> 410 | struct StaticArrayType { 411 | typedef StringType type; 412 | }; 413 | 414 | template<> 415 | struct StaticArrayType { 416 | typedef StringType type; 417 | }; 418 | 419 | #ifndef BOOST_NO_CXX11_CHAR16_T 420 | template<> 421 | struct StaticArrayType { 422 | typedef StringType type; 423 | }; 424 | #endif 425 | 426 | #ifndef BOOST_NO_CXX11_CHAR32_T 427 | template<> 428 | struct StaticArrayType { 429 | typedef StringType type; 430 | }; 431 | #endif 432 | 433 | template 434 | struct TypeToType > { 435 | typedef BOOST_DEDUCED_TYPENAME ContainerType::type type; 436 | typedef Element element; 437 | }; 438 | 439 | //#ifndef BOOST_NO_CXX11_HDR_ARRAY 440 | //template 441 | //struct TypeToType > { 442 | // typedef BOOST_DEDUCED_TYPENAME ContainerType::type type; 443 | // typedef Element element; 444 | //}; 445 | //#endif 446 | 447 | template 448 | struct TypeToType > { 449 | typedef BOOST_DEDUCED_TYPENAME ContainerType::type type; 450 | typedef Element element; 451 | }; 452 | 453 | template 454 | struct TypeToType > { 455 | typedef BOOST_DEDUCED_TYPENAME ContainerType::type type; 456 | typedef Element element; 457 | }; 458 | 459 | template 460 | struct TypeToType > { 461 | typedef BOOST_DEDUCED_TYPENAME ContainerType::type type; 462 | typedef Element element; 463 | }; 464 | 465 | template 466 | struct TypeToType > { 467 | typedef BOOST_DEDUCED_TYPENAME ContainerType::type type; 468 | typedef Element element; 469 | }; 470 | 471 | template 472 | struct TypeToType > { 473 | typedef BOOST_DEDUCED_TYPENAME ContainerType::type type; 474 | typedef Element element; 475 | }; 476 | 477 | template 478 | struct TypeToType > { 479 | typedef BOOST_DEDUCED_TYPENAME ContainerType::type type; 480 | typedef Element element; 481 | }; 482 | 483 | template 484 | struct TypeToType > { 485 | typedef BOOST_DEDUCED_TYPENAME ContainerType::type type; 486 | typedef Element element; 487 | }; 488 | 489 | template 490 | struct TypeToType > { 491 | typedef ListType type; 492 | typedef bool element; 493 | }; 494 | 495 | template 496 | struct TypeToType > { 497 | typedef BOOST_DEDUCED_TYPENAME ContainerType::type type; 498 | typedef Element element; 499 | }; 500 | 501 | template 502 | struct TypeToType > { 503 | typedef BOOST_DEDUCED_TYPENAME ContainerType::type type; 504 | typedef Element element; 505 | }; 506 | 507 | //#ifdef BOOST_NO_CXX11_HDR_UNORDERED_SET 508 | //template 509 | //struct TypeToType > { 510 | // typedef BOOST_DEDUCED_TYPENAME ContainerType::type type; 511 | // typedef Element element; 512 | //}; 513 | // 514 | //template 515 | //struct TypeToType > { 516 | // typedef BOOST_DEDUCED_TYPENAME ContainerType::type type; 517 | // typedef Element element; 518 | //}; 519 | //#endif 520 | 521 | template 522 | struct TypeToType > { 523 | typedef MapType type; 524 | typedef KeyType key; 525 | typedef ValueType value; 526 | }; 527 | 528 | template 529 | struct TypeToType > { 530 | typedef MapType type; 531 | typedef KeyType key; 532 | typedef ValueType value; 533 | }; 534 | 535 | template 536 | struct TypeToType > { 537 | typedef MapType type; 538 | typedef KeyType key; 539 | typedef ValueType value; 540 | }; 541 | 542 | template 543 | struct TypeToType > { 544 | typedef MapType type; 545 | typedef KeyType key; 546 | typedef ValueType value; 547 | }; 548 | 549 | //#ifdef BOOST_NO_CXX11_HDR_UNORDERED_MAP 550 | //template 551 | //struct TypeToType > { 552 | // typedef MapType type; 553 | // typedef KeyType key; 554 | // typedef ValueType value; 555 | //}; 556 | // 557 | //template 558 | //struct TypeToType > { 559 | // typedef MapType type; 560 | // typedef KeyType key; 561 | // typedef ValueType value; 562 | //}; 563 | //#endif 564 | 565 | template 566 | struct NonCVType 567 | : public TypeToType::type>::type { 568 | }; 569 | 570 | template 571 | struct NonCVListType 572 | : public ContainerType::type>::type { 573 | }; 574 | 575 | template 576 | struct NonCVArrayType 577 | : public StaticArrayType::type>::type { 578 | }; 579 | 580 | template 581 | struct NonCVElementType { 582 | typedef BOOST_DEDUCED_TYPENAME std::remove_cv::type noncv; 583 | typedef BOOST_DEDUCED_TYPENAME TypeToType::element type; 584 | }; 585 | 586 | template 587 | struct NonCVKeyType { 588 | typedef BOOST_DEDUCED_TYPENAME std::remove_cv::type noncv; 589 | typedef BOOST_DEDUCED_TYPENAME TypeToType::key type; 590 | }; 591 | 592 | template 593 | struct NonCVValueType { 594 | typedef BOOST_DEDUCED_TYPENAME std::remove_cv::type noncv; 595 | typedef BOOST_DEDUCED_TYPENAME TypeToType::value type; 596 | }; 597 | 598 | } // namespace hprose 599 | 600 | #endif // HPROSE_IO_HPROSE_TYPES_HPP 601 | -------------------------------------------------------------------------------- /hprose/io/HproseWriter.hpp: -------------------------------------------------------------------------------- 1 | /**********************************************************\ 2 | | | 3 | | hprose | 4 | | | 5 | | Official WebSite: http://www.hprose.com/ | 6 | | http://www.hprose.org/ | 7 | | | 8 | \**********************************************************/ 9 | 10 | /**********************************************************\ 11 | * * 12 | * HproseWriter.hpp * 13 | * * 14 | * hprose writer unit for cpp. * 15 | * * 16 | * LastModified: Apr 27, 2015 * 17 | * Author: Chen fei * 18 | * * 19 | \**********************************************************/ 20 | 21 | #ifndef HPROSE_IO_HPROSE_WRITER_HPP 22 | #define HPROSE_IO_HPROSE_WRITER_HPP 23 | 24 | #if defined(_MSC_VER) && (_MSC_VER >= 1020) 25 | #pragma once 26 | #endif 27 | 28 | #include 29 | 30 | #include 31 | #include 32 | #include 33 | 34 | namespace hprose { 35 | 36 | class HproseWriter { 37 | public: 38 | 39 | HproseWriter(std::ostream & stream, bool simple = false) 40 | : stream(stream), simple(simple) { 41 | } 42 | 43 | public: 44 | 45 | template 46 | inline void Serialize(const ValueType & value) { 47 | Serialize(value, NonCVType()); 48 | } 49 | 50 | template 51 | inline void Serialize(const ValueType (&value)[ArraySize]) { 52 | Serialize(value, NonCVArrayType()); 53 | } 54 | 55 | #ifndef BOOST_NO_INITIALIZER_LISTS 56 | template 57 | inline void Serialize(const std::initializer_list & value) { 58 | Serialize(value, NonCVListType()); 59 | } 60 | #endif 61 | 62 | public: 63 | 64 | inline void WriteNull() { 65 | stream << HproseTags::TagNull; 66 | } 67 | 68 | inline void WriteEmpty() { 69 | stream << HproseTags::TagEmpty; 70 | } 71 | 72 | inline void WriteBool(const bool & b) { 73 | stream << (b ? HproseTags::TagTrue : HproseTags::TagFalse); 74 | } 75 | 76 | template 77 | inline void WriteEnum(const ValueType & e) { 78 | HPROSE_STATIC_ASSERT(NonCVType::value == EnumType::value, "Require EnumType"); 79 | WriteInteger(static_cast(e), SignedType()); 80 | } 81 | 82 | template 83 | inline void WriteInteger(const ValueType & i) { 84 | HPROSE_STATIC_ASSERT( 85 | (NonCVType::value == ByteType::value) || 86 | (NonCVType::value == CharType::value) || 87 | (NonCVType::value == IntegerType::value), "Require [ByteType, CharType, IntegerType]"); 88 | WriteInteger(i, std::is_signed()); 89 | } 90 | 91 | template 92 | inline void WriteLong(const ValueType & l) { // Todo: BigInteger 93 | HPROSE_STATIC_ASSERT( 94 | (NonCVType::value == ByteType::value) || 95 | (NonCVType::value == CharType::value) || 96 | (NonCVType::value == IntegerType::value) || 97 | (NonCVType::value == LongType::value), "Require [ByteType, CharType, IntegerType, LongType]"); 98 | WriteLong(l, std::is_signed()); 99 | } 100 | 101 | inline void WriteNaN() { 102 | stream << HproseTags::TagNaN; 103 | } 104 | 105 | inline void WriteInfinity(bool positive) { 106 | stream << HproseTags::TagInfinity << (positive ? HproseTags::TagPos : HproseTags::TagNeg); 107 | } 108 | 109 | template 110 | void WriteDouble(const ValueType & d) { 111 | HPROSE_STATIC_ASSERT(NonCVType::value == DoubleType::value, "Require DoubleType"); 112 | if (d != d) { 113 | WriteNaN(); 114 | } else if (d == std::numeric_limits::infinity()) { 115 | WriteInfinity(true); 116 | } else if (d == -std::numeric_limits::infinity()) { 117 | WriteInfinity(false); 118 | } else { 119 | stream.precision(std::numeric_limits::digits10); 120 | stream << HproseTags::TagDouble << d << HproseTags::TagSemicolon; 121 | } 122 | } 123 | 124 | template 125 | void WriteBytes(const ValueType & b, bool checkRef = true) { 126 | HPROSE_STATIC_ASSERT(NonCVType::value == BytesType::value, "Require BytesType"); 127 | size_t n = b.size(); 128 | if (WriteRef(&b, checkRef)) { 129 | stream << HproseTags::TagBytes; 130 | if (n > 0) WriteIntFast(n, stream); 131 | stream << HproseTags::TagQuote; 132 | #ifdef _MSC_VER 133 | stream.write(reinterpret_cast(b.data()), n); 134 | #else 135 | for (BOOST_DEDUCED_TYPENAME ValueType::const_iterator itr = b.begin(); itr != b.end(); ++itr) { 136 | stream << *itr; 137 | } 138 | #endif 139 | stream << HproseTags::TagQuote; 140 | } 141 | } 142 | 143 | template 144 | void WriteBytes(const std::stack & s, bool checkRef = true) { 145 | #ifdef _MSC_VER 146 | WriteBytes(s._Get_container(), checkRef); 147 | #else 148 | size_t n = s.size(); 149 | if (WriteRef(&s, checkRef)) { 150 | std::stack temp = s; 151 | std::vector v; 152 | v.resize(n); 153 | for (size_t i = 1; i <= n; i++) { 154 | v[n - i] = temp.top(); 155 | temp.pop(); 156 | } 157 | WriteBytes(v, false); 158 | } 159 | #endif 160 | } 161 | 162 | template 163 | void WriteBytes(const std::queue & q, bool checkRef = true) { 164 | #ifdef _MSC_VER 165 | WriteBytes(q._Get_container(), checkRef); 166 | #else 167 | size_t n = q.size(); 168 | if (WriteRef(&q, checkRef)) { 169 | std::queue temp = q; 170 | std::vector v; 171 | v.resize(n); 172 | for (size_t i = 0; i < n; i++) { 173 | v[i] = temp.front(); 174 | temp.pop(); 175 | } 176 | WriteBytes(v, false); 177 | } 178 | #endif 179 | } 180 | 181 | template 182 | void WriteBytes(const ValueType * b, size_t n, bool checkRef = true) { 183 | HPROSE_STATIC_ASSERT(NonCVListType::value == BytesType::value, "Require BytesType"); 184 | if (checkRef) { 185 | references.push_back(Any()); 186 | } 187 | stream << HproseTags::TagBytes; 188 | if (n > 0) WriteIntFast(n, stream); 189 | stream << HproseTags::TagQuote; 190 | stream.write(reinterpret_cast(b), n); 191 | stream << HproseTags::TagQuote; 192 | } 193 | 194 | template 195 | inline void WriteBytes(const ValueType (&value)[ArraySize], bool checkRef = true) { 196 | WriteBytes(value, ArraySize, checkRef); 197 | } 198 | 199 | #ifndef BOOST_NO_INITIALIZER_LISTS 200 | template 201 | inline void WriteBytes(const std::initializer_list & l, bool checkRef = true) { 202 | if (WriteRef(&l, checkRef)) { 203 | WriteBytes(l.begin(), l.size(), false); 204 | } 205 | } 206 | #endif 207 | 208 | template 209 | inline void WriteUTF8Char(const ValueType & c) { 210 | HPROSE_STATIC_ASSERT(NonCVType::value == CharType::value, "Require CharType"); 211 | size_t len = UTF8Encode(c, buf, CharSize()); 212 | if (len > 0 && len < 4) { 213 | stream << HproseTags::TagUTF8Char; 214 | stream.write(buf, len); 215 | } else { 216 | HPROSE_THROW_EXCEPTION("Malformed UTF-8 char"); 217 | } 218 | } 219 | 220 | inline void WriteUTF8Char(const char & c) { 221 | #if defined(BOOST_WINDOWS) && (!defined(HPROSE_CHARSET_UTF8)) 222 | WriteUTF8Char(AnsiToUnicode(c)); 223 | #else 224 | if (is_ascii(c)) { 225 | stream << HproseTags::TagUTF8Char << c; 226 | } else { 227 | WriteInteger(c); 228 | } 229 | #endif 230 | } 231 | 232 | template 233 | inline void WriteString(const ValueType & s, bool checkRef = true) { 234 | typedef BOOST_DEDUCED_TYPENAME NonCVElementType::type element; 235 | WriteString(std::basic_string(s), checkRef); 236 | } 237 | 238 | template 239 | inline void WriteString(const std::basic_string & s, bool checkRef = true) { 240 | if (WriteRef(s, checkRef)) { 241 | stream << HproseTags::TagString; 242 | WriteUTF8String(UTF8Encode(s), UTF16Size(s), stream); 243 | } 244 | } 245 | 246 | inline void WriteString(const std::string & s, bool checkRef = true) { 247 | #if defined(BOOST_WINDOWS) && (!defined(HPROSE_CHARSET_UTF8)) 248 | WriteString(AnsiToUnicode(s), checkRef); 249 | #else 250 | size_t len = UTF8Length(s.begin(), s.end(), Char16Type()); 251 | if (len == 1) { 252 | stream << HproseTags::TagUTF8Char << s; 253 | } else { 254 | if (WriteRef(s, checkRef)) { 255 | stream << HproseTags::TagString; 256 | WriteUTF8String(s, len, stream); 257 | } 258 | } 259 | #endif 260 | } 261 | 262 | #ifdef BOOST_WINDOWS 263 | inline void WriteGUID(const GUID & g, bool checkRef = true) { 264 | if (WriteRef(g, checkRef)) { 265 | #ifdef __STDC_WANT_SECURE_LIB__ 266 | sprintf_s(buf, 40, 267 | #else 268 | sprintf(buf, 269 | #endif 270 | "g{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}", 271 | g.Data1, g.Data2, g.Data3, g.Data4[0], g.Data4[1], g.Data4[2], 272 | g.Data4[3], g.Data4[4], g.Data4[5], g.Data4[6], g.Data4[7]); 273 | stream.write(buf, 39); 274 | } 275 | } 276 | #else 277 | // inline void WriteGUID(const uuid_t & u, bool checkRef = true) { 278 | // if (WriteRef(u, checkRef)) { 279 | // buf[0] = 'g'; 280 | // uuid_unparse(u, &buf[1]); 281 | // // sprintf(buf, 282 | // // "g{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}", 283 | // // g.Data1, g.Data2, g.Data3, g.Data4[0], g.Data4[1], g.Data4[2], 284 | // // g.Data4[3], g.Data4[4], g.Data4[5], g.Data4[6], g.Data4[7]); 285 | // stream.write(buf, 39); 286 | // } 287 | // } 288 | #endif 289 | 290 | template 291 | void WriteList(const ValueType & a, bool checkRef = true) { 292 | HPROSE_STATIC_ASSERT( 293 | (NonCVType::value == BytesType::value) || 294 | (NonCVType::value == ListType::value), "Require [BytesType, ListType]"); 295 | size_t n = a.size(); 296 | if (n > 0) { 297 | if (WriteRef(&a, checkRef)) { 298 | stream << HproseTags::TagList; 299 | WriteIntFast(n, stream); 300 | stream << HproseTags::TagOpenbrace; 301 | for (BOOST_DEDUCED_TYPENAME ValueType::const_iterator itr = a.begin(); itr != a.end(); ++itr) { 302 | Serialize(*itr); 303 | } 304 | stream << HproseTags::TagClosebrace; 305 | } 306 | } else { 307 | stream << HproseTags::TagList << HproseTags::TagOpenbrace << HproseTags::TagClosebrace; 308 | } 309 | } 310 | 311 | template 312 | void WriteList(const std::stack & s, bool checkRef = true) { 313 | #ifdef _MSC_VER 314 | WriteList(s._Get_container(), checkRef); 315 | #else 316 | size_t n = s.size(); 317 | if (n > 0) { 318 | if (WriteRef(&s, checkRef)) { 319 | std::stack temp = s; 320 | std::vector v; 321 | v.resize(n); 322 | for (size_t i = 1; i <= n; i++) { 323 | v[n - i] = temp.top(); 324 | temp.pop(); 325 | } 326 | WriteList(v, false); 327 | } 328 | } else { 329 | stream << HproseTags::TagList << HproseTags::TagOpenbrace << HproseTags::TagClosebrace; 330 | } 331 | #endif 332 | } 333 | 334 | template 335 | void WriteList(const std::queue & q, bool checkRef = true) { 336 | #ifdef _MSC_VER 337 | WriteList(q._Get_container(), checkRef); 338 | #else 339 | size_t n = q.size(); 340 | if (n > 0) { 341 | if (WriteRef(&q, checkRef)) { 342 | std::queue temp = q; 343 | std::vector v; 344 | v.resize(n); 345 | for (size_t i = 0; i < n; i++) { 346 | v[i] = temp.front(); 347 | temp.pop(); 348 | } 349 | WriteList(v, false); 350 | } 351 | } else { 352 | stream << HproseTags::TagList << HproseTags::TagOpenbrace << HproseTags::TagClosebrace; 353 | } 354 | #endif 355 | } 356 | 357 | template 358 | void WriteList(const std::bitset & b, bool checkRef = true) { 359 | if (Bits > 0) { 360 | stream << HproseTags::TagList; 361 | WriteIntFast(Bits, stream); 362 | stream << HproseTags::TagOpenbrace; 363 | for (size_t i = 0; i < Bits; i++) { 364 | Serialize(b[i]); 365 | } 366 | stream << HproseTags::TagClosebrace; 367 | } else { 368 | stream << HproseTags::TagList << HproseTags::TagOpenbrace << HproseTags::TagClosebrace; 369 | } 370 | } 371 | 372 | template 373 | void WriteList(const ValueType * a, size_t n, bool checkRef = true) { 374 | if (checkRef) { 375 | references.push_back(Any()); 376 | } 377 | if (n > 0) { 378 | stream << HproseTags::TagList; 379 | WriteIntFast(n, stream); 380 | stream << HproseTags::TagOpenbrace; 381 | for (size_t i = 0; i < n; i++) { 382 | Serialize(a[i]); 383 | } 384 | stream << HproseTags::TagClosebrace; 385 | } else { 386 | stream << HproseTags::TagList << HproseTags::TagOpenbrace << HproseTags::TagClosebrace; 387 | } 388 | } 389 | 390 | template 391 | inline void WriteList(const ValueType (&value)[ArraySize], bool checkRef = true) { 392 | WriteList(value, ArraySize, checkRef); 393 | } 394 | 395 | #ifndef BOOST_NO_INITIALIZER_LISTS 396 | template 397 | inline void WriteList(const std::initializer_list & l, bool checkRef = true) { 398 | if (WriteRef(&l, checkRef)) { 399 | WriteList(l.begin(), l.size(), false); 400 | } 401 | } 402 | #endif 403 | 404 | template 405 | void WriteMap(const ValueType & m, bool checkRef = true) { 406 | HPROSE_STATIC_ASSERT(NonCVType::value == MapType::value, "Require MapType"); 407 | size_t n = m.size(); 408 | if (n > 0) { 409 | if (WriteRef(&m, checkRef)) { 410 | stream << HproseTags::TagMap; 411 | WriteIntFast(n, stream); 412 | stream << HproseTags::TagOpenbrace; 413 | for (BOOST_DEDUCED_TYPENAME ValueType::const_iterator itr = m.begin(); itr != m.end(); ++itr) { 414 | Serialize(itr->first); 415 | Serialize(itr->second); 416 | } 417 | stream << HproseTags::TagClosebrace; 418 | } 419 | } else { 420 | stream << HproseTags::TagMap << HproseTags::TagOpenbrace << HproseTags::TagClosebrace; 421 | } 422 | } 423 | 424 | template 425 | void WriteObject(const ValueType & o, bool checkRef = true) { 426 | if (WriteRef(&o, checkRef)) { 427 | const std::type_info * type = &typeid(ValueType); 428 | long cr; 429 | std::vector::iterator itr = std::find(classRef.begin(), classRef.end(), type); 430 | if (itr != classRef.end()) { 431 | cr = itr - classRef.begin(); 432 | } else { 433 | cr = WriteClass(o); 434 | } 435 | stream << HproseTags::TagObject; 436 | WriteIntFast((int)cr, stream); 437 | stream << HproseTags::TagOpenbrace; 438 | ClassManager::ClassProperty * m = ClassManager::SharedInstance()->GetClassProperty(type); 439 | if (m) { 440 | for (ClassManager::ClassProperty::const_iterator itr = m->begin(); itr != m->end(); ++itr) { 441 | itr->second.Serialize(*this, o); 442 | } 443 | } 444 | stream << HproseTags::TagClosebrace; 445 | } 446 | } 447 | 448 | private: 449 | 450 | struct SerializeCache { 451 | int refCount; 452 | std::string data; 453 | }; 454 | 455 | typedef std::tr1::unordered_map ClassCaches; 456 | 457 | private: 458 | 459 | template 460 | inline void Serialize(const ValueType &, UnknownType) { 461 | HPROSE_THROW_EXCEPTION(std::string(typeid(ValueType).name()) + " is not a serializable type"); 462 | } 463 | 464 | #ifndef BOOST_NO_CXX11_NULLPTR 465 | inline void Serialize(const std::nullptr_t &, NullPtrType) { 466 | WriteNull(); 467 | } 468 | #endif 469 | 470 | template 471 | inline void Serialize(const ValueType & p, AutoPtrType) { 472 | Serialize(p.get()); // Pointer 473 | } 474 | 475 | template 476 | inline void Serialize(const ValueType & p, PointerType) { 477 | if (p) { 478 | Serialize(*p); 479 | } else { 480 | WriteNull(); 481 | } 482 | } 483 | 484 | template 485 | inline void Serialize(const ValueType & a, AnyType) { 486 | a.Serialize(*this); 487 | } 488 | 489 | template 490 | inline void Serialize(const ValueType & b, BoolType) { 491 | WriteBool(b); 492 | } 493 | 494 | template 495 | inline void Serialize(const ValueType & b, ByteType) { 496 | WriteInteger(b); 497 | } 498 | 499 | template 500 | inline void Serialize(const ValueType & c, CharType) { 501 | WriteUTF8Char(c); 502 | } 503 | 504 | template 505 | inline void Serialize(const ValueType & e, EnumType) { 506 | WriteEnum(e); 507 | } 508 | 509 | template 510 | inline void Serialize(const ValueType & i, IntegerType) { 511 | WriteInteger(i); 512 | } 513 | 514 | template 515 | inline void Serialize(const ValueType & l, LongType) { 516 | WriteLong(l); 517 | } 518 | 519 | template 520 | inline void Serialize(const ValueType & d, DoubleType) { 521 | WriteDouble(d); 522 | } 523 | 524 | template 525 | inline void Serialize(const ValueType & t, TimeType) { 526 | WriteDateTime(t); 527 | } 528 | 529 | template 530 | inline void Serialize(const ValueType & b, BytesType) { 531 | WriteBytes(b); 532 | } 533 | 534 | template 535 | inline void Serialize(const ValueType (&value)[ArraySize], BytesType) { 536 | WriteBytes(value); 537 | } 538 | 539 | template 540 | inline void Serialize(const ValueType & s, StringType) { 541 | typedef BOOST_DEDUCED_TYPENAME NonCVElementType::type element; 542 | Serialize(std::basic_string(s)); 543 | } 544 | 545 | template 546 | inline void Serialize(const std::basic_string & s, StringType) { 547 | switch (s.size()) { 548 | case 0: 549 | WriteEmpty(); 550 | break; 551 | case 1: 552 | WriteUTF8Char(s[0]); 553 | break; 554 | default: 555 | WriteString(s); 556 | } 557 | } 558 | 559 | template 560 | inline void Serialize(const ValueType (&value)[ArraySize], StringType) { 561 | size_t len = value[ArraySize - 1] == 0 ? (ArraySize - 1) : ArraySize; 562 | switch (len) { 563 | case 0: 564 | WriteEmpty(); 565 | break; 566 | case 1: 567 | WriteUTF8Char(value[0]); 568 | break; 569 | default: 570 | WriteString(std::basic_string(value, len)); 571 | } 572 | } 573 | 574 | template 575 | inline void Serialize(const std::basic_ostringstream & oss, StringType) { 576 | Serialize(oss.str()); 577 | } 578 | 579 | template 580 | inline void Serialize(const std::basic_stringbuf & sb, StringType) { 581 | Serialize(sb.str()); 582 | } 583 | 584 | template 585 | inline void Serialize(const std::basic_stringstream & ss, StringType) { 586 | Serialize(ss.str()); 587 | } 588 | 589 | template 590 | inline void Serialize(const ValueType & g, GuidType) { 591 | WriteGUID(g); 592 | } 593 | 594 | template 595 | inline void Serialize(const ValueType & a, ListType) { 596 | WriteList(a); 597 | } 598 | 599 | template 600 | inline void Serialize(const ValueType (&value)[ArraySize], ListType) { 601 | WriteList(value); 602 | } 603 | 604 | template 605 | inline void Serialize(const ValueType & m, MapType) { 606 | WriteMap(m); 607 | } 608 | 609 | template 610 | inline void Serialize(const ValueType & o, ObjectType) { 611 | WriteObject(o); 612 | } 613 | 614 | private: 615 | 616 | template 617 | inline void WriteInteger(ValueType i, const SignedType & s) { 618 | if (i >= 0 && i <= 9) { 619 | stream << static_cast('0' + i); 620 | } else { 621 | stream << HproseTags::TagInteger; 622 | WriteIntFast(i, stream, s); 623 | stream << HproseTags::TagSemicolon; 624 | } 625 | } 626 | 627 | template 628 | inline void WriteInteger(ValueType i, const UnignedType & u) { 629 | if (i <= 9) { 630 | stream << static_cast('0' + i); 631 | } else { 632 | stream << HproseTags::TagInteger; 633 | WriteIntFast(i, stream, u); 634 | stream << HproseTags::TagSemicolon; 635 | } 636 | } 637 | 638 | template 639 | inline void WriteLong(ValueType l, const SignedType & s) { 640 | if (l >= 0 && l <= 9) { 641 | stream << static_cast('0' + l); 642 | } else { 643 | stream << HproseTags::TagLong; 644 | WriteIntFast(l, stream, s); 645 | stream << HproseTags::TagSemicolon; 646 | } 647 | } 648 | 649 | template 650 | inline void WriteLong(ValueType l, const UnignedType & u) { 651 | if (l <= 9) { 652 | stream << static_cast('0' + l); 653 | } else { 654 | stream << HproseTags::TagLong; 655 | WriteIntFast(l, stream, u); 656 | stream << HproseTags::TagSemicolon; 657 | } 658 | } 659 | 660 | void WriteDateTime(const tm & t) { 661 | int year = t.tm_year + 1900; 662 | int month = t.tm_mon + 1; 663 | int day = t.tm_mday; 664 | int hour = t.tm_hour; 665 | int minute = t.tm_min; 666 | int second = t.tm_sec; 667 | if ((hour == 0) && (minute == 0) && (second == 0)) { 668 | WriteDate(year, month, day); 669 | } else if ((year == 1970) && (month == 1) && (day == 1)) { 670 | WriteTime(hour, minute, second); 671 | } else { 672 | WriteDate(year, month, day); 673 | WriteTime(hour, minute, second); 674 | } 675 | stream << HproseTags::TagUTC; 676 | } 677 | 678 | void WriteDate(int year, int month, int day) { 679 | stream << HproseTags::TagDate; 680 | stream << static_cast('0' + (year / 1000 % 10)); 681 | stream << static_cast('0' + (year / 100 % 10)); 682 | stream << static_cast('0' + (year / 10 % 10)); 683 | stream << static_cast('0' + (year % 10)); 684 | stream << static_cast('0' + (month / 10 % 10)); 685 | stream << static_cast('0' + (month % 10)); 686 | stream << static_cast('0' + (day / 10 % 10)); 687 | stream << static_cast('0' + (day % 10)); 688 | } 689 | 690 | void WriteTime(int hour, int minute, int second, int milliseconds = 0) { 691 | stream << HproseTags::TagTime; 692 | stream << static_cast('0' + (hour / 10 % 10)); 693 | stream << static_cast('0' + (hour % 10)); 694 | stream << static_cast('0' + (minute / 10 % 10)); 695 | stream << static_cast('0' + (minute % 10)); 696 | stream << static_cast('0' + (second / 10 % 10)); 697 | stream << static_cast('0' + (second % 10)); 698 | if (milliseconds > 0) { 699 | stream << HproseTags::TagPoint; 700 | stream << static_cast('0' + (milliseconds / 100 % 10)); 701 | stream << static_cast('0' + (milliseconds / 10 % 10)); 702 | stream << static_cast('0' + (milliseconds % 10)); 703 | } 704 | } 705 | 706 | inline void WriteUTF8String(const std::string & s, size_t len, std::ostream & os) { 707 | if (len) { 708 | WriteIntFast(len, os); 709 | } 710 | os << HproseTags::TagQuote << s << HproseTags::TagQuote; 711 | } 712 | 713 | inline void WriteUTF8String(const std::string & s, std::ostream & os) { 714 | #if defined(BOOST_WINDOWS) && (!defined(HPROSE_CHARSET_UTF8)) 715 | std::wstring w = AnsiToUnicode(s); 716 | WriteUTF8String(UTF8Encode(w), w.size(), os); 717 | #else 718 | WriteUTF8String(s, UTF8Length(s.begin(), s.end(), Char16Type()), os); 719 | #endif 720 | } 721 | 722 | template 723 | long WriteClass(const ValueType & o) { 724 | const std::type_info * type = &typeid(ValueType); 725 | SerializeCache cache = GetCache(type); 726 | if (cache.data.empty()) { 727 | cache.refCount = 0; 728 | std::string alias = ClassManager::SharedInstance()->GetClassAlias(type); 729 | if (!alias.empty()) { 730 | std::ostringstream os; 731 | os << HproseTags::TagClass; 732 | WriteUTF8String(alias, os); 733 | ClassManager::ClassProperty * m = ClassManager::SharedInstance()->GetClassProperty(alias); 734 | if (m) { 735 | size_t n = m->size(); 736 | if (n > 0) WriteIntFast(n, os); 737 | } 738 | os << HproseTags::TagOpenbrace; 739 | if (m) { 740 | for (ClassManager::ClassProperty::const_iterator itr = m->begin(); itr != m->end(); ++itr, ++cache.refCount) { 741 | os << HproseTags::TagString; 742 | WriteUTF8String(itr->first, os); 743 | } 744 | } 745 | os << HproseTags::TagClosebrace; 746 | cache.data = os.str(); 747 | SetCache(type, cache); 748 | } else { 749 | Serialize(o, UnknownType()); 750 | } 751 | } 752 | stream << cache.data; 753 | references.resize(references.size() + cache.refCount); 754 | classRef.push_back(type); 755 | return classRef.size() - 1; 756 | } 757 | 758 | template 759 | bool WriteRef(const ValueType & value, bool checkRef) { 760 | if (simple) return true; 761 | if (checkRef) { 762 | int ref = vector_index_of(references, value); 763 | if (ref > -1) { 764 | WriteRef(ref); 765 | return false; 766 | } 767 | } 768 | references.push_back(value); 769 | return true; 770 | } 771 | 772 | inline void WriteRef(int ref) { 773 | stream << HproseTags::TagRef; 774 | WriteIntFast(ref, stream); 775 | stream << HproseTags::TagSemicolon; 776 | } 777 | 778 | private: 779 | 780 | HPROSE_STATIC_MEMBER(ClassCaches, Caches); 781 | 782 | HPROSE_STATIC_MEMBER(boost::shared_mutex, Mutex); 783 | 784 | SerializeCache & GetCache(const std::type_info * type) { 785 | boost::shared_mutex & mutex = GetMutex(); 786 | boost::shared_lock lock(mutex); 787 | ClassCaches & caches = GetCaches(); 788 | return caches[type]; 789 | } 790 | 791 | void SetCache(const std::type_info * type, const SerializeCache & cache) { 792 | boost::shared_mutex & mutex = GetMutex(); 793 | boost::unique_lock lock(mutex); 794 | ClassCaches & caches = GetCaches(); 795 | caches[type] = cache; 796 | } 797 | 798 | private: 799 | 800 | char buf[40]; 801 | 802 | std::ostream & stream; 803 | bool simple; 804 | 805 | std::vector references; 806 | std::vector classRef; 807 | 808 | }; // class HproseWriter 809 | 810 | } // namespace hprose 811 | 812 | #endif // HPROSE_IO_HPROSE_WRITER_HPP 813 | -------------------------------------------------------------------------------- /tests/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "hprose/ext/CTime.hpp" 3 | #include "hprose/client.hpp" 4 | 5 | using namespace std; 6 | using namespace hprose; 7 | 8 | HproseHTTPClient client("http://www.hprose.com/example/"); 9 | 10 | boost::shared_mutex print_mutex; 11 | 12 | void println(string msg) { 13 | boost::unique_lock lock(print_mutex); 14 | cout << msg << endl; 15 | } 16 | 17 | void callback(string result, vector args) { 18 | println(result); 19 | } 20 | 21 | struct handler { 22 | void operator()(string result, vector args) { 23 | println(result); 24 | } 25 | }; 26 | 27 | void hello1() { 28 | string args[] = {"world"}; 29 | cout << client.Invoke("hello", args) << endl; 30 | } 31 | 32 | void hello2() { 33 | string args[] = {"asynchronous world 2"}; 34 | client.AsyncInvoke("hello", args, callback); 35 | } 36 | 37 | void hello3() { 38 | vector args; 39 | args.push_back("asynchronous world 3"); 40 | client.AsyncInvoke("hello", args, handler()); 41 | } 42 | 43 | int main() { 44 | cout << "hello1 start ............" << endl; 45 | hello1(); 46 | cout << "hello2 start 5 times ............" << endl; 47 | for (int i = 0; i < 5; ++i) { 48 | hello2(); 49 | } 50 | cout << "hello3 start 5 times ............" << endl; 51 | for (int i = 0; i < 5; ++i) { 52 | hello3(); 53 | } 54 | int i; 55 | cin >> i; 56 | return 0; 57 | } 58 | --------------------------------------------------------------------------------