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:     24th August 2008
00008  *
00009  * Home:        http://synesis.com.au/software/
00010  *
00011  * Copyright 2004-2008, 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   5
00068 # define B64_VER_B64_HPP_B64_EDIT       30
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 < 0x010930ff
00089 # error Requires STLSoft 1.9.48, 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 
00223 public:
00225     coding_exception(B64_RC rc, char const *badChar)
00226         : parent_class_type("decoding error")
00227         , m_rc(rc)
00228         , m_badChar(badChar)
00229     {}
00230 
00231 public:
00233     virtual char const *what() const throw()
00234     {
00235         return "decoding error";
00236     }
00237 
00238 public:
00240     B64_RC      get_rc() const
00241     {
00242         return m_rc;
00243     }
00248     char const  *get_badChar() const
00249     {
00250         return m_badChar;
00251     }
00252 
00253 private:
00254     B64_RC      m_rc;
00255     char const  *m_badChar;
00256 };
00257 #endif /* STLSOFT_CF_EXCEPTION_SUPPORT */
00258 
00259 /* /////////////////////////////////////////////////////////////////////////////
00260  * Typedefs
00261  */
00262 
00284 #if defined(B64_USE_CUSTOM_STRING)
00285 typedef B64_CUSTOM_STRING_TYPE          string_t;
00286 #else /* B64_USE_CUSTOM_STRING */
00287 typedef std::string                     string_t;
00288 #endif /* !B64_USE_CUSTOM_STRING */
00289 
00312 #if defined(B64_USE_CUSTOM_VECTOR)
00313 typedef B64_CUSTOM_BLOB_TYPE            blob_t;
00314 #else /* B64_USE_CUSTOM_VECTOR */
00315 # ifndef B64_DOCUMENTATION_SKIP_SECTION
00316 typedef ::stlsoft::byte_t               byte_t_;
00317 typedef std::vector<byte_t_>            blob_t;
00318 # else /* !B64_DOCUMENTATION_SKIP_SECTION */
00319 typedef std::vector< ::stlsoft::byte_t> blob_t;
00320 # endif /* !B64_DOCUMENTATION_SKIP_SECTION */
00321 #endif /* !B64_USE_CUSTOM_VECTOR */
00322 
00323 /* /////////////////////////////////////////////////////////////////////////////
00324  * Functions
00325  */
00326 
00357 inline string_t encode(void const *src, size_t srcSize, unsigned flags, int lineLen = 0, B64_RC *rc = NULL)
00358 {
00359     B64_RC  rc_;
00360 
00361     // Make sure rc is non-NULL, since we will need to get the RC in order to
00362     // throw exception later.
00363     if(NULL == rc)
00364     {
00365         rc = &rc_;
00366     }
00367 
00368     size_t      n   =   B64_NAMESPACE_QUALIFIER::b64_encode2(src, srcSize, NULL, 0, flags, lineLen, rc);
00369 
00370 #ifdef B64_STRING_TYPE_IS_CONTIGUOUS
00371 
00372     // If the string type is known to have contiguous storage we can avoid
00373     // any intermediate memory, and decode directly into its internal
00374     // buffer.
00375 
00376     string_t    s(n, '~'); // ~ is used for an invalid / eyecatcher
00377 
00378     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));
00379 
00380     size_t      n2  =   B64_NAMESPACE_QUALIFIER::b64_encode2(src, srcSize, &s[0], s.length(), flags, lineLen, rc);
00381 
00382     s.resize(n2);
00383 
00384 #else /* ? B64_STRING_TYPE_IS_CONTIGUOUS */
00385 
00386     // If the string type is not known to be contiguous, then we must use
00387     // intermediate storage. Here we use a 1KB auto_buffer, so that only
00388     // data in excess of that will incur an additional (over the string's)
00389     // heap allocation.
00390 
00391     typedef stlsoft::auto_buffer<char, 1024>        buffer_t;
00392 
00393     buffer_t    buffer(n);
00394     size_t      n2  =   B64_NAMESPACE_QUALIFIER::b64_encode2(src, srcSize, &buffer[0], buffer.size(), flags, lineLen, rc);
00395 
00396     string_t    s(&buffer[0], n2);
00397 #endif /* B64_STRING_TYPE_IS_CONTIGUOUS */
00398 
00399 #ifdef STLSOFT_CF_EXCEPTION_SUPPORT
00400     if( 0 != srcSize &&
00401         0 == n2 &&
00402         rc == &rc_)
00403     {
00404         throw coding_exception(*rc, NULL);
00405     }
00406 #endif /* STLSOFT_CF_EXCEPTION_SUPPORT */
00407 
00408     return s;
00409 }
00410 
00434 inline string_t encode(void const *src, size_t srcSize)
00435 {
00436     return encode(src, srcSize, 0, 0, NULL);
00437 }
00438 
00439 #ifdef STLSOFT_CF_STATIC_ARRAY_SIZE_DETERMINATION_SUPPORT
00440 
00462 template <typename T, size_t N>
00463 inline string_t encode(T (&ar)[N])
00464 {
00465     return encode(&ar[0], sizeof(T) * N);
00466 }
00467 #endif /* STLSOFT_CF_STATIC_ARRAY_SIZE_DETERMINATION_SUPPORT */
00468 
00486 inline string_t encode(blob_t const &blob)
00487 {
00488     return encode(&blob[0], blob.size());
00489 }
00490 
00515 inline string_t encode(blob_t const &blob, unsigned flags, int lineLen = 0, B64_RC *rc = NULL)
00516 {
00517     return encode(&blob[0], blob.size(), flags, lineLen, rc);
00518 }
00519 
00546 inline blob_t decode(char const *src, size_t srcLen, unsigned flags, char const **badChar = NULL, B64_RC *rc = NULL)
00547 {
00548 #ifdef STLSOFT_CF_EXCEPTION_SUPPORT
00549     B64_RC      rc_;
00550     char const  *badChar_;
00551 
00552     if(NULL == rc)
00553     {
00554         rc = &rc_;
00555     }
00556     if(NULL == badChar)
00557     {
00558         badChar = &badChar_;
00559     }
00560 #endif /* STLSOFT_CF_EXCEPTION_SUPPORT */
00561 
00562     size_t  n   =   B64_NAMESPACE_QUALIFIER::b64_decode2(src, srcLen, NULL, 0, flags, badChar, rc);
00563     blob_t  v(n);
00564     size_t  n2  =   v.empty() ? 0 : B64_NAMESPACE_QUALIFIER::b64_decode2(src, srcLen, &v[0], v.size(), flags, badChar, rc);
00565 
00566     v.resize(n2);
00567 
00568 #ifdef STLSOFT_CF_EXCEPTION_SUPPORT
00569     if( 0 != srcLen &&
00570         0 == n2 &&
00571         rc == &rc_)
00572     {
00573         throw coding_exception(*rc, *badChar);
00574     }
00575 #endif /* STLSOFT_CF_EXCEPTION_SUPPORT */
00576 
00577     return v;
00578 }
00579 
00598 inline blob_t decode(char const *src, size_t srcLen)
00599 {
00600     return decode(src, srcLen, 0, NULL, NULL);
00601 }
00602 
00620 template <class S>
00621 inline blob_t decode(S const &str)
00622 {
00623     stlsoft_ns_using(c_str_data_a);
00624     stlsoft_ns_using(c_str_len_a);
00625 
00626     return decode(c_str_data_a(str), c_str_len_a(str));
00627 }
00628 
00649 inline blob_t decode(string_t const &str, unsigned flags = 0)
00650 {
00651     stlsoft_ns_using(c_str_data_a);
00652     stlsoft_ns_using(c_str_len_a);
00653 
00654     return decode(c_str_data_a(str), c_str_len_a(str), flags, NULL, NULL);
00655 }
00656 
00682 inline blob_t decode(string_t const &str, unsigned flags, char const **badChar, B64_RC *rc = NULL)
00683 {
00684     stlsoft_ns_using(c_str_data_a);
00685     stlsoft_ns_using(c_str_len_a);
00686 
00687     return decode(c_str_data_a(str), c_str_len_a(str), flags, badChar, rc);
00688 }
00689 
00690 /* /////////////////////////////////////////////////////////////////////////////
00691  * Namespace
00692  */
00693 
00702 namespace cpp
00703 {
00704 
00705     using B64_NAMESPACE::coding_exception;
00706 
00707     using B64_NAMESPACE::blob_t;
00708     using B64_NAMESPACE::string_t;
00709 
00710     using B64_NAMESPACE::decode;
00711     using B64_NAMESPACE::encode;
00712 
00713 } /* namespace cpp */
00714 
00715 #ifndef B64_NO_NAMESPACE
00716 } /* namespace B64_NAMESPACE */
00717 #endif /* !B64_NO_NAMESPACE */
00718 
00719 /* ////////////////////////////////////////////////////////////////////////// */
00720 
00721 #endif /* B64_INCL_B64_HPP_B64 */
00722 
00723 /* ////////////////////////////////////////////////////////////////////////// */

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