// Unlike regular baseINV, and incompatible with it. Intended to encode stuff small enough that it might be human typed and human transmitted, therefore maps 'o' and 'O' to '0', 'I' and 'l' to '1'
// uses six url safe additional characters !$*+-_ to bring it up to six bits
static_assert(index2base64[63]=='_',"surprise numeral at 63");
// Being intended for small bits of data, assumes no whitespace within an entity
// Encode and decode are called with a bit buffer, consisting of an unsigned byte pointer, a starting bit position relative to the pointer, and a bit count. We assume that there is room enough in the object pointed to to accommodate the bytes referenced by Bit Position+BitCount. We don't change bits outside the range.
// The bit buffer does not need to be aligned, nor does it need to be a multiple of six bits, eight bits, or twenty four bits.
// If the input bit buffer to be encoded to base sixty four is not a multiple of six bits, the last base sixty four numeral output will represent the bit buffer padded with trailing zeroes.
// If there is no room in the output span for all the base sixty four digits, the encode routine will return a number of bits less than the size of the input bit buffer, less than the bitcount it was given.
0x2f,0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0xff,0xff,0xff,0xff,0xff,//a-z the characters {|} ~` are stops, as is the mysterious control character 0x7F (del)
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff// utf8 multibyte characters, all stops.
};
// Table to convert ascii to six bit as a good old fashioned non owning naked pointer to const, whose storage is owned by a const static which exists until the program terminates.
staticconstuint8_t*ascii2six{&ascii2six_ar[0]};
// Compile time execution is C++ is a pain, because expressions are apt to unpredictably lose their constexpr character for reasons that are far from clear.
// You really have to write compile time code in templates as a language, which is the totally obscure and hard to use language apt to generate remarkably voluminous error messages will little obvious connection to the actual problem, and surprising result that are very difficult to predict in advance or understand at all.
//In general, the better solution is to have a routine that is called once and only once at the beginning of the program, which initializes a bunch of static const values, if that solution is adequate, or to have a preproces routine written in python which generates the required C files and header files.
// After this experiment in compile time code, I swear off it.
// Decode does not have an input span of encoded characters, but a char *, because it assumes the string is always terminated by an invalid character, such as the trailing null at the end of string or a space, or any character that is not one of our base sixty four numerals
// If the there are not enough input base sixty four numerals, it returns a size less than requested.
// if the requested bit buffer is not a multiple of six bits, and the last base 64 numeral had trailing ones that would not fit in the buffer, rather than the expected trailing zeroes, then it returns a size larger than the buffer, as if it changed stuff outside the buffer but does not actually change bits outside the buffer. This is likely an error, because obviously we want to decode something from base sixty four that was originally decoded using the same sized buffer.
unsignedintcount{length-bitsInAccumulator};//count is bits lifted out of the buffer.
// We need to keep track of count, because the last byte lifted out of the buffer may well have to be an incomplete byte, so when count gets down to below 8, we have to special case loading the bitAccumulator.
// When we drop out of the for loop, we may have more than 0 bits left but less than six, in which case we then have to special case the last numeral by filling the bit accumulator with our zeropadding.
intcount{length-bitsInAccumulator};//count is bits remaining in buffer, may go negative
// We need to keep track of count, because the last byte lifted out of the buffer may well have to be an incomplete byte, so when count gets down to below 8, we have to special case loading the bitAccumulator.