diff options
-rw-r--r-- | include/jau/base_codec.hpp | 103 | ||||
-rw-r--r-- | java_base/org/jau/util/BaseCodec.java | 143 | ||||
-rw-r--r-- | src/base_codec.cpp | 27 | ||||
-rw-r--r-- | src/file_util.cpp | 2 | ||||
-rw-r--r-- | test/java/jau/test/util/TestBaseCodec.java | 112 | ||||
-rw-r--r-- | test/test_codec_base01.cpp | 112 |
6 files changed, 287 insertions, 212 deletions
diff --git a/include/jau/base_codec.hpp b/include/jau/base_codec.hpp index d5d9e3c..1d6ffc3 100644 --- a/include/jau/base_codec.hpp +++ b/include/jau/base_codec.hpp @@ -56,17 +56,22 @@ namespace jau::codec::base { private: std::string name_; - int max_base_; + int base_; std::string_view symbols_; char padding64_; code_point_func cpf; public: - alphabet(const std::string& _name, int _max_base, std::string_view _symbols, char _padding64, code_point_func _cpf) noexcept - : name_(_name), max_base_(_max_base), symbols_(_symbols), padding64_(_padding64), cpf(_cpf) {} + alphabet(const std::string& _name, int _base, std::string_view _symbols, char _padding64, code_point_func _cpf) noexcept + : name_(_name), base_(_base), symbols_(_symbols), padding64_(_padding64), cpf(_cpf) {} + /** Human readable name for this alphabet instance. */ constexpr const std::string& name() const noexcept { return name_; } - constexpr int max_base() const noexcept { return max_base_; } + + /** The fixed base used for this alphabet. */ + constexpr int base() const noexcept { return base_; } + + /** The string of symbols of this alphabet. */ constexpr const std::string_view& symbols() const noexcept { return symbols_; } /** Padding symbol for base <= 64 and block encoding only. May return zero for no padding. */ @@ -75,14 +80,13 @@ namespace jau::codec::base { /** Returns the code-point of the given character or -1 if not element of this alphabet. */ constexpr int code_point(const char c) const noexcept { return cpf(c); } - constexpr char at( size_t pos ) const { return symbols_.at(pos); } - constexpr char operator[]( size_t pos ) const { return symbols_[pos]; } - constexpr char symbol( size_t pos ) const { return symbols_[pos]; } + /** Retrieve the character at given code-point of this alphabet. */ + constexpr char operator[]( size_t cp ) const noexcept { return symbols_[cp]; } std::string to_string() const noexcept { std::string res("alphabet["); res.append(name()); - res.append(", base <= "+std::to_string(max_base())+"]"); + res.append(", base <= "+std::to_string(base())+"]"); return res; } }; @@ -90,7 +94,7 @@ namespace jau::codec::base { inline std::string to_string(const alphabet& v) noexcept { return v.to_string(); } inline bool operator!=(const alphabet& lhs, const alphabet& rhs ) noexcept { - return lhs.max_base() != rhs.max_base() || lhs.name() != rhs.name() || lhs.symbols() != rhs.symbols(); + return lhs.base() != rhs.base() || lhs.name() != rhs.name() || lhs.symbols() != rhs.symbols(); } inline bool operator==(const alphabet& lhs, const alphabet& rhs ) noexcept { @@ -107,6 +111,7 @@ namespace jau::codec::base { * - Padding: `=` * * ### Properties + * - Base 64 * - 7-bit ASCII * - Code page 437 compatible * - [`base64` alphabet](https://www.rfc-editor.org/rfc/rfc4648.html), identical order @@ -149,6 +154,7 @@ namespace jau::codec::base { * - Padding: `=` * * ### Properties + * - Base 64 * - 7-bit ASCII * - Code page 437 compatible * - [`base64url` alphabet](https://www.rfc-editor.org/rfc/rfc4648.html), identical order @@ -184,14 +190,15 @@ namespace jau::codec::base { }; /** - * Natural base 86 alphabet including a safe base 64 subset, both without ASCII code-point sorting order. + * Safe natural base 64 alphabet, both without ASCII code-point sorting order. * - * Order is considered a natural extension of decimal symbols, i.e. `0` < `a` < `A` < `_` < `~` + * Order is considered a natural extension of decimal symbols, i.e. `0` < `a` < `A` < `_`. * - * - Value: `0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_!#%&()+,/:;<=>?@[]^{}~` - * - Padding: `=` (base <= 64) + * - Value: `0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_` + * - Padding: `=` * - * ### Properties up to base <= 64 + * ### Properties + * - Base 64 * - 7-bit ASCII * - Code page 437 compatible * - [`base64url` alphabet](https://www.rfc-editor.org/rfc/rfc4648.html), but different order @@ -200,8 +207,42 @@ namespace jau::codec::base { * - Excludes quoting chars: "'$ and space * - Not supporting ASCII code-point sorting. * - Order: `0` < `a` < `A` < `_` + */ + class natural64_alphabet : public alphabet { + private: + static inline constexpr const std::string_view data = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_"; + + static int s_code_point(const char c) noexcept { + if ('0' <= c && c <= '9') { + return c - '0'; + } else if ('a' <= c && c <= 'z') { + return c - 'a' + 10; + } else if ('A' <= c && c <= 'Z') { + return c - 'A' + 36; + } else if ('-' == c) { + return 62; + } else if ('_' == c) { + return 63; + } else { + return -1; + } + } + + public: + natural64_alphabet() noexcept + : alphabet("natural64", 64, data, '=', s_code_point) {} + }; + + /** + * Natural base 86 alphabet, without ASCII code-point sorting order. + * + * Order is considered a natural extension of decimal symbols, i.e. `0` < `a` < `A` < `_` < `~` + * + * - Value: `0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_!#%&()+,/:;<=>?@[]^{}~` + * - Padding: none * - * ### Properties base range [65 .. 86] + * ### Properties + * - Base 86 * - 7-bit ASCII * - Code page 437 compatible * - Excludes quoting chars: "'$ and space @@ -252,7 +293,7 @@ namespace jau::codec::base { public: natural86_alphabet() noexcept - : alphabet("natural86", 86, data, '=', s_code_point) {} + : alphabet("natural86", 86, data, 0, s_code_point) {} }; /** @@ -262,6 +303,7 @@ namespace jau::codec::base { * - Padding: `=` * * ### Properties + * - Base 38 * - 7-bit ASCII * - Code page 437 compatible * - Safe URL and filename use @@ -301,6 +343,7 @@ namespace jau::codec::base { * - Padding: `=` * * ### Properties + * - Base 64 * - 7-bit ASCII * - Code page 437 compatible * - [`base64url` alphabet](https://www.rfc-editor.org/rfc/rfc4648.html), but different order @@ -342,6 +385,7 @@ namespace jau::codec::base { * - Padding: None * * ### Properties + * - Base 86 * - 7-bit ASCII * - Code page 437 compatible * - Excludes quoting chars: "'$ and space @@ -399,7 +443,7 @@ namespace jau::codec::base { }; /** - * Encodes a given positive decimal number to a symbolic string representing a given base and alphabet. + * Encodes a given positive decimal number to a symbolic string representing a given alphabet and its base. * * Besides using a custom alphabet, the following build-in alphabets are provided * - jau::codec::base::base64_alphabet @@ -409,7 +453,6 @@ namespace jau::codec::base { * - jau::codec::base::ascii86_alphabet * * @param num a positive decimal number - * @param base positive radix to use <= alphabet::max_base() * @param aspec the used alphabet specification * @param min_width minimum width of the encoded string, encoded zero is used for padding * @return the encoded string or an empty string if base exceeds alphabet::max_base() or invalid arguments @@ -417,10 +460,10 @@ namespace jau::codec::base { * @see encodeBase() * @see decodeBase() */ - std::string encode(int num, const int base, const alphabet& aspec, const unsigned int min_width=0) noexcept; + std::string encode(int num, const alphabet& aspec, const unsigned int min_width=0) noexcept; /** - * Encodes a given positive decimal number to a symbolic string representing a given base and alphabet. + * Encodes a given positive decimal number to a symbolic string representing a given alphabet and its base. * * Besides using a custom alphabet, the following build-in alphabets are provided * - jau::codec::base::base64_alphabet @@ -430,7 +473,6 @@ namespace jau::codec::base { * - jau::codec::base::ascii86_alphabet * * @param num a positive decimal number - * @param base positive radix to use <= alphabet::max_base() * @param aspec the used alphabet specification * @param min_width minimum width of the encoded string, encoded zero is used for padding * @return the encoded string or an empty string if base exceeds alphabet::max_base() or invalid arguments @@ -438,10 +480,10 @@ namespace jau::codec::base { * @see encodeBase() * @see decodeBase() */ - std::string encode(int64_t num, const int base, const alphabet& aspec, const unsigned int min_width=0) noexcept; + std::string encode(int64_t num, const alphabet& aspec, const unsigned int min_width=0) noexcept; /** - * Decodes a given symbolic string representing a given base and alphabet to a positive decimal number. + * Decodes a given symbolic string representing a given alphabet and its base to a positive decimal number. * * Besides using a custom alphabet, the following build-in alphabets are provided * - jau::codec::base::base64_alphabet @@ -451,13 +493,12 @@ namespace jau::codec::base { * - jau::codec::base::ascii86_alphabet * * @param str an encoded string - * @param base positive radix to use <= alphabet::max_base() * @param aspec the used alphabet specification * @return the decoded decimal value or -1 if base exceeds alphabet::max_base(), unknown code-point or invalid arguments * * @see encodeBase() */ - int64_t decode(const std::string_view& str, const int base, const alphabet& aspec) noexcept; + int64_t decode(const std::string_view& str, const alphabet& aspec) noexcept; /** * Encodes given octets using the given alphabet and fixed base 64 encoding @@ -467,7 +508,7 @@ namespace jau::codec::base { * * @param in_octets pointer to octets start * @param in_len length of octets in bytes - * @param aspec the used alphabet specification + * @param aspec the used base 64 alphabet specification * @return the encoded string, empty if base exceeds alphabet::max_base() or invalid arguments */ std::string encode64(const void* in_octets, size_t in_len, const alphabet& aspec) noexcept; @@ -479,7 +520,7 @@ namespace jau::codec::base { * An error only occurs if the encoded string length > 0 and resulting decoded octets size is empty. * * @param str encoded string - * @param aspec the used alphabet specification + * @param aspec the used base 64 alphabet specification * @return the decoded octets, empty if base exceeds alphabet::max_base(), unknown code-point or invalid arguments */ std::vector<uint8_t> decode64(const std::string_view& str, const alphabet& aspec) noexcept; @@ -510,7 +551,7 @@ namespace jau::codec::base { * * @param in_octets pointer to octets start * @param in_len length of octets in bytes - * @param aspec the used alphabet specification + * @param aspec the used base 64 alphabet specification * @return the encoded string, empty if base exceeds alphabet::max_base() or invalid arguments */ inline std::string encode64_pem(const void* in_octets, size_t in_len, const alphabet& aspec) noexcept { @@ -528,7 +569,7 @@ namespace jau::codec::base { * * @param in_octets pointer to octets start * @param in_len length of octets in bytes - * @param aspec the used alphabet specification + * @param aspec the used base 64 alphabet specification * @return the encoded string, empty if base exceeds alphabet::max_base() or invalid arguments */ inline std::string encode64_mime(const void* in_octets, size_t in_len, const alphabet& aspec) noexcept { @@ -545,7 +586,7 @@ namespace jau::codec::base { * An error only occurs if the encoded string length > 0 and resulting decoded octets size is empty. * * @param str and encoded string, will be copied - * @param aspec the used alphabet specification + * @param aspec the used base 64 alphabet specification * @return the decoded octets, empty if base exceeds alphabet::max_base(), unknown code-point or invalid arguments */ inline std::vector<uint8_t> decode64_lf(const std::string_view& str, const alphabet& aspec) noexcept { @@ -562,7 +603,7 @@ namespace jau::codec::base { * An error only occurs if the encoded string length > 0 and resulting decoded octets size is empty. * * @param str and encoded string, no copy, will be mutated - * @param aspec the used alphabet specification + * @param aspec the used base 64 alphabet specification * @return the decoded octets, empty if base exceeds alphabet::max_base(), unknown code-point or invalid arguments */ inline std::vector<uint8_t> decode64_lf(std::string& str, const alphabet& aspec) noexcept { diff --git a/java_base/org/jau/util/BaseCodec.java b/java_base/org/jau/util/BaseCodec.java index dca1fa3..22338cd 100644 --- a/java_base/org/jau/util/BaseCodec.java +++ b/java_base/org/jau/util/BaseCodec.java @@ -39,19 +39,24 @@ public class BaseCodec { */ public static abstract class Alphabet { private final String name_; - private final int max_base_; + private final int base_; private final String symbols_; private final char padding64_; - protected Alphabet(final String name, final int max_base, final String symbols, final char passing64) { + protected Alphabet(final String name, final int base, final String symbols, final char passing64) { this.name_ = name; - this.max_base_ = max_base; + this.base_ = base; this.symbols_ = symbols; this.padding64_ = passing64; } + /** Human readable name for this alphabet instance. */ public final String name() { return name_; } - public final int max_base() { return max_base_; } + + /** The fixed base used for this alphabet. */ + public final int base() { return base_; } + + /** The string of symbols of this alphabet. */ public final String symbols() { return symbols_; } /** Padding symbol for base <= 64 and block encoding only. May return zero for no padding. */ @@ -60,8 +65,8 @@ public class BaseCodec { /** Returns the code-point of the given character or -1 if not element of this alphabet. */ public abstract int code_point(final char c); - public final char charAt( final int pos ) { return symbols().charAt(pos); } - public final char symbol( final int pos ) { return symbols().charAt(pos); } + /** Retrieve the character at given code-point of this alphabet. */ + public final char charAt( final int cp ) { return symbols().charAt(cp); } @Override public boolean equals(final Object o) { @@ -70,14 +75,14 @@ public class BaseCodec { } if( o instanceof Alphabet ) { final Alphabet oa = (Alphabet)o; - return max_base() == max_base() && name().equals(oa.name()) && symbols().equals(oa.symbols()); + return base() == base() && name().equals(oa.name()) && symbols().equals(oa.symbols()); } return false; } @Override public String toString() { - return "Alphabet["+name_+", base <= "+max_base_+"]"; + return "Alphabet["+name_+", base <= "+base_+"]"; } }; @@ -91,6 +96,7 @@ public class BaseCodec { * - Padding: `=` * * ### Properties + * - Base 64 * - 7-bit ASCII * - Code page 437 compatible * - [`base64` alphabet](https://www.rfc-editor.org/rfc/rfc4648.html), identical order @@ -133,6 +139,7 @@ public class BaseCodec { * - Padding: `=` * * ### Properties + * - Base 64 * - 7-bit ASCII * - Code page 437 compatible * - [`base64url` alphabet](https://www.rfc-editor.org/rfc/rfc4648.html), identical order @@ -141,9 +148,6 @@ public class BaseCodec { * - Excludes quoting chars: "'$ and space * - Not supporting ASCII code-point sorting. * - Order: `A` < `a` < `0` < `_` - * - * @see encodeBase() - * @see decodeBase() */ public static class Base64urlAlphabet extends Alphabet { private static final String data = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"; @@ -171,14 +175,15 @@ public class BaseCodec { } /** - * Natural base 86 alphabet including a safe base 64 subset, both without ASCII code-point sorting order. + * Safe natural base 64 alphabet, both without ASCII code-point sorting order. * - * Order is considered a natural extension of decimal symbols, i.e. `0` < `a` < `A` < `_` < `~` + * Order is considered a natural extension of decimal symbols, i.e. `0` < `a` < `A` < `_`. * - * - Value: `0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_!#%&()+,/:;<=>?@[]^{}~` - * - Padding: `=` (base <= 64) + * - Value: `0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_` + * - Padding: `=` * - * ### Properties up to base <= 64 + * ### Properties + * - Base 64 * - 7-bit ASCII * - Code page 437 compatible * - [`base64url` alphabet](https://www.rfc-editor.org/rfc/rfc4648.html), but different order @@ -187,8 +192,42 @@ public class BaseCodec { * - Excludes quoting chars: "'$ and space * - Not supporting ASCII code-point sorting. * - Order: `0` < `a` < `A` < `_` + */ + public static class Natural64Alphabet extends Alphabet { + private static final String data = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_"; + + @Override + public int code_point(final char c) { + if ('0' <= c && c <= '9') { + return c - '0'; + } else if ('a' <= c && c <= 'z') { + return c - 'a' + 10; + } else if ('A' <= c && c <= 'Z') { + return c - 'A' + 36; + } else if ('-' == c) { + return 62; + } else if ('_' == c) { + return 63; + } else { + return -1; + } + } + + public Natural64Alphabet() { + super("natural64", 64, data, '='); + } + } + + /** + * Natural base 86 alphabet, without ASCII code-point sorting order. * - * ### Properties base range [65 .. 86] + * Order is considered a natural extension of decimal symbols, i.e. `0` < `a` < `A` < `_` < `~` + * + * - Value: `0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_!#%&()+,/:;<=>?@[]^{}~` + * - Padding: none + * + * ### Properties + * - Base 86 * - 7-bit ASCII * - Code page 437 compatible * - Excludes quoting chars: "'$ and space @@ -241,7 +280,7 @@ public class BaseCodec { } public Natural86Alphabet() { - super("natural86", 86, data, '='); + super("natural86", 86, data, (char)0); } } @@ -252,6 +291,7 @@ public class BaseCodec { * - Padding: `=` * * ### Properties + * - Base 38 * - 7-bit ASCII * - Code page 437 compatible * - Safe URL and filename use @@ -294,6 +334,7 @@ public class BaseCodec { * - Padding: `=` * * ### Properties + * - Base 64 * - 7-bit ASCII * - Code page 437 compatible * - [`base64url` alphabet](https://www.rfc-editor.org/rfc/rfc4648.html), but different order @@ -338,6 +379,7 @@ public class BaseCodec { * - Padding: None * * ### Properties + * - Base 86 * - 7-bit ASCII * - Code page 437 compatible * - Excludes quoting chars: "'$ and space @@ -398,7 +440,7 @@ public class BaseCodec { } /** - * Encodes a given positive decimal number to a symbolic string representing a given base and alphabet. + * Encodes a given positive decimal number to a symbolic string representing a given alphabet and its base. * * Besides using a custom alphabet, the following build-in alphabets are provided * - {@link BaseCodec.Base64Alphabet} @@ -408,7 +450,6 @@ public class BaseCodec { * - {@link BaseCodec.Ascii86Alphabet} * * @param num a positive decimal number - * @param base positive radix to use <= Alphabet.max_base() * @param aspec the used alphabet specification * @param min_width minimum width of the encoded string, encoded zero is used for padding * @return the encoded string or an empty string if base exceeds Alphabet.max_base() or invalid arguments @@ -416,8 +457,9 @@ public class BaseCodec { * @see {@link BaseCodec#encode(long, int, Alphabet, int)} * @see {@link BaseCodec#decode(String, int, Alphabet)} */ - public static String encode(int num, final int base, final Alphabet aspec, final int min_width) { - if( 0 > num || 1 >= base || base > aspec.max_base() ) { + public static String encode(int num, final Alphabet aspec, final int min_width) { + final int base = aspec.base(); + if( 0 > num || 1 >= base ) { return ""; } final StringBuilder res = new StringBuilder(); @@ -434,7 +476,7 @@ public class BaseCodec { } /** - * Encodes a given positive decimal number to a symbolic string representing a given base and alphabet. + * Encodes a given positive decimal number to a symbolic string representing given alphabet and its base. * * Besides using a custom alphabet, the following build-in alphabets are provided * - {@link BaseCodec.Base64Alphabet} @@ -444,7 +486,6 @@ public class BaseCodec { * - {@link BaseCodec.Ascii86Alphabet} * * @param num a positive decimal number - * @param base positive radix to use <= Alphabet.max_base() * @param aspec the used alphabet specification * @param min_width minimum width of the encoded string, encoded zero is used for padding * @return the encoded string or an empty string if base exceeds Alphabet.max_base() or invalid arguments @@ -452,15 +493,15 @@ public class BaseCodec { * @see {@link BaseCodec#encode(int, int, Alphabet, int)} * @see {@link BaseCodec#decode(String, int, Alphabet)} */ - public static String encode(long num, final int base, final Alphabet aspec, final int min_width) { - if( 0 > num || 1 >= base || base > aspec.max_base() ) { + public static String encode(long num, final Alphabet aspec, final int min_width) { + final long base = aspec.base(); + if( 0 > num || 1 >= base ) { return ""; } final StringBuilder res = new StringBuilder(); - final long lbase = base; do { - res.insert( 0, aspec.charAt( (int)( num % lbase ) ) ); // safe: base <= alphabet.length() - num /= lbase; + res.insert( 0, aspec.charAt( (int)( num % base ) ) ); // safe: base <= alphabet.length() + num /= base; } while ( 0 != num ); final char s0 = aspec.charAt(0); @@ -471,7 +512,7 @@ public class BaseCodec { } /** - * Encodes a given positive decimal number to a symbolic string representing a given base and alphabet. + * Encodes a given positive decimal number to a symbolic string representing a given alphabet and its base. * * Besides using a custom alphabet, the following build-in alphabets are provided * - {@link BaseCodec.Base64Alphabet} @@ -481,19 +522,18 @@ public class BaseCodec { * - {@link BaseCodec.Ascii86Alphabet} * * @param num a positive decimal number - * @param base positive radix to use <= Alphabet.max_base() * @param aspec the used alphabet specification * @return the encoded string or an empty string if base exceeds Alphabet.max_base() or invalid arguments * * @see {@link BaseCodec#encode(int, int, Alphabet, int)} * @see {@link BaseCodec#decode(String, int, Alphabet)} */ - public static String encode(final int num, final int base, final Alphabet aspec) { - return encode(num, base, aspec, 0 /* min_width */); + public static String encode(final int num, final Alphabet aspec) { + return encode(num, aspec, 0 /* min_width */); } /** - * Encodes a given positive decimal number to a symbolic string representing a given base and alphabet. + * Encodes a given positive decimal number to a symbolic string representing a given alphabet and its base. * * Besides using a custom alphabet, the following build-in alphabets are provided * - {@link BaseCodec.Base64Alphabet} @@ -503,19 +543,18 @@ public class BaseCodec { * - {@link BaseCodec.Ascii86Alphabet} * * @param num a positive decimal number - * @param base positive radix to use <= Alphabet.max_base() * @param aspec the used alphabet specification * @return the encoded string or an empty string if base exceeds Alphabet.max_base() or invalid arguments * * @see {@link BaseCodec#encode(long, int, Alphabet, int)} * @see {@link BaseCodec#decode(String, int, Alphabet)} */ - public static String encode(final long num, final int base, final Alphabet aspec) { - return encode(num, base, aspec, 0 /* min_width */); + public static String encode(final long num, final Alphabet aspec) { + return encode(num, aspec, 0 /* min_width */); } /** - * Decodes a given symbolic string representing a given base and alphabet to a positive decimal number. + * Decodes a given symbolic string representing a given alphabet and its base to a positive decimal number. * * Besides using a custom alphabet, the following build-in alphabets are provided * - {@link BaseCodec.Base64Alphabet} @@ -525,22 +564,22 @@ public class BaseCodec { * - {@link BaseCodec.Ascii86Alphabet} * * @param str an encoded string - * @param base positive radix to use <= Alphabet.max_base() * @param aspec the used alphabet specification * @return the decoded radix decimal value or -1 if base exceeds Alphabet.max_base(), unknown code-point or invalid arguments * * @see {@link BaseCodec#encode(int, int, Alphabet, int)} * @see {@link BaseCodec#encode(long, int, Alphabet, int)} */ - public static long decode(final String str, final int base, final Alphabet aspec) { - if( 1 >= base || base > aspec.max_base() ) { + public static long decode(final String str, final Alphabet aspec) { + final int base = aspec.base(); + if( 1 >= base ) { return -1; } final int str_len = str.length(); long res = 0; for (int i = 0; i < str_len; ++i) { final int d = aspec.code_point( str.charAt(i) ); - if( 0 > d || d >= base ) { + if( 0 > d ) { return -1; // encoded value not found } res = res * base + d; @@ -559,11 +598,11 @@ public class BaseCodec { * @param in_octets source byte array * @param in_pos index to octets start * @param in_len length of octets in bytes - * @param aspec the used alphabet specification + * @param aspec the used base 64 alphabet specification * @return the encoded string, empty if base exceeds alphabet::max_base() or invalid arguments */ public static StringBuilder encode64(final byte[] in_octets, int in_pos, int in_len, final Alphabet aspec) { - if( 64 > aspec.max_base() || in_pos + in_len > in_octets.length ) { + if( 64 != aspec.base() || in_pos + in_len > in_octets.length ) { return new StringBuilder(0); } final char padding = aspec.padding64(); @@ -618,11 +657,11 @@ public class BaseCodec { * An error only occurs if the encoded string length > 0 and resulting decoded octets size is empty. * * @param in_code encoded string - * @param aspec the used alphabet specification + * @param aspec the used base 64 alphabet specification * @return the decoded octets, empty if base exceeds alphabet::max_base(), unknown code-point or invalid arguments */ public static ByteBuffer decode64(final String in_code, final Alphabet aspec) { - if( 64 > aspec.max_base() ) { + if( 64 != aspec.base() ) { return ByteBuffer.allocate(0); // Error } int in_len = in_code.length(); @@ -638,7 +677,7 @@ public class BaseCodec { while( in_len >= 2 ) { final int cp0 = aspec.code_point( in_code.charAt( in_pos + 0 ) ); final int cp1 = aspec.code_point( in_code.charAt( in_pos + 1 ) ); - if( 0 > cp0 || cp0 >= 64 || 0 > cp1 || cp1 >= 64 ) { + if( 0 > cp0 || 0 > cp1 ) { break; } res.put( (byte)(cp0 << 2 | cp1 >> 4) ); @@ -657,7 +696,7 @@ public class BaseCodec { } } else { final int cp2 = aspec.code_point( in_code.charAt( in_pos + 2 ) ); - if( 0 > cp2 || cp2 >= 64 ) { + if( 0 > cp2 ) { break; } res.put( (byte)( ( ( cp1 << 4 ) & 0xf0 ) | ( cp2 >> 2 ) ) ); @@ -673,7 +712,7 @@ public class BaseCodec { } } else { final int cp3 = aspec.code_point( in_code.charAt( in_pos + 3 ) ); - if( 0 > cp3 || cp3 >= 64 ) { + if( 0 > cp3 ) { break; } res.put( (byte)( ( ( cp2 << 6 ) & 0xc0 ) | cp3 ) ); @@ -752,7 +791,7 @@ public class BaseCodec { * * @param in_octets pointer to octets start * @param in_len length of octets in bytes - * @param aspec the used alphabet specification + * @param aspec the used base 64 alphabet specification * @return the encoded string, empty if base exceeds alphabet::max_base() or invalid arguments */ public static StringBuilder encode64_mime(final byte[] in_octets, final int in_pos, final int in_len, final Alphabet aspec) { @@ -769,7 +808,7 @@ public class BaseCodec { * An error only occurs if the encoded string length > 0 and resulting decoded octets size is empty. * * @param str and encoded string, will be copied - * @param aspec the used alphabet specification + * @param aspec the used base 64 alphabet specification * @return the decoded octets, empty if base exceeds alphabet::max_base(), unknown code-point or invalid arguments */ public static ByteBuffer decode64_lf(final String str, final Alphabet aspec) { @@ -786,7 +825,7 @@ public class BaseCodec { * An error only occurs if the encoded string length > 0 and resulting decoded octets size is empty. * * @param str and encoded string, no copy, will be mutated - * @param aspec the used alphabet specification + * @param aspec the used base 64 alphabet specification * @return the decoded octets, empty if base exceeds alphabet::max_base(), unknown code-point or invalid arguments */ public static ByteBuffer decode64_lf(final StringBuilder str, final Alphabet aspec) { diff --git a/src/base_codec.cpp b/src/base_codec.cpp index 26c6ba7..0860a6e 100644 --- a/src/base_codec.cpp +++ b/src/base_codec.cpp @@ -29,9 +29,10 @@ using namespace jau; using namespace jau::codec::base; -std::string jau::codec::base::encode(int num, const int base, const alphabet& aspec, const unsigned int min_width) noexcept +std::string jau::codec::base::encode(int num, const alphabet& aspec, const unsigned int min_width) noexcept { - if( 0 > num || 1 >= base || base > aspec.max_base() ) { + const int base = aspec.base(); + if( 0 > num || 1 >= base ) { return ""; } std::string res; @@ -48,8 +49,9 @@ std::string jau::codec::base::encode(int num, const int base, const alphabet& as return res; } -std::string jau::codec::base::encode(int64_t num, const int base, const alphabet& aspec, const unsigned int min_width) noexcept { - if( 0 > num || 1 >= base || base > aspec.max_base() ) { +std::string jau::codec::base::encode(int64_t num, const alphabet& aspec, const unsigned int min_width) noexcept { + const int base = aspec.base(); + if( 0 > num || 1 >= base ) { return ""; } std::string res; @@ -66,16 +68,17 @@ std::string jau::codec::base::encode(int64_t num, const int base, const alphabet return res; } -int64_t jau::codec::base::decode(const std::string_view& str, const int base, const alphabet& aspec) noexcept +int64_t jau::codec::base::decode(const std::string_view& str, const alphabet& aspec) noexcept { - if( 1 >= base || base > aspec.max_base() ) { + const int base = aspec.base(); + if( 1 >= base ) { return -1; } std::string::size_type str_len = str.length(); int64_t res = 0; for (std::string::size_type pos = 0; pos < str_len; ++pos) { const int cp = aspec.code_point( str[pos] ); - if( 0 > cp || cp >= base ) { + if( 0 > cp ) { return -1; // encoded value not found } res = res * base + static_cast<int64_t>(cp); @@ -84,7 +87,7 @@ int64_t jau::codec::base::decode(const std::string_view& str, const int base, co } std::string jau::codec::base::encode64(const void* in_octets, size_t in_len, const alphabet& aspec) noexcept { - if( 64 > aspec.max_base() ) { + if( 64 != aspec.base() ) { return ""; } const char padding = aspec.padding64(); @@ -135,7 +138,7 @@ std::string jau::codec::base::encode64(const void* in_octets, size_t in_len, con } std::vector<uint8_t> jau::codec::base::decode64(const std::string_view& in_code, const alphabet& aspec) noexcept { - if( 64 > aspec.max_base() ) { + if( 64 != aspec.base() ) { return std::vector<uint8_t>(); // Error } size_t in_len = in_code.length(); @@ -152,7 +155,7 @@ std::vector<uint8_t> jau::codec::base::decode64(const std::string_view& in_code, while( in_len >= 2 ) { const int cp0 = aspec.code_point( in_chars[0] ); const int cp1 = aspec.code_point( in_chars[1] ); - if( 0 > cp0 || cp0 >= 64 || 0 > cp1 || cp1 >= 64 ) { + if( 0 > cp0 || 0 > cp1 ) { break; } res.push_back( cp0 << 2 | cp1 >> 4 ); @@ -171,7 +174,7 @@ std::vector<uint8_t> jau::codec::base::decode64(const std::string_view& in_code, } } else { const int cp2 = aspec.code_point( in_chars[2] ); - if( 0 > cp2 || cp2 >= 64 ) { + if( 0 > cp2 ) { break; } res.push_back( ( ( cp1 << 4 ) & 0xf0 ) | ( cp2 >> 2 ) ); @@ -187,7 +190,7 @@ std::vector<uint8_t> jau::codec::base::decode64(const std::string_view& in_code, } } else { const int cp3 = aspec.code_point( in_chars[3] ); - if( 0 > cp3 || cp3 >= 64 ) { + if( 0 > cp3 ) { break; } res.push_back( ( ( cp2 << 6 ) & 0xc0 ) | cp3 ); diff --git a/src/file_util.cpp b/src/file_util.cpp index 9fdaf68..31354a1 100644 --- a/src/file_util.cpp +++ b/src/file_util.cpp @@ -1539,7 +1539,7 @@ static bool copy_push_mkdir(const file_stats& dst_stats, copy_context_t& ctx) no do { ++mkdir_cntr; const int32_t val_d = prng_dist(prng); - basename_ = "."+jau::codec::base::encode(val_d, 38, jau::codec::base::ascii38_alphabet(), 6); // base 38, 6 digits + basename_ = "."+jau::codec::base::encode(val_d, jau::codec::base::ascii38_alphabet(), 6); // base 38, 6 digits if( 0 == ::mkdirat(dest_dirfd, basename_.c_str(), jau::fs::posix_protection_bits(fmode_t::rwx_usr)) ) { mkdir_ok = true; } else if (errno != EINTR && errno != EEXIST) { diff --git a/test/java/jau/test/util/TestBaseCodec.java b/test/java/jau/test/util/TestBaseCodec.java index d5ea37e..49c5b98 100644 --- a/test/java/jau/test/util/TestBaseCodec.java +++ b/test/java/jau/test/util/TestBaseCodec.java @@ -40,72 +40,72 @@ public class TestBaseCodec { static final Alphabet natural86_alphabet = new BaseCodec.Natural86Alphabet(); - private static void testRadix_3digits_int32(final int base, final Alphabet aspec) { + private static void testRadix_3digits_int32(final Alphabet aspec) { + final int base = aspec.base(); Assert.assertTrue( 1 < base ); - Assert.assertTrue( base <= aspec.max_base() ); final char min_cp = aspec.charAt(0); // minimum code-point final char max_cp = aspec.charAt(base-1); // maximum code-point - final int min = (int)BaseCodec.decode(""+min_cp, base, aspec); - final int max = (int)BaseCodec.decode(""+max_cp+max_cp+max_cp, base, aspec); - final int max_s = (int)BaseCodec.decode(""+max_cp, base, aspec); + final int min = (int)BaseCodec.decode(""+min_cp, aspec); + final int max = (int)BaseCodec.decode(""+max_cp+max_cp+max_cp, aspec); + final int max_s = (int)BaseCodec.decode(""+max_cp, aspec); final double machine_epsilon = BasicTypes.machineEpsilonDouble(); Assert.assertEquals(0, min); Assert.assertEquals(base-1, max_s); Assert.assertTrue( Math.abs( Math.pow(base, 3)-1 - max ) <= machine_epsilon ); - final String r1_min = BaseCodec.encode(0, base, aspec, 3); - final String r1_min_s = BaseCodec.encode(0, base, aspec); + final String r1_min = BaseCodec.encode(0, aspec, 3); + final String r1_min_s = BaseCodec.encode(0, aspec); Assert.assertEquals(""+min_cp+min_cp+min_cp, r1_min); Assert.assertEquals(""+min_cp, r1_min_s); - final String r1_max = BaseCodec.encode(base-1, base, aspec, 3); - final String r1_max_s = BaseCodec.encode(base-1, base, aspec); + final String r1_max = BaseCodec.encode(base-1, aspec, 3); + final String r1_max_s = BaseCodec.encode(base-1, aspec); Assert.assertEquals(""+min_cp+min_cp+max_cp, r1_max); Assert.assertEquals(""+max_cp, r1_max_s); - final String r3_max = BaseCodec.encode((int)Math.pow(base, 3)-1, base, aspec, 3); + final String r3_max = BaseCodec.encode((int)Math.pow(base, 3)-1, aspec, 3); Assert.assertEquals(""+max_cp+max_cp+max_cp, r3_max); System.err.printf("Test base %d, %s: [%d .. %d] <-> ['%s' .. '%s'], %d years (max/365d)\n", base, aspec, min, max, - BaseCodec.encode(min, base, aspec), - BaseCodec.encode(max, base, aspec), (max/365)); + BaseCodec.encode(min, aspec), + BaseCodec.encode(max, aspec), (max/365)); - Assert.assertEquals(0, BaseCodec.decode(""+min_cp+min_cp+min_cp, base, aspec)); - Assert.assertEquals(""+min_cp, BaseCodec.encode(0, base, aspec)); - Assert.assertEquals(""+min_cp+min_cp+min_cp, BaseCodec.encode(0, base, aspec, 3)); + Assert.assertEquals(0, BaseCodec.decode(""+min_cp+min_cp+min_cp, aspec)); + Assert.assertEquals(""+min_cp, BaseCodec.encode(0, aspec)); + Assert.assertEquals(""+min_cp+min_cp+min_cp, BaseCodec.encode(0, aspec, 3)); - Assert.assertEquals(max, BaseCodec.decode(""+max_cp+max_cp+max_cp, base, aspec)); - Assert.assertEquals(""+max_cp+max_cp+max_cp, BaseCodec.encode(max, base, aspec, 3)); - Assert.assertEquals(max_s, BaseCodec.decode(""+max_cp, base, aspec)); - Assert.assertEquals(""+min_cp+min_cp+max_cp, BaseCodec.encode(max_s, base, aspec, 3)); + Assert.assertEquals(max, BaseCodec.decode(""+max_cp+max_cp+max_cp, aspec)); + Assert.assertEquals(""+max_cp+max_cp+max_cp, BaseCodec.encode(max, aspec, 3)); + Assert.assertEquals(max_s, BaseCodec.decode(""+max_cp, aspec)); + Assert.assertEquals(""+min_cp+min_cp+max_cp, BaseCodec.encode(max_s, aspec, 3)); { - final int v0_d = (int)BaseCodec.decode(r1_max, base, aspec); - final String v1_s = BaseCodec.encode(base-1, base, aspec, 3); + final int v0_d = (int)BaseCodec.decode(r1_max, aspec); + final String v1_s = BaseCodec.encode(base-1, aspec, 3); // System.err.printf("r1_max '%s' ('%s'), base-1 %d (%d)\n", r1_max, v1_s, base-1, v0_d); Assert.assertEquals(r1_max, v1_s); Assert.assertEquals(base-1, v0_d); } { - final int v0_d = (int)BaseCodec.decode(r3_max, base, aspec); - final String v1_s = BaseCodec.encode(max, base, aspec, 3); + final int v0_d = (int)BaseCodec.decode(r3_max, aspec); + final String v1_s = BaseCodec.encode(max, aspec, 3); Assert.assertEquals(r3_max, v1_s); Assert.assertEquals(max, v0_d); } for(int iter=min; iter<=max; ++iter) { - final String rad = BaseCodec.encode(iter, base, aspec, 3); - final int dec = (int)BaseCodec.decode(rad, base, aspec); + final String rad = BaseCodec.encode(iter, aspec, 3); + final int dec = (int)BaseCodec.decode(rad, aspec); Assert.assertEquals(iter, dec); } if( natural86_alphabet.equals( aspec ) ) { // Test 0-9 .. System.err.printf("Natural 0-9: "); for(int iter=0; iter<=9; ++iter) { - final String rad = BaseCodec.encode(iter, base, aspec); + final String rad = BaseCodec.encode(iter, aspec); System.err.printf("%s, ", rad); final char c = (char)('0'+iter); Assert.assertEquals(""+c, rad); @@ -114,57 +114,56 @@ public class TestBaseCodec { } } - private static void testRadix_int64(final int base, final Alphabet aspec, final long test_min, final long test_max) { + private static void testRadix_int64(final Alphabet aspec, final long test_min, final long test_max) { final int int64_max_enc_width = 11; // 9223372036854775807 == '7__________' (base 64, natural) - + final int base = aspec.base(); Assert.assertTrue( 1 < base ); - Assert.assertTrue( base <= aspec.max_base() ); final char min_cp = aspec.charAt(0); // minimum code-point final char max_cp = aspec.charAt(base-1); // maximum code-point - final String max_radix = BaseCodec.encode(Long.MAX_VALUE, base, aspec, int64_max_enc_width); + final String max_radix = BaseCodec.encode(Long.MAX_VALUE, aspec, int64_max_enc_width); - final long min = BaseCodec.decode(""+min_cp, base, aspec); - final long max = BaseCodec.decode(max_radix, base, aspec); - final long max_s = BaseCodec.decode(""+max_cp, base, aspec); + final long min = BaseCodec.decode(""+min_cp, aspec); + final long max = BaseCodec.decode(max_radix, aspec); + final long max_s = BaseCodec.decode(""+max_cp, aspec); Assert.assertEquals(0, min); Assert.assertEquals(base-1, max_s); Assert.assertEquals(Long.MAX_VALUE, max); - final String r1_min = BaseCodec.encode(0, base, aspec, int64_max_enc_width); - final String r1_min_s = BaseCodec.encode(0, base, aspec); + final String r1_min = BaseCodec.encode(0, aspec, int64_max_enc_width); + final String r1_min_s = BaseCodec.encode(0, aspec); Assert.assertEquals(""+min_cp+min_cp+min_cp+min_cp+min_cp+min_cp+min_cp+min_cp+min_cp+min_cp+min_cp, r1_min); Assert.assertEquals(""+min_cp, r1_min_s); - final String r1_max = BaseCodec.encode(base-1, base, aspec, int64_max_enc_width); - final String r1_max_s = BaseCodec.encode(base-1, base, aspec); + final String r1_max = BaseCodec.encode(base-1, aspec, int64_max_enc_width); + final String r1_max_s = BaseCodec.encode(base-1, aspec); Assert.assertEquals(""+min_cp+min_cp+min_cp+min_cp+min_cp+min_cp+min_cp+min_cp+min_cp+min_cp+max_cp, r1_max); Assert.assertEquals(""+max_cp, r1_max_s); System.err.printf("Test base %d, %s: [%d .. %d] <-> ['%s' .. '%s'], %d years (max/365d)\n", base, aspec, min, max, - BaseCodec.encode(min, base, aspec), - BaseCodec.encode(max, base, aspec), (max/365)); + BaseCodec.encode(min, aspec), + BaseCodec.encode(max, aspec), (max/365)); System.err.printf("- range: [%d .. %d] <-> ['%s' .. '%s']\n", test_min, test_max, - BaseCodec.encode(test_min, base, aspec), BaseCodec.encode(test_max, base, aspec)); + BaseCodec.encode(test_min, aspec), BaseCodec.encode(test_max, aspec)); - Assert.assertEquals(0, BaseCodec.decode(""+min_cp+min_cp+min_cp, base, aspec)); - Assert.assertEquals(""+min_cp, BaseCodec.encode(0, base, aspec)); + Assert.assertEquals(0, BaseCodec.decode(""+min_cp+min_cp+min_cp, aspec)); + Assert.assertEquals(""+min_cp, BaseCodec.encode(0, aspec)); { - final long v0_d = BaseCodec.decode(r1_max, base, aspec); - final String v1_s = BaseCodec.encode(base-1, base, aspec, int64_max_enc_width); + final long v0_d = BaseCodec.decode(r1_max, aspec); + final String v1_s = BaseCodec.encode(base-1, aspec, int64_max_enc_width); Assert.assertEquals(r1_max, v1_s); Assert.assertEquals(base-1, v0_d); } for(long iter=Math.max(0L, test_min-1); iter<test_max; ) { ++iter; - final String rad = BaseCodec.encode(iter, base, aspec, int64_max_enc_width); - final long dec = BaseCodec.decode(rad, base, aspec); + final String rad = BaseCodec.encode(iter, aspec, int64_max_enc_width); + final long dec = BaseCodec.decode(rad, aspec); if( false ) { System.err.printf("test base %d: iter %d, rad '%s', dec %d\n", base, iter, rad, dec); } @@ -173,32 +172,29 @@ public class TestBaseCodec { } private static void testIntegerBase64(final Alphabet alphabet) { - testRadix_3digits_int32(64, alphabet); - testRadix_int64(64, alphabet, 0x7fffff00L, 0x80000100L); - testRadix_int64(64, alphabet, 0xFFFFFFF0L, 0x100000010L); - testRadix_int64(64, alphabet, 0x7FFFFFFFFFFFFFF0L, 0x7FFFFFFFFFFFFFFFL); + testRadix_3digits_int32(alphabet); + testRadix_int64(alphabet, 0x7fffff00L, 0x80000100L); + testRadix_int64(alphabet, 0xFFFFFFF0L, 0x100000010L); + testRadix_int64(alphabet, 0x7FFFFFFFFFFFFFF0L, 0x7FFFFFFFFFFFFFFFL); } private static void testIntegerBase86(final Alphabet alphabet) { - testRadix_3digits_int32(86, alphabet); - testRadix_int64(86, alphabet, 0x7fffff00L, 0x80000100L); - testRadix_int64(86, alphabet, 0xFFFFFFF0L, 0x100000010L); - testRadix_int64(86, alphabet, 0x7FFFFFFFFFFFFFF0L, 0x7FFFFFFFFFFFFFFFL); + testRadix_3digits_int32(alphabet); + testRadix_int64(alphabet, 0x7fffff00L, 0x80000100L); + testRadix_int64(alphabet, 0xFFFFFFF0L, 0x100000010L); + testRadix_int64(alphabet, 0x7FFFFFFFFFFFFFF0L, 0x7FFFFFFFFFFFFFFFL); } @Test public void test01IntegerBase38() { - testRadix_3digits_int32(38, new BaseCodec.Ascii38Alphabet()); - testRadix_3digits_int32(38, new BaseCodec.Ascii64Alphabet()); + testRadix_3digits_int32(new BaseCodec.Ascii38Alphabet()); } @Test public void test02IntegerBase64() { testIntegerBase64(new BaseCodec.Base64Alphabet()); testIntegerBase64(new BaseCodec.Base64urlAlphabet()); - testIntegerBase64(new BaseCodec.Natural86Alphabet()); testIntegerBase64(new BaseCodec.Ascii64Alphabet()); - testIntegerBase64(new BaseCodec.Ascii86Alphabet()); } @Test diff --git a/test/test_codec_base01.cpp b/test/test_codec_base01.cpp index e5f9f2b..e8c38fa 100644 --- a/test/test_codec_base01.cpp +++ b/test/test_codec_base01.cpp @@ -31,62 +31,62 @@ using namespace jau::int_literals; -static void testRadix_3digits_int32(const int base, const jau::codec::base::alphabet& aspec) { +static void testRadix_3digits_int32(const jau::codec::base::alphabet& aspec) { + const int base = aspec.base(); REQUIRE( 1 < base ); - REQUIRE( base <= aspec.max_base() ); const char min_cp = aspec[0]; // minimum code-point const char max_cp = aspec[base-1]; // maximum code-point - const int min = (int)jau::codec::base::decode(std::string()+min_cp, base, aspec); - const int max = (int)jau::codec::base::decode(std::string()+max_cp+max_cp+max_cp, base, aspec); - const int max_s = (int)jau::codec::base::decode(std::string()+max_cp, base, aspec); + const int min = (int)jau::codec::base::decode(std::string()+min_cp, aspec); + const int max = (int)jau::codec::base::decode(std::string()+max_cp+max_cp+max_cp, aspec); + const int max_s = (int)jau::codec::base::decode(std::string()+max_cp, aspec); const double machine_epsilon = std::numeric_limits<double>::epsilon(); REQUIRE(0 == min); REQUIRE(base-1 == max_s); REQUIRE( std::abs( std::pow(base, 3)-1 - max ) <= machine_epsilon ); - const std::string r1_min = jau::codec::base::encode(0, base, aspec, 3); - const std::string r1_min_s = jau::codec::base::encode(0, base, aspec); + const std::string r1_min = jau::codec::base::encode(0, aspec, 3); + const std::string r1_min_s = jau::codec::base::encode(0, aspec); REQUIRE(std::string()+min_cp+min_cp+min_cp == r1_min); REQUIRE(std::string()+min_cp == r1_min_s); - const std::string r1_max = jau::codec::base::encode(base-1, base, aspec, 3); - const std::string r1_max_s = jau::codec::base::encode(base-1, base, aspec); + const std::string r1_max = jau::codec::base::encode(base-1, aspec, 3); + const std::string r1_max_s = jau::codec::base::encode(base-1, aspec); REQUIRE(std::string()+min_cp+min_cp+max_cp == r1_max); REQUIRE(std::string()+max_cp == r1_max_s); - const std::string r3_max = jau::codec::base::encode((int)std::pow(base, 3)-1, base, aspec, 3); + const std::string r3_max = jau::codec::base::encode((int)std::pow(base, 3)-1, aspec, 3); REQUIRE(std::string()+max_cp+max_cp+max_cp == r3_max); fprintf(stderr, "Test32Bit base %d, %s: [%d .. %d] <-> ['%s' .. '%s'], %d years (max/365d) \n", - base, aspec.to_string().c_str(), min, max, jau::codec::base::encode(min, base, aspec).c_str(), jau::codec::base::encode(max, base, aspec).c_str(), (max/365)); + base, aspec.to_string().c_str(), min, max, jau::codec::base::encode(min, aspec).c_str(), jau::codec::base::encode(max, aspec).c_str(), (max/365)); - REQUIRE(0 == jau::codec::base::decode(std::string()+min_cp+min_cp+min_cp, base, aspec)); - REQUIRE(std::string()+min_cp == jau::codec::base::encode(0, base, aspec)); - REQUIRE(std::string()+min_cp+min_cp+min_cp == jau::codec::base::encode(0, base, aspec, 3)); + REQUIRE(0 == jau::codec::base::decode(std::string()+min_cp+min_cp+min_cp, aspec)); + REQUIRE(std::string()+min_cp == jau::codec::base::encode(0, aspec)); + REQUIRE(std::string()+min_cp+min_cp+min_cp == jau::codec::base::encode(0, aspec, 3)); - REQUIRE(max == jau::codec::base::decode(std::string()+max_cp+max_cp+max_cp, base, aspec)); - REQUIRE(std::string()+max_cp+max_cp+max_cp == jau::codec::base::encode(max, base, aspec, 3)); - REQUIRE(max_s == jau::codec::base::decode(std::string()+max_cp, base, aspec)); - REQUIRE(std::string()+min_cp+min_cp+max_cp == jau::codec::base::encode(max_s, base, aspec, 3)); + REQUIRE(max == jau::codec::base::decode(std::string()+max_cp+max_cp+max_cp, aspec)); + REQUIRE(std::string()+max_cp+max_cp+max_cp == jau::codec::base::encode(max, aspec, 3)); + REQUIRE(max_s == jau::codec::base::decode(std::string()+max_cp, aspec)); + REQUIRE(std::string()+min_cp+min_cp+max_cp == jau::codec::base::encode(max_s, aspec, 3)); { - const int v0_d = jau::codec::base::decode(r1_max, base, aspec); - const std::string v1_s = jau::codec::base::encode(base-1, base, aspec, 3); + const int v0_d = jau::codec::base::decode(r1_max, aspec); + const std::string v1_s = jau::codec::base::encode(base-1, aspec, 3); REQUIRE(r1_max == v1_s); REQUIRE(base-1 == v0_d); } { - const int v0_d = jau::codec::base::decode(r3_max, base, aspec); - const std::string v1_s = jau::codec::base::encode(max, base, aspec, 3); + const int v0_d = jau::codec::base::decode(r3_max, aspec); + const std::string v1_s = jau::codec::base::encode(max, aspec, 3); REQUIRE(r3_max == v1_s); REQUIRE(max == v0_d); } for(int iter=min; iter<=max; ++iter) { - const std::string rad = jau::codec::base::encode(iter, base, aspec, 3); - const int dec = jau::codec::base::decode(rad, base, aspec); + const std::string rad = jau::codec::base::encode(iter, aspec, 3); + const int dec = jau::codec::base::decode(rad, aspec); #if 0 fprintf(stderr, "test base %d: iter %d, rad '%s' %03d %03d %03d, dec %d\n", base, iter, rad.c_str(), (int)(0xFF & rad[0]), (int)(0xFF & rad[1]), (int)(0xFF & rad[2]), dec); @@ -98,7 +98,7 @@ static void testRadix_3digits_int32(const int base, const jau::codec::base::alph // Test 0-9 .. fprintf(stderr, "Natural 0-9: "); for(int iter=0; iter<=9; ++iter) { - const std::string rad = jau::codec::base::encode(iter, base, aspec); + const std::string rad = jau::codec::base::encode(iter, aspec); fprintf(stderr, "%s, ", rad.c_str()); const char c = (char)('0'+iter); REQUIRE(std::string()+c == rad); @@ -107,32 +107,31 @@ static void testRadix_3digits_int32(const int base, const jau::codec::base::alph } } -static void testRadix_int64(const int base, const jau::codec::base::alphabet& aspec, const int64_t test_min, const int64_t test_max) { +static void testRadix_int64(const jau::codec::base::alphabet& aspec, const int64_t test_min, const int64_t test_max) { const int int64_max_enc_width = 11; // 9223372036854775807 == '7__________' (base 64, natural) - + const int base = aspec.base(); REQUIRE( 1 < base ); - REQUIRE( base <= aspec.max_base() ); const char min_cp = aspec[0]; // minimum code-point const char max_cp = aspec[base-1]; // maximum code-point - const std::string max_radix = jau::codec::base::encode(std::numeric_limits<int64_t>::max(), base, aspec, int64_max_enc_width); + const std::string max_radix = jau::codec::base::encode(std::numeric_limits<int64_t>::max(), aspec, int64_max_enc_width); - const int64_t min = jau::codec::base::decode(std::string()+min_cp, base, aspec); - const int64_t max = jau::codec::base::decode(max_radix, base, aspec); - const int64_t max_s = jau::codec::base::decode(std::string()+max_cp, base, aspec); + const int64_t min = jau::codec::base::decode(std::string()+min_cp, aspec); + const int64_t max = jau::codec::base::decode(max_radix, aspec); + const int64_t max_s = jau::codec::base::decode(std::string()+max_cp, aspec); REQUIRE(0 == min); REQUIRE(base-1 == max_s); REQUIRE(std::numeric_limits<int64_t>::max() == max); - const std::string r1_min = jau::codec::base::encode(0, base, aspec, int64_max_enc_width); - const std::string r1_min_s = jau::codec::base::encode(0, base, aspec); + const std::string r1_min = jau::codec::base::encode(0, aspec, int64_max_enc_width); + const std::string r1_min_s = jau::codec::base::encode(0, aspec); REQUIRE(std::string()+min_cp+min_cp+min_cp+min_cp+min_cp+min_cp+min_cp+min_cp+min_cp+min_cp+min_cp == r1_min); REQUIRE(std::string()+min_cp == r1_min_s); - const std::string r1_max = jau::codec::base::encode(base-1, base, aspec, int64_max_enc_width); - const std::string r1_max_s = jau::codec::base::encode(base-1, base, aspec); + const std::string r1_max = jau::codec::base::encode(base-1, aspec, int64_max_enc_width); + const std::string r1_max_s = jau::codec::base::encode(base-1, aspec); REQUIRE(std::string()+min_cp+min_cp+min_cp+min_cp+min_cp+min_cp+min_cp+min_cp+min_cp+min_cp+max_cp == r1_max); REQUIRE(std::string()+max_cp == r1_max_s); @@ -142,24 +141,24 @@ static void testRadix_int64(const int base, const jau::codec::base::alphabet& as fprintf(stderr, "Test64bit base %d, %s: [%" PRIi64 " .. %" PRIi64 "] <-> ['%s' .. '%s'], %" PRIi64 " years (max/365d) \n", base, aspec.to_string().c_str(), - min, max, jau::codec::base::encode(min, base, aspec).c_str(), jau::codec::base::encode(max, base, aspec).c_str(), (max/365)); + min, max, jau::codec::base::encode(min, aspec).c_str(), jau::codec::base::encode(max, aspec).c_str(), (max/365)); fprintf(stderr, "- range: [%" PRIi64 " .. %" PRIi64 "] <-> ['%s' .. '%s']\n", - test_min, test_max, jau::codec::base::encode(test_min, base, aspec).c_str(), jau::codec::base::encode(test_max, base, aspec).c_str()); + test_min, test_max, jau::codec::base::encode(test_min, aspec).c_str(), jau::codec::base::encode(test_max, aspec).c_str()); - REQUIRE(0 == jau::codec::base::decode(std::string()+min_cp+min_cp+min_cp, base, aspec)); - REQUIRE(std::string()+min_cp == jau::codec::base::encode(0, base, aspec)); + REQUIRE(0 == jau::codec::base::decode(std::string()+min_cp+min_cp+min_cp, aspec)); + REQUIRE(std::string()+min_cp == jau::codec::base::encode(0, aspec)); { - const int64_t v0_d = jau::codec::base::decode(r1_max, base, aspec); - const std::string v1_s = jau::codec::base::encode(base-1, base, aspec, int64_max_enc_width); + const int64_t v0_d = jau::codec::base::decode(r1_max, aspec); + const std::string v1_s = jau::codec::base::encode(base-1, aspec, int64_max_enc_width); REQUIRE(r1_max == v1_s); REQUIRE(base-1 == v0_d); } for(int64_t iter=std::max(0_i64, test_min-1); iter<test_max; ) { ++iter; - const std::string rad = jau::codec::base::encode(iter, base, aspec, int64_max_enc_width); - const int64_t dec = jau::codec::base::decode(rad, base, aspec); + const std::string rad = jau::codec::base::encode(iter, aspec, int64_max_enc_width); + const int64_t dec = jau::codec::base::decode(rad, aspec); #if 0 fprintf(stderr, "test base %d: iter %" PRIi64 ", rad '%s', dec %" PRIi64 "\n", base, iter, rad.c_str(), dec); #endif @@ -168,32 +167,29 @@ static void testRadix_int64(const int base, const jau::codec::base::alphabet& as } static void testIntegerBase64(const jau::codec::base::alphabet& aspec) { - testRadix_3digits_int32(64, aspec); - testRadix_int64(64, aspec, 0x7fffff00_i64, 0x80000100_i64); - testRadix_int64(64, aspec, 0xFFFFFFF0_i64, 0x100000010_i64); - testRadix_int64(64, aspec, 0x7FFFFFFFFFFFFFF0_i64, 0x7FFFFFFFFFFFFFFF_i64); - // testRadix_int64(64, aspec, 0x0_i64, 0x7FFFFFFFFFFFFFFF_i64); + testRadix_3digits_int32(aspec); + testRadix_int64(aspec, 0x7fffff00_i64, 0x80000100_i64); + testRadix_int64(aspec, 0xFFFFFFF0_i64, 0x100000010_i64); + testRadix_int64(aspec, 0x7FFFFFFFFFFFFFF0_i64, 0x7FFFFFFFFFFFFFFF_i64); + // testRadix_int64(aspec, 0x0_i64, 0x7FFFFFFFFFFFFFFF_i64); } static void testIntegerBase86(const jau::codec::base::alphabet& aspec) { - testRadix_3digits_int32(86, aspec); - testRadix_int64(86, aspec, 0x7fffff00_i64, 0x80000100_i64); - testRadix_int64(86, aspec, 0xFFFFFFF0_i64, 0x100000010_i64); - testRadix_int64(86, aspec, 0x7FFFFFFFFFFFFFF0_i64, 0x7FFFFFFFFFFFFFFF_i64); - // testRadix_int64(86, aspec, 0x0_i64, 0x7FFFFFFFFFFFFFFF_i64); + testRadix_3digits_int32(aspec); + testRadix_int64(aspec, 0x7fffff00_i64, 0x80000100_i64); + testRadix_int64(aspec, 0xFFFFFFF0_i64, 0x100000010_i64); + testRadix_int64(aspec, 0x7FFFFFFFFFFFFFF0_i64, 0x7FFFFFFFFFFFFFFF_i64); + // testRadix_int64(aspec, 0x0_i64, 0x7FFFFFFFFFFFFFFF_i64); } TEST_CASE( "Integer Base 38 Encoding Test 01", "[integer][type]" ) { - testRadix_3digits_int32(38, jau::codec::base::ascii38_alphabet()); - testRadix_3digits_int32(38, jau::codec::base::ascii64_alphabet()); + testRadix_3digits_int32(jau::codec::base::ascii38_alphabet()); } TEST_CASE( "Integer Base 64 Encoding Test 02", "[integer][type]" ) { testIntegerBase64(jau::codec::base::base64_alphabet()); testIntegerBase64(jau::codec::base::base64url_alphabet()); - testIntegerBase64(jau::codec::base::natural86_alphabet()); testIntegerBase64(jau::codec::base::ascii64_alphabet()); - testIntegerBase64(jau::codec::base::ascii86_alphabet()); } TEST_CASE( "Integer Base 86 Encoding Test 03", "[integer][type]" ) { |