|
Hi all!
Not so long ago I was looking for a solution to Base64 encoding/decoding. In this page - http://www.boost.org/doc/libs/1_46_1/libs/serialization/doc/dataflow.html - I found example of such solution, with 'base64_from_binary' and 'transform_width' iteartors. But it is just a "blank", not ready-to-use solution. I created solution. But I definitely know many developers looking for a simple, ready-to-use, header-only and 'real C++' solution for Base64. So I want to offer you such solution. Some examples: int main() { std::string my_text = "My text for encoding!"; std::string encoded_text = boost::base64().encode( my_text ); std::string my_text_again = boost::base64().decode< std::string >( encoded ); } For binary data: int main() { typedef std::vector< unsigned char > binary_string; binary_string my_bin = list_of( 0xFF )( 0xAA )( 0x01 ); std::string encoded_bin = boost::base64().encode( my_bin ); binary_string my_bin_again = boost::base64().decode< binary_string >( encoded ); } For streams: int main() { boost::filesystem::ifstream my_jpeg( "/some/path/to/my/image" ); // fstream checking omitted... std::string encoded_jpeg = boost::base64().encode( my_jpeg ); boost::filesystem::ofstream my_jpeg_again( "/some/path/to/decoded/image" ); // fstream checking omitted... boost::base64().decode( encoded_jpeg, my_jpeg_again ); } This is first variant. IMHO such solution will be useful for Boost users. What you think about it? - Denis _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost |
|
On Thu, Jun 9, 2011 at 8:43 PM, Denis Shevchenko
<[hidden email]> wrote: > This is first variant. IMHO such solution will be useful for Boost users. > > What you think about it? Looks fine! A base16 (hex) variant would be nice too. Olaf _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost |
|
In reply to this post by Denis Shevchenko
Denis Shevchenko wrote:
> > I definitely know many developers looking for a simple, > ready-to-use, header-only and 'real C++' solution for Base64. I'm not sure how much need there is for Base64.... > Some examples: > > int main() { > std::string my_text = "My text for encoding!"; > std::string encoded_text = boost::base64().encode( > my_text); > std::string my_text_again = > boost::base64().decode<std::string>(encoded); > } > > For binary data: > > int main() { > typedef std::vector< unsigned char > binary_string; > > binary_string my_bin = list_of( 0xFF )( 0xAA )( 0x01 ); > std::string encoded_bin = boost::base64().encode( > my_bin); > binary_string my_bin_again = > boost::base64().decode<binary_string>(encoded); > } > > For streams: > > int main() { > boost::filesystem::ifstream my_jpeg( > "/some/path/to/my/image"); > // fstream checking omitted... > > std::string encoded_jpeg = > boost::base64().encode(my_jpeg); > > boost::filesystem::ofstream my_jpeg_again( > "/some/path/to/decoded/image"); > // fstream checking omitted... > > boost::base64().decode(encoded_jpeg, my_jpeg_again); > } That interface is restrictive. Why not take iterators and ranges for input and output iterators for output. That would grant greater flexibility to source and destination: your code would be captured as algorithms. In the JPEG example, that could mean writing the encoded image straight to disk, instead of to an intermediate string, which would reduce memory pressure, for example. _____ Rob Stewart [hidden email] Software Engineer using std::disclaimer; Dev Tools & Components Susquehanna International Group, LLP http://www.sig.com IMPORTANT: The information contained in this email and/or its attachments is confidential. If you are not the intended recipient, please notify the sender immediately by reply and immediately delete this message and all its attachments. Any review, use, reproduction, disclosure or dissemination of this message or any attachment by an unintended recipient is strictly prohibited. Neither this message nor any attachment is intended as or should be construed as an offer, solicitation or recommendation to buy or sell any security or other financial instrument. Neither the sender, his or her employer nor any of their respective affiliates makes any warranties as to the completeness or accuracy of any of the information contained herein or that this message or any of its attachments is free of viruses. _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost |
|
In reply to this post by Olaf van der Spek-3
> Looks fine! A base16 (hex) variant would be nice too.
> > Olaf Thanks, Olaf! Yes, there are three such encodings: Base16, Base32 and Base64. But Base64, IMHO, is most often required. - Denis _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost |
|
In reply to this post by Stewart, Robert
> That interface is restrictive. Why not take iterators and ranges for
> input and output iterators for output. That would grant greater > flexibility to source and destination: your code would be captured as > algorithms. > > Rob Stewart [hidden email] Yes, Rob, iterators are more flexible, but this flexibility is not always necessary. For example, we can write: std::vector< int > v{ 1, 2, 3 }; auto it = std::find( v.begin(), v.end(), 2 ); But Boost.Range provides "less flexible" solution: std::vector< int > v{ 1, 2, 3 }; auto it = boost::range::find( v, 2 ); IMO, this solution is much easier and safer, but less flexible. - Denis _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost |
|
One of golden rules of Unix philosophy for libraries: "Do one thing, and
do it good". Base64 encoding/decoding is very common task, and, IMHO, Boost must have one simple solution for this common task. - Denis _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost |
|
In reply to this post by Denis Shevchenko
Denis Shevchenko wrote:
> Rob Stewart wrote: > > > That interface is restrictive. Why not take iterators and > > ranges for input and output iterators for output. That > > would grant greater flexibility to source and destination: > > your code would be captured as algorithms. > > Yes, Rob, iterators are more flexible, but this flexibility is > not always necessary. > > For example, we can write: > > std::vector< int > v{ 1, 2, 3 }; > auto it = std::find( v.begin(), v.end(), 2 ); > > But Boost.Range provides "less flexible" solution: > > std::vector< int > v{ 1, 2, 3 }; > auto it = boost::range::find( v, 2 ); > > IMO, this solution is much easier and safer, but less flexible. Since I suggested iterators and ranges as the interface, and your examples implied neither, I fail to understand how your answer actually bears on my suggestion. Does your interface support ranges without your having shown it? Is there output iterator support? _____ Rob Stewart [hidden email] Software Engineer using std::disclaimer; Dev Tools & Components Susquehanna International Group, LLP http://www.sig.com IMPORTANT: The information contained in this email and/or its attachments is confidential. If you are not the intended recipient, please notify the sender immediately by reply and immediately delete this message and all its attachments. Any review, use, reproduction, disclosure or dissemination of this message or any attachment by an unintended recipient is strictly prohibited. Neither this message nor any attachment is intended as or should be construed as an offer, solicitation or recommendation to buy or sell any security or other financial instrument. Neither the sender, his or her employer nor any of their respective affiliates makes any warranties as to the completeness or accuracy of any of the information contained herein or that this message or any of its attachments is free of viruses. _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost |
|
On Thu, Jun 9, 2011 at 9:21 PM, Stewart, Robert <[hidden email]> wrote:
>> std::vector< int > v{ 1, 2, 3 }; >> auto it = std::find( v.begin(), v.end(), 2 ); >> >> But Boost.Range provides "less flexible" solution: >> >> std::vector< int > v{ 1, 2, 3 }; >> auto it = boost::range::find( v, 2 ); >> >> IMO, this solution is much easier and safer, but less flexible. > > Since I suggested iterators and ranges as the interface, and your examples implied neither, I fail to understand how your answer actually bears on my suggestion. Â Does your interface support ranges without your having shown it? Â Is there output iterator support? I assume it's pretty easy to provide both APIs. Olaf _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost |
|
In reply to this post by Stewart, Robert
> Does your interface support ranges without your having shown it? Is
> there output iterator support? > > Rob Stewart [hidden email] Sorry, Rob, perhaps I misunderstood your question. In fact, now is the main question about fundamental interest to Boost-based base64 ready-to-use solution, but not about implementation details. Of course, details will be discussed. - Denis _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost |
|
In reply to this post by Stewart, Robert
We can extend this solution like this:
int main() { std::string my_text = "My text for encoding!"; std::string encoded_text; boost::base64().encode( my_text, std::back_inserter( encoded_text ) ); // Or like this: // boost::base64().encode( my_text, encoded_text ); // or: // boost::base64().encode( my_text.begin() // , my_text.end() // , encoded_text ); std::string my_text_again; boost::base64().decode( encoded_text, std::back_inserter( my_text_again ) ); // Or like this: // boost::base64().decode( encoded_text.begin() // , encoded_text.end() // , std::back_inserter( my_text_again ) ); } So developer can choose the interface he likes. All technical details, of course, will be discussed... - Denis _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost |
|
In reply to this post by Denis Shevchenko
Denis Shevchenko wrote:
> Hi all! > > Not so long ago I was looking for a solution to Base64 > encoding/decoding. > In this page - > http://www.boost.org/doc/libs/1_46_1/libs/serialization/doc/dataflow.html > - I found example of such solution, with 'base64_from_binary' and > 'transform_width' iteartors. But it is just a "blank", not > ready-to-use solution. Hmmm - I'm not sure what this means. It is used in serialization library so it's not just a "blank". Perhaps you're refering to the way it's implemented by building up from more primitive concepts using concepts now implemented are part of the range library. It predates the range library but it seems to me it's very similar. I find the way it's implemented very appealing. For example, if one wanted to change the line length, this would be easy to do without adding anything. The base64 implementation in the serialization library isn't really a library, but more of an instance of a huge family of text processing facilities. So I think a much more interesting and useful project would be: "an optimally fast, character range processing library which can be used construct a wide variety of character processing algorithms by composition of more primitive concepts in a regular way." Examples include base64, ... and generation of custom code_convert facets for io_streams.. Robert Ramey _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost |
|
In reply to this post by Denis Shevchenko
I'm assuming folks have looked at using:
> http://code.google.com/p/stringencoders/ Pretty simple API: > char buf[100]; > char result[10]; > char endian[] = {(char)0, (char)0, (char)1}; > int d = modp_b64_encode(buf, endian, 3); And very fast: > http://code.google.com/p/stringencoders/#Why With some neat, very platform specific tricks: > http://code.google.com/p/stringencoders/#How_It_Works Don't get me wrong, I'd definitely like to see Boost have something because that extreme of performance isn't always necessary, but FYI for those interested in the discussion. -sc -- Sean Chittenden [hidden email] _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost |
|
In reply to this post by Robert Ramey
> So I think a much more interesting and useful project would be:
> > "an optimally fast, character range processing library which can be used > construct a wide variety of character processing algorithms by > composition of more primitive concepts in a regular way." Examples > include base64, ... and generation of custom code_convert facets > for io_streams.. > > Robert Ramey I understand you, Robert. You're talking about flexible (and probably big) library, and I'm talking about the utility. But this utility solves one concrete common task, and do it (IMHO) good. This can be compared with boost::mem_fn or boost::lexical_cast - do one concrete task and do it well. My solution is a single .hpp file, and it can be part of... hmmm... Boost.Utility, for example, or even part of Boost.Serialization. - Denis _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost |
|
Denis Shevchenko wrote:
>> So I think a much more interesting and useful project would be: >> >> "an optimally fast, character range processing library which can be >> used construct a wide variety of character processing algorithms by >> composition of more primitive concepts in a regular way." Examples >> include base64, ... and generation of custom code_convert facets >> for io_streams.. >> >> Robert Ramey > > I understand you, Robert. You're talking about flexible (and probably > big) library, and I'm talking about the utility. But this utility > solves one concrete common task, and do it (IMHO) good. This can be > compared with boost::mem_fn or boost::lexical_cast - do one concrete > task and do it well. > My solution is a single .hpp file, and it can be part of... hmmm... > Boost.Utility, for example, or even part of Boost.Serialization. > > - Denis > _______________________________________________ > Unsubscribe & other changes: > http://lists.boost.org/mailman/listinfo.cgi/boost _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost |
|
In reply to this post by Denis Shevchenko
On 09/06/2011 20:43, Denis Shevchenko wrote:
> Hi all! > > Not so long ago I was looking for a solution to Base64 encoding/decoding. > > In this page - > http://www.boost.org/doc/libs/1_46_1/libs/serialization/doc/dataflow.html - > I found example of such solution, with 'base64_from_binary' and > 'transform_width' iteartors. But it is just a "blank", not ready-to-use > solution. > > I created solution. But I definitely know many developers looking for a > simple, ready-to-use, header-only and 'real C++' solution for Base64. So > I want to offer you such solution. I also have one solution for base64. The code is short and trivial, it can be used with arbitrary input and output iterators or ranges, and can also be used to generate a range that computes base64 lazily as it is being iterated. _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost |
|
In reply to this post by Denis Shevchenko
On 09/06/2011 21:04, Denis Shevchenko wrote:
>> That interface is restrictive. Why not take iterators and ranges for >> input and output iterators for output. That would grant greater >> flexibility to source and destination: your code would be captured as >> algorithms. >> >> Rob Stewart [hidden email] > > Yes, Rob, iterators are more flexible, but this flexibility is not > always necessary. > > For example, we can write: > > std::vector< int > v{ 1, 2, 3 }; > auto it = std::find( v.begin(), v.end(), 2 ); > > But Boost.Range provides "less flexible" solution: > > std::vector< int > v{ 1, 2, 3 }; > auto it = boost::range::find( v, 2 ); > > IMO, this solution is much easier and safer, but less flexible. Exactly where is flexibility lost? _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost |
|
In reply to this post by Denis Shevchenko
Denis Shevchenko wrote:
>> So I think a much more interesting and useful project would be: >> >> "an optimally fast, character range processing library which can be >> used construct a wide variety of character processing algorithms by >> composition of more primitive concepts in a regular way." Examples >> include base64, ... and generation of custom code_convert facets >> for io_streams.. >> >> Robert Ramey > > I understand you, Robert. You're talking about flexible (and probably > big) library, and I'm talking about the utility. But this utility > solves one concrete common task, and do it (IMHO) good. This can be > compared with boost::mem_fn or boost::lexical_cast - do one concrete > task and do it well. > My solution is a single .hpp file, and it can be part of... hmmm... > Boost.Utility, for example, or even part of Boost.Serialization. >> Does your interface support ranges without your having shown it? Is >> there output iterator support? >> >> Rob Stewart [hidden email] > > Sorry, Rob, perhaps I misunderstood your question. > > In fact, now is the main question about fundamental interest to > Boost-based base64 ready-to-use solution, but not about implementation > details. Of course, details will be discussed. I think you'd find it interesting to see how the serialization library does it. ../boost/archive/iterators/base64_from_binary ../boost/archive/iterators/binary_from_base64 These provide a pair of iterators which can be used with any algorithm which take a pair of iterators - ie most of of the standard ones. It's much more than an implementation detail - it's a whole different way of looking at the problem. It works with all of lot's of overstuff. Of course there's nothing that prevents one from creating a wrapper which provides a more convenient interface for many situations. So I would encourage you to think bigger: a) take a look at dataflow iterators in the boost serializaiton library b) take a look at range iterators. (this uses similar technique but is much more general). c) craft a more general - text processing toolkit which includes as examples a convenient wrapper for base64 conversion, also I would like to see it include examples for implementing code_cvt facets. Robert Ramey _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost |
|
In reply to this post by Denis Shevchenko
2011/6/10 Robert Ramey <[hidden email]>
> I think you'd find it interesting to see how the serialization library does > it. > ../boost/archive/iterators/base64_from_binary > ../boost/archive/iterators/binary_from_base64 Yes, Robert. :-) I took theese iterators (and 'transform_width') and wrap them in one simple and ready-to-use solution. Simple and ready-to-use even for novices. I need a such solution, for this common task. And I definetly know many developers looking for such solution. Solution they can use immediately, without long studying the documentation. Just few lines of code: int main() { std::string text = "TEXT"; std::string encoded = boost::base64().encode( text ); std::string text_again = boost::base64().decode< std::string >( encoded ); } You think such (or similar) solution is not needed for Boost? Well, probably it is not needed, but I think it's useful. If not - I apologize for troubling. - Denis _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost |
|
2011/6/10 Robert Ramey <[hidden email]>
> I think you'd find it interesting to see how the serialization library does > it. > ../boost/archive/iterators/base64_from_binary > ../boost/archive/iterators/binary_from_base64 Yes, Robert. :-) I took theese iterators (and 'transform_width') and wrap them in one simple and ready-to-use solution. Simple and ready-to-use even for novices. I need a such solution, for this common task. And I definetly know many developers looking for such solution. Solution they can use immediately, without long studying the documentation. Just few lines of code: int main() { std::string text = "TEXT"; std::string encoded = boost::base64().encode( text ); std::string text_again = boost::base64().decode< std::string >( encoded ); } You think such (or similar) solution is not needed for Boost? Well, probably it is not needed, but I think it's useful. If not - I apologize for troubling. - Denis _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost |
|
In reply to this post by Denis Shevchenko
Denis Shevchenko wrote:
> 2011/6/10 Robert Ramey <[hidden email]> > >> I think you'd find it interesting to see how the serialization >> library > does >> it. > >> ../boost/archive/iterators/base64_from_binary >> ../boost/archive/iterators/binary_from_base64 > > Yes, Robert. :-) > > I took theese iterators (and 'transform_width') and wrap them in one > simple and ready-to-use solution. Simple and ready-to-use even for > novices. > > I need a such solution, for this common task. And I definetly know > many developers looking for such solution. Solution they can use > immediately, without long studying the documentation. Just few lines > of code: > > int main() { > std::string text = "TEXT"; > std::string encoded = boost::base64().encode( text ); > std::string text_again = boost::base64().decode< std::string >( > encoded ); > } > > You think such (or similar) solution is not needed for Boost? Well, > probably it is not needed, but I think it's useful. If not - I > apologize for troubling. Hmmm - so you are proposing that something like the following header be added to boost? #include <string> #include <list> #include <boost/archive/iterators/binary_from_base64.hpp> #include <boost/archive/iterators/base64_from_binary.hpp> #include <boost/archive/iterators/insert_linebreaks.hpp> #include <boost/archive/iterators/remove_whitespace.hpp> #include <boost/archive/iterators/transform_width.hpp> namespace boost{ namespace base64{ // convert to base64 template<typename CharType> std::string encode(std::basic_string<CharType> & s){ CharType *raw_data = s.c_str(); std::size_t size = s.size(); typedef std::list<CharType> text_base64_type; text_base64_type text_base64; typedef boost::archive::iterators::insert_linebreaks< boost::archive::iterators::base64_from_binary< boost::archive::iterators::transform_width< CharType * ,6 ,sizeof(CharType) * 8 > > ,72 > translate_out; std::copy( translate_out(static_cast<CharType *>(rawdata)), translate_out(rawdata + size), std::back_inserter(text_base64) ); } std::string decode(std::string & s){ ... } Which I don't really see as a bad idea in and of itself. But I wonder about other aspects? a) where in the directory/namespace would this be? boost, boost/utility, or? b) would it include all the boost machinery besides code? documentation, formal review tests etc? c) All this for one small special purpose function? d) How is a user going to find this pair of functions in the boost libraries. e) As soon as someone puts this in, imediately some else will ask - great but it needs a parameter to so I can change the line width. Then someone asks for someother tweak. This is the result of making a "simple solution". It's easy enough to make a simple solution - it's very hard to keep it simple. This is the reasoning behind my suggestion that for something like this one should be prepared to think bigger. In my view value of something like this (it DOES have value) isn't justified by the cost of getting it into boost. My advice - think bigger. I realize that the overhead of all this isn't your fault, but it still exists. I don't see boost as having the infrasture to handle an army of small (special purpose) functions such as this. Robert Ramey _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost |
| Powered by Nabble | Edit this page |
