arma_str.hpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550
  1. // Copyright 2008-2016 Conrad Sanderson (http://conradsanderson.id.au)
  2. // Copyright 2008-2016 National ICT Australia (NICTA)
  3. //
  4. // Licensed under the Apache License, Version 2.0 (the "License");
  5. // you may not use this file except in compliance with the License.
  6. // You may obtain a copy of the License at
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. // ------------------------------------------------------------------------
  15. //! \addtogroup arma_str
  16. //! @{
  17. namespace arma_str
  18. {
  19. #if ( defined(ARMA_USE_CXX11) || defined(ARMA_HAVE_SNPRINTF) )
  20. #define arma_snprintf std::snprintf
  21. #else
  22. // better-than-nothing emulation of C99 snprintf(),
  23. // with correct return value and null-terminated output string.
  24. // note that _snprintf() provided by MS is not a good substitute for snprintf()
  25. inline
  26. int
  27. arma_snprintf(char* out, size_t size, const char* fmt, ...)
  28. {
  29. size_t i;
  30. for(i=0; i<size; ++i)
  31. {
  32. out[i] = fmt[i];
  33. if(fmt[i] == char(0))
  34. break;
  35. }
  36. if(size > 0)
  37. out[size-1] = char(0);
  38. return int(i);
  39. }
  40. #endif
  41. class format
  42. {
  43. public:
  44. format(const char* in_fmt)
  45. : A(in_fmt)
  46. {
  47. }
  48. format(const std::string& in_fmt)
  49. : A(in_fmt)
  50. {
  51. }
  52. const std::string A;
  53. private:
  54. format();
  55. };
  56. template<typename T1, typename T2>
  57. class basic_format
  58. {
  59. public:
  60. basic_format(const T1& in_A, const T2& in_B)
  61. : A(in_A)
  62. , B(in_B)
  63. {
  64. }
  65. const T1& A;
  66. const T2& B;
  67. private:
  68. basic_format();
  69. };
  70. template<typename T2>
  71. inline
  72. basic_format< format, T2 >
  73. operator% (const format& X, const T2& arg)
  74. {
  75. return basic_format< format, T2 >(X, arg);
  76. }
  77. template<typename T1, typename T2, typename T3>
  78. inline
  79. basic_format< basic_format<T1,T2>, T3 >
  80. operator% (const basic_format<T1,T2>& X, const T3& arg)
  81. {
  82. return basic_format< basic_format<T1,T2>, T3 >(X, arg);
  83. }
  84. template<typename T2>
  85. inline
  86. std::string
  87. str(const basic_format< format, T2>& X)
  88. {
  89. char local_buffer[1024];
  90. char* buffer = local_buffer;
  91. int buffer_size = 1024;
  92. int required_size = buffer_size;
  93. bool using_local_buffer = true;
  94. std::string out;
  95. do
  96. {
  97. if(using_local_buffer == false)
  98. {
  99. buffer = new char[size_t(buffer_size)];
  100. }
  101. required_size = arma_snprintf(buffer, size_t(buffer_size), X.A.A.c_str(), X.B);
  102. if(required_size < 0) { break; }
  103. if(required_size < buffer_size)
  104. {
  105. if(required_size > 0)
  106. {
  107. out = buffer;
  108. }
  109. }
  110. else
  111. {
  112. buffer_size *= 2;
  113. }
  114. if(using_local_buffer)
  115. {
  116. using_local_buffer = false;
  117. }
  118. else
  119. {
  120. delete[] buffer;
  121. }
  122. } while( (required_size >= buffer_size) );
  123. return out;
  124. }
  125. template<typename T2, typename T3>
  126. inline
  127. std::string
  128. str(const basic_format< basic_format< format, T2>, T3>& X)
  129. {
  130. char local_buffer[1024];
  131. char* buffer = local_buffer;
  132. int buffer_size = 1024;
  133. int required_size = buffer_size;
  134. bool using_local_buffer = true;
  135. std::string out;
  136. do
  137. {
  138. if(using_local_buffer == false)
  139. {
  140. buffer = new char[size_t(buffer_size)];
  141. }
  142. required_size = arma_snprintf(buffer, size_t(buffer_size), X.A.A.A.c_str(), X.A.B, X.B);
  143. if(required_size < 0) { break; }
  144. if(required_size < buffer_size)
  145. {
  146. if(required_size > 0)
  147. {
  148. out = buffer;
  149. }
  150. }
  151. else
  152. {
  153. buffer_size *= 2;
  154. }
  155. if(using_local_buffer)
  156. {
  157. using_local_buffer = false;
  158. }
  159. else
  160. {
  161. delete[] buffer;
  162. }
  163. } while( (required_size >= buffer_size) );
  164. return out;
  165. }
  166. template<typename T2, typename T3, typename T4>
  167. inline
  168. std::string
  169. str(const basic_format< basic_format< basic_format< format, T2>, T3>, T4>& X)
  170. {
  171. char local_buffer[1024];
  172. char* buffer = local_buffer;
  173. int buffer_size = 1024;
  174. int required_size = buffer_size;
  175. bool using_local_buffer = true;
  176. std::string out;
  177. do
  178. {
  179. if(using_local_buffer == false)
  180. {
  181. buffer = new char[size_t(buffer_size)];
  182. }
  183. required_size = arma_snprintf(buffer, size_t(buffer_size), X.A.A.A.A.c_str(), X.A.A.B, X.A.B, X.B);
  184. if(required_size < 0) { break; }
  185. if(required_size < buffer_size)
  186. {
  187. if(required_size > 0)
  188. {
  189. out = buffer;
  190. }
  191. }
  192. else
  193. {
  194. buffer_size *= 2;
  195. }
  196. if(using_local_buffer)
  197. {
  198. using_local_buffer = false;
  199. }
  200. else
  201. {
  202. delete[] buffer;
  203. }
  204. } while( (required_size >= buffer_size) );
  205. return out;
  206. }
  207. template<typename T2, typename T3, typename T4, typename T5>
  208. inline
  209. std::string
  210. str(const basic_format< basic_format< basic_format< basic_format< format, T2>, T3>, T4>, T5>& X)
  211. {
  212. char local_buffer[1024];
  213. char* buffer = local_buffer;
  214. int buffer_size = 1024;
  215. int required_size = buffer_size;
  216. bool using_local_buffer = true;
  217. std::string out;
  218. do
  219. {
  220. if(using_local_buffer == false)
  221. {
  222. buffer = new char[size_t(buffer_size)];
  223. }
  224. required_size = arma_snprintf(buffer, size_t(buffer_size), X.A.A.A.A.A.c_str(), X.A.A.A.B, X.A.A.B, X.A.B, X.B);
  225. if(required_size < 0) { break; }
  226. if(required_size < buffer_size)
  227. {
  228. if(required_size > 0)
  229. {
  230. out = buffer;
  231. }
  232. }
  233. else
  234. {
  235. buffer_size *= 2;
  236. }
  237. if(using_local_buffer)
  238. {
  239. using_local_buffer = false;
  240. }
  241. else
  242. {
  243. delete[] buffer;
  244. }
  245. } while( (required_size >= buffer_size) );
  246. return out;
  247. }
  248. template<typename T2, typename T3, typename T4, typename T5, typename T6>
  249. inline
  250. std::string
  251. str(const basic_format< basic_format< basic_format< basic_format< basic_format< format, T2>, T3>, T4>, T5>, T6>& X)
  252. {
  253. char local_buffer[1024];
  254. char* buffer = local_buffer;
  255. int buffer_size = 1024;
  256. int required_size = buffer_size;
  257. bool using_local_buffer = true;
  258. std::string out;
  259. do
  260. {
  261. if(using_local_buffer == false)
  262. {
  263. buffer = new char[size_t(buffer_size)];
  264. }
  265. required_size = arma_snprintf(buffer, size_t(buffer_size), X.A.A.A.A.A.A.c_str(), X.A.A.A.A.B, X.A.A.A.B, X.A.A.B, X.A.B, X.B);
  266. if(required_size < 0) { break; }
  267. if(required_size < buffer_size)
  268. {
  269. if(required_size > 0)
  270. {
  271. out = buffer;
  272. }
  273. }
  274. else
  275. {
  276. buffer_size *= 2;
  277. }
  278. if(using_local_buffer)
  279. {
  280. using_local_buffer = false;
  281. }
  282. else
  283. {
  284. delete[] buffer;
  285. }
  286. } while( (required_size >= buffer_size) );
  287. return out;
  288. }
  289. template<typename T2, typename T3, typename T4, typename T5, typename T6, typename T7>
  290. inline
  291. std::string
  292. str(const basic_format< basic_format< basic_format< basic_format< basic_format< basic_format< format, T2>, T3>, T4>, T5>, T6>, T7>& X)
  293. {
  294. char local_buffer[1024];
  295. char* buffer = local_buffer;
  296. int buffer_size = 1024;
  297. int required_size = buffer_size;
  298. bool using_local_buffer = true;
  299. std::string out;
  300. do
  301. {
  302. if(using_local_buffer == false)
  303. {
  304. buffer = new char[size_t(buffer_size)];
  305. }
  306. required_size = arma_snprintf(buffer, size_t(buffer_size), X.A.A.A.A.A.A.A.c_str(), X.A.A.A.A.A.B, X.A.A.A.A.B, X.A.A.A.B, X.A.A.B, X.A.B, X.B);
  307. if(required_size < 0) { break; }
  308. if(required_size < buffer_size)
  309. {
  310. if(required_size > 0)
  311. {
  312. out = buffer;
  313. }
  314. }
  315. else
  316. {
  317. buffer_size *= 2;
  318. }
  319. if(using_local_buffer)
  320. {
  321. using_local_buffer = false;
  322. }
  323. else
  324. {
  325. delete[] buffer;
  326. }
  327. } while( (required_size >= buffer_size) );
  328. return out;
  329. }
  330. template<typename T1>
  331. struct format_metaprog
  332. {
  333. static const uword depth = 0;
  334. inline
  335. static
  336. const std::string&
  337. get_fmt(const T1& X)
  338. {
  339. return X.A;
  340. }
  341. };
  342. //template<>
  343. template<typename T1, typename T2>
  344. struct format_metaprog< basic_format<T1,T2> >
  345. {
  346. static const uword depth = 1 + format_metaprog<T1>::depth;
  347. inline
  348. static
  349. const std::string&
  350. get_fmt(const T1& X)
  351. {
  352. return format_metaprog<T1>::get_fmt(X.A);
  353. }
  354. };
  355. template<typename T1, typename T2>
  356. inline
  357. std::string
  358. str(const basic_format<T1,T2>& X)
  359. {
  360. return format_metaprog< basic_format<T1,T2> >::get_fmt(X.A);
  361. }
  362. template<typename T1, typename T2>
  363. inline
  364. std::ostream&
  365. operator<< (std::ostream& o, const basic_format<T1,T2>& X)
  366. {
  367. o << str(X);
  368. return o;
  369. }
  370. template<typename T> struct string_only { };
  371. template<> struct string_only<std::string> { typedef std::string result; };
  372. template<typename T> struct char_only { };
  373. template<> struct char_only<char > { typedef char result; };
  374. template<typename T>
  375. struct basic_format_only { };
  376. template<typename T1, typename T2>
  377. struct basic_format_only< basic_format<T1, T2> > { typedef basic_format<T1,T2> result; };
  378. template<typename T1>
  379. inline
  380. static
  381. const T1&
  382. str_wrapper(const T1& x, const typename string_only<T1>::result* junk = 0)
  383. {
  384. arma_ignore(junk);
  385. return x;
  386. }
  387. template<typename T1>
  388. inline
  389. static
  390. const T1*
  391. str_wrapper(const T1* x, const typename char_only<T1>::result* junk = 0)
  392. {
  393. arma_ignore(junk);
  394. return x;
  395. }
  396. template<typename T1>
  397. inline
  398. static
  399. std::string
  400. str_wrapper(const T1& x, const typename basic_format_only<T1>::result* junk = 0)
  401. {
  402. arma_ignore(junk);
  403. return str(x);
  404. }
  405. }
  406. //! @}