PageRenderTime 51ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/poco-1.3.6p2/Foundation/src/Format.cpp

https://bitbucket.org/rosselm/projects
C++ | 362 lines | 283 code | 45 blank | 34 comment | 73 complexity | c093c806b186c76d66d1ac271ae33f7c MD5 | raw file
Possible License(s): GPL-2.0, MIT, GPL-3.0, BSD-3-Clause, LGPL-3.0
  1. //
  2. // Format.cpp
  3. //
  4. // $Id: //poco/1.3/Foundation/src/Format.cpp#7 $
  5. //
  6. // Library: Foundation
  7. // Package: Core
  8. // Module: Format
  9. //
  10. // Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
  11. // and Contributors.
  12. //
  13. // Permission is hereby granted, free of charge, to any person or organization
  14. // obtaining a copy of the software and accompanying documentation covered by
  15. // this license (the "Software") to use, reproduce, display, distribute,
  16. // execute, and transmit the Software, and to prepare derivative works of the
  17. // Software, and to permit third-parties to whom the Software is furnished to
  18. // do so, all subject to the following:
  19. //
  20. // The copyright notices in the Software and this entire statement, including
  21. // the above license grant, this restriction and the following disclaimer,
  22. // must be included in all copies of the Software, in whole or in part, and
  23. // all derivative works of the Software, unless such copies or derivative
  24. // works are solely in the form of machine-executable object code generated by
  25. // a source language processor.
  26. //
  27. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  28. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  29. // FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
  30. // SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
  31. // FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
  32. // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  33. // DEALINGS IN THE SOFTWARE.
  34. //
  35. #include "Poco/Format.h"
  36. #include "Poco/Exception.h"
  37. #include <sstream>
  38. #include <cctype>
  39. #include <cstddef>
  40. namespace Poco {
  41. namespace
  42. {
  43. void parseFlags(std::ostream& str, std::string::const_iterator& itFmt, const std::string::const_iterator& endFmt)
  44. {
  45. bool isFlag = true;
  46. while (isFlag && itFmt != endFmt)
  47. {
  48. switch (*itFmt)
  49. {
  50. case '-': str.setf(std::ios::left); ++itFmt; break;
  51. case '+': str.setf(std::ios::showpos); ++itFmt; break;
  52. case '0': str.fill('0'); ++itFmt; break;
  53. case '#': str.setf(std::ios::showpoint | std::ios_base::showbase); ++itFmt; break;
  54. default: isFlag = false; break;
  55. }
  56. }
  57. }
  58. void parseWidth(std::ostream& str, std::string::const_iterator& itFmt, const std::string::const_iterator& endFmt)
  59. {
  60. int width = 0;
  61. while (itFmt != endFmt && std::isdigit(*itFmt))
  62. {
  63. width = 10*width + *itFmt - '0';
  64. ++itFmt;
  65. }
  66. if (width != 0) str.width(width);
  67. }
  68. void parsePrec(std::ostream& str, std::string::const_iterator& itFmt, const std::string::const_iterator& endFmt)
  69. {
  70. if (itFmt != endFmt && *itFmt == '.')
  71. {
  72. ++itFmt;
  73. int prec = 0;
  74. while (itFmt != endFmt && std::isdigit(*itFmt))
  75. {
  76. prec = 10*prec + *itFmt - '0';
  77. ++itFmt;
  78. }
  79. if (prec != 0) str.precision(prec);
  80. }
  81. }
  82. char parseMod(std::string::const_iterator& itFmt, const std::string::const_iterator& endFmt)
  83. {
  84. char mod = 0;
  85. if (itFmt != endFmt)
  86. {
  87. switch (*itFmt)
  88. {
  89. case 'l':
  90. case 'h':
  91. case 'L':
  92. case '?': mod = *itFmt++; break;
  93. }
  94. }
  95. return mod;
  96. }
  97. void prepareFormat(std::ostream& str, char type)
  98. {
  99. switch (type)
  100. {
  101. case 'd':
  102. case 'i': str << std::dec; break;
  103. case 'o': str << std::oct; break;
  104. case 'x': str << std::hex; break;
  105. case 'X': str << std::hex << std::uppercase; break;
  106. case 'e': str << std::scientific; break;
  107. case 'E': str << std::scientific << std::uppercase; break;
  108. case 'f': str << std::fixed; break;
  109. }
  110. }
  111. void writeAnyInt(std::ostream& str, const Any& any)
  112. {
  113. if (any.type() == typeid(char))
  114. str << static_cast<int>(AnyCast<char>(any));
  115. else if (any.type() == typeid(signed char))
  116. str << static_cast<int>(AnyCast<signed char>(any));
  117. else if (any.type() == typeid(unsigned char))
  118. str << static_cast<unsigned>(AnyCast<unsigned char>(any));
  119. else if (any.type() == typeid(short))
  120. str << AnyCast<short>(any);
  121. else if (any.type() == typeid(unsigned short))
  122. str << AnyCast<unsigned short>(any);
  123. else if (any.type() == typeid(int))
  124. str << AnyCast<int>(any);
  125. else if (any.type() == typeid(unsigned int))
  126. str << AnyCast<unsigned int>(any);
  127. else if (any.type() == typeid(long))
  128. str << AnyCast<long>(any);
  129. else if (any.type() == typeid(unsigned long))
  130. str << AnyCast<unsigned long>(any);
  131. else if (any.type() == typeid(Int64))
  132. str << AnyCast<Int64>(any);
  133. else if (any.type() == typeid(UInt64))
  134. str << AnyCast<UInt64>(any);
  135. else if (any.type() == typeid(bool))
  136. str << AnyCast<bool>(any);
  137. }
  138. void formatOne(std::string& result, std::string::const_iterator& itFmt, const std::string::const_iterator& endFmt, std::vector<Any>::const_iterator& itVal)
  139. {
  140. std::ostringstream str;
  141. parseFlags(str, itFmt, endFmt);
  142. parseWidth(str, itFmt, endFmt);
  143. parsePrec(str, itFmt, endFmt);
  144. char mod = parseMod(itFmt, endFmt);
  145. if (itFmt != endFmt)
  146. {
  147. char type = *itFmt++;
  148. prepareFormat(str, type);
  149. switch (type)
  150. {
  151. case 'b':
  152. str << AnyCast<bool>(*itVal++);
  153. break;
  154. case 'c':
  155. str << AnyCast<char>(*itVal++);
  156. break;
  157. case 'd':
  158. case 'i':
  159. switch (mod)
  160. {
  161. case 'l': str << AnyCast<long>(*itVal++); break;
  162. case 'L': str << AnyCast<Int64>(*itVal++); break;
  163. case 'h': str << AnyCast<short>(*itVal++); break;
  164. case '?': writeAnyInt(str, *itVal++); break;
  165. default: str << AnyCast<int>(*itVal++); break;
  166. }
  167. break;
  168. case 'o':
  169. case 'u':
  170. case 'x':
  171. case 'X':
  172. switch (mod)
  173. {
  174. case 'l': str << AnyCast<unsigned long>(*itVal++); break;
  175. case 'L': str << AnyCast<UInt64>(*itVal++); break;
  176. case 'h': str << AnyCast<unsigned short>(*itVal++); break;
  177. case '?': writeAnyInt(str, *itVal++); break;
  178. default: str << AnyCast<unsigned>(*itVal++); break;
  179. }
  180. break;
  181. case 'e':
  182. case 'E':
  183. case 'f':
  184. switch (mod)
  185. {
  186. case 'l': str << AnyCast<long double>(*itVal++); break;
  187. case 'L': str << AnyCast<long double>(*itVal++); break;
  188. case 'h': str << AnyCast<float>(*itVal++); break;
  189. default: str << AnyCast<double>(*itVal++); break;
  190. }
  191. break;
  192. case 's':
  193. str << RefAnyCast<std::string>(*itVal++);
  194. break;
  195. case 'z':
  196. str << AnyCast<std::size_t>(*itVal++);
  197. break;
  198. case 'I':
  199. case 'D':
  200. default:
  201. str << type;
  202. }
  203. }
  204. result.append(str.str());
  205. }
  206. }
  207. std::string format(const std::string& fmt, const Any& value)
  208. {
  209. std::string result;
  210. format(result, fmt, value);
  211. return result;
  212. }
  213. std::string format(const std::string& fmt, const Any& value1, const Any& value2)
  214. {
  215. std::string result;
  216. format(result, fmt, value1, value2);
  217. return result;
  218. }
  219. std::string format(const std::string& fmt, const Any& value1, const Any& value2, const Any& value3)
  220. {
  221. std::string result;
  222. format(result, fmt, value1, value2, value3);
  223. return result;
  224. }
  225. std::string format(const std::string& fmt, const Any& value1, const Any& value2, const Any& value3, const Any& value4)
  226. {
  227. std::string result;
  228. format(result, fmt, value1, value2, value3, value4);
  229. return result;
  230. }
  231. std::string format(const std::string& fmt, const Any& value1, const Any& value2, const Any& value3, const Any& value4, const Any& value5)
  232. {
  233. std::string result;
  234. format(result, fmt, value1, value2, value3, value4, value5);
  235. return result;
  236. }
  237. std::string format(const std::string& fmt, const Any& value1, const Any& value2, const Any& value3, const Any& value4, const Any& value5, const Any& value6)
  238. {
  239. std::string result;
  240. format(result, fmt, value1, value2, value3, value4, value5, value6);
  241. return result;
  242. }
  243. void format(std::string& result, const std::string& fmt, const Any& value)
  244. {
  245. std::vector<Any> args;
  246. args.push_back(value);
  247. format(result, fmt, args);
  248. }
  249. void format(std::string& result, const std::string& fmt, const Any& value1, const Any& value2)
  250. {
  251. std::vector<Any> args;
  252. args.push_back(value1);
  253. args.push_back(value2);
  254. format(result, fmt, args);
  255. }
  256. void format(std::string& result, const std::string& fmt, const Any& value1, const Any& value2, const Any& value3)
  257. {
  258. std::vector<Any> args;
  259. args.push_back(value1);
  260. args.push_back(value2);
  261. args.push_back(value3);
  262. format(result, fmt, args);
  263. }
  264. void format(std::string& result, const std::string& fmt, const Any& value1, const Any& value2, const Any& value3, const Any& value4)
  265. {
  266. std::vector<Any> args;
  267. args.push_back(value1);
  268. args.push_back(value2);
  269. args.push_back(value3);
  270. args.push_back(value4);
  271. format(result, fmt, args);
  272. }
  273. void format(std::string& result, const std::string& fmt, const Any& value1, const Any& value2, const Any& value3, const Any& value4, const Any& value5)
  274. {
  275. std::vector<Any> args;
  276. args.push_back(value1);
  277. args.push_back(value2);
  278. args.push_back(value3);
  279. args.push_back(value4);
  280. args.push_back(value5);
  281. format(result, fmt, args);
  282. }
  283. void format(std::string& result, const std::string& fmt, const Any& value1, const Any& value2, const Any& value3, const Any& value4, const Any& value5, const Any& value6)
  284. {
  285. std::vector<Any> args;
  286. args.push_back(value1);
  287. args.push_back(value2);
  288. args.push_back(value3);
  289. args.push_back(value4);
  290. args.push_back(value5);
  291. args.push_back(value6);
  292. format(result, fmt, args);
  293. }
  294. void format(std::string& result, const std::string& fmt, const std::vector<Any>& values)
  295. {
  296. std::string::const_iterator itFmt = fmt.begin();
  297. std::string::const_iterator endFmt = fmt.end();
  298. std::vector<Any>::const_iterator itVal = values.begin();
  299. std::vector<Any>::const_iterator endVal = values.end();
  300. while (itFmt != endFmt)
  301. {
  302. switch (*itFmt)
  303. {
  304. case '%':
  305. ++itFmt;
  306. if (itFmt != endFmt && itVal != endVal)
  307. formatOne(result, itFmt, endFmt, itVal);
  308. else if (itFmt != endFmt)
  309. result += *itFmt++;
  310. break;
  311. default:
  312. result += *itFmt;
  313. ++itFmt;
  314. }
  315. }
  316. }
  317. } // namespace Poco