aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSven Gothel <[email protected]>2022-09-07 09:15:15 +0200
committerSven Gothel <[email protected]>2022-09-07 09:15:15 +0200
commit78e2ed807fdc351cd87d44fb4f2ad7c4b534ce8d (patch)
treeee6e063540814b7313b2c629a8702231c92e7d96
parentc767d10a5e0550bc164c045ac3e1bd9317decb1f (diff)
jau::codec::base: API use a fixed alphabet::base() and drop extra alphabet::code_point() validation for safety and performance.v0.15.0
As hinted in commit c767d10a5e0550bc164c045ac3e1bd9317decb1f, the design of using a variable base up to alphabet::max_base() introduced unwarranted complexity and extra validation. This API change uses a fixed base per alphabet, hence alphabet::code_point() definetely returns the result w/o further bounds checking against a lower base. The [encode/decode]64() hence required base==64. Besides safety, this reduction also speeds up the decoding a little.
-rw-r--r--include/jau/base_codec.hpp103
-rw-r--r--java_base/org/jau/util/BaseCodec.java143
-rw-r--r--src/base_codec.cpp27
-rw-r--r--src/file_util.cpp2
-rw-r--r--test/java/jau/test/util/TestBaseCodec.java112
-rw-r--r--test/test_codec_base01.cpp112
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]" ) {