← Back to team overview

zorba-coders team mailing list archive

[Merge] lp:~zorba-coders/zorba/bug-1153800 into lp:zorba

 

Paul J. Lucas has proposed merging lp:~zorba-coders/zorba/bug-1153800 into lp:zorba.

Commit message:
Added ability to create a hexBinary item with either encoded or unencoded data.

Requested reviews:
  Paul J. Lucas (paul-lucas)
Related bugs:
  Bug #1153800 in Zorba: "construct hexBinary without encoding the data"
  https://bugs.launchpad.net/zorba/+bug/1153800

For more details, see:
https://code.launchpad.net/~zorba-coders/zorba/bug-1153800/+merge/153675

Added ability to create a hexBinary item with either encoded or unencoded data.
-- 
https://code.launchpad.net/~zorba-coders/zorba/bug-1153800/+merge/153675
Your team Zorba Coders is subscribed to branch lp:zorba.
=== modified file 'ChangeLog'
--- ChangeLog	2013-03-16 20:55:24 +0000
+++ ChangeLog	2013-03-17 04:52:23 +0000
@@ -36,6 +36,7 @@
   * Fixed bug #1148335 (where-clause expression was not always reset when it should be)
   * Fixed bug #1122396 (Associate origin/destination URI to I/O stream)
   * Fixed bug #1111786 (xml/json parse error location in catch clause).
+  * Fixed bug #1153800 (construct hexBinary without encoding the data)
   * NaN items are considered equal to each other during grouping
   * Fixed bug #855481 (Too small time types on Windows).
   * Fixed bug #1132032 (Certain regexes involving ^ should be legal)

=== modified file 'src/diagnostics/diagnostic_en.xml'
--- src/diagnostics/diagnostic_en.xml	2013-03-07 10:10:10 +0000
+++ src/diagnostics/diagnostic_en.xml	2013-03-17 04:52:23 +0000
@@ -1319,53 +1319,41 @@
 
     <diagnostic code="FORG0001">
       <comment>
-       Invalid value for cast/constructor.
+        Invalid value for cast/constructor.
       </comment>
-
       <value>$1</value>
-
-      <entry key="NoCastTo_234">
-        <value>"$2": value of type $3 is not castable to type $4</value>
-      </entry>
-
-      <entry key="NoCastTo_234o">
-        <value>"$2": value is not castable to type $3${: 4}</value>
-      </entry>
-
+      <entry key="BadHexDigit_2">
+        <value>'$2': invalid hexedecimal digit</value>
+      </entry>
+      <entry key="Base64BadChar_2">
+        <value>'$2': invalid Base64 character</value>
+      </entry>
+      <entry key="Base64Multiple4">
+        <value>Base64 data must be a multiple of 4 bytes</value>
+      </entry>
+      <entry key="HexBinaryMustBeEven">
+        <value>hexBinary value must contain an even number of bytes</value>
+      </entry>
       <entry key="LocalNotNCName_2">
         <value>"$2": local name in qname is not an xs:NCName</value>
       </entry>
-
-      <entry key="PrefixNotNCName_2">
-        <value>"$2": prefix in qname is not an xs:NCName</value>
-      </entry>
-
       <entry key="NameNotNCName_2">
         <value>"$2": name is not an xs:NCName</value>
       </entry>
-
+      <entry key="NoCastTo_234">
+        <value>"$2": value of type $3 is not castable to type $4</value>
+      </entry>
+      <entry key="NoCastTo_234o">
+        <value>"$2": value is not castable to type $3${: 4}</value>
+      </entry>
+      <entry key="NoTypeInCtx_2">
+        <value>"$2": type no defined in current context</value>
+      </entry>
       <entry key="PrefixNotBound_2">
         <value>"$2": prefix has no known namespace binding</value>
       </entry>
-
-      <entry key="Base64BadChar_2">
-        <value>"$2": invalid Base64 character</value>
-      </entry>
-
-      <entry key="Base64Multiple4">
-        <value>Base64 data must be a multiple of 4 characters</value>
-      </entry>
-
-      <entry key="HexBinaryMustBeEven">
-        <value>HexBinary value must contain an even number of characters</value>
-      </entry>
-
-      <entry key="BadHexDigit_2">
-        <value>'$2': invalid hexedecimal digit</value>
-      </entry>
-
-      <entry key="NoTypeInCtx_2">
-        <value>"$2": type no defined in current context</value>
+      <entry key="PrefixNotNCName_2">
+        <value>"$2": prefix in qname is not an xs:NCName</value>
       </entry>
     </diagnostic>
 

=== modified file 'src/diagnostics/pregenerated/dict_en.cpp'
--- src/diagnostics/pregenerated/dict_en.cpp	2013-03-07 10:10:10 +0000
+++ src/diagnostics/pregenerated/dict_en.cpp	2013-03-17 04:52:23 +0000
@@ -614,9 +614,9 @@
   { "~FOCA0002_NoCastTo_234", "\"$2\": value of type $3 is not castable to type $4" },
   { "~FOCA0002_NoURIforPrefix_2", "no namespace URI provided for prefix in lexical QName \"$2\"" },
   { "~FORG0001_BadHexDigit_2", "'$2': invalid hexedecimal digit" },
-  { "~FORG0001_Base64BadChar_2", "\"$2\": invalid Base64 character" },
-  { "~FORG0001_Base64Multiple4", "Base64 data must be a multiple of 4 characters" },
-  { "~FORG0001_HexBinaryMustBeEven", "HexBinary value must contain an even number of characters" },
+  { "~FORG0001_Base64BadChar_2", "'$2': invalid Base64 character" },
+  { "~FORG0001_Base64Multiple4", "Base64 data must be a multiple of 4 bytes" },
+  { "~FORG0001_HexBinaryMustBeEven", "hexBinary value must contain an even number of bytes" },
   { "~FORG0001_LocalNotNCName_2", "\"$2\": local name in qname is not an xs:NCName" },
   { "~FORG0001_NameNotNCName_2", "\"$2\": name is not an xs:NCName" },
   { "~FORG0001_NoCastTo_234", "\"$2\": value of type $3 is not castable to type $4" },

=== modified file 'src/diagnostics/pregenerated/dict_zed_keys.h'
--- src/diagnostics/pregenerated/dict_zed_keys.h	2013-03-07 10:10:10 +0000
+++ src/diagnostics/pregenerated/dict_zed_keys.h	2013-03-17 04:52:23 +0000
@@ -70,17 +70,17 @@
 #define ZED_FOCA0002_BadLexicalQName_2 "~FOCA0002_BadLexicalQName_2"
 #define ZED_FOCA0002_NoURIforPrefix_2 "~FOCA0002_NoURIforPrefix_2"
 #define ZED_FOCA0002_NoCastTo_234 "~FOCA0002_NoCastTo_234"
-#define ZED_FORG0001_NoCastTo_234 "~FORG0001_NoCastTo_234"
-#define ZED_FORG0001_NoCastTo_234o "~FORG0001_NoCastTo_234o"
-#define ZED_FORG0001_LocalNotNCName_2 "~FORG0001_LocalNotNCName_2"
-#define ZED_FORG0001_PrefixNotNCName_2 "~FORG0001_PrefixNotNCName_2"
-#define ZED_FORG0001_NameNotNCName_2 "~FORG0001_NameNotNCName_2"
-#define ZED_FORG0001_PrefixNotBound_2 "~FORG0001_PrefixNotBound_2"
+#define ZED_FORG0001_BadHexDigit_2 "~FORG0001_BadHexDigit_2"
 #define ZED_FORG0001_Base64BadChar_2 "~FORG0001_Base64BadChar_2"
 #define ZED_FORG0001_Base64Multiple4 "~FORG0001_Base64Multiple4"
 #define ZED_FORG0001_HexBinaryMustBeEven "~FORG0001_HexBinaryMustBeEven"
-#define ZED_FORG0001_BadHexDigit_2 "~FORG0001_BadHexDigit_2"
+#define ZED_FORG0001_LocalNotNCName_2 "~FORG0001_LocalNotNCName_2"
+#define ZED_FORG0001_NameNotNCName_2 "~FORG0001_NameNotNCName_2"
+#define ZED_FORG0001_NoCastTo_234 "~FORG0001_NoCastTo_234"
+#define ZED_FORG0001_NoCastTo_234o "~FORG0001_NoCastTo_234o"
 #define ZED_FORG0001_NoTypeInCtx_2 "~FORG0001_NoTypeInCtx_2"
+#define ZED_FORG0001_PrefixNotBound_2 "~FORG0001_PrefixNotBound_2"
+#define ZED_FORG0001_PrefixNotNCName_2 "~FORG0001_PrefixNotNCName_2"
 #define ZED_XUST0001_CONCAT "~XUST0001_CONCAT"
 #define ZED_XUST0001_TRYCATCH "~XUST0001_TRYCATCH"
 #define ZED_XUST0001_Generic "~XUST0001_Generic"

=== modified file 'src/store/api/item.h'
--- src/store/api/item.h	2013-03-05 12:34:19 +0000
+++ src/store/api/item.h	2013-03-17 04:52:23 +0000
@@ -481,8 +481,8 @@
 
   /** Accessor for xs:hexBinary
    */
-  virtual xs_hexBinary
-  getHexBinaryValue() const;
+  virtual char const*
+  getHexBinaryValue(size_t& size) const;
 
   /**
    * Helper method for numeric atomic items

=== modified file 'src/store/api/item_factory.h'
--- src/store/api/item_factory.h	2013-03-12 17:03:31 +0000
+++ src/store/api/item_factory.h	2013-03-17 04:52:23 +0000
@@ -216,13 +216,33 @@
    * Specification: [http://www.w3.org/TR/xmlschema-2/#hexBinary]
    * @param value
    */
-  virtual bool createHexBinary(Item_t& result, xs_hexBinary value) = 0;
+  virtual bool createHexBinary(
+      Item_t& result,
+      xs_hexBinary const &value) = 0;
+
+  /**
+   * Specification: [http://www.w3.org/TR/xmlschema-2/#hexBinary]
+   * creates a hexBinary item with the given content.
+   *
+   * @param result The resulting item.
+   * @param data The data to use.
+   * @param size The number of bytes of \a data.
+   * @param encoded specifies whether the given content is already hexBinary
+   * encoded or not.
+   */
+  virtual bool createHexBinary(
+      Item_t& result,
+      const char* data,
+      size_t size,
+      bool encoded) = 0;
 
   /**
    * Specification: [http://www.w3.org/TR/xmlschema-2/#base64Binary]
-   * @param value)?
+   * @param value
    */
