On Wed, 5 Nov 2025 16:13:45 +0200 Andy Shevchenko <[email protected]> wrote:
> On Wed, Nov 05, 2025 at 09:48:27AM +0000, David Laight wrote: > > On Tue, 4 Nov 2025 11:48:57 +0200 > > Andy Shevchenko <[email protected]> wrote: > > > On Tue, Nov 04, 2025 at 09:03:26AM +0000, David Laight wrote: > > > > On Mon, 3 Nov 2025 19:07:24 +0800 > > > > Kuan-Wei Chiu <[email protected]> wrote: > > > > > On Mon, Nov 03, 2025 at 11:24:35AM +0100, Andy Shevchenko wrote: > ... > > How about this one? > > Better than previous one(s) but quite cryptic to understand. Will need a > comment explaining the logic behind, if we go this way. My first version (of this version) had all three character ranges in the define: so: #define INIT_1(v, ch_62, ch_63) \ [ v ] = (v) >= '0' && (v) <= '9' ? (v) - '0' \ : (v) >= 'A' && (v) <= 'Z' ? (v) - 'A' + 10 \ : (v) >= 'a' && (v) <= 'z' ? (v) - 'a' + 36 \ : (v) == ch_62 ? 62 : (v) == ch_63 ? 63 : -1 Perhaps less cryptic - even if the .i line will be rather longer. It could be replicated for all 256 bytes, but I think the range initialisers are reasonable for the non-printable ranges. I did wonder if the encode and decode lookup tables count be interleaved and both initialisers generated from the same #define. But I can't think of a way of generating 'x' and "X" from a #define parameter. (I don't think "X"[0] is constant enough...) David > > > #define INIT_1(v, ch_lo, ch_hi, off, ch_62, ch_63) \ > > [ v ] = ((v) >= ch_lo && (v) <= ch_hi) ? (v) - ch_lo + off \ > > : (v) == ch_62 ? 62 : (v) == ch_63 ? 63 : -1 > > #define INIT_2(v, ...) INIT_1(v, __VA_ARGS__), INIT_1((v) + 1, __VA_ARGS__) > > #define INIT_4(v, ...) INIT_2(v, __VA_ARGS__), INIT_2((v) + 2, __VA_ARGS__) > > #define INIT_8(v, ...) INIT_4(v, __VA_ARGS__), INIT_4((v) + 4, __VA_ARGS__) > > #define INIT_16(v, ...) INIT_8(v, __VA_ARGS__), INIT_8((v) + 8, __VA_ARGS__) > > #define INIT_32(v, ...) INIT_16(v, __VA_ARGS__), INIT_16((v) + 16, > > __VA_ARGS__) > > > > #define BASE64_REV_INIT(ch_62, ch_63) { \ > > [ 0 ... 0x1f ] = -1, \ > > INIT_32(0x20, '0', '9', 0, ch_62, ch_63), \ > > INIT_32(0x40, 'A', 'Z', 10, ch_62, ch_63), \ > > INIT_32(0x60, 'a', 'z', 26, ch_62, ch_63), \ > > [ 0x80 ... 0xff ] = -1 } > > > > which gets the pre-processor to do all the work. > > ch_62 and ch_63 can be any printable characters. > > > > Note that the #define names are all in a .c file - so don't need any > > kind of namespace protection. > > > They can also all be #undef after the initialiser. > > Yes, that's too. > > > > Moreover this table is basically a dup of the strings in the first array. > > > Which already makes an unnecessary duplication. > > > > That is what the self tests are for. > > > > > That's why I prefer to > > > see a script (one source of data) to generate the header or something like > > > this to have the tables and strings robust against typos. > > > > We have to differ on that one. > > Especially in cases (like this) where generating that data is reasonably > > trivial. > > > > > The above is simply an unreadable mess. >
