aboutsummaryrefslogtreecommitdiff
path: root/libxsde/xsde/cxx/parser/non-validating/base64-binary.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'libxsde/xsde/cxx/parser/non-validating/base64-binary.cxx')
-rw-r--r--libxsde/xsde/cxx/parser/non-validating/base64-binary.cxx241
1 files changed, 241 insertions, 0 deletions
diff --git a/libxsde/xsde/cxx/parser/non-validating/base64-binary.cxx b/libxsde/xsde/cxx/parser/non-validating/base64-binary.cxx
new file mode 100644
index 0000000..95588a2
--- /dev/null
+++ b/libxsde/xsde/cxx/parser/non-validating/base64-binary.cxx
@@ -0,0 +1,241 @@
+// file : xsde/cxx/parser/non-validating/base64-binary.cxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <xsde/cxx/config.hxx>
+
+#include <xsde/cxx/parser/non-validating/base64-binary.hxx>
+
+static unsigned char
+base64_decode (char c)
+{
+ unsigned char r = 0xFF;
+
+ if (c >= 'A' && c <= 'Z')
+ r = static_cast<unsigned char> (c - 'A');
+ else if (c >= 'a' && c <= 'z')
+ r = static_cast<unsigned char> (c - 'a' + 26);
+ else if (c >= '0' && c <= '9')
+ r = static_cast<unsigned char> (c - '0' + 52);
+ else if (c == '+')
+ r = 62;
+ else if (c == '/')
+ r = 63;
+
+ return r;
+}
+
+namespace xsde
+{
+ namespace cxx
+ {
+ namespace parser
+ {
+ namespace non_validating
+ {
+ base64_binary_pimpl::
+ ~base64_binary_pimpl ()
+ {
+ if (!base_)
+ delete buf_;
+ }
+
+ void base64_binary_pimpl::
+ _reset ()
+ {
+ base64_binary_pskel::_reset ();
+
+ if (!base_)
+ {
+ delete buf_;
+ buf_ = 0;
+ }
+ }
+
+ base64_binary_pimpl::
+ base64_binary_pimpl (bool base)
+ : base_ (base), buf_ (0)
+ {
+ }
+
+ void base64_binary_pimpl::
+ pre_impl (buffer* b)
+ {
+ buf_ = b;
+ }
+
+ void base64_binary_pimpl::
+ _pre ()
+ {
+ if (buf_ == 0)
+ {
+ buf_ = new buffer ();
+
+#ifndef XSDE_EXCEPTIONS
+ if (buf_ == 0)
+ {
+ _sys_error (sys_error::no_memory);
+ return;
+ }
+#endif
+ }
+
+#ifdef XSDE_EXCEPTIONS
+ str_.assign ("", 0);
+#else
+ if (str_.assign ("", 0))
+ _sys_error (sys_error::no_memory);
+#endif
+ }
+
+ void base64_binary_pimpl::
+ _characters (const ro_string& s)
+ {
+ if (str_.size () == 0)
+ {
+ ro_string tmp (s.data (), s.size ());
+
+ if (trim_left (tmp) != 0)
+ {
+#ifdef XSDE_EXCEPTIONS
+ str_.append (tmp.data (), tmp.size ());
+#else
+ if (str_.append (tmp.data (), tmp.size ()))
+ _sys_error (sys_error::no_memory);
+#endif
+ }
+ }
+ else
+ {
+#ifdef XSDE_EXCEPTIONS
+ str_.append (s.data (), s.size ());
+#else
+ if (str_.append (s.data (), s.size ()))
+ _sys_error (sys_error::no_memory);
+#endif
+ }
+ }
+
+ buffer* base64_binary_pimpl::
+ post_base64_binary ()
+ {
+ typedef string::size_type size_type;
+
+ size_type size = str_.size ();
+ const char* src = str_.data ();
+
+ // Remove all whitespaces.
+ //
+ {
+ size_type j = 0;
+ bool subs = false;
+
+ for (size_type i = 0; i < size; ++i)
+ {
+ char c = str_[i];
+
+ if (c == 0x20 || c == 0x0A || c == 0x0D || c == 0x09)
+ {
+ subs = true;
+ }
+ else
+ {
+ if (subs)
+ subs = false;
+
+ str_[j++] = c;
+ }
+ }
+
+ size = j;
+ str_.truncate (size);
+ }
+
+ // Our length should be a multiple of four.
+ //
+ size_type quad_count = size / 4;
+ size_type capacity = quad_count * 3 + 1;
+
+#ifdef XSDE_EXCEPTIONS
+ buf_->size (capacity);
+#else
+ if (buf_->size (capacity))
+ {
+ _sys_error (sys_error::no_memory);
+ return 0;
+ }
+#endif
+ char* dst = buf_->data ();
+
+ // Source and destination indexes.
+ //
+ size_type si = 0;
+ size_type di = 0;
+
+ // Process all quads except the last one.
+ //
+ unsigned char b1, b2, b3, b4;
+
+ for (size_type q = 0; q < quad_count - 1; ++q)
+ {
+ b1 = base64_decode (src[si++]);
+ b2 = base64_decode (src[si++]);
+ b3 = base64_decode (src[si++]);
+ b4 = base64_decode (src[si++]);
+
+ dst[di++] = (b1 << 2) | (b2 >> 4);
+ dst[di++] = (b2 << 4) | (b3 >> 2);
+ dst[di++] = (b3 << 6) | b4;
+ }
+
+ // Process the last quad. The first two octets are always there.
+ //
+ b1 = base64_decode (src[si++]);
+ b2 = base64_decode (src[si++]);
+
+ char e3 = src[si++];
+ char e4 = src[si++];
+
+ if (e4 == '=')
+ {
+ if (e3 == '=')
+ {
+ // Two pads. Last 4 bits in b2 should be zero.
+ //
+ dst[di++] = (b1 << 2) | (b2 >> 4);
+ }
+ else
+ {
+ // One pad. Last 2 bits in b3 should be zero.
+ //
+ b3 = base64_decode (e3);
+
+ dst[di++] = (b1 << 2) | (b2 >> 4);
+ dst[di++] = (b2 << 4) | (b3 >> 2);
+ }
+ }
+ else
+ {
+ // No pads.
+ //
+ b3 = base64_decode (e3);
+ b4 = base64_decode (e4);
+
+ dst[di++] = (b1 << 2) | (b2 >> 4);
+ dst[di++] = (b2 << 4) | (b3 >> 2);
+ dst[di++] = (b3 << 6) | b4;
+ }
+
+ // Set the real size.
+ //
+ buf_->size (di);
+
+ buffer* r = buf_;
+ buf_ = 0;
+ return r;
+ }
+ }
+ }
+ }
+}