-  virtual bool createBase64Binary(Item_t& result, xs_base64Binary value) = 0;
+  virtual bool createBase64Binary(
+      Item_t& result,
+      xs_base64Binary const &value) = 0;
 
   /**
    * Specification: [http://www.w3.org/TR/xmlschema-2/#base64Binary]

=== modified file 'src/store/naive/atomic_items.cpp'
--- src/store/naive/atomic_items.cpp	2013-02-26 04:12:43 +0000
+++ src/store/naive/atomic_items.cpp	2013-03-17 04:52:23 +0000
@@ -3667,13 +3667,10 @@
 }
 
 
-bool
-Base64BinaryItem::equals(
-      const store::Item* other,
-      long timezone,
-      const XQPCollator* aCollation) const
+bool Base64BinaryItem::equals( store::Item const *other, long timezone,
+                               XQPCollator const *aCollation ) const
 {
-  if (isEncoded() == other->isEncoded())
+  if ( isEncoded() == other->isEncoded() )
   {
     size_t this_size, other_size;
     const char* this_data = getBase64BinaryValue(this_size);
@@ -3694,12 +3691,11 @@
   // always need to hash on the string-value because otherwise
   // a base64 item that is encoded would have a different hash-value
   // as a base64 item that is decoded but represents the same binary content
-  return utf8::hash(getStringValue(), aCollation);
+  return utf8::hash( getStringValue(), aCollation );
 }
 
 
-const char*
-Base64BinaryItem::getBase64BinaryValue(size_t& size) const
+char const* Base64BinaryItem::getBase64BinaryValue( size_t &size ) const
 {
   size = theValue.size();
   return size > 0 ? &theValue[0] : "";
@@ -3730,13 +3726,9 @@
 void Base64BinaryItem::appendStringValue(zstring& buf) const
 {
   if (theValue.empty())
-  {
     return;
-  }
   if (theIsEncoded)
-  {
     buf.insert(buf.size(), &theValue[0], theValue.size());
-  }
   else
   {
     std::vector<char> encoded;
@@ -3936,6 +3928,29 @@
 }
 
 
+bool HexBinaryItem::equals( store::Item const *other, long timezone,
+                            XQPCollator const *aCollation ) const
+{
+  if ( isEncoded() == other->isEncoded() )
+  {
+    size_t this_size, other_size;
+    const char* this_data = getHexBinaryValue(this_size);
+    const char* other_data = other->getHexBinaryValue(other_size);
+    return this_size == other_size &&
+      memcmp(this_data, other_data, this_size) == 0;
+  }
+  else
+  {
+    return getStringValue().compare(other->getStringValue()) == 0;
+  }
+}
+
+char const* HexBinaryItem::getHexBinaryValue( size_t &size ) const
+{
+  size = theValue.size();
+  return size > 0 ? &theValue[0] : "";
+}
+
 store::Item* HexBinaryItem::getType() const
 {
   return GET_STORE().theSchemaTypeNames[store::XS_HEXBINARY];
@@ -3944,19 +3959,32 @@
 
 zstring HexBinaryItem::getStringValue() const
 {
-  return theValue.str();
+  zstring lRes;
+  getStringValue2(lRes);
+  return lRes;
 }
 
 
 void HexBinaryItem::getStringValue2(zstring& val) const
 {
-  val = theValue.str();
+  val.clear();
+  appendStringValue(val);
 }
 
 
 void HexBinaryItem::appendStringValue(zstring& buf) const
 {
-  buf += theValue.str();
+  if (theValue.empty())
+    return;
+  if (theIsEncoded)
+    buf.insert(buf.size(), &theValue[0], theValue.size());
+  else
+  {
+    std::vector<char> encoded;
+    encoded.reserve(theValue.size());
+    Base16::encode(theValue, encoded);
+    buf.insert(buf.size(), &encoded[0], encoded.size());
+  }
 }
 
 
@@ -3971,7 +3999,10 @@
 
 uint32_t HexBinaryItem::hash(long timezone, const XQPCollator* aCollation) const
 {
-  return theValue.hash();
+  // always need to hash on the string-value because otherwise
+  // a base64 item that is encoded would have a different hash-value
+  // as a hexBinary item that is decoded but represents the same binary content
+  return utf8::hash( getStringValue(), aCollation );
 }
 
 

=== modified file 'src/store/naive/atomic_items.h'
--- src/store/naive/atomic_items.h	2013-02-26 04:12:43 +0000
+++ src/store/naive/atomic_items.h	2013-03-17 04:52:23 +0000
@@ -162,7 +162,10 @@
     return theBaseItem->getBase64BinaryValue(s);
   }
 
-  xs_hexBinary getHexBinaryValue() const { return theBaseItem->getHexBinaryValue(); }
+  char const* getHexBinaryValue(size_t& s) const
+  {
+    return theBaseItem->getHexBinaryValue(s);
+  }
 
   bool getBooleanValue() const { return theBaseItem->getBooleanValue(); }
 
@@ -2510,62 +2513,43 @@
   bool              theIsEncoded;
 
 protected:
-  Base64BinaryItem(store::SchemaTypeCode t, bool aIsEncoded)
-    :
+  Base64BinaryItem( store::SchemaTypeCode t, bool aIsEncoded ) :
     AtomicItem(t),
     theIsEncoded(aIsEncoded)
   {
   }
 
-  Base64BinaryItem(
-      store::SchemaTypeCode t,
-      const char* aValue,
-      size_t aSize,
-      bool aIsEncoded = true)
-    :
+  Base64BinaryItem( store::SchemaTypeCode t, char const *data,
+                    size_t size, bool aIsEncoded = true ) :
     AtomicItem(t),
     theIsEncoded(aIsEncoded)
   {
-    theValue.reserve(aSize);
-    theValue.insert(theValue.begin(), aValue, aValue + aSize);
+    theValue.reserve( size );
+    theValue.insert( theValue.begin(), data, data + size );
   }
 
 public:
   size_t alloc_size() const;
   size_t dynamic_size() const;
 
-  const char* getBase64BinaryValue(size_t& data) const;
+  char const* getBase64BinaryValue( size_t &data ) const;
 
   store::Item* getType() const;
 
   bool isEncoded() const { return theIsEncoded; }
 
-  uint32_t hash(long timezone = 0, const XQPCollator* aCollation = 0) const;
+  uint32_t hash( long timezone = 0, XQPCollator const* = 0 ) const;
 
-  bool equals(
-        const store::Item* other,
-        long timezone = 0,
-        const XQPCollator* aCollation = 0 ) const;
+  bool equals( store::Item const *other, long timezone = 0,
+               XQPCollator const* = 0 ) const;
 
   zstring getStringValue() const;
 
-  void getStringValue2(zstring& val) const;
+  void getStringValue2( zstring& val ) const;
 
-  void appendStringValue(zstring& buf) const;
+  void appendStringValue( zstring &buf ) const;
 
   zstring show() const;
-  
-protected:
-  // used in hash doing simple xor of the data
-  struct hash_functor
-  {
-    uint32_t hash_value;
-
-    void operator() (char c)
-    {
-      hash_value ^= (uint32_t) c;
-    }
-  };
 };
 
 
@@ -2645,38 +2629,45 @@
   friend class BasicItemFactory;
 
 protected:
-  xs_hexBinary theValue;
+  std::vector<char> theValue;
+  bool              theIsEncoded;
 
 protected:
-  HexBinaryItem(store::SchemaTypeCode t, xs_hexBinary v)
-    :
+  HexBinaryItem(store::SchemaTypeCode t, bool aIsEncoded) :
     AtomicItem(t),
-    theValue(v)
+    theIsEncoded(aIsEncoded)
   {
   }
 
-  HexBinaryItem(store::SchemaTypeCode t) : AtomicItem(t) {}
+  HexBinaryItem( store::SchemaTypeCode t, char const *data, size_t size,
+                 bool encoded = true ) :
+    AtomicItem(t),
+    theIsEncoded(encoded)
+  {
+    theValue.reserve( size );
+    theValue.insert( theValue.begin(), data, data + size );
+  }
 
 public:
   size_t alloc_size() const;
   size_t dynamic_size() const;
 
-  xs_hexBinary getHexBinaryValue() const { return theValue; }
+  char const* getHexBinaryValue( size_t &size ) const;
 
   store::Item* getType() const;
 
-  uint32_t hash(long timezone = 0, const XQPCollator* coll = 0) const;
-
-  bool equals(const store::Item* other, long tz = 0, const XQPCollator* coll = 0) const
-  {
-    return theValue.equal(other->getHexBinaryValue());
-  }
+  bool isEncoded() const { return theIsEncoded; }
+
+  uint32_t hash( long timezone = 0, XQPCollator const* = 0 ) const;
+
+  bool equals( store::Item const *other, long timezone = 0,
+               XQPCollator const* = 0) const;
 
   zstring getStringValue() const;
 
-  void getStringValue2(zstring& val) const;
+  void getStringValue2( zstring &val ) const;
 
-  void appendStringValue(zstring& buf) const;
+  void appendStringValue( zstring &buf ) const;
 
   zstring show() const;
 };

=== modified file 'src/store/naive/item.cpp'
--- src/store/naive/item.cpp	2013-03-05 12:34:19 +0000
+++ src/store/naive/item.cpp	2013-03-17 04:52:23 +0000
@@ -864,7 +864,7 @@
 /**
  * Accessor for xs:hexBinary
  */
