You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

811 lines
29 KiB

  1. /* /////////////////////////////////////////////////////////////////////////
  2. * File: b64/b64.hpp
  3. *
  4. * Purpose: Header file for the b64 C++-API.
  5. *
  6. * Created: 18th October 2004
  7. * Updated: 4th February 2012
  8. *
  9. * Home: http://synesis.com.au/software/
  10. *
  11. * Copyright 2004-2012, Matthew Wilson and Synesis Software
  12. * All rights reserved.
  13. *
  14. * Redistribution and use in source and binary forms, with or without
  15. * modification, are permitted provided that the following conditions are met:
  16. *
  17. * - Redistributions of source code must retain the above copyright notice, this
  18. * list of conditions and the following disclaimer.
  19. * - Redistributions in binary form must reproduce the above copyright notice,
  20. * this list of conditions and the following disclaimer in the documentation
  21. * and/or other materials provided with the distribution.
  22. * - Neither the name(s) of Matthew Wilson and Synesis Software nor the names of
  23. * any contributors may be used to endorse or promote products derived from
  24. * this software without specific prior written permission.
  25. *
  26. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  27. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  28. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  29. * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
  30. * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  31. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  32. * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  33. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  34. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  35. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  36. * POSSIBILITY OF SUCH DAMAGE.
  37. *
  38. * ////////////////////////////////////////////////////////////////////// */
  39. /** \file b64/b64.hpp [C++ only] Header file for the b64 C++-API
  40. *
  41. * This header file contains the b64 C++-API types and functions. There are
  42. * no associated implementation files; in other words, the b64 C++-API is
  43. * header only.
  44. *
  45. * The b64/C++ is dependent on several components from the
  46. * <a href = "http://stlsoft.org/">STLSoft</a> libraries (also 100% header-only)
  47. * so you will need to have them available on your include path when using this
  48. * header.
  49. *
  50. * \htmlonly
  51. * <hr>
  52. * \endhtmlonly
  53. */
  54. #ifndef B64_INCL_B64_HPP_B64
  55. #define B64_INCL_B64_HPP_B64
  56. /* /////////////////////////////////////////////////////////////////////////
  57. * Version information
  58. */
  59. #ifndef B64_DOCUMENTATION_SKIP_SECTION
  60. # define B64_VER_B64_HPP_B64_MAJOR 2
  61. # define B64_VER_B64_HPP_B64_MINOR 1
  62. # define B64_VER_B64_HPP_B64_REVISION 12
  63. # define B64_VER_B64_HPP_B64_EDIT 38
  64. #endif /* !B64_DOCUMENTATION_SKIP_SECTION */
  65. /* /////////////////////////////////////////////////////////////////////////
  66. * Includes
  67. */
  68. #ifndef B64_INCL_B64_H_B64
  69. # include <b64/b64.h>
  70. #endif /* !B64_INCL_B64_H_B64 */
  71. /* If the compiler cannot find the following include, you may have not
  72. * upgraded to the latest version of STLSoft: 1.9.1. Go to
  73. * http://stlsoft.org/ and download this version or later.
  74. */
  75. #ifndef STLSOFT_INCL_STLSOFT_H_STLSOFT
  76. # include <stlsoft/stlsoft.h>
  77. #endif /* !STLSOFT_INCL_STLSOFT_H_STLSOFT */
  78. #if !defined(_STLSOFT_VER) || \
  79. _STLSOFT_VER < 0x01096fff
  80. # error Requires STLSoft 1.9.111, or later. (www.stlsoft.org/downloads.html)
  81. #endif /* STLSoft version */
  82. #ifdef STLSOFT_CF_std_NAMESPACE
  83. # if defined(B64_USE_CUSTOM_STRING)
  84. # include B64_CUSTOM_STRING_INCLUDE
  85. # else /* B64_USE_CUSTOM_STRING */
  86. # include <string>
  87. # endif /* !B64_USE_CUSTOM_STRING */
  88. # if defined(B64_USE_CUSTOM_VECTOR)
  89. # include B64_CUSTOM_VECTOR_INCLUDE
  90. # else /* B64_USE_CUSTOM_VECTOR */
  91. # include <vector>
  92. # endif /* !B64_USE_CUSTOM_VECTOR */
  93. /* We'll now have a go at checking whether the string type is
  94. * known to be contiguous
  95. */
  96. # ifndef STLSOFT_INCL_STLSOFT_UTIL_STD_LIBRARY_DISCRIMINATOR
  97. # include <stlsoft/util/std/library_discriminator.hpp>
  98. # endif /* !STLSOFT_INCL_STLSOFT_UTIL_STD_LIBRARY_DISCRIMINATOR */
  99. # ifdef STLSOFT_CF_STD_LIBRARY_IS_DINKUMWARE_VC
  100. # if STLSOFT_CF_STD_LIBRARY_DINKUMWARE_VC_VERSION <= STLSOFT_CF_DINKUMWARE_VC_VERSION_7_1
  101. # define B64_STRING_TYPE_IS_CONTIGUOUS
  102. # endif /* STLSOFT_CF_STD_LIBRARY_DINKUMWARE_VC_VERSION */
  103. # endif /* STLSOFT_CF_STD_LIBRARY_IS_DINKUMWARE_VC */
  104. #else /* ? STLSOFT_CF_std_NAMESPACE */
  105. # if defined(STLSOFT_COMPILER_IS_WATCOM)
  106. # include <string.hpp>
  107. # include <wcvector.h>
  108. # define B64_USE_CUSTOM_STRING
  109. # define B64_CUSTOM_STRING_TYPE watcom_string_for_b64
  110. # define B64_USE_CUSTOM_VECTOR
  111. # define B64_CUSTOM_BLOB_TYPE watcom_vector_for_b64
  112. # define B64_STRING_TYPE_IS_CONTIGUOUS
  113. # else /* ? compiler */
  114. # error No other non-std compiler is known
  115. # endif /* ? compiler */
  116. #endif /* STLSOFT_CF_std_NAMESPACE */
  117. #ifdef B64_NO_CONTIGUOUS_STRING_TYPE
  118. # ifdef B64_STRING_TYPE_IS_CONTIGUOUS
  119. # undef B64_STRING_TYPE_IS_CONTIGUOUS
  120. # endif /* B64_STRING_TYPE_IS_CONTIGUOUS */
  121. #endif /* B64_NO_CONTIGUOUS_STRING_TYPE */
  122. #if !defined(B64_STRING_TYPE_IS_CONTIGUOUS)
  123. # ifndef STLSOFT_INCL_STLSOFT_MEMORY_HPP_AUTO_BUFFER
  124. # include <stlsoft/memory/auto_buffer.hpp>
  125. # endif /* !STLSOFT_INCL_STLSOFT_MEMORY_HPP_AUTO_BUFFER */
  126. #endif /* !B64_STRING_TYPE_IS_CONTIGUOUS */
  127. #ifndef STLSOFT_INCL_STLSOFT_SHIMS_ACCESS_HPP_STRING
  128. # include <stlsoft/shims/access/string.hpp>
  129. #endif /* !STLSOFT_INCL_STLSOFT_SHIMS_ACCESS_HPP_STRING */
  130. /* #ifdef B64_ */
  131. #define B64_DECLARE_SHIM_PAIR_() stlsoft_ns_using(c_str_data_a); stlsoft_ns_using(c_str_len_a)
  132. #define B64_INVOKE_SHIM_data_(s) c_str_data_a(s)
  133. #define B64_INVOKE_SHIM_len_(s) c_str_len_a(s)
  134. #ifdef STLSOFT_CF_EXCEPTION_SUPPORT
  135. # if defined(STLSOFT_COMPILER_IS_WATCOM)
  136. # include <stdexcep.h>
  137. # else /* ? compiler */
  138. # include <stdexcept>
  139. # endif /* compiler */
  140. #endif /* STLSOFT_CF_EXCEPTION_SUPPORT */
  141. /* /////////////////////////////////////////////////////////////////////////
  142. * Namespace
  143. */
  144. #ifndef B64_NO_NAMESPACE
  145. namespace B64_NAMESPACE
  146. {
  147. #endif /* !B64_NO_NAMESPACE */
  148. /* /////////////////////////////////////////////////////////////////////////
  149. * Classes
  150. */
  151. #if defined(STLSOFT_COMPILER_IS_WATCOM)
  152. class watcom_vector_for_b64
  153. : public WCValVector<unsigned char>
  154. {
  155. private:
  156. typedef WCValVector<unsigned char> parent_class_type;
  157. typedef watcom_vector_for_b64 class_type;
  158. public:
  159. watcom_vector_for_b64()
  160. {}
  161. watcom_vector_for_b64(size_t n)
  162. : parent_class_type(n)
  163. {}
  164. watcom_vector_for_b64(class_type const &rhs)
  165. : parent_class_type(rhs)
  166. {}
  167. public:
  168. size_t size() const
  169. {
  170. return parent_class_type::length();
  171. }
  172. };
  173. class watcom_string_for_b64
  174. : public String
  175. {
  176. public:
  177. watcom_string_for_b64(size_t n, char ch)
  178. : String(ch, n)
  179. {}
  180. public:
  181. void resize(size_t n)
  182. {
  183. String& this_ = *this;
  184. this_ = String(*this, n);
  185. }
  186. };
  187. #endif /* STLSOFT_COMPILER_IS_WATCOM */
  188. #ifdef STLSOFT_CF_EXCEPTION_SUPPORT
  189. /** \brief Exception thrown during encoding/decoding
  190. */
  191. class coding_exception
  192. : public stlsoft_ns_qual_std(runtime_error)
  193. {
  194. public:
  195. typedef stlsoft_ns_qual_std(runtime_error) parent_class_type;
  196. typedef coding_exception class_type;
  197. private:
  198. #if defined(B64_USE_CUSTOM_STRING)
  199. typedef B64_CUSTOM_STRING_TYPE string_type;
  200. #else /* B64_USE_CUSTOM_STRING */
  201. typedef std::string string_type;
  202. #endif /* !B64_USE_CUSTOM_STRING */
  203. public:
  204. /** Constructs an exception based on the error code, and a pointer to the bad character. */
  205. coding_exception(B64_RC rc, char const* badChar)
  206. : parent_class_type(make_message_(rc))
  207. , m_rc(rc)
  208. , m_badChar(badChar)
  209. {}
  210. public:
  211. /** The error code associated with the exception. */
  212. B64_RC get_rc() const
  213. {
  214. return m_rc;
  215. }
  216. /** The return code associated with the exception.
  217. *
  218. * \note May be NULL, if the error is not associated with an invalid character encountered during decoding.
  219. */
  220. char const* get_badChar() const
  221. {
  222. return m_badChar;
  223. }
  224. private:
  225. static string_type make_message_(B64_RC rc)
  226. {
  227. return string_type("Decoding error: ") + b64_getStatusCodeString(rc);
  228. }
  229. private:
  230. B64_RC m_rc;
  231. char const* m_badChar;
  232. };
  233. #endif /* STLSOFT_CF_EXCEPTION_SUPPORT */
  234. /* /////////////////////////////////////////////////////////////////////////
  235. * Typedefs
  236. */
  237. /** The string type for the b64 namespace
  238. *
  239. * \note This defaults to <tt>::std::string</tt>. It is possible to override this, using
  240. * preprocessor symbol definitions. To do this, you must define
  241. * the symbol \c B64_USE_CUSTOM_STRING to instruct the compiler that the <b>b64</b>
  242. * library is to use a custom string type. In that case you <b>must also</b>
  243. * define the \c B64_CUSTOM_STRING_INCLUDE and \c B64_CUSTOM_STRING_TYPE and symbols.
  244. *
  245. * \c B64_CUSTOM_STRING_INCLUDE specifies the \c <> or \c "" surrounded include file name, e.g.
  246. *
  247. * <tt>&nbsp;&nbsp;\#define B64_CUSTOM_STRING_INCLUDE <stlsoft/simple_string.hpp></tt>
  248. *
  249. * \c B64_CUSTOM_STRING_TYPE specifies the string type, e.g.
  250. *
  251. * <tt>&nbsp;&nbsp;\#define B64_CUSTOM_STRING_TYPE&nbsp;&nbsp;&nbsp;&nbsp;::stlsoft::basic_simple_string<char></tt>
  252. *
  253. * \note For Open Watcom compilation, this type is actually the class
  254. * class <code>b64::watcom_string_for_b64</code>, a class adaptor for
  255. * the Open Watcom <code>String</code> class. The definition
  256. * of this class can be found in b64/b64.hpp.
  257. */
  258. #if defined(B64_USE_CUSTOM_STRING)
  259. typedef B64_CUSTOM_STRING_TYPE string_t;
  260. #else /* B64_USE_CUSTOM_STRING */
  261. typedef std::string string_t;
  262. #endif /* !B64_USE_CUSTOM_STRING */
  263. /** The blob type for the b64 namespace
  264. *
  265. * \note This defaults to <tt>::std::vector< ::stlsoft::byte_t></tt>. It is possible to
  266. * override this, using
  267. * preprocessor symbol definitions. To do this, you must define
  268. * the symbol \c B64_USE_CUSTOM_VECTOR to instruct the compiler that the <b>b64</b>
  269. * library is to use a custom string type. In that case you <b>must also</b>
  270. * define the \c B64_CUSTOM_VECTOR_INCLUDE and \c B64_CUSTOM_BLOB_TYPE and symbols.
  271. *
  272. * \c B64_CUSTOM_VECTOR_INCLUDE specifies the \c <> or \c "" surrounded include file name, e.g.
  273. *
  274. * <tt>&nbsp;&nbsp;\#define B64_CUSTOM_VECTOR_INCLUDE <stlsoft/pod_vector.hpp></tt>
  275. *
  276. * \c B64_CUSTOM_BLOB_TYPE specifies the string type, e.g.
  277. *
  278. * <tt>&nbsp;&nbsp;\#define B64_CUSTOM_BLOB_TYPE&nbsp;&nbsp;&nbsp;&nbsp;::stlsoft::pod_vector<unsigned char></tt>
  279. *
  280. * \note For Open Watcom compilation, this type is actually the class
  281. * class <code>b64::watcom_vector_for_b64</code>, a class adaptor for
  282. * the <code>WCValVector&lt;unsigned char&gt;</code> specialisation. The definition
  283. * of this class can be found in b64/b64.hpp.
  284. */
  285. #if defined(B64_USE_CUSTOM_VECTOR)
  286. typedef B64_CUSTOM_BLOB_TYPE blob_t;
  287. #else /* B64_USE_CUSTOM_VECTOR */
  288. # ifndef B64_DOCUMENTATION_SKIP_SECTION
  289. typedef ::stlsoft::byte_t byte_t_;
  290. typedef std::vector<byte_t_> blob_t;
  291. # else /* !B64_DOCUMENTATION_SKIP_SECTION */
  292. typedef std::vector< ::stlsoft::byte_t> blob_t;
  293. # endif /* !B64_DOCUMENTATION_SKIP_SECTION */
  294. #endif /* !B64_USE_CUSTOM_VECTOR */
  295. /* /////////////////////////////////////////////////////////////////////////
  296. * Functions
  297. */
  298. /** \brief Encodes the given block of memory into base-64.
  299. *
  300. * This function takes a pointer to a memory block to be encoded, and a number of
  301. * bytes to be encoded, and carries out a base-64 encoding on it, returning the
  302. * results in an instance of the string type \link #string_t string_t \endlink. See the
  303. * \ref section__cpp_api "example" from the main page
  304. *
  305. * \param src Pointer to the block to be encoded
  306. * \param srcSize Number of bytes in the block to be encoded
  307. * \param flags A combination of the B64_FLAGS enumeration, that moderate the
  308. * behaviour of the function
  309. * \param lineLen If the flags parameter contains B64_F_LINE_LEN_USE_PARAM, then
  310. * this parameter represents the length of the lines into which the encoded form is split,
  311. * with a hard line break ('\\r\\n'). If this value is 0, then the line is not
  312. * split. If it is <0, then the RFC-1113 recommended line length of 64 is used
  313. * \param rc The return code representing the status of the operation. May be NULL.
  314. *
  315. * \return The string form of the block
  316. *
  317. * \note There is no error return. If insufficient memory can be allocated, an
  318. * instance of \c std::bad_alloc will be thrown
  319. *
  320. * \note Threading: The function is fully re-entrant, assuming that the heap for the
  321. * system is re-entrant.
  322. *
  323. * \note Exceptions: Provides the strong guarantee, assuming that the constructor for
  324. * the string type (\c string_t) does so.
  325. *
  326. * \exception std::bad_alloc If insufficient memory is available to complete the operation
  327. */
  328. inline string_t encode(void const* src, size_t srcSize, int flags, int lineLen = 0, B64_RC* rc = NULL)
  329. {
  330. B64_RC rc_;
  331. // Make sure rc is non-NULL, since we will need to get the RC in order to
  332. // throw exception later.
  333. if(NULL == rc)
  334. {
  335. rc = &rc_;
  336. }
  337. size_t n = B64_NAMESPACE_QUALIFIER::b64_encode2(src, srcSize, NULL, 0u, static_cast<unsigned>(flags), lineLen, rc);
  338. #ifdef B64_STRING_TYPE_IS_CONTIGUOUS
  339. // If the string type is known to have contiguous storage we can avoid
  340. // any intermediate memory, and decode directly into its internal
  341. // buffer.
  342. string_t s(n, '~'); // ~ is used for an invalid / eyecatcher
  343. STLSOFT_MESSAGE_ASSERT("assumed contiguous string type is not so. Please report this error. To effect fix now, #define B64_NO_CONTIGUOUS_STRING_TYPE", 0 == n || &s[n - 1] == &s[0] + (n - 1));
  344. size_t n2 = B64_NAMESPACE_QUALIFIER::b64_encode2(src, srcSize, &s[0], s.length(), static_cast<unsigned>(flags), lineLen, rc);
  345. s.resize(n2);
  346. #else /* ? B64_STRING_TYPE_IS_CONTIGUOUS */
  347. // If the string type is not known to be contiguous, then we must use
  348. // intermediate storage. Here we use a 1KB auto_buffer, so that only
  349. // data in excess of that will incur an additional (over the string's)
  350. // heap allocation.
  351. typedef stlsoft::auto_buffer<b64_char_t, 1024> buffer_t;
  352. buffer_t buffer(n);
  353. size_t n2 = B64_NAMESPACE_QUALIFIER::b64_encode2(src, srcSize, &buffer[0], buffer.size(), static_cast<unsigned>(flags), lineLen, rc);
  354. string_t s(&buffer[0], n2);
  355. #endif /* B64_STRING_TYPE_IS_CONTIGUOUS */
  356. #ifdef STLSOFT_CF_EXCEPTION_SUPPORT
  357. if( 0 != srcSize &&
  358. 0 == n2 &&
  359. rc == &rc_)
  360. {
  361. throw coding_exception(*rc, NULL);
  362. }
  363. #endif /* STLSOFT_CF_EXCEPTION_SUPPORT */
  364. return s;
  365. }
  366. /** \brief Encodes the given block of memory into base-64.
  367. *
  368. * This function takes a pointer to a memory block to be encoded, and a number of
  369. * bytes to be encoded, and carries out a base-64 encoding on it, returning the
  370. * results in an instance of the string type \link #string_t string_t \endlink. See the
  371. * \ref section__cpp_api "example" from the main page
  372. *
  373. * \param src Pointer to the block to be encoded
  374. * \param srcSize Number of bytes in the block to be encoded
  375. *
  376. * \return The string form of the block
  377. *
  378. * \note There is no error return. If insufficient memory can be allocated, an
  379. * instance of \c std::bad_alloc will be thrown
  380. *
  381. * \note Threading: The function is fully re-entrant, assuming that the heap for the
  382. * system is re-entrant.
  383. *
  384. * \note Exceptions: Provides the strong guarantee, assuming that the constructor for
  385. * the string type (\c string_t) does so.
  386. *
  387. * \exception std::bad_alloc If insufficient memory is available to complete the operation
  388. */
  389. inline string_t encode(void const* src, size_t srcSize)
  390. {
  391. return encode(src, srcSize, 0, 0, NULL);
  392. }
  393. #ifdef STLSOFT_CF_STATIC_ARRAY_SIZE_DETERMINATION_SUPPORT
  394. /** \brief Encodes the given array into base-64
  395. *
  396. * \param ar The array whose contents are to be encoded
  397. *
  398. * \return The string form of the block
  399. *
  400. * \note This function is only defined for compilers that are able to discriminate
  401. * between pointers and arrays. See Chapter 14 of <a href = "http://imperfectcplusplus.com/">Imperfect C++</a>
  402. * for details about this facility, and consult your <a href = "http://stlsoft.org/">STLSoft</a> header files
  403. * to find out to which compilers this applies.
  404. *
  405. * \note There is no error return. If insufficient memory can be allocated, an
  406. * instance of \c std::bad_alloc will be thrown
  407. *
  408. * \note Threading: The function is fully re-entrant, assuming that the heap for the
  409. * system is re-entrant.
  410. *
  411. * \note Exceptions: Provides the strong guarantee, assuming that the constructor for
  412. * the string type (\c string_t) does so.
  413. *
  414. * \exception std::bad_alloc If insufficient memory is available to complete the operation
  415. */
  416. template <typename T, size_t N>
  417. inline string_t encode(T (&ar)[N])
  418. {
  419. return encode(&ar[0], sizeof(T) * N);
  420. }
  421. #endif /* STLSOFT_CF_STATIC_ARRAY_SIZE_DETERMINATION_SUPPORT */
  422. /** \brief Encodes the given blob into base-64
  423. *
  424. * \param blob The blob whose contents are to be encoded
  425. *
  426. * \return The string form of the block
  427. *
  428. * \note There is no error return. If insufficient memory can be allocated, an
  429. * instance of \c std::bad_alloc will be thrown
  430. *
  431. * \note Threading: The function is fully re-entrant, assuming that the heap for the
  432. * system is re-entrant.
  433. *
  434. * \note Exceptions: Provides the strong guarantee, assuming that the constructor for
  435. * the string type (\c string_t) does so.
  436. *
  437. * \exception std::bad_alloc If insufficient memory is available to complete the operation
  438. */
  439. inline string_t encode(blob_t const &blob)
  440. {
  441. return encode(blob.empty() ? NULL : &blob[0], blob.size());
  442. }
  443. /** \brief Encodes the given blob into base-64
  444. *
  445. * \param blob The blob whose contents are to be encoded
  446. * \param flags A combination of the B64_FLAGS enumeration, that moderate the
  447. * behaviour of the function
  448. * \param lineLen If the flags parameter contains B64_F_LINE_LEN_USE_PARAM, then
  449. * this parameter represents the length of the lines into which the encoded form is split,
  450. * with a hard line break ('\\r\\n'). If this value is 0, then the line is not
  451. * split. If it is <0, then the RFC-1113 recommended line length of 64 is used
  452. * \param rc The return code representing the status of the operation. May be NULL.
  453. *
  454. * \return The string form of the block
  455. *
  456. * \note There is no error return. If insufficient memory can be allocated, an
  457. * instance of \c std::bad_alloc will be thrown
  458. *
  459. * \note Threading: The function is fully re-entrant, assuming that the heap for the
  460. * system is re-entrant.
  461. *
  462. * \note Exceptions: Provides the strong guarantee, assuming that the constructor for
  463. * the string type (\c string_t) does so.
  464. *
  465. * \exception std::bad_alloc If insufficient memory is available to complete the operation
  466. */
  467. inline string_t encode(blob_t const &blob, int flags, int lineLen = 0, B64_RC* rc = NULL)
  468. {
  469. return encode(blob.empty() ? NULL : &blob[0], blob.size(), flags, lineLen, rc);
  470. }
  471. /** \brief Decodes the given base-64 block into binary
  472. *
  473. * \param src Pointer to the block to be decoded
  474. * \param srcLen Number of characters in the block to be decoded
  475. * \param flags A combination of the B64_FLAGS enumeration, that moderate the
  476. * behaviour of the function.
  477. * \param rc The return code representing the status of the operation. May be NULL.
  478. * \param badChar If the flags parameter does not contain B64_F_STOP_ON_NOTHING, this
  479. * parameter specifies the address of a pointer that will be set to point to the
  480. * character in the sequence that stops the parsing, as dictated by the flags
  481. * parameter. May be NULL.
  482. *
  483. * \return The binary form of the block, as a \c blob_t
  484. *
  485. * \note There is no error return. If insufficient memory can be allocated, an
  486. * instance of \c std::bad_alloc will be thrown
  487. *
  488. * \note Threading: The function is fully re-entrant, assuming that the heap for the
  489. * system is re-entrant.
  490. *
  491. * \note Exceptions: Provides the strong guarantee, assuming that the constructor for
  492. * the string type (\c string_t) does so.
  493. *
  494. * \exception std::bad_alloc If insufficient memory is available to complete the operation
  495. * \exception b64::coding_exception If a bad character is encountered in the encoded block (as moderated by the flags parameter; see \link b64::B64_FLAGS B64_FLAGS\endlink)
  496. */
  497. inline blob_t decode(b64_char_t const* src, size_t srcLen, int flags, b64_char_t const** badChar = NULL, B64_RC* rc = NULL)
  498. {
  499. #ifdef STLSOFT_CF_EXCEPTION_SUPPORT
  500. B64_RC rc_;
  501. b64_char_t const* badChar_;
  502. if(NULL == rc)
  503. {
  504. rc = &rc_;
  505. }
  506. if(NULL == badChar)
  507. {
  508. badChar = &badChar_;
  509. }
  510. #endif /* STLSOFT_CF_EXCEPTION_SUPPORT */
  511. size_t n = B64_NAMESPACE_QUALIFIER::b64_decode2(src, srcLen, NULL, 0, static_cast<unsigned>(flags), badChar, rc);
  512. blob_t v(n);
  513. size_t n2 = v.empty() ? 0 : B64_NAMESPACE_QUALIFIER::b64_decode2(src, srcLen, &v[0], v.size(), static_cast<unsigned>(flags), badChar, rc);
  514. v.resize(n2);
  515. #ifdef STLSOFT_CF_EXCEPTION_SUPPORT
  516. if( 0 != srcLen &&
  517. 0 == n2 &&
  518. rc == &rc_)
  519. {
  520. if(B64_RC_OK == *rc)
  521. {
  522. *rc = B64_RC_TRUNCATED_INPUT;
  523. }
  524. throw coding_exception(*rc, (badChar == &badChar_) ? *badChar : NULL);
  525. }
  526. #endif /* STLSOFT_CF_EXCEPTION_SUPPORT */
  527. return v;
  528. }
  529. /** \brief Decodes the given base-64 block into binary
  530. *
  531. * \param src Pointer to the block to be decoded
  532. * \param srcLen Number of characters in the block to be decoded
  533. *
  534. * \return The binary form of the block, as a \c blob_t
  535. *
  536. * \note There is no error return. If insufficient memory can be allocated, an
  537. * instance of \c std::bad_alloc will be thrown
  538. *
  539. * \note Threading: The function is fully re-entrant, assuming that the heap for the
  540. * system is re-entrant.
  541. *
  542. * \note Exceptions: Provides the strong guarantee, assuming that the constructor for
  543. * the string type (\c string_t) does so.
  544. *
  545. * \exception std::bad_alloc If insufficient memory is available to complete the operation
  546. */
  547. inline blob_t decode(b64_char_t const* src, size_t srcLen)
  548. {
  549. return decode(src, srcLen, B64_F_STOP_ON_BAD_CHAR, NULL, NULL);
  550. }
  551. #ifndef B64_DOCUMENTATION_SKIP_SECTION
  552. STLSOFT_OPEN_WORKER_NS_(impl)
  553. /** \brief Function template that decodes an instance of an arbitrary string type from base-64 into binary
  554. *
  555. * \param str The string whose contents are to be decoded
  556. * \param flags Flags that moderate the decoding
  557. *
  558. * \return The binary form of the block, as a \c blob_t
  559. *
  560. * \note There is no error return. If insufficient memory can be allocated, an
  561. * instance of \c std::bad_alloc will be thrown
  562. *
  563. * \note Threading: The function is fully re-entrant, assuming that the heap for the
  564. * system is re-entrant.
  565. *
  566. * \note Exceptions: Provides the strong guarantee, assuming that the constructor for
  567. * the string type (\c string_t) does so.
  568. *
  569. * \exception std::bad_alloc If insufficient memory is available to complete the operation
  570. */
  571. template <class S>
  572. inline blob_t b64_impl_decode_(int flags, S const &str)
  573. {
  574. B64_DECLARE_SHIM_PAIR_();
  575. b64_char_t const* dummy; // Cannot rely on badChar being available in str
  576. return decode(
  577. B64_INVOKE_SHIM_data_(str)
  578. , B64_INVOKE_SHIM_len_(str)
  579. , static_cast<B64_FLAGS>(flags)
  580. , &dummy
  581. , NULL
  582. );
  583. }
  584. STLSOFT_CLOSE_WORKER_NS_(ns)
  585. #endif /* !B64_DOCUMENTATION_SKIP_SECTION */
  586. /** \brief Function template that decodes an instance of an arbitrary string type from base-64 into binary
  587. *
  588. * \param str The string whose contents are to be decoded
  589. *
  590. * \return The binary form of the block, as a \c blob_t
  591. *
  592. * \note There is no error return. If insufficient memory can be allocated, an
  593. * instance of \c std::bad_alloc will be thrown
  594. *
  595. * \note Threading: The function is fully re-entrant, assuming that the heap for the
  596. * system is re-entrant.
  597. *
  598. * \note Exceptions: Provides the strong guarantee, assuming that the constructor for
  599. * the string type (\c string_t) does so.
  600. *
  601. * \exception std::bad_alloc If insufficient memory is available to complete the operation
  602. */
  603. template <class S>
  604. inline blob_t decode(S const &str)
  605. {
  606. return STLSOFT_WORKER_NS_QUAL_(impl, b64_impl_decode_)(B64_F_STOP_ON_BAD_CHAR, str);
  607. }
  608. /** \brief Function template that decodes an instance of an arbitrary string type from base-64 into binary
  609. *
  610. * \param str The string whose contents are to be decoded
  611. * \param flags Flags that moderate the decoding
  612. *
  613. * \return The binary form of the block, as a \c blob_t
  614. *
  615. * \note There is no error return. If insufficient memory can be allocated, an
  616. * instance of \c std::bad_alloc will be thrown
  617. *
  618. * \note Threading: The function is fully re-entrant, assuming that the heap for the
  619. * system is re-entrant.
  620. *
  621. * \note Exceptions: Provides the strong guarantee, assuming that the constructor for
  622. * the string type (\c string_t) does so.
  623. *
  624. * \exception std::bad_alloc If insufficient memory is available to complete the operation
  625. */
  626. template <class S>
  627. inline blob_t decode(int flags, S const &str) // NOTE: This has to be overloaded, rather than use default arguments, otherwise VC has a spit
  628. {
  629. return STLSOFT_WORKER_NS_QUAL_(impl, b64_impl_decode_)(flags, str);
  630. }
  631. /** \brief Decodes the given string from base-64 into binary
  632. *
  633. * \param str The string whose contents are to be decoded
  634. * \param flags A combination of the B64_FLAGS enumeration, that moderate the
  635. * behaviour of the function.
  636. *
  637. * \return The binary form of the block, as a \c blob_t
  638. *
  639. * \note There is no error return. If insufficient memory can be allocated, an
  640. * instance of \c std::bad_alloc will be thrown
  641. *
  642. * \note Threading: The function is fully re-entrant, assuming that the heap for the
  643. * system is re-entrant.
  644. *
  645. * \note Exceptions: Provides the strong guarantee, assuming that the constructor for
  646. * the string type (\c string_t) does so.
  647. *
  648. * \exception std::bad_alloc If insufficient memory is available to complete the operation
  649. * \exception b64::coding_exception If a bad character is encountered in the encoded block (as moderated by the flags parameter; see \link b64::B64_FLAGS B64_FLAGS\endlink)
  650. */
  651. inline blob_t decode(string_t const &str, int flags = B64_F_STOP_ON_BAD_CHAR)
  652. {
  653. B64_DECLARE_SHIM_PAIR_();
  654. return decode(
  655. B64_INVOKE_SHIM_data_(str)
  656. , B64_INVOKE_SHIM_len_(str)
  657. , flags
  658. , NULL
  659. , NULL
  660. );
  661. }
  662. /** \brief Decodes the given string from base-64 into binary
  663. *
  664. * \param str The string whose contents are to be decoded
  665. * \param flags A combination of the B64_FLAGS enumeration, that moderate the
  666. * behaviour of the function.
  667. * \param rc The return code representing the status of the operation. May be NULL.
  668. * \param badChar If the flags parameter does not contain B64_F_STOP_ON_NOTHING, this
  669. * parameter specifies the address of a pointer that will be set to point to the
  670. * character in the sequence that stops the parsing, as dictated by the flags
  671. * parameter. May be NULL.
  672. *
  673. * \return The binary form of the block, as a \c blob_t
  674. *
  675. * \note There is no error return. If insufficient memory can be allocated, an
  676. * instance of \c std::bad_alloc will be thrown
  677. *
  678. * \note Threading: The function is fully re-entrant, assuming that the heap for the
  679. * system is re-entrant.
  680. *
  681. * \note Exceptions: Provides the strong guarantee, assuming that the constructor for
  682. * the string type (\c string_t) does so.
  683. *
  684. * \exception std::bad_alloc If insufficient memory is available to complete the operation
  685. * \exception b64::coding_exception If a bad character is encountered in the encoded block (as moderated by the flags parameter; see \link b64::B64_FLAGS B64_FLAGS\endlink)
  686. */
  687. inline blob_t decode(string_t const &str, int flags, b64_char_t const** badChar, B64_RC* rc = NULL)
  688. {
  689. B64_DECLARE_SHIM_PAIR_();
  690. return decode(
  691. B64_INVOKE_SHIM_data_(str)
  692. , B64_INVOKE_SHIM_len_(str)
  693. , flags
  694. , badChar
  695. , rc
  696. );
  697. }
  698. /* /////////////////////////////////////////////////////////////////////////
  699. * Namespace
  700. */
  701. /** \brief [C++ only] The <code>b64::cpp</code> namespace, within which the C++
  702. * types and functions <b><i>used</i></b> to reside; they now reside
  703. * within the <code>b64</code> namespace.
  704. *
  705. * \deprecated All the constructs that were formerly in the
  706. * <code>b64::cpp</code> namespace now reside within the <code>b64</code>
  707. * namespace.
  708. */
  709. namespace cpp
  710. {
  711. using B64_NAMESPACE::coding_exception;
  712. using B64_NAMESPACE::blob_t;
  713. using B64_NAMESPACE::string_t;
  714. using B64_NAMESPACE::decode;
  715. using B64_NAMESPACE::encode;
  716. } /* namespace cpp */
  717. #ifndef B64_NO_NAMESPACE
  718. } /* namespace B64_NAMESPACE */
  719. #endif /* !B64_NO_NAMESPACE */
  720. /* ////////////////////////////////////////////////////////////////////// */
  721. #endif /* B64_INCL_B64_HPP_B64 */
  722. /* ///////////////////////////// end of file //////////////////////////// */