- Source:
Methods
toBaseX(value, baseOrAlphabetopt, useCharacterMapopt, nullable, useChunksopt, nullable, chunkSizeopt, nullable) → {String}
This function converts a value to a representation in a defined base between 2 and 64. So this covers common use cases like binary, octal, hexadecimal, alphabetical, alphanumeric and of course base64.
The result of this function is always either a decimal number or a string, just as the input value. All numbers apart from decimal ones are returned as strings without prefix. So, decimal 5 will be the number 5, but the binary version will be the string "101". Positive and negative decimal integers are valid numbers here, but this implementation does not support floats (multiply and divide if needed). Only numerical bases above 36 contain lower case characters, so decimal 255 is "FF" in base 16 and not "ff".
This function is unicode safe, by using byte conversion
(see: https://developer.mozilla.org/en-US/docs/Glossary/Base64#the_unicode_problem).
Be aware, that this also means, that results of btoa/atob()
and toBaseX/fromBaseX()
are not interchangeable,
since they work with different values internally.
There are three approaches to changing the base of a value in JavaScript:
-
Either you are taking the numerical/mathematical road, treating a value as a number in its alphabet being interpreted as a number, where each character, counting from the back is the base to the power of the character index. This is the approach you'd expect, when, for instance, you'd want to convert the decimal number 5 to binary 101. The downside of this approach is, that the relatively small max safe integer in JavaScript makes converting large numbers, such as longer strings, impossible.
-
Therefore, the second approach takes the numeric approach, but combines it with chunking, splitting the value into pieces, which are, by themselves, safely convertible. The downside is, that we need an extra character to delimit chunks in the result, since values have non-uniform lengths. This means, that this does not work with the basic binary base, and we need at least 3 alphabet characters.
-
The last approach uses the native base64 string encoding with
btoa()
as a safe translation layer, mapping the resulting string to the target base, using a generated (and possibly paged) character map. This way treats all values as strings and is not compatible to numerical conversion anymore, but uses the same characters. The result of this approach can encode every string of every length without structural tricks, but has the longest results.
This function is capable of all three approaches, which are equally safe for unicode values. The numerical
approach is the default. If you want to encode large numbers or strings longer than ~6 characters, select
a different approach using the useCharacterMap
or useChunks
parameters. Character mapping has preference, while
chunks have no effect in character mapping.
Each encoding process ends with a self-test, checking if the result is actually decodable using
fromBaseX()
, using the same settings again. This ensures, that every result is valid and retrievable in the future,
preventing any undiscovered errors, which would make it impossible to work with the original value again.
You may define the base as an integer between 2 and 64 or as a custom alphabet in the same range. Integer based alphabets are generated using defined base alphabets, which are sliced if necessary. Custom alphabets are automatically sorted to match base64 are far as possible, pushing additional characters to the end, which are then sorted ascending by character value.
"{" and "}" are the only forbidden characters in a custom alphabet, since we need these to mark number values in
fromBaseX()
.
Numerical conversion keeps negative numbers negative and marks the result with a preceding "-".
Hint: if you want to genrate codes to be presented to the user, see Random:randomUserCode
.
Parameters:
Name | Type | Attributes | Default | Description |
---|---|---|---|---|
value |
Number | String | value to be encoded |
||
baseOrAlphabet |
Number | String | Array.<String> |
<optional> |
64 | either the numerical base to convert to (64, 36, ...) or the alphabet of characters to use in encoding; numerical bases must be between 2 and 64 (if the result is chunked, we need a base 3) |
useCharacterMap |
Boolean |
<optional> <nullable> |
true | set to true, to use a character map, based on btoa(), instead of numerical conversion |
useChunks |
Boolean |
<optional> <nullable> |
false | set to true, to add chunking to the numerical approach, converting the value in groups separated by a delimiter, which is the first letter of the base's alphabet |
chunkSize |
Number |
<optional> <nullable> |
6 | define a different chunks size; only change this, if 6 seems too big in your context, going higher is not advisable |
- Source:
- See:
Throws:
-
error if baseOrAlphabet is not usable
-
error if result is not decodable again using the same settings
Returns:
- Type
- String
Example
toBaseX('foobar')
=> 'Zm9vYmFy'
toBaseX(-5, 2)
=> '-101'
toBaseX(42, 'abcdefghij')
=> 'ec'
toBaseX('too-long-for-number-conversion', 36, true)
=> 'U70R0DCN0F0DS04T0BQ040R0GCN0N0JSNA03TZ0J01S0K0N0KQOA0HRN0R0C'
toBaseX('too-long-for-number-conversion', 16, false, true)
=> 'D3EF5D81F026D9DFDA970BBF17222402A47D5AD650CF6C2FE2102A494BCBDD0A2864C'