-xs_hexBinary Item::getHexBinaryValue() const
+char const* Item::getHexBinaryValue(size_t&) const
 {
   throw ZORBA_EXCEPTION(
     zerr::ZSTR0040_TYPE_ERROR,

=== modified file 'src/store/naive/simple_item_factory.cpp'
--- src/store/naive/simple_item_factory.cpp	2013-03-12 17:03:31 +0000
+++ src/store/naive/simple_item_factory.cpp	2013-03-17 04:52:23 +0000
@@ -1130,7 +1130,7 @@
 
 bool BasicItemFactory::createBase64Binary(
     store::Item_t& result,
-    xs_base64Binary value)
+    xs_base64Binary const &value)
 {
   const std::vector<char>& data = value.getData();
   result = new Base64BinaryItem(store::XS_BASE64BINARY,
@@ -1185,9 +1185,22 @@
 }
 
 
-bool BasicItemFactory::createHexBinary(store::Item_t& result,  xs_hexBinary value)
-{
-  result = new HexBinaryItem(store::XS_HEXBINARY, value);
+bool BasicItemFactory::createHexBinary(store::Item_t& result,
+                                       xs_hexBinary const &value)
+{
+  std::vector<char> const &data = value.getData();
+  result = new HexBinaryItem(
+    store::XS_HEXBINARY, data.empty() ? 0 : &data[0], data.size(), true
+  );
+  return true;
+}
+
+
+bool BasicItemFactory::createHexBinary( store::Item_t& result,
+                                        char const *data, size_t size,
+                                        bool encoded )
+{
+  result = new HexBinaryItem(store::XS_HEXBINARY, data, size, encoded);
   return true;
 }
 

=== modified file 'src/store/naive/simple_item_factory.h'
--- src/store/naive/simple_item_factory.h	2013-03-12 17:03:31 +0000
+++ src/store/naive/simple_item_factory.h	2013-03-17 04:52:23 +0000
@@ -120,7 +120,7 @@
       store::Item_t& result,
       store::Item_t& streamable_dependent);
 
-  bool createBase64Binary(store::Item_t& result, xs_base64Binary value);
+  bool createBase64Binary(store::Item_t& result, xs_base64Binary const &value);
 
   bool createBase64Binary(
       store::Item_t& result,
@@ -263,7 +263,9 @@
   bool createENTITY(store::Item_t& result, zstring& value);
 
 
-  bool createHexBinary (store::Item_t& result,  xs_hexBinary value );
+  bool createHexBinary (store::Item_t& result,  xs_hexBinary const &value );
+
+  bool createHexBinary (store::Item_t& result,  char const *data, size_t size, bool encoded);
 
   bool createID (store::Item_t& result, zstring& value );
 

=== modified file 'src/types/casting.cpp'
--- src/types/casting.cpp	2013-03-12 17:03:31 +0000
+++ src/types/casting.cpp	2013-03-17 04:52:23 +0000
@@ -1400,15 +1400,11 @@
 {
   size_t s;
   const char* c = aItem->getBase64BinaryValue(s);
-  Base64 tmp;
+  xs_base64Binary tmp;
   if (aItem->isEncoded())
-  {
-    Base64::parseString(c, s, tmp);
-  }
+    xs_base64Binary::parseString(c, s, tmp);
   else
-  {
-    Base64::encode((const unsigned char*)c, s, tmp);
-  }
+    xs_base64Binary::encode(c, s, tmp);
   aFactory->createHexBinary(result, xs_hexBinary(tmp));
 }
 
@@ -1429,8 +1425,14 @@
 
 T1_TO_T2(hxB, b64)
 {
-  aFactory->
-  createBase64Binary(result, xs_base64Binary(aItem->getHexBinaryValue()));
+  size_t s;
+  char const *const c = aItem->getHexBinaryValue(s);
+  xs_hexBinary tmp;
+  if (aItem->isEncoded())
+    xs_hexBinary::parseString(c, s, tmp);
+  else
+    xs_hexBinary::encode(c, s, tmp);
+  aFactory->createBase64Binary(result, xs_base64Binary(tmp));
 }
 
 

=== modified file 'src/unit_tests/CMakeLists.txt'
--- src/unit_tests/CMakeLists.txt	2013-02-26 04:12:43 +0000
+++ src/unit_tests/CMakeLists.txt	2013-03-17 04:52:23 +0000
@@ -17,6 +17,7 @@
   test_base64.cpp
   test_base64_streambuf.cpp
   test_hashmaps.cpp
+  test_hexbinary.cpp
   test_json_parser.cpp
   test_mem_sizeof.cpp
   test_parameters.cpp

=== added file 'src/unit_tests/test_hexbinary.cpp'
--- src/unit_tests/test_hexbinary.cpp	1970-01-01 00:00:00 +0000
+++ src/unit_tests/test_hexbinary.cpp	2013-03-17 04:52:23 +0000
@@ -0,0 +1,261 @@
+/*
+ * Copyright 2006-2008 The FLWOR Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "stdafx.h"
+#include <cstring>
+#include <iostream>
+#include <sstream>
+#include <stdexcept>
+#include <string>
+
+#include "util/hexbinary_util.h"
+
+using namespace std;
+using namespace zorba;
+
+struct test {
+  char const *input;
+  char const *expected;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+static int failures;
+
+static bool assert_true( int no, char const *expr, int line, bool result ) {
+  if ( !result ) {
+    cout << '#' << no << " FAILED, line " << line << ": " << expr << endl;
+    ++failures;
+  }
+  return result;
+}
+
+static void print_exception( int no, char const *expr, int line,
+                             std::exception const &e ) {
+  assert_true( no, expr, line, false );
+  cout << "+ exception: " << e.what() << endl;
+}
+
+#define ASSERT_TRUE( NO, EXPR ) assert_true( NO, #EXPR, __LINE__, !!(EXPR) )
+
+#define ASSERT_NO_EXCEPTION( NO, EXPR ) \
+  try { EXPR; } \
+  catch ( exception const &e ) { print_exception( NO, #EXPR, __LINE__, e ); } \
+  catch ( ... ) { assert_true( NO, #EXPR, __LINE__, false ); }
+
+#define ASSERT_EXCEPTION( NO, EXPR, EXCEPTION ) \
+  try { EXPR; assert_true( NO, #EXPR, __LINE__, false ); } \
+  catch ( EXCEPTION const& ) { } \
+  catch ( ... ) { assert_true( NO, #EXPR, __LINE__, false ); }
+
+///////////////////////////////////////////////////////////////////////////////}
+
+static void test_decode_buf_to_buf( int no, string const &in,
+                                    string const &expected ) {
+  hexbinary::size_type n = 0;
+  char out[ 1024 ];
+  ASSERT_NO_EXCEPTION( no, n = hexbinary::decode( in.data(), in.size(), out ) );
+  ASSERT_TRUE( no, n == expected.size() );
+  out[ n ] = '\0';
+  ASSERT_TRUE( no, out == expected );
+}
+
+static void test_decode_buf_to_string( int no, string const &in,
+                                       string const &expected ) {
+  hexbinary::size_type n = 0;
+  string out;
+  ASSERT_NO_EXCEPTION(
+    no, n = hexbinary::decode( in.data(), in.size(), &out )
+  );
+  ASSERT_TRUE( no, n == expected.size() );
+  ASSERT_TRUE( no, out.size() == expected.size() );
+  ASSERT_TRUE( no, out == expected );
+}
+
+static void test_decode_buf_to_vector( int no, string const &in,
+                                       string const &expected ) {
+  hexbinary::size_type n = 0;
+  vector<char> out;
+  ASSERT_NO_EXCEPTION(
+    no, n = hexbinary::decode( in.data(), in.size(), &out )
+  );
+  ASSERT_TRUE( no, n == expected.size() );
+  ASSERT_TRUE( no, out.size() == expected.size() );
+  ASSERT_TRUE( no, !strncmp( &out[0], expected.data(), expected.size() ) );
+}
+
+static void test_decode_stream_to_stream( int no, string const &in,
+                                          string const &expected ) {
+  hexbinary::size_type n = 0;
+  istringstream sin( in );
+  ostringstream sout;
+  ASSERT_NO_EXCEPTION( no, n = hexbinary::decode( sin, sout ) );
+  ASSERT_TRUE( no, n == expected.size() );
+  ASSERT_TRUE( no, sout.str().size() == expected.size() );
+  ASSERT_TRUE( no, sout.str() == expected );
+}
+
+static void test_decode_stream_to_string( int no, string const &in,
+                                          string const &expected ) {
+  hexbinary::size_type n = 0;
+  istringstream sin( in );
+  string out;
+  ASSERT_NO_EXCEPTION( no, n = hexbinary::decode( sin, &out ) );
+  ASSERT_TRUE( no, n == expected.size() );
+  ASSERT_TRUE( no, out.size() == expected.size() );
+  ASSERT_TRUE( no, out == expected );
+}
+
+static void test_decode_stream_to_vector( int no, string const &in,
+                                          string const &expected ) {
+  hexbinary::size_type n = 0;
+  istringstream sin( in );
+  vector<char> out;
+  ASSERT_NO_EXCEPTION( no, n = hexbinary::decode( sin, &out ) );
+  ASSERT_TRUE( no, n == expected.size() );
+  ASSERT_TRUE( no, out.size() == expected.size() );
+  ASSERT_TRUE( no, !strncmp( &out[0], expected.data(), expected.size() ) );
+}
+
+static void test_decode_exception( int no, string const &in ) {
+  char out[ 1024 ];
+  ASSERT_EXCEPTION(
+    no, hexbinary::decode( in.data(), in.size(), out ), invalid_argument
+  );
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+static void test_encode_buf_to_buf( int no, string const &in,
+                                    string const &expected ) {
+  char out[ 1024 ];
+  hexbinary::size_type const n = hexbinary::encode( in.data(), in.size(), out );
+  ASSERT_TRUE( no, n == expected.size() );
+  out[ n ] = '\0';
+  ASSERT_TRUE( no, out == expected );
+}
+
+static void test_encode_buf_to_string( int no, string const &in,
+                                       string const &expected ) {
+  string out;
+  hexbinary::size_type const n =
+    hexbinary::encode( in.data(), in.size(), &out );
+  ASSERT_TRUE( no, n == expected.size() );
+  ASSERT_TRUE( no, out.size() == expected.size() );
+  ASSERT_TRUE( no, out == expected );
+}
+
+static void test_encode_buf_to_vector( int no, string const &in,
+                                       string const &expected ) {
+  vector<char> out;
+  hexbinary::size_type const n =
+    hexbinary::encode( in.data(), in.size(), &out );
+  ASSERT_TRUE( no, n == expected.size() );
+  ASSERT_TRUE( no, out.size() == expected.size() );
+  ASSERT_TRUE( no, !strncmp( &out[0], expected.data(), expected.size() ) );
+}
+
+static void test_encode_stream_to_stream( int no, string const &in,
+                                          string const &expected ) {
+  istringstream sin( in );
+  ostringstream sout;
+  hexbinary::size_type const n = hexbinary::encode( sin, sout );
+  ASSERT_TRUE( no, n == expected.size() );
+  ASSERT_TRUE( no, sout.str().size() == expected.size() );
+  ASSERT_TRUE( no, sout.str() == expected );
+}
+
+static void test_encode_stream_to_string( int no, string const &in,
+                                          string const &expected ) {
+  istringstream sin( in );
+  string out;
+  hexbinary::size_type const n = hexbinary::encode( sin, &out );
+  ASSERT_TRUE( no, n == expected.size() );
+  ASSERT_TRUE( no, out.size() == expected.size() );
+  ASSERT_TRUE( no, out == expected );
+}
+
+static void test_encode_stream_to_vector( int no, string const &in,
+                                          string const &expected ) {
+  istringstream sin( in );
+  vector<char> out;
+  hexbinary::size_type const n = hexbinary::encode( sin, &out );
+  ASSERT_TRUE( no, n == expected.size() );
+  ASSERT_TRUE( no, out.size() == expected.size() );
+  ASSERT_TRUE( no, !strncmp( &out[0], expected.data(), expected.size() ) );
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+static test const encode_tests[] = {
+  /* 0 */ { "Now is the time" , "4E6F77206973207468652074696D65"   },
+  /* 1 */ { "Now is the time.", "4E6F77206973207468652074696D652E" },
+
+  { 0, 0 }
+};
+
+static test const decode_tests[] = {
+  /* 2 */ { "4E6F77206973207468652074696D65"  , "Now is the time"  },
+  /* 3 */ { "4e6f77206973207468652074696d652e", "Now is the time." },
+
+  { 0, 0 }
+};
+
+static char const *const decode_exception_tests[] = {
+  /* 4 */ "A",
+  /* 5 */ "AAA",
+  /* 6 */ "``",
+  /* 7 */ "!!",
+  /* 8 */ "##",
+  /* 9 */ "$$",
+  0
+};
+
+namespace zorba {
+namespace UnitTests {
+
+int test_hexbinary( int, char*[] ) {
+  int test_no = 0;
+
+  for ( test const *t = encode_tests; t->input; ++t, ++test_no ) {
+    test_encode_buf_to_buf( test_no, t->input, t->expected );
+    test_encode_buf_to_string( test_no, t->input, t->expected );
+    test_encode_buf_to_vector( test_no, t->input, t->expected );
+    test_encode_stream_to_stream( test_no, t->input, t->expected );
+    test_encode_stream_to_string( test_no, t->input, t->expected );
+    test_encode_stream_to_vector( test_no, t->input, t->expected );
+  }
+
+  for ( test const *t = decode_tests; t->input; ++t, ++test_no ) {
+    test_decode_buf_to_buf( test_no, t->input, t->expected );
+    test_decode_buf_to_string( test_no, t->input, t->expected );
+    test_decode_buf_to_vector( test_no, t->input, t->expected );
+    test_decode_stream_to_stream( test_no, t->input, t->expected );
+    test_decode_stream_to_string( test_no, t->input, t->expected );
+    test_decode_stream_to_vector( test_no, t->input, t->expected );
+  }
+
+  for ( char const *const *t = decode_exception_tests; *t; ++t, ++test_no )
+    test_decode_exception( test_no, *t );
+
+  cout << failures << " test(s) failed\n";
+  return failures ? 1 : 0;
+}
+
+} // namespace UnitTests
+} // namespace zorba
+
+/* vim:set et sw=2 ts=2: */

=== modified file 'src/unit_tests/unit_test_list.h'
--- src/unit_tests/unit_test_list.h	2013-02-26 04:12:43 +0000
+++ src/unit_tests/unit_test_list.h	2013-03-17 04:52:23 +0000
@@ -31,6 +31,7 @@
   int test_base64( int, char*[] );
   int test_base64_streambuf( int, char*[] );
   int test_hashmaps( int argc, char* argv[] );
+  int test_hexbinary( int argc, char* argv[] );
 
 #ifndef ZORBA_NO_ICU
   int test_icu_streambuf( int, char*[] );

=== modified file 'src/unit_tests/unit_tests.cpp'
--- src/unit_tests/unit_tests.cpp	2013-02-26 04:12:43 +0000
+++ src/unit_tests/unit_tests.cpp	2013-03-17 04:52:23 +0000
@@ -45,6 +45,7 @@
 #endif /* ZORBA_WITH_FILE_ACCESS */
 
   libunittests["hashmaps"] = test_hashmaps;
+  libunittests["hexbinary"] = test_hexbinary;
 
 #ifndef ZORBA_NO_ICU
   libunittests["icu_streambuf"] = test_icu_streambuf;

=== modified file 'src/util/CMakeLists.txt'
--- src/util/CMakeLists.txt	2013-02-26 04:12:43 +0000
+++ src/util/CMakeLists.txt	2013-03-17 04:52:23 +0000
@@ -19,6 +19,7 @@
   error_util.cpp
   file.cpp
   fs_util.cpp
+  hexbinary_util.cpp
   indent.cpp
   json_parser.cpp
   json_util.cpp

=== modified file 'src/util/base64_util.cpp'
--- src/util/base64_util.cpp	2013-02-07 17:24:36 +0000
+++ src/util/base64_util.cpp	2013-03-17 04:52:23 +0000
@@ -15,9 +15,12 @@
  */
 
 #include "stdafx.h"
+
+// standard
 #include <algorithm>
 #include <cstring>
 
+// local
 #include "ascii_util.h"
 #include "base64_util.h"
 #include "string_util.h"
@@ -114,21 +117,6 @@
   to[3] = alphabet[   u[2] & 0x3F                      ];
 }
 
-streamsize read_without_whitespace( istream &is, char *buf, streamsize n ) {
-  char const *const buf_orig = buf;
-  char const *const buf_end = buf + n;
-
-  while ( buf < buf_end ) {
-    is.read( buf, n );
-    if ( streamsize read = is.gcount() ) {
-      read = ascii::remove_whitespace( buf, read );
-      buf += read, n -= read;
-    } else
-      break;
-  }
-  return buf - buf_orig;
-}
-
 ///////////////////////////////////////////////////////////////////////////////
 
 size_type decode( char const *from, size_type from_len, char *to,
@@ -149,13 +137,13 @@
         // and that the byte preceding '=' is valid.
         //
         case 2:
-          if ( !strchr( "AQgw", from[-1] ) )
+          if ( !::strchr( "AQgw", from[-1] ) )
             throw base64::exception(
               c, pos, BUILD_STRING( '\'', c, "': invalid character before '='" )
             );
           break;
         case 3:
-          if ( !strchr( "=048AEIMQUYcgkosw", from[-1] ) )
+          if ( !::strchr( "=048AEIMQUYcgkosw", from[-1] ) )
             throw base64::exception(
               c, pos, BUILD_STRING( '\'', c, "': invalid character before '='" )
             );
@@ -192,7 +180,7 @@
           }
         } else
           ++chunk_len;
