[prev in list] [next in list] [prev in thread] [next in thread] 

List:       boost
Subject:    Re: [boost] A base64 library?
From:       Rainer Deyke via Boost <boost () lists ! boost ! org>
Date:       2024-03-22 11:11:55
Message-ID: utjp1t$fgi$1 () ciao ! gmane ! io
[Download RAW message or body]

On 21.03.24 14:43, René Ferdinand Rivera Morell via Boost wrote:
> On Thu, Mar 21, 2024 at 3:35 AM Rainer Deyke via Boost
> <boost@lists.boost.org> wrote:
>> This is not so good, because it mixes the options of different
>> encodings, resulting in potentially nonsensical combinations:
>>
>>     result = baseX_encode<64>(source, encoding_options::no_padding);
>>     result2 = baseX_encode<16>(source, encoding_options::lower_case);
>>
>>     // The lower_case option is non-sensical for base 64; can this
>>     // error be caught at compile time?
>>     // result3 = baseX_encode<64>(source, encoding_options::lower_case);
> 
> It can be caught at compile time. But not with that interface.

Actually it can be caught at compile time even with that interface, if 
encoding_options is a namespace instead of an enum type and 
encoding_options::lower_case has a distinct type from 
encoding_options::no_padding.  For example:

template<uint8_t> class encoding_option {};
constexpr encoding_option<0x01> lower_case;
constexpr encoding_option<0x02> no_padding;

template<uint8_t a, uint8_t b>
constexpr encoding_option<a | b> operator|(
     encoding_option<a>,
     encoding_option<b>) {
   return {};
}

However, I don't see any benefit whatsoever in having a single 
encoding-neutral template as the main entry point.  Specifying 64 as an 
integer is especially problematic because base-X as a generalization 
does not exist.  Rather, base-64 and base-16 are distinct members of the 
larger family of bindary-to-text encodings that also includes 
uuencoding, BinHex, and percent encoding.

> Yeah, as Adrey mentions, making this a runtime choice is sufficiently
> rare that it's not worth even thinking about it. I certainly never had
> a use for a runtime choice for that. As for a sane interface.. I would
> think having encoder/decoder templates (perhaps as functors) is the
> way to go. For example:
> 
> auto base64enc = boost::thing::base_encoder<64,
> boost::thing::encoding_options::no_padding>();
> auto encoded = base64enc.encode(data);
> auto decoded = base64enc.decode(encoded);
> 
> This makes it possible to pass the encoder object to generic code
> without worrying about calling some specific base64 or base16
> functions. Having the template args also makes it possible to check
> valid combinations. It also makes it easier to specialize performant
> combinations and still cover everything else with not-so-performant
> default implementation.

Having an encoder object makes sense.  Defining a reusable concept for 
this encoder object makes sense.  Defining a single class template for 
the encoder object does not make sense, because the set of encoder 
objects I might want to use is open.


-- 
Rainer Deyke (rainerd@eldwood.com)



_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic