zorba-coders team mailing list archive
-
zorba-coders team
-
Mailing list archive
-
Message #18980
[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<char>. 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<char;>.
+ *
+ * @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<char>.
+ *
+ * @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<char;>.
+ *
+ * @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
-
[Merge] lp:~zorba-coders/zorba/bug-1153800 into lp:zorba
From: noreply, 2013-03-21
-
[Merge] lp:~zorba-coders/zorba/bug-1153800 into lp:zorba
From: Zorba Build Bot, 2013-03-21
-
[Merge] lp:~zorba-coders/zorba/bug-1153800 into lp:zorba
From: Zorba Build Bot, 2013-03-21
-
[Merge] lp:~zorba-coders/zorba/bug-1153800 into lp:zorba
From: Paul J. Lucas, 2013-03-20
-
[Merge] lp:~zorba-coders/zorba/bug-1153800 into lp:zorba
From: Zorba Build Bot, 2013-03-20
-
Re: [Merge] lp:~zorba-coders/zorba/bug-1153800 into lp:zorba
From: Zorba Build Bot, 2013-03-20
-
[Merge] lp:~zorba-coders/zorba/bug-1153800 into lp:zorba
From: Zorba Build Bot, 2013-03-20
-
[Merge] lp:~zorba-coders/zorba/bug-1153800 into lp:zorba
From: Matthias Brantner, 2013-03-20
-
Re: [Merge] lp:~zorba-coders/zorba/bug-1153800 into lp:zorba
From: Matthias Brantner, 2013-03-20
-
Re: [Merge] lp:~zorba-coders/zorba/bug-1153800 into lp:zorba
From: Matthias Brantner, 2013-03-19
-
[Merge] lp:~zorba-coders/zorba/bug-1153800 into lp:zorba
From: Zorba Build Bot, 2013-03-19
-
Re: [Merge] lp:~zorba-coders/zorba/bug-1153800 into lp:zorba
From: Zorba Build Bot, 2013-03-19
-
[Merge] lp:~zorba-coders/zorba/bug-1153800 into lp:zorba
From: Zorba Build Bot, 2013-03-19
-
[Merge] lp:~zorba-coders/zorba/bug-1153800 into lp:zorba
From: Zorba Build Bot, 2013-03-19
-
[Merge] lp:~zorba-coders/zorba/bug-1153800 into lp:zorba
From: Paul J. Lucas, 2013-03-19
-
[Merge] lp:~zorba-coders/zorba/bug-1153800 into lp:zorba
From: Zorba Build Bot, 2013-03-19
-
Re: [Merge] lp:~zorba-coders/zorba/bug-1153800 into lp:zorba
From: Zorba Build Bot, 2013-03-19
-
[Merge] lp:~zorba-coders/zorba/bug-1153800 into lp:zorba
From: Zorba Build Bot, 2013-03-19
-
[Merge] lp:~zorba-coders/zorba/bug-1153800 into lp:zorba
From: Paul J. Lucas, 2013-03-19
-
[Merge] lp:~zorba-coders/zorba/bug-1153800 into lp:zorba
From: Zorba Build Bot, 2013-03-17
-
Re: [Merge] lp:~zorba-coders/zorba/bug-1153800 into lp:zorba
From: Zorba Build Bot, 2013-03-17
-
[Merge] lp:~zorba-coders/zorba/bug-1153800 into lp:zorba
From: Zorba Build Bot, 2013-03-17
-
[Merge] lp:~zorba-coders/zorba/bug-1153800 into lp:zorba
From: Paul J. Lucas, 2013-03-17
-
Re: [Merge] lp:~zorba-coders/zorba/bug-1153800 into lp:zorba
From: Paul J. Lucas, 2013-03-17