-    }
+    } // switch
   } // for
 
   if ( (chunk_len % 4) && !(options & dopt_any_len) )

=== modified file 'src/util/base64_util.h'
--- src/util/base64_util.h	2012-06-20 22:26:09 +0000
+++ src/util/base64_util.h	2013-03-17 04:52:23 +0000
@@ -18,13 +18,13 @@
 #ifndef ZORBA_BASE64_UTIL_H
 #define ZORBA_BASE64_UTIL_H
 
-#include <algorithm>
 #include <iostream>
 #include <stdexcept>
 #include <sys/types.h>                  /* for size_t */
 #include <vector>
 
 #include "cxx_util.h"
+#include "stream_util.h"
 
 namespace zorba {
 namespace base64 {
@@ -69,19 +69,6 @@
 ////////// Decoding ///////////////////////////////////////////////////////////
 
 /**
- * \internal
- * Reads from the given istream until \a n non-whitespace characters are read
- * or until EOF is encountered.
- *
- * @param is The istream to read from.
- * @param buf A pointer to the start of a buffer to read into.
- * @param n The number of non-whitespace characters to read.
- * @return Returns the number of non-whitespace characters read.
- */
-std::streamsize read_without_whitespace( std::istream &is, char *buf,
-                                         std::streamsize n );
-
-/**
  * Calculates the number of bytes required to decode \a n Base64-encoded bytes.
  *
  * @param n The number of bytes to decode.
@@ -164,8 +151,6 @@
  * @param from The istream to read from until EOF is reached.
  * @param to The ostream to write the decoded bytes to.
  * @param options The options to use.
- * 4 otherwise an exception is thrown; if \a false, missing trailing bytes are
- * assumed to be padding.
  * @return Returns the number of decoded bytes.
  * @throws invalid_argument if \a options does not have the \c dopt_any_len bit
  * set and the number of Base64 bytes decoded is not a multiple of 4.
@@ -183,8 +168,6 @@
  * @param from The istream to read from until EOF is reached.
  * @param to The string to append the decoded bytes to.
  * @param options The options to use.
- * 4 otherwise an exception is thrown; if \a false, missing trailing bytes are
- * assumed to be padding.
  * @return Returns the number of decoded bytes.
  * @throws invalid_argument if \a options does not have the \c dopt_any_len bit
  * set and the number of Base64 bytes decoded is not a multiple of 4.

=== added file 'src/util/hexbinary_util.cpp'
--- src/util/hexbinary_util.cpp	1970-01-01 00:00:00 +0000
+++ src/util/hexbinary_util.cpp	2013-03-17 04:52:23 +0000
@@ -0,0 +1,202 @@
+/*
+ * Copyright 2006-2008 The FLWOR Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "stdafx.h"
+
+// standard
+#include <algorithm>
+#include <cstring>
+
+// local
+#include "ascii_util.h"
+#include "hexbinary_util.h"
+#include "string_util.h"
+
+using namespace std;
+
+namespace zorba {
+namespace hexbinary {
+
+///////////////////////////////////////////////////////////////////////////////
+
+/**
+ * HexBinary decoding table.  A value of -1 means "invalid".
+ */
+static signed char const decode_table[] = {
+  /* 00-07 */ -1, -1, -1, -1, -1, -1, -1, -1,
+  /* 08-0F */ -1, -1, -1, -1, -1, -1, -1, -1,
+  /* 10-17 */ -1, -1, -1, -1, -1, -1, -1, -1,
+  /* 18-1F */ -1, -1, -1, -1, -1, -1, -1, -1,
+  /* 20-27 */ -1, -1, -1, -1, -1, -1, -1, -1,
+  /* 28-2F */ -1, -1, -1, -1, -1, -1, -1, -1,
+  /* 30-37 */  0,  1,  2,  3,  4,  5,  6,  7, // 0 1 2 3 4 5 6 7
+  /* 38-3F */  8,  9, -1, -1, -1, -1, -1, -1, // 8 9 . . . . . .
+  /* 40-47 */ -1, 10, 11, 12, 13, 14, 15, -1, // . A B C D E F .
+  /* 48-4F */ -1, -1, -1, -1, -1, -1, -1, -1,
+  /* 50-57 */ -1, -1, -1, -1, -1, -1, -1, -1,
+  /* 58-5F */ -1, -1, -1, -1, -1, -1, -1, -1,
+  /* 60-67 */ -1, 10, 11, 12, 13, 14, 15, -1, // . a b c d e f .
+  /* 68-6F */ -1, -1, -1, -1, -1, -1, -1, -1,
+  /* 70-77 */ -1, -1, -1, -1, -1, -1, -1, -1,
+  /* 78-7F */ -1, -1, -1, -1, -1, -1, -1, -1,
+  /* 80-87 */ -1, -1, -1, -1, -1, -1, -1, -1,
+  /* 88-8F */ -1, -1, -1, -1, -1, -1, -1, -1,
+  /* 90-97 */ -1, -1, -1, -1, -1, -1, -1, -1,
+  /* 98-9F */ -1, -1, -1, -1, -1, -1, -1, -1,
+  /* A0-A7 */ -1, -1, -1, -1, -1, -1, -1, -1,
+  /* A8-AF */ -1, -1, -1, -1, -1, -1, -1, -1,
+  /* B0-B7 */ -1, -1, -1, -1, -1, -1, -1, -1,
+  /* B8-BF */ -1, -1, -1, -1, -1, -1, -1, -1,
+  /* C0-C7 */ -1, -1, -1, -1, -1, -1, -1, -1,
+  /* C8-CF */ -1, -1, -1, -1, -1, -1, -1, -1,
+  /* D0-D7 */ -1, -1, -1, -1, -1, -1, -1, -1,
+  /* D8-DF */ -1, -1, -1, -1, -1, -1, -1, -1,
+  /* E0-E7 */ -1, -1, -1, -1, -1, -1, -1, -1,
+  /* E8-EF */ -1, -1, -1, -1, -1, -1, -1, -1,
+  /* F0-F7 */ -1, -1, -1, -1, -1, -1, -1, -1,
+  /* F8-FF */ -1, -1, -1, -1, -1, -1, -1, -1,
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+size_type decode( char const *from, size_type from_len, char *to ) {
+  if ( from_len % 2 )
+    throw invalid_argument( "HexBinary length is not a multiple of 2" );
+
+  char const *const from_orig = from;
+  char const *const from_end = from + from_len;
+  char const *const to_orig = to;
+  char c;
+
+  while ( from < from_end ) {
+    signed char const high = decode_table[ (unsigned char)(c = *from++) ];
+    if ( high == -1 )
+      goto bad_char;
+    signed char const low  = decode_table[ (unsigned char)(c = *from++) ];
+    if ( low == -1 )
+      goto bad_char;
+    if ( to )
+      *to++ = ((unsigned char)high << 4) | ((unsigned char)low);
+  }
+
+  return to - to_orig;
+
+bad_char:
+  throw hexbinary::exception(
+    c, from - from_orig, BUILD_STRING( '\'', c, "': invalid character" )
+  );
+}
+
+size_type decode( char const *from, size_type from_len,
+                  std::vector<char> *to ) {
+  if ( from_len ) {
+    std::vector<char>::size_type const orig_size = to->size();
+    to->resize( orig_size + decoded_size( from_len ) );
+    return decode( from, from_len, &(*to)[ orig_size ] );
+  }
+  return 0;
+}
+
+size_type decode( istream &from, ostream &to ) {
+  size_type total_decoded = 0;
+  while ( !from.eof() ) {
+    char from_buf[ 1024 * 2 ], to_buf[ 1024 ];
+    from.read( from_buf, sizeof from_buf );
+    if ( streamsize const gcount = from.gcount() ) {
+      size_type const decoded = decode( from_buf, gcount, to_buf );
+      to.write( to_buf, decoded );
+      total_decoded += decoded;
+    } else
+      break;
+  }
+  return total_decoded;
+}
+
+size_type decode( istream &from, vector<char> *to ) {
+  vector<char>::size_type const orig_size = to->size();
+  size_type total_decoded = 0;
+  while ( !from.eof() ) {
+    char from_buf[ 1024 * 4 ];
+    from.read( from_buf, sizeof from_buf );
+    if ( streamsize const gcount = from.gcount() ) {
+      to->resize( to->size() + decoded_size( gcount ) );
+      total_decoded += decode( from_buf, gcount, &(*to)[ total_decoded ] );
+    } else
+      break;
+  }
+  return total_decoded;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+size_type encode( char const *from, size_type from_len, char *to ) {
+  static char const encode_table[] = "0123456789ABCDEF";
+
+  char const *const to_orig = to;
+  while ( from_len-- ) {
+    unsigned char const c = *from++;
+    *to++ = encode_table[ c >> 4   ];
+    *to++ = encode_table[ c & 0x0F ];
+  }
+  return to - to_orig;
+}
+
+size_type encode( char const *from, size_type from_len,
+                  std::vector<char> *to ) {
+  size_type encoded = 0;
+  if ( from_len ) {
+    std::vector<char>::size_type const orig_size = to->size();
+    to->resize( orig_size + encoded_size( from_len ) );
+    encoded = encode( from, from_len, &(*to)[ orig_size ] );
+  }
+  return encoded;
+}
+
+size_type encode( istream &from, ostream &to ) {
+  size_type total_encoded = 0;
+  while ( !from.eof() ) {
+    char from_buf[ 1024 ], to_buf[ 1024 * 2 ];
+    from.read( from_buf, sizeof from_buf );
+    if ( streamsize const gcount = from.gcount() ) {
+      size_type const encoded = encode( from_buf, gcount, to_buf );
+      to.write( to_buf, encoded );
+      total_encoded += encoded;
+    } else
+      break;
+  }
+  return total_encoded;
+}
+
+size_type encode( istream &from, vector<char> *to ) {
+  vector<char>::size_type const orig_size = to->size();
+  size_type total_encoded = 0;
+  while ( !from.eof() ) {
+    char from_buf[ 1024 ];
+    from.read( from_buf, sizeof from_buf );
+    if ( streamsize const gcount = from.gcount() ) {
+      to->resize( to->size() + encoded_size( gcount ) );
+      total_encoded += encode( from_buf, gcount, &(*to)[ total_encoded ] );
+    } else
+      break;
+  }
+  return total_encoded;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+} // namespace hexbinary
+} // namespace zorba
+/* vim:set et sw=2 ts=2: */

=== added file 'src/util/hexbinary_util.h'
--- src/util/hexbinary_util.h	1970-01-01 00:00:00 +0000
+++ src/util/hexbinary_util.h	2013-03-17 04:52:23 +0000
@@ -0,0 +1,307 @@
+/*
+ * Copyright 2006-2008 The FLWOR Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+#ifndef ZORBA_HEXBINARY_UTIL_H
+#define ZORBA_HEXBINARY_UTIL_H
+
+#include <iostream>
+#include <stdexcept>
+#include <sys/types.h>                  /* for size_t */
+#include <vector>
+
+#include "cxx_util.h"
+
+namespace zorba {
+namespace hexbinary {
+
+////////// Types //////////////////////////////////////////////////////////////
+
+typedef size_t size_type;
+
+////////// Exception //////////////////////////////////////////////////////////
+
+/**
+ * A %hexbinary::exception is-an invalid_argument that contains additional
+ * details about the exception such as the invalid character and its offset.
+ */
+class exception : public std::invalid_argument {
+public:
+  exception( char c, size_type offset, std::string const &msg ) :
+    std::invalid_argument( msg ), char_( c ), offset_( offset ) { }
+
+  char invalid_char() const {
+    return char_;
+  }
+
+  size_type char_offset() const {
+    return offset_;
+  }
+
+private:
+  char char_;
+  size_type offset_;
+};
+
+////////// Decoding ///////////////////////////////////////////////////////////
+
+/**
+ * Calculates the number of bytes required to decode \a n hexBinary-encoded
+ * bytes.
+ *
+ * @param n The number of bytes to decode.
+ * @return Returns the number of bytes needed for hexBinary decoding.
+ */
+inline size_type decoded_size( size_type n ) {
+  return n / 2;
+}
+
+/**
+ * Decodes a hexBinary-encoded buffer.  Embedded newlines and carriage-returns
+ * are skipped.
+ *
+ * @param from A pointer to the hexBinary buffer to be decoded.
+ * @param from_len The number of bytes to decode.
+ * @paran to A pointer to the buffer to receive the decoded bytes.  The buffer
+ * must be large enough to contain them.  Note that the buffer is \e not null
+ * terminated.
+ * @return Returns the number of decoded bytes.
+ * @throws invalid_argument if \a from_len is not a multiple of 2.
+ * @throws hexbinary::exception if an invalid byte is encountered.
+ * @see decoded_size()
+ */
+size_type decode( char const *from, size_type from_len, char *to );
+
+/**
+ * Decodes a hexBinary-encoded buffer and appends the decoded bytes onto a
+ * vector&lt;char&gt;.  Embedded newlines and carriage-returns are skipped.
+ *
+ * @param from A pointer to the buffer to be encoded.
+ * @param from_len The number of bytes to encode.
+ * @param to A pointer to the vector to append the encoded bytes appended onto.
+ * The vector is made large enough to contain the additional bytes.
+ * @return Returns the number of decoded bytes.
+ * @throws invalid_argument if the number of hexBinary bytes decoded is not a
+ * multiple of 2.
+ * @throws hexbinary::exception if an invalid byte is encountered.
+ */
+size_type decode( char const *from, size_type from_len, std::vector<char> *to );
+
+/**
+ * Decodes a hexBinary-encoded buffer and appends the decoded bytes onto a
+ * string.  Embedded newlines and carriage-returns are skipped.
+ *
+ * @tparam ToStringType The string type.
+ * @param from A pointer to the hexBinary buffer to be decoded.
+ * @param from_len The number of bytes to decode.
+ * @param to The string to append the decoded bytes to.
+ * @return Returns the number of decoded bytes.
+ * @throws invalid_argument if the number of hexBinary bytes decoded is not a
+ * multiple of 2.
+ * @throws hexbinary::exception if an invalid byte is encountered.
+ */
+template<class ToStringType>
+size_type decode( char const *from, size_type from_len, ToStringType *to ) {
+  size_type total_decoded = 0;
+  if ( from_len ) {
+    typename ToStringType::size_type const orig_size = to->size();
+    to->resize( orig_size + decoded_size( from_len ) );
+    total_decoded = decode( from, from_len, &to->at( orig_size ) );
+  }
+  return total_decoded;
+}
+
+/**
+ * Decodes a hexBinary-encoded istream.  Embedded newlines and carriage-returns
+ * are skipped.
+ *
+ * @param from The istream to read from until EOF is reached.
+ * @param to The ostream to write the decoded bytes to.
+ * @return Returns the number of decoded bytes.
+ * @throws invalid_argument if the number of hexBinary bytes decoded is not a
+ * multiple of 2.
+ * @throws hexbinary::exception if an invalid byte is encountered.
+ */
+size_type decode( std::istream &from, std::ostream &to );
+
+/**
+ * Decodes a hexBinary-encoded istream and appends the decoded bytes to a
+ * string.  Embedded newlines and carriage-returns are skipped.
+ *
+ * @tparam ToStringType The string type.
+ * @param from The istream to read from until EOF is reached.
+ * @param to The string to append the decoded bytes to.
+ * 4 otherwise an exception is thrown; if \a false, missing trailing bytes are
+ * assumed to be padding.
+ * @return Returns the number of decoded bytes.
+ * @throws invalid_argument if the number of hexBinary bytes decoded is not a
+ * multiple of 2.
+ * @throws hexbinary::exception if an invalid byte is encountered.
+ */
+template<class ToStringType>
+size_type decode( std::istream &from, ToStringType *to ) {
+  size_type total_decoded = 0;
+  while ( !from.eof() ) {
+    char from_buf[ 1024 * 4 ], to_buf[ 1024 * 3 ];
+    from.read( from_buf, sizeof from_buf );
+    if ( std::streamsize const gcount = from.gcount() ) {
+      size_type const decoded = decode( from_buf, gcount, to_buf );
+      to->append( to_buf, decoded );
+      total_decoded += decoded;
+    } else
+      break;
+  }
+  return total_decoded;
+}
+
+/**
+ * Decodes a hexBinary-encoded stream and appends the decoded bytes onto a
+ * vector&lt;char;&gt;.
+ *
+ * @param from The istream to read from until EOF is reached.
+ * @param to The string to append the decoded bytes to.
+ * @param Returns the number of decoded bytes.
+ * @throws invalid_argument if \a the number of hexBinary bytes decoded is not
+ * a multiple of 2.
+ * @throws hexbinary::exception if an invalid byte is encountered.
+ */
+size_type decode( std::istream &from, std::vector<char> *to );
+
+/**
+ * Validates a hexBinary-encoded buffer.  Embedded newlines and
+ * carriage-returns are skipped.
+ *
+ * @param buf A pointer to the hexBinary buffer to be validated.
+ * @param buf_len The number of bytes to validate.
+ * @throws invalid_argument if the number of hexBinary bytes validated is not a
+ * multiple of 2.
+ * @throws hexbinary::exception if an invalid byte is encountered.
+ * @see decoded_size()
+ */
+inline void validate( char const *buf, size_type buf_len ) {
+  decode( buf, buf_len, static_cast<char*>( nullptr ) );
+}
+
+////////// Encoding ///////////////////////////////////////////////////////////
+
+/**
+ * Calculates the number of bytes required to hexBinary-encode \a n bytes.
+ *
+ * @param n The number of bytes to encode.
+ * @return Returns the number of bytes needed for hexBinary encoding.
+ */
+inline size_type encoded_size( size_type n ) {
+  return n * 2;
+}
+
+/**
+ * HexBinary-encodes a buffer.
+ *
+ * @param from A pointer to the buffer to be encoded.
+ * @param from_len The number of bytes to encode.
+ * @param to A pointer to the buffer to receive the encoded bytes.  The buffer
+ * must be large enough to contain them.  Note that the buffer is \e not null
+ * terminated.
+ * @return Returns the number of encoded bytes.
+ * @see encoded_size()
+ */
+size_type encode( char const *from, size_type from_len, char *to );
+
+/**
+ * HexBinary-encodes a buffer and appends the encoded bytes onto a
+ * vector&lt;char&gt;.
+ *
+ * @param from A pointer to the buffer to be encoded.
+ * @param from_len The number of bytes to encode.
+ * @param to A pointer to the vector to append the encoded bytes appended onto.
+ * The vector is made large enough to contain the additional bytes.
+ */
+size_type encode( char const *from, size_type from_len, std::vector<char> *to );
+
+/**
+ * HexBinary-encodes a buffer and appends the encoded bytes onto a string.
+ *
+ * @tparam ToStringType The string type.
+ * @param from A pointer to the hexBinary buffer to be encoded.
+ * @param from_len The number of bytes to encode.
+ * @param to A pointer to the string to append the encoded bytes onto.
+ * @return Returns the number of encoded bytes.
+ */
+template<class ToStringType>
+size_type encode( char const *from, size_type from_len, ToStringType *to ) {
+  size_type total_encoded = 0;
+  if ( from_len ) {
+    typename ToStringType::size_type const orig_size = to->size();
+    to->resize( orig_size + encoded_size( from_len ) );
+    total_encoded = encode( from, from_len, &to->at( orig_size ) );
+  }
+  return total_encoded;
+}
+
+/**
+ * HexBinary-encodes one stream and write the encoded bytes to another.
+ *
+ * @param from The istream to read from until EOF is reached.
+ * @param to The ostream to write the encoded bytes to.
+ */
+size_type encode( std::istream &from, std::ostream &to );
+
+/**
+ * Encodes a stream to hexBinary and appends the encoded bytes to a string.
+ *
+ * @tparam ToStringType The string type.
+ * @param from The istream to read from until EOF is reached.
+ * @param to The string to append the encoded bytes to.
+ * @return Returns the number of encoded bytes.
+ */
+template<class ToStringType>
+size_type encode( std::istream &from, ToStringType *to ) {
+  size_type total_encoded = 0;
+  while ( !from.eof() ) {
+    char from_buf[ 1024 * 2 ], to_buf[ 1024 ];
+    from.read( from_buf, sizeof from_buf );
+    if ( std::streamsize const gcount = from.gcount() ) {
+      size_type const encoded = encode( from_buf, gcount, to_buf );
+      to->append( to_buf, encoded );
+      total_encoded += encoded;
+    } else
+      break;
+  }
+  return total_encoded;
+}
+
+/**
+ * HexBinary-encodes a stream and appends the encoded bytes onto a
+ * vector&lt;char;&gt;.
+ *
+ * @param from The istream to read from until EOF is reached.
+ * @param to The string to append the encoded bytes to.
+ * @param Returns the number of encoded bytes.
+ */
+size_type encode( std::istream &from, std::vector<char> *to );
+
+///////////////////////////////////////////////////////////////////////////////
+
+} // namespace hexbinary
+} // namespace zorba
+
+#endif /* ZORBA_HEXBINARY_UTIL_H */
+/*
+ * Local variables:
+ * mode: c++
+ * End:
+ */
+/* vim:set et sw=2 ts=2: */

=== modified file 'src/util/stream_util.cpp'
--- src/util/stream_util.cpp	2013-02-12 03:55:18 +0000
+++ src/util/stream_util.cpp	2013-03-17 04:52:23 +0000
@@ -15,6 +15,8 @@
  */
 #include "stdafx.h"
 
+// local
+#include "ascii_util.h"
 #include "stream_util.h"
 
 using namespace std;
@@ -40,7 +42,7 @@
   return index;
 }
 
-void delete_stream_uri_callback( ios_base::event e, ::ios_base &ios,
+void delete_stream_uri_callback( ios_base::event e, ios_base &ios,
                                  int index ) {
   //
   // See: "Standard C++ IOStreams and Locales: Advanced Programmer's Guide and
@@ -53,5 +55,22 @@
 
 ///////////////////////////////////////////////////////////////////////////////
 
+streamsize read_without_whitespace( istream &is, char *buf, streamsize n ) {
+  char const *const buf_orig = buf;
+  char const *const buf_end = buf + n;
+
+  while ( buf < buf_end ) {
+    is.read( buf, n );
+    if ( streamsize read = is.gcount() ) {
+      read = ascii::remove_whitespace( buf, read );
+      buf += read, n -= read;
+    } else
+      break;
+  }
+  return buf - buf_orig;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
 } // namespace zorba
 /* vim:set et sw=2 ts=2: */

=== modified file 'src/util/stream_util.h'
--- src/util/stream_util.h	2013-02-12 03:55:18 +0000
+++ src/util/stream_util.h	2013-03-17 04:52:23 +0000
@@ -61,6 +61,20 @@
 
 ///////////////////////////////////////////////////////////////////////////////
 
+/**
+ * Reads from the given istream until \a n non-whitespace characters are read
+ * or until EOF is encountered.
+ *
+ * @param is The istream to read from.
+ * @param buf A pointer to the start of a buffer to read into.
+ * @param n The number of non-whitespace characters to read.
+ * @return Returns the number of non-whitespace characters read.
+ */
+std::streamsize read_without_whitespace( std::istream &is, char *buf,
+                                         std::streamsize n );
+
+///////////////////////////////////////////////////////////////////////////////
+
 } // namespace zorba
 
 #endif /* ZORBA_STREAM_UTIL_H */

=== modified file 'src/zorbaserialization/serialize_zorba_types.cpp'
--- src/zorbaserialization/serialize_zorba_types.cpp	2013-02-07 17:24:36 +0000
+++ src/zorbaserialization/serialize_zorba_types.cpp	2013-03-17 04:52:23 +0000
@@ -726,7 +726,25 @@
 
   case store::XS_HEXBINARY:
   {
-    SERIALIZE_ATOMIC_ITEM(xs_hexBinary, getHexBinaryValue());
+    ar.set_is_temp_field(true);
+
+    size_t s;
+    const char* c = obj->getHexBinaryValue(s);
+    if (obj->isEncoded())
+    {
+      Base16 tmp;
+      Base16::parseString(c, s, tmp);
+      ar & tmp;
+    }
+    else
+    {
+      Base16 tmp(c, s);
+      ar & tmp;
+    }
+    
+    ar.set_is_temp_field(false);
+
+    break;
   }
   case store::XS_BASE64BINARY:
   {
@@ -742,7 +760,7 @@
     }
     else
     {
-      Base64 tmp((const unsigned char*)c, s);
+      Base64 tmp(c, s);
       ar & tmp;
     }
     

=== modified file 'src/zorbatypes/binary.cpp'
--- src/zorbatypes/binary.cpp	2013-02-07 17:24:36 +0000
+++ src/zorbatypes/binary.cpp	2013-03-17 04:52:23 +0000
@@ -26,43 +26,46 @@
 
 #include "util/ascii_util.h"
 #include "util/base64_util.h"
+#include "util/hash/hash.h"
+#include "util/hexbinary_util.h"
 #include "util/stl_util.h"
 
+using namespace std;
+
+namespace zorba {
+
+///////////////////////////////////////////////////////////////////////////////
+
 #define CATCH_BASE64_EXCEPTION()                                        \
   catch (const base64::exception& e)                                    \
   {                                                                     \
     throw XQUERY_EXCEPTION(err::FORG0001,                               \
     ERROR_PARAMS(ZED(FORG0001_Base64BadChar_2), e.invalid_char()));     \
   }                                                                     \
-  catch (const std::invalid_argument& )                                 \
+  catch (const std::invalid_argument&)                                  \
   {                                                                     \
     throw XQUERY_EXCEPTION(err::FORG0001,                               \
     ERROR_PARAMS(ZED(FORG0001_Base64Multiple4)));                       \
   }
 
-using namespace std;
-
-namespace zorba {
-
-static size_t copy_without_ws( char const *from, size_t len, char *to ) {
-  char const *const end = from + len;
+static size_t copy_without_ws( char const *from, size_t from_len, char *to ) {
   char const *const to_orig = to;
-  for ( ; from < end; ++from )
+  for ( char const *const from_end = from + from_len; from < from_end; ++from )
     if ( !ascii::is_space( *from ) )
       *to++ = *from;
   return to - to_orig;
 }
 
 
-bool Base64::parseString(const char* aString, size_t aLength,  Base64& aBase64)
+bool Base64::parseString(char const *s, size_t len, Base64& aBase64)
 {
-  if ( aLength ) {
+  if ( len ) {
     try 
     {
-      base64::validate( aString, aLength, base64::dopt_ignore_ws );
-      aBase64.theData.resize( aLength );
+      base64::validate( s, len, base64::dopt_ignore_ws );
+      aBase64.theData.resize( len );
       aBase64.theData.resize(
-        copy_without_ws( aString, aLength, &aBase64.theData[0] )
+        copy_without_ws( s, len, &aBase64.theData[0] )
       );
     }
     catch (...) 
@@ -75,19 +78,16 @@
 }
 
 
-bool Base64::parseString(
-    const char* aString,
-    size_t aLength,
-    Base64& aBase64, 
-    string& lErrorMessage)
+bool Base64::parseString( char const *s, size_t len, Base64 &aBase64, 
+                          string &lErrorMessage )
 {
-  if ( aLength ) {
+  if ( len ) {
     try 
     {
-      base64::validate( aString, aLength, base64::dopt_ignore_ws );
-      aBase64.theData.resize( aLength );
+      base64::validate( s, len, base64::dopt_ignore_ws );
+      aBase64.theData.resize( len );
       aBase64.theData.resize(
-        copy_without_ws( aString, aLength, &aBase64.theData[0] )
+        copy_without_ws( s, len, &aBase64.theData[0] )
       );
     }
     catch (ZorbaException const& e) 
@@ -101,58 +101,53 @@
 }
 
 
-void Base64::encode(const zstring& aString, Base64& aResult)
-{
-  base64::encode( aString.data(), aString.size(), &aResult.theData );
-}
-
-
-void Base64::encode(istream& aStream, Base64& aResult)
-{
-  base64::encode( aStream, &aResult.theData );
-}
-
-
-zstring Base64::encode(istream& aStream)
+void Base64::encode( zstring const &s, Base64 &to )
+{
+  base64::encode( s.data(), s.size(), &to.theData );
+}
+
+
+void Base64::encode( istream &is, Base64 &to )
+{
+  base64::encode( is, &to.theData );
+}
+
+
+zstring Base64::encode( istream &is )
 {
   zstring result;
-  base64::encode( aStream, &result );
+  base64::encode( is, &result );
   return result;
 }
 
 
-void Base64::encode(const vector<char>& aSource, vector<char>& aResult)
-{
-  if ( !aSource.empty() )
-    base64::encode( &aSource[0], aSource.size(), &aResult );
-}
-
-
-void Base64::encode(
-    const unsigned char* aSource, 
-    unsigned int in_len,
-    Base64& aResult)
-{
-  base64::encode( (char*)aSource, in_len, &aResult.theData );
-}
-
-
-void Base64::decode(istream& aStream, zstring *result)
+void Base64::encode( vector<char> const &from, vector<char> &to )
+{
+  if ( !from.empty() )
+    base64::encode( &from[0], from.size(), &to );
+}
+
+
+void Base64::encode( char const *from, size_t from_len, Base64 &to )
+{
+  base64::encode( from, from_len, &to.theData );
+}
+
+
+void Base64::decode( istream &is, zstring *to )
 {
   try {
-    base64::decode(
-      aStream, result, base64::dopt_any_len | base64::dopt_ignore_ws
-    );
+    base64::decode( is, to, base64::dopt_any_len | base64::dopt_ignore_ws );
   }
   CATCH_BASE64_EXCEPTION()
 }
 
-void Base64::decode(const vector<char>& aSource, vector<char>& aResult)
+void Base64::decode(vector<char> const &from, vector<char> &to )
 {
-  if ( !aSource.empty() ) {
+  if ( !from.empty() ) {
     try {
       base64::decode(
-        &aSource[0], aSource.size(), &aResult,
+        &from[0], from.size(), &to,
         base64::dopt_any_len | base64::dopt_ignore_ws
       );
     }
@@ -170,52 +165,37 @@
 }
 
 
-Base64::Base64(const Base16& aBase16)
+Base64::Base64( Base16 const &aBase16 )
 {
-  vector<char> lOrig;
-  Base16::decode(aBase16.getData(), lOrig);
-  Base64::encode(lOrig, theData);
+  vector<char> tmp;
+  Base16::decode( aBase16.getData(), tmp );
+  Base64::encode( tmp, theData );
 }
 
 
-Base64::Base64(const unsigned char *bin_data, size_t len)
+Base64::Base64( char const *bin_data, size_t len )
 {
   try {
-    base64::encode( (char const*)bin_data, len, &theData );
+    base64::encode( bin_data, len, &theData );
   }
   CATCH_BASE64_EXCEPTION()
 }
 
 
 
-bool Base64::equal(const Base64& aBase64) const
+bool Base64::equal( Base64 const &aBase64 ) const
 {
-  if (size() != aBase64.size())
+  if ( size() != aBase64.size() )
     return false;
-
-  vector<char>::const_iterator lIter0 = theData.begin();
-  vector<char>::const_iterator lEnd0 = theData.end();
-  vector<char>::const_iterator lIter1 = aBase64.theData.begin();
-
-  while ( lIter0 != lEnd0 )
-  {
-    if (*lIter0 != *lIter1)
-      return false;
-    ++lIter0; ++lIter1;
-  }
-  return true;
+  return ::strncmp( &theData[0], &aBase64.theData[0], size() ) == 0;
 }
 
 
 zstring Base64::str() const 
 {
   zstring result;
-  vector<char>::const_iterator lIter = theData.begin();
-  vector<char>::const_iterator lEnd = theData.end();
-  for( ; lIter != lEnd ; ++lIter)
-  {
-    result.push_back( *lIter );
-  }
+  if ( theData.size() )
+    result.assign( &theData[0], theData.size() );
   return result;
 }
 
@@ -229,73 +209,49 @@
 }
 
 
-void Base64::decode(vector<char>& aResult)
+void Base64::decode( vector<char> &to )
 {
   if ( !theData.empty() )
-    base64::decode( &theData[0], theData.size(), &aResult );
+    base64::decode( &theData[0], theData.size(), &to );
 }
 
 
 uint32_t Base64::hash() const
 {
-  uint32_t lHash = 0;
-  vector<char>::const_iterator lIter = theData.begin();
-  vector<char>::const_iterator lEnd = theData.end();
-  for(;lIter!=lEnd;++lIter)
-  {
-    uint32_t lDiff = 65535-*lIter;
-    if (lDiff < lHash)
-    {
-      lHash = lHash - lDiff;
-    } else {
-      lHash += *lIter; 
-    }
-  }
-  return lHash;
+  return theData.size() ? ztd::hash_bytes( &theData[0], theData.size() ) : 0;
 }
 
 
 ostream& operator<<(ostream& os, const Base64& aBase64)
 {
-  vector<char>::const_iterator lIter = aBase64.getData().begin();
-  vector<char>::const_iterator lEnd = aBase64.getData().end();
-  for( ; lIter != lEnd ; ++lIter)
-  {
-    os << *lIter;
-  }
+  if ( aBase64.size() )
+    os.write( &aBase64.getData()[0], aBase64.size() );
   return os;
 }
 
 ///////////////////////////////////////////////////////////////////////////////
 
-const char* Base16::ENCODE_TABLE = "0123456789ABCDEF";
-
-const unsigned char Base16::DECODE_TABLE[ 0x80 ] = {
-  /*00-07*/ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-  /*08-0f*/ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-  /*10-17*/ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-  /*18-1f*/ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-  /*20-27*/ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-  /*28-2f*/ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-  /*30-37*/ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, //8 = '0'-'7'
-  /*38-3f*/ 0x08, 0x09, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, //2 = '8'-'9'
-  /*40-47*/ 0xFF, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0xFF, //6 = 'A'-'F'
-  /*48-4f*/ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-  /*50-57*/ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-  /*58-5f*/ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-  /*60-67*/ 0xFF, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0xFF, //6 = 'a'-'f' (same as 'A'-'F')
-  /*68-6f*/ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-  /*70-77*/ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-  /*78-7f*/ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
-};
-
-size_t Base16::ENCODE_INPUT = 1;
-size_t Base16::ENCODE_OUTPUT = 2;
-size_t Base16::DECODE_INPUT = 2;
-size_t Base16::DECODE_OUTPUT = 1;
-
-
-Base16::Base16(const Base64& aBase64)
+#define CATCH_HEXBINARY_EXCEPTION()                                     \
+  catch (const hexbinary::exception& e)                                 \
+  {                                                                     \
+    throw XQUERY_EXCEPTION(err::FORG0001,                               \
+    ERROR_PARAMS(ZED(FORG0001_BadHexDigit_2), e.invalid_char()));       \
+  }                                                                     \
+  catch (const std::invalid_argument&)                                  \
+  {                                                                     \
+    throw XQUERY_EXCEPTION(err::FORG0001,                               \
+    ERROR_PARAMS(ZED(FORG0001_HexBinaryMustBeEven)));                   \
+  }
+
+Base16::Base16( char const *bin_data, size_t len )
+{
+  try {
+    hexbinary::encode( bin_data, len, &theData );
+  }
+  CATCH_HEXBINARY_EXCEPTION()
+}
+
+Base16::Base16(Base64 const &aBase64)
 {
   vector<char> lOrig;
   Base64::decode(aBase64.getData(), lOrig);
@@ -303,12 +259,12 @@
 }
 
 
-bool Base16::parseString(const char* aString, size_t aLength, Base16& aBase16)
+bool Base16::parseString(char const *aString, size_t len, Base16& aBase16)
 {
   aBase16.theData.clear();
   try 
   {
-    aBase16.insertData(aString, aLength);
+    aBase16.insertData(aString, len);
   }
   catch (...)
   {
@@ -318,7 +274,7 @@
 }
 
 
-void Base16::insertData(const char* str, size_t len)
+void Base16::insertData(char const *str, size_t len)
 {
   zstring_b wrap;
   wrap.wrap_memory(str, len);
@@ -328,136 +284,64 @@
   len = wrap.size();
   str = wrap.data();
 
-  if (len % 2 != 0) 
-  {
-    throw XQUERY_EXCEPTION(err::FORG0001,
-    ERROR_PARAMS(ZED(FORG0001_HexBinaryMustBeEven)));
-  }
-
-  for (size_t i = 0; i < len; ++i)
-  {
-    char lChar = str[i];
-    if ((lChar >= 65 && lChar <= 70)  // A-F
-     || (lChar >= 48 && lChar <= 57))  // 0-9
-    {
-      theData.push_back(lChar);
-    }
-    else if (lChar >= 97 && lChar <= 102) // a-f
-    {
-      theData.push_back(lChar-32);
-    }
-    else
-    {
-      throw XQUERY_EXCEPTION(err::FORG0001,
-      ERROR_PARAMS(ZED(FORG0001_BadHexDigit_2), lChar));
-    }
-  }
+  try {
+    hexbinary::encode( str, len, &theData );
+  }
+  CATCH_HEXBINARY_EXCEPTION()
 }
 
 
-bool Base16::equal(const Base16& aBase16) const
+bool Base16::equal( Base16 const &other ) const
 {
-  if (size() != aBase16.size())
+  if ( size() != other.size() )
     return false;
-
-  vector<char>::const_iterator lIter0 = theData.begin();
-  vector<char>::const_iterator lEnd0 = theData.end();
-  vector<char>::const_iterator lIter1 = aBase16.theData.begin();
-
-  for (; lIter0 != lEnd0 ; )
-  {
-    if (*lIter0 != *lIter1)
-      return false;
-    ++lIter0; ++lIter1;
-  }
-  return true;
+  return ::strncmp( &theData[0], &other.theData[0], theData.size() ) == 0;
 }
 
 
 zstring Base16::str() const 
 {
-  stringstream lStream;
-  lStream << *this;
-  return zstring(lStream.str());
+  if ( size() )
+    return zstring( &theData[0], size() );
+  return zstring();
 }
 
 
-void Base16::encode(const vector<char>& aSource, vector<char>& aResult)
+void Base16::encode( vector<char> const &from, vector<char> &to )
 {
-  size_t lSrcPos = 0;
-  size_t lSrcSize = aSource.size();
-
-  while (lSrcSize >= 1)
-  {
-    // 1 input...
-    char ch = aSource[lSrcPos++];
-    lSrcSize -= ENCODE_INPUT; //1
-
-    // 2 outputs...
-    aResult.push_back(ENCODE_TABLE[ (ch & 0xf0) >> 4 ]);
-    aResult.push_back(ENCODE_TABLE[ (ch & 0x0f)      ]);
+  if ( !from.empty() ) {
+    try {
+      hexbinary::encode( &from[0], from.size(), &to );
+    }
+    CATCH_HEXBINARY_EXCEPTION()
   }
 }
 
-
-void Base16::decode(const vector<char>& aSource, vector<char>& aResult)
-{
-  size_t lSrcSize = aSource.size();
-  size_t lSrcPos = 0;
-  assert(lSrcSize % DECODE_INPUT == 0);
-
-  while (lSrcSize >= 1)
-  {
-    // 2 inputs...
-    char in1 = aSource[lSrcPos++];
-    char in2 = aSource[lSrcPos++];
-    lSrcSize -= DECODE_INPUT;
-
-    // Validate ascii...
-    assert( 0 <= in1 /*&& in1 <= 0x7f*/ );
-    assert( 0 <= in2 /*&& in2 <= 0x7f*/ );
-
-    // Convert ascii to base16...
-    in1 = DECODE_TABLE[ int(in1) ];
-    in2 = DECODE_TABLE[ int(in2) ];
-
-    // Validate base16...
-    /*assert( in1 != 0xff );*/
-    assert( 0 <= in1 && in1 <= 15 );
-    assert( 0 <= in2 && in2 <= 15 );
-
-    // 1 output...
-    aResult.push_back(((in1 << 4) | in2));
+void Base16::encode( char const *from, size_t from_len, Base16 &to )
+{
+  hexbinary::encode( from, from_len, &to.theData );
+}
+
+void Base16::decode( vector<char> const &from, vector<char> &to )
+{
+  if ( !from.empty() ) {
+    try {
+      hexbinary::decode( &from[0], from.size(), &to );
+    }
+    CATCH_HEXBINARY_EXCEPTION()
   }
 }
 
 uint32_t Base16::hash() const
 {
-  uint32_t lHash = 0;
-  vector<char>::const_iterator lIter = theData.begin();
-  vector<char>::const_iterator lEnd = theData.end();
-  for(;lIter!=lEnd;++lIter)
-  {
-    uint32_t lDiff = 65535-*lIter;
-    if (lDiff < lHash)
-    {
-      lHash = lHash - lDiff;
-    } else {
-      lHash += *lIter; 
-    }
-  }
-  return lHash;
+  return theData.size() ? ztd::hash_bytes( &theData[0], theData.size() ) : 0;
 }
 
 
-ostream& operator<<(ostream& os, const Base16& aBase16)
+ostream& operator<<( ostream &os, Base16 const &b16 )
 {
-  vector<char>::const_iterator lIter = aBase16.getData().begin();
-  vector<char>::const_iterator lEnd = aBase16.getData().end();
-  for( ; lIter != lEnd ; ++lIter)
-  {
-    os << *lIter;
-  }
+  if ( b16.size() )
+    os.write( &b16.getData()[0], b16.size() );
   return os;
 }
 

=== modified file 'src/zorbatypes/binary.h'
--- src/zorbatypes/binary.h	2013-02-26 04:12:43 +0000
+++ src/zorbatypes/binary.h	2013-03-17 04:52:23 +0000
@@ -37,24 +37,22 @@
   void operator&(Archiver& ar, Base16& obj);
 }
 
-
-/*******************************************************************************
-
-********************************************************************************/
-class ZORBA_DLL_PUBLIC Base64
+///////////////////////////////////////////////////////////////////////////////
+
+class Base64
 {
-  friend void serialization::operator&(serialization::Archiver& ar, Base64& obj);
+  friend void serialization::operator&(serialization::Archiver&, Base64&);
 
 private:
-  std::vector<char> theData;
+  std::vector<char> theData;            // stored encoded
 
 public:
-  static bool parseString(const zstring& aString, Base64& aBase64) 
+  static bool parseString( zstring const &s, Base64 &to )
   {
-    return parseString(aString.c_str(), aString.size(), aBase64);
+    return parseString( s.data(), s.size(), to );
   }
 
-  static bool parseString(const char* aString, size_t aLength, Base64& aBase64);
+  static bool parseString(char const *s, size_t aLength, Base64& to);
 
   static bool parseString(
         const char* aString, 
@@ -64,16 +62,17 @@
 
   static zstring encode(std::istream& aStream);
 
-  static void encode(std::istream& aStream, Base64& aResult);
+  static void encode(std::istream& aStream, Base64& to);
 
   static void encode(const zstring& aString, Base64&);
 
   static void encode(const std::vector<char>&, std::vector<char>&);
 
-  static void encode(
-        const unsigned char* aSource, 
-        unsigned int in_len,
-        Base64& aResult);
+  static void encode(char const *from, size_t from_len, Base64 &to);
+
+  static void encode(unsigned char const *from, size_t from_len, Base64& to) {
+    return encode( (char const*)from, from_len, to );
+  }
 
   static void decode(const std::vector<char>&, std::vector<char>&);
 
@@ -89,9 +88,9 @@
 
   explicit Base64(const Base16& aBase16);
 
-  Base64(const unsigned char *bin_data, size_t len);
+  Base64(char const *bin_data, size_t len);
 
-  Base64() {}
+  Base64() { }
 
   const std::vector<char>& getData() const { return theData; }
 
@@ -112,56 +111,53 @@
   }
 };
 
-
-std::ostream& operator<<(std::ostream& os, const Base64& aBase64);
-
-
-/*******************************************************************************
-
-********************************************************************************/
-class ZORBA_DLL_PUBLIC Base16
+inline bool operator==( Base64 const &a, Base64 const &b ) {
+  return a.equal( b );
+}
+
+inline bool operator!=( Base64 const &a, Base64 const &b ) {
+  return !(a == b);
+}
+
+std::ostream& operator<<( std::ostream&, Base64 const& );
+
+///////////////////////////////////////////////////////////////////////////////
+
+class Base16
 {
-  friend void serialization::operator&(serialization::Archiver& ar, Base16& obj);
+  friend void serialization::operator&(serialization::Archiver&, Base16&);
 
 private:
-  std::vector<char> theData;
-
-  static const char* ENCODE_TABLE; 
-  static const unsigned char DECODE_TABLE[0x80];
-  static size_t ENCODE_INPUT;
-  static size_t ENCODE_OUTPUT;
-  static size_t DECODE_INPUT;
-  static size_t DECODE_OUTPUT;
-
-public:
-  static bool parseString(const zstring& aString, Base16& aBase16) 
-  {
-    return parseString(aString.c_str(), aString.size(), aBase16);
-  }
-
-  static bool parseString(const char* aString, size_t aLength, Base16& aBase16);
-
-  static void encode(const std::vector<char>&, std::vector<char>&);
-
-  static void decode(const std::vector<char>&, std::vector<char>&);
-
-public:
-  Base16(const Base16& aBase16) 
-  {
-    theData = aBase16.theData;
-  }
-  
-  explicit Base16(const Base64& aBase64);
-  
-  Base16() {}
-  
-  virtual ~Base16() {}
-
+  std::vector<char> theData;            // stored encoded
+
+public:
+  static bool parseString( zstring const &s, Base16 &to )
+  {
+    return parseString( s.data(), s.size(), to );
+  }
+
+  static bool parseString( char const *from, size_t from_len, Base16 &to );
+
+  static void encode( std::vector<char> const&, std::vector<char>& );
+
+  static void encode( char const *from, size_t from_len, Base16 &to );
+
+  static void decode( std::vector<char> const&, std::vector<char>& );
+
+public:
+  Base16() { }
+  
+  Base16( Base16 const &from ) : theData( from.theData ) { }
+
+  Base16( char const *bin_data, size_t len );
+
+  explicit Base16( Base64 const& );
+  
   const std::vector<char>& getData() const { return theData; }
 
   size_t size() const { return theData.size(); }
 
-  bool equal(const Base16& aBase16) const;
+  bool equal( Base16 const& ) const;
 
   zstring str() const;
 
@@ -172,16 +168,24 @@
   }
 
 private:
-  void insertData(const char* aCharStar, size_t len);
+  void insertData( char const *from, size_t len );
 };
 
-
-std::ostream& operator<<(std::ostream& os, const Base16& aBase16);
+inline bool operator==( Base16 const &a, Base16 const &b ) {
+  return a.equal( b );
+}
+
+inline bool operator!=( Base16 const &a, Base16 const &b ) {
+  return !(a == b);
+}
+
+std::ostream& operator<<(std::ostream&s, const Base16& );
+
+///////////////////////////////////////////////////////////////////////////////
 
 } // namespace zorba
 
-#endif
-
+#endif /* ZORBA_ZORBATYPES_BINARY_H */
 /*
  * Local variables:
  * mode: c++


Follow ups