Synesis Software STLSoft - ... Robust, Lightweight, Cross-platform, Template Software ...

b64/b64.hpp

Go to the documentation of this file.
00001 /* /////////////////////////////////////////////////////////////////////////
00002  * File:        b64/b64.hpp
00003  *
00004  * Purpose:     Header file for the b64 C++-API.
00005  *
00006  * Created:     18th October 2004
00007  * Updated:     20th January 2010
00008  *
00009  * Home:        http://synesis.com.au/software/
00010  *
00011  * Copyright 2004-2010, Matthew Wilson and Synesis Software
00012  * All rights reserved.
00013  *
00014  * Redistribution and use in source and binary forms, with or without 
00015  * modification, are permitted provided that the following conditions are met:
00016  *
00017  * - Redistributions of source code must retain the above copyright notice, this
00018  *   list of conditions and the following disclaimer. 
00019  * - Redistributions in binary form must reproduce the above copyright notice,
00020  *   this list of conditions and the following disclaimer in the documentation
00021  *   and/or other materials provided with the distribution.
00022  * - Neither the name(s) of Matthew Wilson and Synesis Software nor the names of
00023  *   any contributors may be used to endorse or promote products derived from
00024  *   this software without specific prior written permission.
00025  *
00026  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00027  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00028  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00029  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
00030  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00031  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00032  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00033  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00034  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00035  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00036  * POSSIBILITY OF SUCH DAMAGE.
00037  *
00038  * ////////////////////////////////////////////////////////////////////// */
00039 
00040 
00057 #ifndef B64_INCL_B64_HPP_B64
00058 #define B64_INCL_B64_HPP_B64
00059 
00060 /* /////////////////////////////////////////////////////////////////////////
00061  * Version information
00062  */
00063 
00064 #ifndef B64_DOCUMENTATION_SKIP_SECTION
00065 # define B64_VER_B64_HPP_B64_MAJOR      2
00066 # define B64_VER_B64_HPP_B64_MINOR      1
00067 # define B64_VER_B64_HPP_B64_REVISION   8
00068 # define B64_VER_B64_HPP_B64_EDIT       33
00069 #endif /* !B64_DOCUMENTATION_SKIP_SECTION */
00070 
00071 /* /////////////////////////////////////////////////////////////////////////
00072  * Includes
00073  */
00074 
00075 #ifndef B64_INCL_B64_H_B64
00076 # include <b64/b64.h>
00077 #endif /* !B64_INCL_B64_H_B64 */
00078 
00079 /* If the compiler cannot find the following include, you may have not
00080  * upgraded to the latest version of STLSoft: 1.9.1. Go to
00081  *  http://stlsoft.org/ and download this version or later.
00082  */
00083 #ifndef STLSOFT_INCL_STLSOFT_H_STLSOFT
00084 # include <stlsoft/stlsoft.h>
00085 #endif /* !STLSOFT_INCL_STLSOFT_H_STLSOFT */
00086 
00087 #if !defined(_STLSOFT_VER) || \
00088     _STLSOFT_VER < 0x010957ff
00089 # error Requires STLSoft 1.9.87, or later. (www.stlsoft.org/downloads.html)
00090 #endif /* STLSoft version */
00091 
00092 #ifdef STLSOFT_CF_std_NAMESPACE
00093 
00094 # if defined(B64_USE_CUSTOM_STRING)
00095 #  include B64_CUSTOM_STRING_INCLUDE
00096 # else /* B64_USE_CUSTOM_STRING */
00097 #  include <string>
00098 # endif /* !B64_USE_CUSTOM_STRING */
00099 
00100 # if defined(B64_USE_CUSTOM_VECTOR)
00101 #  include B64_CUSTOM_VECTOR_INCLUDE
00102 # else /* B64_USE_CUSTOM_VECTOR */
00103 #  include <vector>
00104 # endif /* !B64_USE_CUSTOM_VECTOR */
00105 
00106  /* We'll now have a go at checking whether the string type is 
00107   * known to be contiguous
00108   */
00109 # ifndef STLSOFT_INCL_STLSOFT_UTIL_STD_LIBRARY_DISCRIMINATOR
00110 #  include <stlsoft/util/std/library_discriminator.hpp>
00111 # endif /* !STLSOFT_INCL_STLSOFT_UTIL_STD_LIBRARY_DISCRIMINATOR */
00112 # ifdef STLSOFT_CF_STD_LIBRARY_IS_DINKUMWARE_VC
00113 #  if STLSOFT_CF_STD_LIBRARY_DINKUMWARE_VC_VERSION <= STLSOFT_CF_DINKUMWARE_VC_VERSION_7_1
00114 #   define B64_STRING_TYPE_IS_CONTIGUOUS
00115 #  endif /* STLSOFT_CF_STD_LIBRARY_DINKUMWARE_VC_VERSION */
00116 # endif /* STLSOFT_CF_STD_LIBRARY_IS_DINKUMWARE_VC */
00117 
00118 #else /* ? STLSOFT_CF_std_NAMESPACE */
00119 
00120 # if defined(STLSOFT_COMPILER_IS_WATCOM)
00121 #  include <string.hpp>
00122 #  include <wcvector.h>
00123 #  define   B64_USE_CUSTOM_STRING
00124 #  define   B64_CUSTOM_STRING_TYPE      watcom_string_for_b64
00125 #  define   B64_USE_CUSTOM_VECTOR
00126 #  define   B64_CUSTOM_BLOB_TYPE        watcom_vector_for_b64
00127 #  define   B64_STRING_TYPE_IS_CONTIGUOUS
00128 # else /* ? compiler */
00129 #  error No other non-std compiler is known
00130 # endif /* ? compiler */
00131 
00132 #endif /* STLSOFT_CF_std_NAMESPACE */
00133 
00134 #ifdef B64_NO_CONTIGUOUS_STRING_TYPE
00135 # ifdef B64_STRING_TYPE_IS_CONTIGUOUS
00136 #  undef B64_STRING_TYPE_IS_CONTIGUOUS
00137 # endif /* B64_STRING_TYPE_IS_CONTIGUOUS */
00138 #endif /* B64_NO_CONTIGUOUS_STRING_TYPE */
00139 
00140 #if !defined(B64_STRING_TYPE_IS_CONTIGUOUS)
00141 # ifndef STLSOFT_INCL_STLSOFT_MEMORY_HPP_AUTO_BUFFER
00142 #  include <stlsoft/memory/auto_buffer.hpp>
00143 # endif /* !STLSOFT_INCL_STLSOFT_MEMORY_HPP_AUTO_BUFFER */
00144 #endif /* !B64_STRING_TYPE_IS_CONTIGUOUS */
00145 
00146 #ifndef STLSOFT_INCL_STLSOFT_SHIMS_ACCESS_HPP_STRING
00147 # include <stlsoft/shims/access/string.hpp>
00148 #endif /* !STLSOFT_INCL_STLSOFT_SHIMS_ACCESS_HPP_STRING */
00149 
00150 #ifdef STLSOFT_CF_EXCEPTION_SUPPORT
00151 # if defined(STLSOFT_COMPILER_IS_WATCOM)
00152 #  include <stdexcep.h>
00153 # else /* ? compiler */
00154 #  include <stdexcept>
00155 # endif /* compiler */
00156 #endif /* STLSOFT_CF_EXCEPTION_SUPPORT */
00157 
00158 /* /////////////////////////////////////////////////////////////////////////
00159  * Namespace
00160  */
00161 
00162 #ifndef B64_NO_NAMESPACE
00163 namespace B64_NAMESPACE
00164 {
00165 #endif /* !B64_NO_NAMESPACE */
00166 
00167 /* /////////////////////////////////////////////////////////////////////////
00168  * Classes
00169  */
00170 
00171 #if defined(STLSOFT_COMPILER_IS_WATCOM)
00172 class watcom_vector_for_b64
00173     : public WCValVector<unsigned char>
00174 {
00175 private:
00176     typedef WCValVector<unsigned char>  parent_class_type;
00177     typedef watcom_vector_for_b64       class_type;
00178 public:
00179     watcom_vector_for_b64()
00180     {}
00181     watcom_vector_for_b64(size_t n)
00182         : parent_class_type(n)
00183     {}
00184     watcom_vector_for_b64(class_type const &rhs)
00185         : parent_class_type(rhs)
00186     {}
00187 
00188 public:
00189     size_t size() const
00190     {
00191         return parent_class_type::length();
00192     }
00193 };
00194 
00195 class watcom_string_for_b64
00196     : public String
00197 {
00198 public:
00199     watcom_string_for_b64(size_t n, char ch)
00200         : String(ch, n)
00201     {}
00202 
00203 public:
00204     void resize(size_t n)
00205     {
00206         String& this_ = *this;
00207 
00208         this_ = String(*this, n);
00209     }
00210 };
00211 #endif /* STLSOFT_COMPILER_IS_WATCOM */
00212 
00213 #ifdef STLSOFT_CF_EXCEPTION_SUPPORT
00214 
00216 class coding_exception
00217     : public stlsoft_ns_qual_std(runtime_error)
00218 {
00219 public:
00220     typedef stlsoft_ns_qual_std(runtime_error)  parent_class_type;
00221     typedef coding_exception                    class_type;
00222 private:
00223 #if defined(B64_USE_CUSTOM_STRING)
00224     typedef B64_CUSTOM_STRING_TYPE              string_type;
00225 #else /* B64_USE_CUSTOM_STRING */
00226     typedef std::string                         string_type;
00227 #endif /* !B64_USE_CUSTOM_STRING */
00228 
00229 public:
00231     coding_exception(B64_RC rc, char const* badChar)
00232         : parent_class_type(make_message_(rc))
00233         , m_rc(rc)
00234         , m_badChar(badChar)
00235     {}
00236 
00237 public:
00239     B64_RC get_rc() const
00240     {
00241         return m_rc;
00242     }
00247     char const* get_badChar() const
00248     {
00249         return m_badChar;
00250     }
00251 
00252 private:
00253     static string_type make_message_(B64_RC rc)
00254     {
00255         return string_type("Decoding error: ") + b64_getErrorString(rc);
00256     }
00257 
00258 private:
00259     B64_RC      m_rc;
00260     char const* m_badChar;
00261 };
00262 #endif /* STLSOFT_CF_EXCEPTION_SUPPORT */
00263 
00264 /* /////////////////////////////////////////////////////////////////////////
00265  * Typedefs
00266  */
00267 
00289 #if defined(B64_USE_CUSTOM_STRING)
00290 typedef B64_CUSTOM_STRING_TYPE          string_t;
00291 #else /* B64_USE_CUSTOM_STRING */
00292 typedef std::string                     string_t;
00293 #endif /* !B64_USE_CUSTOM_STRING */
00294 
00317 #if defined(B64_USE_CUSTOM_VECTOR)
00318 typedef B64_CUSTOM_BLOB_TYPE            blob_t;
00319 #else /* B64_USE_CUSTOM_VECTOR */
00320 # ifndef B64_DOCUMENTATION_SKIP_SECTION
00321 typedef ::stlsoft::byte_t               byte_t_;
00322 typedef std::vector<byte_t_>            blob_t;
00323 # else /* !B64_DOCUMENTATION_SKIP_SECTION */
00324 typedef std::vector< ::stlsoft::byte_t> blob_t;
00325 # endif /* !B64_DOCUMENTATION_SKIP_SECTION */
00326 #endif /* !B64_USE_CUSTOM_VECTOR */
00327 
00328 /* /////////////////////////////////////////////////////////////////////////
00329  * Functions
00330  */
00331 
00362 inline string_t encode(void const* src, size_t srcSize, int flags, int lineLen = 0, B64_RC* rc = NULL)
00363 {
00364     B64_RC  rc_;
00365 
00366     // Make sure rc is non-NULL, since we will need to get the RC in order to
00367     // throw exception later.
00368     if(NULL == rc)
00369     {
00370         rc = &rc_;
00371     }
00372 
00373     size_t      n   =   B64_NAMESPACE_QUALIFIER::b64_encode2(src, srcSize, NULL, 0u, static_cast<unsigned>(flags), lineLen, rc);
00374 
00375 #ifdef B64_STRING_TYPE_IS_CONTIGUOUS
00376 
00377     // If the string type is known to have contiguous storage we can avoid
00378     // any intermediate memory, and decode directly into its internal
00379     // buffer.
00380 
00381     string_t    s(n, '~'); // ~ is used for an invalid / eyecatcher
00382 
00383     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));
00384 
00385     size_t      n2  =   B64_NAMESPACE_QUALIFIER::b64_encode2(src, srcSize, &s[0], s.length(), static_cast<unsigned>(flags), lineLen, rc);
00386 
00387     s.resize(n2);
00388 
00389 #else /* ? B64_STRING_TYPE_IS_CONTIGUOUS */
00390 
00391     // If the string type is not known to be contiguous, then we must use
00392     // intermediate storage. Here we use a 1KB auto_buffer, so that only
00393     // data in excess of that will incur an additional (over the string's)
00394     // heap allocation.
00395 
00396     typedef stlsoft::auto_buffer<b64_char_t, 1024>  buffer_t;
00397 
00398     buffer_t    buffer(n);
00399     size_t      n2  =   B64_NAMESPACE_QUALIFIER::b64_encode2(src, srcSize, &buffer[0], buffer.size(), static_cast<unsigned>(flags), lineLen, rc);
00400 
00401     string_t    s(&buffer[0], n2);
00402 #endif /* B64_STRING_TYPE_IS_CONTIGUOUS */
00403 
00404 #ifdef STLSOFT_CF_EXCEPTION_SUPPORT
00405     if( 0 != srcSize &&
00406         0 == n2 &&
00407         rc == &rc_)
00408     {
00409         throw coding_exception(*rc, NULL);
00410     }
00411 #endif /* STLSOFT_CF_EXCEPTION_SUPPORT */
00412 
00413     return s;
00414 }
00415 
00439 inline string_t encode(void const* src, size_t srcSize)
00440 {
00441     return encode(src, srcSize, 0, 0, NULL);
00442 }
00443 
00444 #ifdef STLSOFT_CF_STATIC_ARRAY_SIZE_DETERMINATION_SUPPORT
00445 
00467 template <typename T, size_t N>
00468 inline string_t encode(T (&ar)[N])
00469 {
00470     return encode(&ar[0], sizeof(T) * N);
00471 }
00472 #endif /* STLSOFT_CF_STATIC_ARRAY_SIZE_DETERMINATION_SUPPORT */
00473 
00491 inline string_t encode(blob_t const &blob)
00492 {
00493     return encode(blob.empty() ? NULL : &blob[0], blob.size());
00494 }
00495 
00520 inline string_t encode(blob_t const &blob, int flags, int lineLen = 0, B64_RC* rc = NULL)
00521 {
00522     return encode(blob.empty() ? NULL : &blob[0], blob.size(), flags, lineLen, rc);
00523 }
00524 
00551 inline blob_t decode(b64_char_t const* src, size_t srcLen, int flags, b64_char_t const** badChar = NULL, B64_RC* rc = NULL)
00552 {
00553 #ifdef STLSOFT_CF_EXCEPTION_SUPPORT
00554     B64_RC              rc_;
00555     b64_char_t const*   badChar_;
00556 
00557     if(NULL == rc)
00558     {
00559         rc = &rc_;
00560     }
00561     if(NULL == badChar)
00562     {
00563         badChar = &badChar_;
00564     }
00565 #endif /* STLSOFT_CF_EXCEPTION_SUPPORT */
00566 
00567     size_t  n   =   B64_NAMESPACE_QUALIFIER::b64_decode2(src, srcLen, NULL, 0, static_cast<unsigned>(flags), badChar, rc);
00568     blob_t  v(n);
00569     size_t  n2  =   v.empty() ? 0 : B64_NAMESPACE_QUALIFIER::b64_decode2(src, srcLen, &v[0], v.size(), static_cast<unsigned>(flags), badChar, rc);
00570 
00571     v.resize(n2);
00572 
00573 #ifdef STLSOFT_CF_EXCEPTION_SUPPORT
00574     if( 0 != srcLen &&
00575         0 == n2 &&
00576         rc == &rc_)
00577     {
00578         throw coding_exception(*rc, (badChar == &badChar_) ? *badChar : NULL);
00579     }
00580 #endif /* STLSOFT_CF_EXCEPTION_SUPPORT */
00581 
00582     return v;
00583 }
00584 
00603 inline blob_t decode(b64_char_t const* src, size_t srcLen)
00604 {
00605     return decode(src, srcLen, B64_F_STOP_ON_BAD_CHAR, NULL, NULL);
00606 }
00607 
00608 #ifndef B64_DOCUMENTATION_SKIP_SECTION
00609 STLSOFT_OPEN_WORKER_NS_(impl)
00610 
00611 
00629 template <class S>
00630 inline blob_t b64_impl_decode_(int flags, S const &str)
00631 {
00632     stlsoft_ns_using(c_str_data_a);
00633     stlsoft_ns_using(c_str_len_a);
00634 
00635     b64_char_t const* dummy; // Cannot rely on badChar being available in str
00636 
00637     return decode(c_str_data_a(str), c_str_len_a(str), static_cast<B64_FLAGS>(flags), &dummy, NULL);
00638 }
00639 
00640 STLSOFT_CLOSE_WORKER_NS_(ns)
00641 #endif /* !B64_DOCUMENTATION_SKIP_SECTION */
00642 
00643 
00661 template <class S>
00662 inline blob_t decode(S const &str)
00663 {
00664     return STLSOFT_WORKER_NS_QUAL_(impl, b64_impl_decode_)(B64_F_STOP_ON_BAD_CHAR, str);
00665 }
00666 
00685 template <class S>
00686 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
00687 {
00688     return STLSOFT_WORKER_NS_QUAL_(impl, b64_impl_decode_)(flags, str);
00689 }
00690 
00711 inline blob_t decode(string_t const &str, int flags = B64_F_STOP_ON_BAD_CHAR)
00712 {
00713     stlsoft_ns_using(c_str_data_a);
00714     stlsoft_ns_using(c_str_len_a);
00715 
00716     return decode(c_str_data_a(str), c_str_len_a(str), flags, NULL, NULL);
00717 }
00718 
00744 inline blob_t decode(string_t const &str, int flags, b64_char_t const** badChar, B64_RC* rc = NULL)
00745 {
00746     stlsoft_ns_using(c_str_data_a);
00747     stlsoft_ns_using(c_str_len_a);
00748 
00749     return decode(c_str_data_a(str), c_str_len_a(str), flags, badChar, rc);
00750 }
00751 
00752 /* /////////////////////////////////////////////////////////////////////////
00753  * Namespace
00754  */
00755 
00764 namespace cpp
00765 {
00766 
00767     using B64_NAMESPACE::coding_exception;
00768 
00769     using B64_NAMESPACE::blob_t;
00770     using B64_NAMESPACE::string_t;
00771 
00772     using B64_NAMESPACE::decode;
00773     using B64_NAMESPACE::encode;
00774 
00775 } /* namespace cpp */
00776 
00777 #ifndef B64_NO_NAMESPACE
00778 } /* namespace B64_NAMESPACE */
00779 #endif /* !B64_NO_NAMESPACE */
00780 
00781 /* ////////////////////////////////////////////////////////////////////// */
00782 
00783 #endif /* B64_INCL_B64_HPP_B64 */
00784 
00785 /* ///////////////////////////// end of file //////////////////////////// */

b64 Library documentation © Synesis Software Pty Ltd, 2004-2007