From 3758c698b97fb528e708898d193b0f7dc9396839 Mon Sep 17 00:00:00 2001 From: Maarten de Vries Date: Sun, 7 May 2017 16:00:33 +0200 Subject: [PATCH 1/3] Replace base64.h with libb64. --- utilities/xmlrpcpp/CMakeLists.txt | 10 +- utilities/xmlrpcpp/include/xmlrpcpp/base64.h | 380 ------------------ utilities/xmlrpcpp/libb64/AUTHORS | 15 + utilities/xmlrpcpp/libb64/BENCHMARKS | 85 ++++ utilities/xmlrpcpp/libb64/CHANGELOG | 33 ++ utilities/xmlrpcpp/libb64/INSTALL | 44 ++ utilities/xmlrpcpp/libb64/LICENSE | 29 ++ utilities/xmlrpcpp/libb64/Makefile | 31 ++ utilities/xmlrpcpp/libb64/README | 143 +++++++ utilities/xmlrpcpp/libb64/TODO | 0 .../xmlrpcpp/libb64/include/b64/cdecode.h | 29 ++ .../xmlrpcpp/libb64/include/b64/cencode.h | 32 ++ .../xmlrpcpp/libb64/include/b64/decode.h | 72 ++++ .../xmlrpcpp/libb64/include/b64/encode.h | 79 ++++ utilities/xmlrpcpp/libb64/src/Makefile | 43 ++ utilities/xmlrpcpp/libb64/src/cdecode.c | 88 ++++ utilities/xmlrpcpp/libb64/src/cencode.c | 109 +++++ utilities/xmlrpcpp/src/XmlRpcValue.cpp | 73 ++-- 18 files changed, 890 insertions(+), 405 deletions(-) delete mode 100644 utilities/xmlrpcpp/include/xmlrpcpp/base64.h create mode 100644 utilities/xmlrpcpp/libb64/AUTHORS create mode 100644 utilities/xmlrpcpp/libb64/BENCHMARKS create mode 100644 utilities/xmlrpcpp/libb64/CHANGELOG create mode 100644 utilities/xmlrpcpp/libb64/INSTALL create mode 100644 utilities/xmlrpcpp/libb64/LICENSE create mode 100644 utilities/xmlrpcpp/libb64/Makefile create mode 100644 utilities/xmlrpcpp/libb64/README create mode 100644 utilities/xmlrpcpp/libb64/TODO create mode 100644 utilities/xmlrpcpp/libb64/include/b64/cdecode.h create mode 100644 utilities/xmlrpcpp/libb64/include/b64/cencode.h create mode 100644 utilities/xmlrpcpp/libb64/include/b64/decode.h create mode 100644 utilities/xmlrpcpp/libb64/include/b64/encode.h create mode 100644 utilities/xmlrpcpp/libb64/src/Makefile create mode 100644 utilities/xmlrpcpp/libb64/src/cdecode.c create mode 100644 utilities/xmlrpcpp/libb64/src/cencode.c diff --git a/utilities/xmlrpcpp/CMakeLists.txt b/utilities/xmlrpcpp/CMakeLists.txt index b69969b321..8112da8873 100644 --- a/utilities/xmlrpcpp/CMakeLists.txt +++ b/utilities/xmlrpcpp/CMakeLists.txt @@ -15,7 +15,11 @@ catkin_package( CFG_EXTRAS xmlrpcpp-extras.cmake ) -include_directories(include ${catkin_INCLUDE_DIRS}) +include_directories( + include + libb64/include + ${catkin_INCLUDE_DIRS} +) link_directories(${catkin_LIBRARY_DIRS}) if(WIN32) @@ -32,7 +36,9 @@ add_library(xmlrpcpp src/XmlRpcSource.cpp src/XmlRpcUtil.cpp src/XmlRpcValue.cpp - ) + libb64/src/cdecode.c + libb64/src/cencode.c +) if(WIN32) target_link_libraries(xmlrpcpp ws2_32) diff --git a/utilities/xmlrpcpp/include/xmlrpcpp/base64.h b/utilities/xmlrpcpp/include/xmlrpcpp/base64.h deleted file mode 100644 index c23940302e..0000000000 --- a/utilities/xmlrpcpp/include/xmlrpcpp/base64.h +++ /dev/null @@ -1,380 +0,0 @@ - - -// base64.hpp -// Autor Konstantin Pilipchuk -// mailto:lostd@ukr.net -// -// - -#if !defined(__BASE64_H_INCLUDED__) -#define __BASE64_H_INCLUDED__ 1 - -#ifndef MAKEDEPEND -# include -#endif - -#include - -static -int _base64Chars[]= {'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z', - 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z', - '0','1','2','3','4','5','6','7','8','9', - '+','/' }; - - -#define _0000_0011 0x03 -#define _1111_1100 0xFC -#define _1111_0000 0xF0 -#define _0011_0000 0x30 -#define _0011_1100 0x3C -#define _0000_1111 0x0F -#define _1100_0000 0xC0 -#define _0011_1111 0x3F - -#define _EQUAL_CHAR (-1) -#define _UNKNOWN_CHAR (-2) - -#define _IOS_FAILBIT std::ios_base::failbit -#define _IOS_EOFBIT std::ios_base::eofbit -#define _IOS_BADBIT std::ios_base::badbit -#define _IOS_GOODBIT std::ios_base::goodbit - -// TEMPLATE CLASS base64_put -template > -class base64 -{ -public: - - typedef unsigned char byte_t; - typedef _E char_type; - typedef _Tr traits_type; - - // base64 requires max line length <= 72 characters - // you can fill end of line - // it may be crlf, crlfsp, noline or other class like it - - - struct crlf - { - template - _OI operator()(_OI _To) const{ - *_To = _Tr::to_char_type('\r'); ++_To; - *_To = _Tr::to_char_type('\n'); ++_To; - - return (_To); - } - }; - - - struct crlfsp - { - template - _OI operator()(_OI _To) const{ - *_To = _Tr::to_char_type('\r'); ++_To; - *_To = _Tr::to_char_type('\n'); ++_To; - *_To = _Tr::to_char_type(' '); ++_To; - - return (_To); - } - }; - - struct noline - { - template - _OI operator()(_OI _To) const{ - return (_To); - } - }; - - struct three2four - { - void zero() - { - _data[0] = 0; - _data[1] = 0; - _data[2] = 0; - } - - byte_t get_0() const - { - return _data[0]; - } - byte_t get_1() const - { - return _data[1]; - } - byte_t get_2() const - { - return _data[2]; - } - - void set_0(byte_t _ch) - { - _data[0] = _ch; - } - - void set_1(byte_t _ch) - { - _data[1] = _ch; - } - - void set_2(byte_t _ch) - { - _data[2] = _ch; - } - - // 0000 0000 1111 1111 2222 2222 - // xxxx xxxx xxxx xxxx xxxx xxxx - // 0000 0011 1111 2222 2233 3333 - - int b64_0() const {return (_data[0] & _1111_1100) >> 2;} - int b64_1() const {return ((_data[0] & _0000_0011) << 4) + ((_data[1] & _1111_0000)>>4);} - int b64_2() const {return ((_data[1] & _0000_1111) << 2) + ((_data[2] & _1100_0000)>>6);} - int b64_3() const {return (_data[2] & _0011_1111);} - - void b64_0(int _ch) {_data[0] = ((_ch & _0011_1111) << 2) | (_0000_0011 & _data[0]);} - - void b64_1(int _ch) { - _data[0] = ((_ch & _0011_0000) >> 4) | (_1111_1100 & _data[0]); - _data[1] = ((_ch & _0000_1111) << 4) | (_0000_1111 & _data[1]); } - - void b64_2(int _ch) { - _data[1] = ((_ch & _0011_1100) >> 2) | (_1111_0000 & _data[1]); - _data[2] = ((_ch & _0000_0011) << 6) | (_0011_1111 & _data[2]); } - - void b64_3(int _ch){ - _data[2] = (_ch & _0011_1111) | (_1100_0000 & _data[2]);} - - private: - byte_t _data[3]; - - }; - - - - - template - _II put(_II _First, _II _Last, _OI _To, _State&, _Endline) const - { - three2four _3to4; - int line_octets = 0; - - while(_First != _Last) - { - _3to4.zero(); - - _3to4.set_0(*_First); - _First++; - - if(_First == _Last) - { - *_To = _Tr::to_char_type(_base64Chars[_3to4.b64_0()]); ++_To; - *_To = _Tr::to_char_type(_base64Chars[_3to4.b64_1()]); ++_To; - *_To = _Tr::to_char_type('='); ++_To; - *_To = _Tr::to_char_type('='); ++_To; - goto __end; - } - - _3to4.set_1(*_First); - _First++; - - if(_First == _Last) - { - *_To = _Tr::to_char_type(_base64Chars[_3to4.b64_0()]); ++_To; - *_To = _Tr::to_char_type(_base64Chars[_3to4.b64_1()]); ++_To; - *_To = _Tr::to_char_type(_base64Chars[_3to4.b64_2()]); ++_To; - *_To = _Tr::to_char_type('='); ++_To; - goto __end; - } - - _3to4.set_2(*_First); - _First++; - - *_To = _Tr::to_char_type(_base64Chars[_3to4.b64_0()]); ++_To; - *_To = _Tr::to_char_type(_base64Chars[_3to4.b64_1()]); ++_To; - *_To = _Tr::to_char_type(_base64Chars[_3to4.b64_2()]); ++_To; - *_To = _Tr::to_char_type(_base64Chars[_3to4.b64_3()]); ++_To; - - if(line_octets == 17) - { - //_To = _Endl(_To); - *_To = '\n'; ++_To; - line_octets = 0; - } - else - ++line_octets; - } - - __end: ; - - return (_First); - - } - - - template - _II get(_II _First, _II _Last, _OI _To, _State& _St) const - { - three2four _3to4; - int _Char; - - while(_First != _Last) - { - - // Take octet - _3to4.zero(); - - // -- 0 -- - // Search next valid char... - while((_Char = _getCharType(*_First)) < 0 && _Char == _UNKNOWN_CHAR) - { - if(++_First == _Last) - { - _St |= _IOS_FAILBIT|_IOS_EOFBIT; return _First; // unexpected EOF - } - } - - if(_Char == _EQUAL_CHAR){ - // Error! First character in octet can't be '=' - _St |= _IOS_FAILBIT; - return _First; - } - else - _3to4.b64_0(_Char); - - - // -- 1 -- - // Search next valid char... - while(++_First != _Last) - if((_Char = _getCharType(*_First)) != _UNKNOWN_CHAR) - break; - - if(_First == _Last) { - _St |= _IOS_FAILBIT|_IOS_EOFBIT; // unexpected EOF - return _First; - } - - if(_Char == _EQUAL_CHAR){ - // Error! Second character in octet can't be '=' - _St |= _IOS_FAILBIT; - return _First; - } - else - _3to4.b64_1(_Char); - - - // -- 2 -- - // Search next valid char... - while(++_First != _Last) - if((_Char = _getCharType(*_First)) != _UNKNOWN_CHAR) - break; - - if(_First == _Last) { - // Error! Unexpected EOF. Must be '=' or base64 character - _St |= _IOS_FAILBIT|_IOS_EOFBIT; - return _First; - } - - if(_Char == _EQUAL_CHAR){ - // OK! - _3to4.b64_2(0); - _3to4.b64_3(0); - - // chek for EOF - if(++_First == _Last) - { - // Error! Unexpected EOF. Must be '='. Ignore it. - //_St |= _IOS_BADBIT|_IOS_EOFBIT; - _St |= _IOS_EOFBIT; - } - else - if(_getCharType(*_First) != _EQUAL_CHAR) - { - // Error! Must be '='. Ignore it. - //_St |= _IOS_BADBIT; - } - else - ++_First; // Skip '=' - - // write 1 byte to output - *_To = (byte_t) _3to4.get_0(); - return _First; - } - else - _3to4.b64_2(_Char); - - - // -- 3 -- - // Search next valid char... - while(++_First != _Last) - if((_Char = _getCharType(*_First)) != _UNKNOWN_CHAR) - break; - - if(_First == _Last) { - // Unexpected EOF. It's error. But ignore it. - //_St |= _IOS_FAILBIT|_IOS_EOFBIT; - _St |= _IOS_EOFBIT; - - return _First; - } - - if(_Char == _EQUAL_CHAR) - { - // OK! - _3to4.b64_3(0); - - // write to output 2 bytes - *_To = (byte_t) _3to4.get_0(); - *_To = (byte_t) _3to4.get_1(); - - ++_First; // set position to next character - - return _First; - } - else - _3to4.b64_3(_Char); - - - // write to output 3 bytes - *_To = (byte_t) _3to4.get_0(); - *_To = (byte_t) _3to4.get_1(); - *_To = (byte_t) _3to4.get_2(); - - ++_First; - - - } // while(_First != _Last) - - return (_First); - } - -protected: - - int _getCharType(int _Ch) const - { - if(_base64Chars[62] == _Ch) - return 62; - - if(_base64Chars[63] == _Ch) - return 63; - - if((_base64Chars[0] <= _Ch) && (_base64Chars[25] >= _Ch)) - return _Ch - _base64Chars[0]; - - if((_base64Chars[26] <= _Ch) && (_base64Chars[51] >= _Ch)) - return _Ch - _base64Chars[26] + 26; - - if((_base64Chars[52] <= _Ch) && (_base64Chars[61] >= _Ch)) - return _Ch - _base64Chars[52] + 52; - - if(_Ch == _Tr::to_int_type('=')) - return _EQUAL_CHAR; - - return _UNKNOWN_CHAR; - } - - -}; - - -#endif diff --git a/utilities/xmlrpcpp/libb64/AUTHORS b/utilities/xmlrpcpp/libb64/AUTHORS new file mode 100644 index 0000000000..bf4a9f4e04 --- /dev/null +++ b/utilities/xmlrpcpp/libb64/AUTHORS @@ -0,0 +1,15 @@ +libb64: Base64 Encoding/Decoding Routines +====================================== + +Authors: +------- + +Chris Venter chris.venter@gmail.com http://controlaltfire.com + +Contributors: +------------ + +Mario Rugiero +Shlok Datye +Peter K. Lee + diff --git a/utilities/xmlrpcpp/libb64/BENCHMARKS b/utilities/xmlrpcpp/libb64/BENCHMARKS new file mode 100644 index 0000000000..fd34056e79 --- /dev/null +++ b/utilities/xmlrpcpp/libb64/BENCHMARKS @@ -0,0 +1,85 @@ +-- Intro + +Some people have expressed opinions about how +fast libb64's encoding and decoding routines +are, as compared to some other BASE64 packages +out there. + +This document shows the result of a short and sweet +benchmark, which takes a large-ish file and +encodes/decodes it a number of times. +The winner is the executable that does this task the quickest. + +-- Platform + +The tests were all run on a Fujitsu-Siemens laptop, +with a Pentium M processor running at 2GHz, with +1GB of RAM, running Ubuntu 10.4. + +-- Packages + +The following BASE64 packages were used in this benchmark: + +- libb64-1.2 (libb64-base64) + From libb64.sourceforge.net + Size of executable: 18808 bytes + Compiled with: + CFLAGS += -O3 + BUFFERSIZE = 16777216 + +- base64-1.5 (fourmilab-base64) + From http://www.fourmilab.ch/webtools/base64/ + Size of executable: 20261 bytes + Compiled with Default package settings + +- coreutils 7.4-2ubuntu2 (coreutils-base64) + From http://www.gnu.org/software/coreutils/ + Size of executable: 38488 bytes + Default binary distributed with Ubuntu 10.4 + +-- Input File + +Using blender-2.49b-linux-glibc236-py25-i386.tar.bz2 +from http://www.blender.org/download/get-blender/ +Size: 18285329 bytes +(approx. 18MB) + +-- Method + +Encode and Decode the Input file 50 times in a loop, +using a simple shell script, and get the running time. + +-- Results + +$ time ./benchmark-libb64.sh +real 0m28.389s +user 0m14.077s +sys 0m12.309s + +$ time ./benchmark-fourmilab.sh +real 1m43.160s +user 1m23.769s +sys 0m8.737s + +$ time ./benchmark-coreutils.sh +real 0m36.288s +user 0m24.746s +sys 0m8.181s + +28.389 for 18MB * 50 += 28.389 for 900 + +-- Conclusion + +libb64 is the fastest encoder/decoder, and +has the smallest executable size. + +On average it will encode and decode at roughly 31.7MB/second. + +The closest "competitor" is base64 from GNU coreutils, which +reaches only 24.8MB/second. + +-- +14/06/2010 +chris.venter@gmail.com + diff --git a/utilities/xmlrpcpp/libb64/CHANGELOG b/utilities/xmlrpcpp/libb64/CHANGELOG new file mode 100644 index 0000000000..c1c0844ed4 --- /dev/null +++ b/utilities/xmlrpcpp/libb64/CHANGELOG @@ -0,0 +1,33 @@ +libb64: Base64 Encoding/Decoding Routines +====================================== + +## Changelog ## + +Version 1.2.1 Release +--------------------- +Fixed a long-standing bug in src/cdecode.c where value_in was not correctly +checked against the bounds [0..decoding_size) +Thanks to both Mario Rugiero and Shlok Datye for pointing this out. +Added some simple example code to answer some of the most common misconceptions +people have about the library usage. + +Version 1.2 Release +------------------- +Removed the b64dec, b64enc, encoder and decoder programs in favour of +a better example, called base64, which encodes and decodes +depending on its arguments. + +Created a solution for Microsoft Visual Studio C++ Express 2010 +edition, which simply builds the base64 example as a console application. + +Version 1.1 Release +------------------- +Modified encode.h to (correctly) read from the iostream argument, +instead of std::cin. +Thanks to Peter K. Lee for the heads-up. + +No API changes. + +Version 1.0 Release +------------------- +The current content is the changeset. diff --git a/utilities/xmlrpcpp/libb64/INSTALL b/utilities/xmlrpcpp/libb64/INSTALL new file mode 100644 index 0000000000..b05f5db69f --- /dev/null +++ b/utilities/xmlrpcpp/libb64/INSTALL @@ -0,0 +1,44 @@ +libb64: Base64 Encoding/Decoding Routines +====================================== + +Requirements: +------------ +This piece of software has minimal requirements. + +I have tested it on the following systems: + +- a Linux machine, with the following specs: +(this was the original development machine) + * FedoraCore 4 + * kernel v. 2.6.11 (stock FC4 kernel) + * gcc version 4.0.1 20050727 (Red Hat 4.0.1-5) + * glibc-2.3.5-10 + * make v. 3.80 + * some arb version of makedepend + +- Windows XP machine + * MSYS 1.0 + * MinGW 5.1.4 + * gcc version 3.4.5 (mingw-vista special r3) + +- Windows XP machine (same as above) + * Microsoft Visual Studio 2010, Version 10.0.30319.1 RTMRel + +Barring any serious screwups on my part, this code should compile and run sweetly +under Cygwin and other systems too. If you DO get it running under some weird arch/os setup, +send me a mail, please. + +Compiling: +--------- +There is no configure. It would be overkill for something so simple... +Run make in the root directory. + +Installing: +---------- +Since the current targets are a standalone executable and a static library +(fancy name for archive) with some headers, an install script has not been implemented yet. +Simply copy the executable into your path, and use it. + +-- +peace out +Chris diff --git a/utilities/xmlrpcpp/libb64/LICENSE b/utilities/xmlrpcpp/libb64/LICENSE new file mode 100644 index 0000000000..a6b56069e7 --- /dev/null +++ b/utilities/xmlrpcpp/libb64/LICENSE @@ -0,0 +1,29 @@ +Copyright-Only Dedication (based on United States law) +or Public Domain Certification + +The person or persons who have associated work with this document (the +"Dedicator" or "Certifier") hereby either (a) certifies that, to the best of +his knowledge, the work of authorship identified is in the public domain of the +country from which the work is published, or (b) hereby dedicates whatever +copyright the dedicators holds in the work of authorship identified below (the +"Work") to the public domain. A certifier, moreover, dedicates any copyright +interest he may have in the associated work, and for these purposes, is +described as a "dedicator" below. + +A certifier has taken reasonable steps to verify the copyright status of this +work. Certifier recognizes that his good faith efforts may not shield him from +liability if in fact the work certified is not in the public domain. + +Dedicator makes this dedication for the benefit of the public at large and to +the detriment of the Dedicator's heirs and successors. Dedicator intends this +dedication to be an overt act of relinquishment in perpetuity of all present +and future rights under copyright law, whether vested or contingent, in the +Work. Dedicator understands that such relinquishment of all rights includes +the relinquishment of all rights to enforce (by lawsuit or otherwise) those +copyrights in the Work. + +Dedicator recognizes that, once placed in the public domain, the Work may be +freely reproduced, distributed, transmitted, used, modified, built upon, or +otherwise exploited by anyone for any purpose, commercial or non-commercial, +and in any way, including by methods that have not yet been invented or +conceived. \ No newline at end of file diff --git a/utilities/xmlrpcpp/libb64/Makefile b/utilities/xmlrpcpp/libb64/Makefile new file mode 100644 index 0000000000..db4035626f --- /dev/null +++ b/utilities/xmlrpcpp/libb64/Makefile @@ -0,0 +1,31 @@ +all: all_src all_base64 all_examples + +all_src: + $(MAKE) -C src +all_base64: all_src + $(MAKE) -C base64 +all_examples: + $(MAKE) -C examples + +clean: clean_src clean_base64 clean_include clean_examples + rm -f *~ *.bak + +clean_include: + rm -f include/b64/*~ + +clean_src: + $(MAKE) -C src clean; +clean_base64: + $(MAKE) -C base64 clean; +clean_examples: + $(MAKE) -C examples clean; + +distclean: clean distclean_src distclean_base64 distclean_examples + +distclean_src: + $(MAKE) -C src distclean; +distclean_base64: + $(MAKE) -C base64 distclean; +distclean_examples: + $(MAKE) -C examples distclean; + diff --git a/utilities/xmlrpcpp/libb64/README b/utilities/xmlrpcpp/libb64/README new file mode 100644 index 0000000000..132f02f508 --- /dev/null +++ b/utilities/xmlrpcpp/libb64/README @@ -0,0 +1,143 @@ +b64: Base64 Encoding/Decoding Routines +====================================== + +Overview: +-------- +libb64 is a library of ANSI C routines for fast encoding/decoding data into and +from a base64-encoded format. C++ wrappers are included, as well as the source +code for standalone encoding and decoding executables. + +base64 consists of ASCII text, and is therefore a useful encoding for storing +binary data in a text file, such as xml, or sending binary data over text-only +email. + +References: +---------- +* Wikipedia article: + http://en.wikipedia.org/wiki/Base64 +* base64, another implementation of a commandline en/decoder: + http://www.fourmilab.ch/webtools/base64/ + +Why? +--- +I did this because I need an implementation of base64 encoding and decoding, +without any licensing problems. Most OS implementations are released under +either the GNU/GPL, or a BSD-variant, which is not what I require. + +Also, the chance to actually use the co-routine implementation in code is rare, +and its use here is fitting. I couldn't pass up the chance. +For more information on this technique, see "Coroutines in C", by Simon Tatham, +which can be found online here: +http://www.chiark.greenend.org.uk/~sgtatham/coroutines.html + +So then, under which license do I release this code? On to the next section... + +License: +------- +This work is released under into the Public Domain. +It basically boils down to this: I put this work in the public domain, and you +can take it and do whatever you want with it. + +An example of this "license" is the Creative Commons Public Domain License, a +copy of which can be found in the LICENSE file, and also online at +http://creativecommons.org/licenses/publicdomain/ + +Commandline Use: +--------------- +There is a new executable available, it is simply called base64. +It can encode and decode files, as instructed by the user. + +To encode a file: +$ ./base64 -e filea fileb +fileb will now be the base64-encoded version of filea. + +To decode a file: +$ ./base64 -d fileb filec +filec will now be identical to filea. + +Programming: +----------- +Some C++ wrappers are provided as well, so you don't have to get your hands +dirty. Encoding from standard input to standard output is as simple as + + #include + #include + int main() + { + base64::encoder E; + E.encode(std::cin, std::cout); + return 0; + } + +Both standalone executables and a static library is provided in the package, + +Example code: +------------ +The 'examples' directory contains some simple example C code, that demonstrates +how to use the C interface of the library. + +Implementation: +-------------- +It is DAMN fast, if I may say so myself. The C code uses a little trick which +has been used to implement coroutines, of which one can say that this +implementation is an example. + +(To see how the libb64 codebase compares with some other BASE64 implementations +available, see the BENCHMARKS file) + +The trick involves the fact that a switch-statement may legally cross into +sub-blocks. A very thorough and enlightening essay on co-routines in C, using +this method, can be found in the above mentioned "Coroutines in C", by Simon +Tatham: http://www.chiark.greenend.org.uk/~sgtatham/coroutines.html + +For example, an RLE decompressing routine, adapted from the article: +1 static int STATE = 0; +2 static int len, c; +3 switch (STATE) +4 { +5 while (1) +6 { +7 c = getchar(); +8 if (c == EOF) return EOF; +9 if (c == 0xFF) { +10 len = getchar(); +11 c = getchar(); +12 while (len--) +13 { +14 STATE = 0; +15 return c; +16 case 0: +17 } +18 } else +19 STATE = 1; +20 return c; +21 case 1: +22 } +23 } +24 } + +As can be seen from this example, a coroutine depends on a state variable, +which it sets directly before exiting (lines 14 and 119). The next time the +routine is entered, the switch moves control to the specific point directly +after the previous exit (lines 16 and 21).hands + +(As an aside, in the mentioned article the combination of the top-level switch, +the various setting of the state, the return of a value, and the labelling of +the exit point is wrapped in #define macros, making the structure of the +routine even clearer.) + +The obvious problem with any such routine is the static keyword. +Any static variables in a function spell doom for multithreaded applications. +Also, in situations where this coroutine is used by more than one other +coroutines, the consistency is disturbed. + +What is needed is a structure for storing these variabled, which is passed to +the routine seperately. This obviously breaks the modularity of the function, +since now the caller has to worry about and care for the internal state of the +routine (the callee). This allows for a fast, multithreading-enabled +implementation, which may (obviously) be wrapped in a C++ object for ease of +use. + +The base64 encoding and decoding functionality in this package is implemented +in exactly this way, providing both a high-speed high-maintanence C interface, +and a wrapped C++ which is low-maintanence and only slightly less performant. diff --git a/utilities/xmlrpcpp/libb64/TODO b/utilities/xmlrpcpp/libb64/TODO new file mode 100644 index 0000000000..e69de29bb2 diff --git a/utilities/xmlrpcpp/libb64/include/b64/cdecode.h b/utilities/xmlrpcpp/libb64/include/b64/cdecode.h new file mode 100644 index 0000000000..5729853d76 --- /dev/null +++ b/utilities/xmlrpcpp/libb64/include/b64/cdecode.h @@ -0,0 +1,29 @@ +/* +cdecode.h - c header for a base64 decoding algorithm + +This is part of the libb64 project, and has been placed in the public domain. +For details, see http://sourceforge.net/projects/libb64 +*/ + +#ifndef BASE64_CDECODE_H +#define BASE64_CDECODE_H + +typedef enum +{ + step_a, step_b, step_c, step_d +} base64_decodestep; + +typedef struct +{ + base64_decodestep step; + char plainchar; +} base64_decodestate; + +void base64_init_decodestate(base64_decodestate* state_in); + +int base64_decode_value(char value_in); + +int base64_decode_block(const char* code_in, const int length_in, char* plaintext_out, base64_decodestate* state_in); + +#endif /* BASE64_CDECODE_H */ + diff --git a/utilities/xmlrpcpp/libb64/include/b64/cencode.h b/utilities/xmlrpcpp/libb64/include/b64/cencode.h new file mode 100644 index 0000000000..cf32131266 --- /dev/null +++ b/utilities/xmlrpcpp/libb64/include/b64/cencode.h @@ -0,0 +1,32 @@ +/* +cencode.h - c header for a base64 encoding algorithm + +This is part of the libb64 project, and has been placed in the public domain. +For details, see http://sourceforge.net/projects/libb64 +*/ + +#ifndef BASE64_CENCODE_H +#define BASE64_CENCODE_H + +typedef enum +{ + step_A, step_B, step_C +} base64_encodestep; + +typedef struct +{ + base64_encodestep step; + char result; + int stepcount; +} base64_encodestate; + +void base64_init_encodestate(base64_encodestate* state_in); + +char base64_encode_value(char value_in); + +int base64_encode_block(const char* plaintext_in, int length_in, char* code_out, base64_encodestate* state_in); + +int base64_encode_blockend(char* code_out, base64_encodestate* state_in); + +#endif /* BASE64_CENCODE_H */ + diff --git a/utilities/xmlrpcpp/libb64/include/b64/decode.h b/utilities/xmlrpcpp/libb64/include/b64/decode.h new file mode 100644 index 0000000000..8fd0188faf --- /dev/null +++ b/utilities/xmlrpcpp/libb64/include/b64/decode.h @@ -0,0 +1,72 @@ +// :mode=c++: +/* +decode.h - c++ wrapper for a base64 decoding algorithm + +This is part of the libb64 project, and has been placed in the public domain. +For details, see http://sourceforge.net/projects/libb64 +*/ +#ifndef BASE64_DECODE_H +#define BASE64_DECODE_H + +#include + +namespace base64 +{ + extern "C" + { + #include "cdecode.h" + } + + struct decoder + { + base64_decodestate _state; + int _buffersize; + + decoder(int buffersize_in = 512) + : _buffersize(buffersize_in) + { + base64_init_decodestate(&_state); + } + + int decode(char value_in) + { + return base64_decode_value(value_in); + } + + int decode(const char* code_in, const int length_in, char* plaintext_out) + { + return base64_decode_block(code_in, length_in, plaintext_out, &_state); + } + + void decode(std::istream& istream_in, std::ostream& ostream_in) + { + base64_init_decodestate(&_state); + // + const int N = _buffersize; + char* code = new char[N]; + char* plaintext = new char[N]; + int codelength; + int plainlength; + + do + { + istream_in.read((char*)code, N); + codelength = istream_in.gcount(); + plainlength = decode(code, codelength, plaintext); + ostream_in.write((const char*)plaintext, plainlength); + } + while (istream_in.good() && codelength > 0); + // + base64_init_decodestate(&_state); + + delete [] code; + delete [] plaintext; + } + }; + +} // namespace base64 + + + +#endif // BASE64_DECODE_H + diff --git a/utilities/xmlrpcpp/libb64/include/b64/encode.h b/utilities/xmlrpcpp/libb64/include/b64/encode.h new file mode 100644 index 0000000000..dc481b1d9f --- /dev/null +++ b/utilities/xmlrpcpp/libb64/include/b64/encode.h @@ -0,0 +1,79 @@ +// :mode=c++: +/* +encode.h - c++ wrapper for a base64 encoding algorithm + +This is part of the libb64 project, and has been placed in the public domain. +For details, see http://sourceforge.net/projects/libb64 +*/ +#ifndef BASE64_ENCODE_H +#define BASE64_ENCODE_H + +#include + +namespace base64 +{ + extern "C" + { + #include "cencode.h" + } + + struct encoder + { + base64_encodestate _state; + int _buffersize; + + encoder(int buffersize_in = 512) + : _buffersize(buffersize_in) + { + base64_init_encodestate(&_state); + } + + int encode(char value_in) + { + return base64_encode_value(value_in); + } + + int encode(const char* code_in, const int length_in, char* plaintext_out) + { + return base64_encode_block(code_in, length_in, plaintext_out, &_state); + } + + int encode_end(char* plaintext_out) + { + return base64_encode_blockend(plaintext_out, &_state); + } + + void encode(std::istream& istream_in, std::ostream& ostream_in) + { + base64_init_encodestate(&_state); + // + const int N = _buffersize; + char* plaintext = new char[N]; + char* code = new char[2*N]; + int plainlength; + int codelength; + + do + { + istream_in.read(plaintext, N); + plainlength = istream_in.gcount(); + // + codelength = encode(plaintext, plainlength, code); + ostream_in.write(code, codelength); + } + while (istream_in.good() && plainlength > 0); + + codelength = encode_end(code); + ostream_in.write(code, codelength); + // + base64_init_encodestate(&_state); + + delete [] code; + delete [] plaintext; + } + }; + +} // namespace base64 + +#endif // BASE64_ENCODE_H + diff --git a/utilities/xmlrpcpp/libb64/src/Makefile b/utilities/xmlrpcpp/libb64/src/Makefile new file mode 100644 index 0000000000..28b2382575 --- /dev/null +++ b/utilities/xmlrpcpp/libb64/src/Makefile @@ -0,0 +1,43 @@ +LIBRARIES = libb64.a + +# Build flags (uncomment one) +############################# +# Release build flags +CFLAGS += -O3 +############################# +# Debug build flags +#CFLAGS += -g +############################# + +SOURCES = cdecode.c cencode.c + +TARGETS = $(LIBRARIES) + +LINK.o = gcc + +CFLAGS += -Werror -pedantic +CFLAGS += -I../include + +vpath %.h ../include/b64 + +.PHONY : clean + +all: $(TARGETS) #strip + +libb64.a: cencode.o cdecode.o + $(AR) $(ARFLAGS) $@ $^ + +strip: + strip $(BINARIES) *.exe + +clean: + rm -f *.exe* *.o $(TARGETS) *.bak *~ + +distclean: clean + rm -f depend + +depend: $(SOURCES) + makedepend -f- $(CFLAGS) $(SOURCES) 2> /dev/null 1> depend + +-include depend + diff --git a/utilities/xmlrpcpp/libb64/src/cdecode.c b/utilities/xmlrpcpp/libb64/src/cdecode.c new file mode 100644 index 0000000000..a6c0a423b6 --- /dev/null +++ b/utilities/xmlrpcpp/libb64/src/cdecode.c @@ -0,0 +1,88 @@ +/* +cdecoder.c - c source to a base64 decoding algorithm implementation + +This is part of the libb64 project, and has been placed in the public domain. +For details, see http://sourceforge.net/projects/libb64 +*/ + +#include + +int base64_decode_value(char value_in) +{ + static const char decoding[] = {62,-1,-1,-1,63,52,53,54,55,56,57,58,59,60,61,-1,-1,-1,-2,-1,-1,-1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,-1,-1,-1,-1,-1,-1,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51}; + static const char decoding_size = sizeof(decoding); + value_in -= 43; + if (value_in < 0 || value_in >= decoding_size) return -1; + return decoding[(int)value_in]; +} + +void base64_init_decodestate(base64_decodestate* state_in) +{ + state_in->step = step_a; + state_in->plainchar = 0; +} + +int base64_decode_block(const char* code_in, const int length_in, char* plaintext_out, base64_decodestate* state_in) +{ + const char* codechar = code_in; + char* plainchar = plaintext_out; + char fragment; + + *plainchar = state_in->plainchar; + + switch (state_in->step) + { + while (1) + { + case step_a: + do { + if (codechar == code_in+length_in) + { + state_in->step = step_a; + state_in->plainchar = *plainchar; + return plainchar - plaintext_out; + } + fragment = (char)base64_decode_value(*codechar++); + } while (fragment < 0); + *plainchar = (fragment & 0x03f) << 2; + case step_b: + do { + if (codechar == code_in+length_in) + { + state_in->step = step_b; + state_in->plainchar = *plainchar; + return plainchar - plaintext_out; + } + fragment = (char)base64_decode_value(*codechar++); + } while (fragment < 0); + *plainchar++ |= (fragment & 0x030) >> 4; + *plainchar = (fragment & 0x00f) << 4; + case step_c: + do { + if (codechar == code_in+length_in) + { + state_in->step = step_c; + state_in->plainchar = *plainchar; + return plainchar - plaintext_out; + } + fragment = (char)base64_decode_value(*codechar++); + } while (fragment < 0); + *plainchar++ |= (fragment & 0x03c) >> 2; + *plainchar = (fragment & 0x003) << 6; + case step_d: + do { + if (codechar == code_in+length_in) + { + state_in->step = step_d; + state_in->plainchar = *plainchar; + return plainchar - plaintext_out; + } + fragment = (char)base64_decode_value(*codechar++); + } while (fragment < 0); + *plainchar++ |= (fragment & 0x03f); + } + } + /* control should not reach here */ + return plainchar - plaintext_out; +} + diff --git a/utilities/xmlrpcpp/libb64/src/cencode.c b/utilities/xmlrpcpp/libb64/src/cencode.c new file mode 100644 index 0000000000..03ba5b6866 --- /dev/null +++ b/utilities/xmlrpcpp/libb64/src/cencode.c @@ -0,0 +1,109 @@ +/* +cencoder.c - c source to a base64 encoding algorithm implementation + +This is part of the libb64 project, and has been placed in the public domain. +For details, see http://sourceforge.net/projects/libb64 +*/ + +#include + +const int CHARS_PER_LINE = 72; + +void base64_init_encodestate(base64_encodestate* state_in) +{ + state_in->step = step_A; + state_in->result = 0; + state_in->stepcount = 0; +} + +char base64_encode_value(char value_in) +{ + static const char* encoding = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + if (value_in > 63) return '='; + return encoding[(int)value_in]; +} + +int base64_encode_block(const char* plaintext_in, int length_in, char* code_out, base64_encodestate* state_in) +{ + const char* plainchar = plaintext_in; + const char* const plaintextend = plaintext_in + length_in; + char* codechar = code_out; + char result; + char fragment; + + result = state_in->result; + + switch (state_in->step) + { + while (1) + { + case step_A: + if (plainchar == plaintextend) + { + state_in->result = result; + state_in->step = step_A; + return codechar - code_out; + } + fragment = *plainchar++; + result = (fragment & 0x0fc) >> 2; + *codechar++ = base64_encode_value(result); + result = (fragment & 0x003) << 4; + case step_B: + if (plainchar == plaintextend) + { + state_in->result = result; + state_in->step = step_B; + return codechar - code_out; + } + fragment = *plainchar++; + result |= (fragment & 0x0f0) >> 4; + *codechar++ = base64_encode_value(result); + result = (fragment & 0x00f) << 2; + case step_C: + if (plainchar == plaintextend) + { + state_in->result = result; + state_in->step = step_C; + return codechar - code_out; + } + fragment = *plainchar++; + result |= (fragment & 0x0c0) >> 6; + *codechar++ = base64_encode_value(result); + result = (fragment & 0x03f) >> 0; + *codechar++ = base64_encode_value(result); + + ++(state_in->stepcount); + if (state_in->stepcount == CHARS_PER_LINE/4) + { + *codechar++ = '\n'; + state_in->stepcount = 0; + } + } + } + /* control should not reach here */ + return codechar - code_out; +} + +int base64_encode_blockend(char* code_out, base64_encodestate* state_in) +{ + char* codechar = code_out; + + switch (state_in->step) + { + case step_B: + *codechar++ = base64_encode_value(state_in->result); + *codechar++ = '='; + *codechar++ = '='; + break; + case step_C: + *codechar++ = base64_encode_value(state_in->result); + *codechar++ = '='; + break; + case step_A: + break; + } + *codechar++ = '\n'; + + return codechar - code_out; +} + diff --git a/utilities/xmlrpcpp/src/XmlRpcValue.cpp b/utilities/xmlrpcpp/src/XmlRpcValue.cpp index e6dabceaa0..a7c3b0b150 100644 --- a/utilities/xmlrpcpp/src/XmlRpcValue.cpp +++ b/utilities/xmlrpcpp/src/XmlRpcValue.cpp @@ -2,7 +2,9 @@ #include "xmlrpcpp/XmlRpcValue.h" #include "xmlrpcpp/XmlRpcException.h" #include "xmlrpcpp/XmlRpcUtil.h" -#include "xmlrpcpp/base64.h" + +#include +#include #ifndef MAKEDEPEND # include @@ -438,6 +440,29 @@ namespace XmlRpc { return xml; } + namespace { + std::size_t base64EncodedSize(std::size_t raw_size) + { + // encoder will still write to output buffer for empty input. + if (raw_size == 0) return 1; + + // 4 encoded character per 3 input bytes, rounded up, + // plus a newline character per 72 output characters, rounded up. + std::size_t encoded = (raw_size + 2) / 3 * 4; + encoded += (encoded + 71) / 72; + return encoded; + } + + std::size_t base64DecodedSize(std::size_t encoded_size) + { + // decoded will still write to output buffer for empty input. + if (encoded_size == 0) return 1; + + // 3 decoded bytes per 4 encoded characters, rounded up just to be sure. + return (encoded_size + 3) / 4 * 3; + } + + } // Base64 bool XmlRpcValue::binaryFromXml(std::string const& valueXml, int* offset) @@ -446,35 +471,37 @@ namespace XmlRpc { if (valueEnd == std::string::npos) return false; // No end tag; + std::size_t encoded_size = valueEnd - *offset; + + _type = TypeBase64; - std::string asString = valueXml.substr(*offset, valueEnd-*offset); - _value.asBinary = new BinaryData(); - // check whether base64 encodings can contain chars xml encodes... + // might reserve too much, we'll shrink later + _value.asBinary = new BinaryData(base64DecodedSize(encoded_size), '\0'); - // convert from base64 to binary - int iostatus = 0; - base64 decoder; - std::back_insert_iterator ins = std::back_inserter(*(_value.asBinary)); - decoder.get(asString.begin(), asString.end(), ins, iostatus); + std::stringstream buffer; + base64::decoder decoder; + std::size_t size = decoder.decode(&valueXml[*offset], encoded_size, &(*_value.asBinary)[0]); + _value.asBinary->resize(size); - *offset += int(asString.length()); + *offset += encoded_size; return true; } - std::string XmlRpcValue::binaryToXml() const { - // convert to base64 - std::vector base64data; - int iostatus = 0; - base64 encoder; - std::back_insert_iterator > ins = std::back_inserter(base64data); - encoder.put(_value.asBinary->begin(), _value.asBinary->end(), ins, iostatus, base64<>::crlf()); - // Wrap with xml std::string xml = VALUE_TAG; xml += BASE64_TAG; - xml.append(base64data.begin(), base64data.end()); + + std::size_t offset = xml.size(); + // might reserve too much, we'll shrink later + xml.resize(xml.size() + base64EncodedSize(_value.asBinary->size())); + + base64::encoder encoder; + offset += encoder.encode(&(*_value.asBinary)[0], _value.asBinary->size(), &xml[offset]); + offset += encoder.encode_end(&xml[offset]); + xml.resize(offset); + xml += BASE64_ETAG; xml += VALUE_ETAG; return xml; @@ -586,10 +613,10 @@ namespace XmlRpc { } case TypeBase64: { - int iostatus = 0; - std::ostreambuf_iterator out(os); - base64 encoder; - encoder.put(_value.asBinary->begin(), _value.asBinary->end(), out, iostatus, base64<>::crlf()); + std::stringstream buffer; + buffer.write(&(*_value.asBinary)[0], _value.asBinary->size()); + base64::encoder encoder; + encoder.encode(buffer, os); break; } case TypeArray: From 16fc0a8238f7c2963ca0b6b08a012ac939c9615e Mon Sep 17 00:00:00 2001 From: Maarten de Vries Date: Sun, 7 May 2017 16:11:24 +0200 Subject: [PATCH 2/3] Add unit test for base64 encoding/decoding. --- utilities/xmlrpcpp/CMakeLists.txt | 4 + .../{test => standalone-tests}/.cvsignore | 0 .../{test => standalone-tests}/FileClient.cpp | 0 .../{test => standalone-tests}/FileClient.dsp | 0 .../FileClient.vcproj | 0 .../HelloClient.cpp | 0 .../HelloClient.dsp | 0 .../HelloClient.vcproj | 0 .../HelloServer.cpp | 0 .../HelloServer.dsp | 0 .../HelloServer.vcproj | 0 .../{test => standalone-tests}/Makefile | 0 .../TestBase64Client.cpp | 0 .../TestBase64Client.dsp | 0 .../TestBase64Client.vcproj | 0 .../TestBase64Server.cpp | 0 .../TestBase64Server.dsp | 0 .../TestBase64Server.vcproj | 0 .../{test => standalone-tests}/TestValues.cpp | 0 .../{test => standalone-tests}/TestValues.dsp | 0 .../TestValues.vcproj | 0 .../TestValuesWin32.cpp | 0 .../{test => standalone-tests}/TestXml.cpp | 0 .../{test => standalone-tests}/TestXml.dsp | 0 .../{test => standalone-tests}/TestXml.vcproj | 0 .../{test => standalone-tests}/Validator.cpp | 0 .../{test => standalone-tests}/Validator.dsp | 0 .../Validator.vcproj | 0 .../arrayOfStructsTest.xml | 0 .../{test => standalone-tests}/bool_test.cpp | 0 .../countTheEntities.xml | 0 .../easyStructTest.xml | 0 .../{test => standalone-tests}/echo.xml | 0 .../echoStructTest.xml | 0 .../{test => standalone-tests}/pngnow.png | 0 .../port_zero_server.cpp | 0 utilities/xmlrpcpp/test/CMakeLists.txt | 2 + .../xmlrpcpp/test/xmlrpcvalue_base64.cpp | 150 ++++++++++++++++++ 38 files changed, 156 insertions(+) rename utilities/xmlrpcpp/{test => standalone-tests}/.cvsignore (100%) rename utilities/xmlrpcpp/{test => standalone-tests}/FileClient.cpp (100%) rename utilities/xmlrpcpp/{test => standalone-tests}/FileClient.dsp (100%) rename utilities/xmlrpcpp/{test => standalone-tests}/FileClient.vcproj (100%) rename utilities/xmlrpcpp/{test => standalone-tests}/HelloClient.cpp (100%) rename utilities/xmlrpcpp/{test => standalone-tests}/HelloClient.dsp (100%) rename utilities/xmlrpcpp/{test => standalone-tests}/HelloClient.vcproj (100%) rename utilities/xmlrpcpp/{test => standalone-tests}/HelloServer.cpp (100%) rename utilities/xmlrpcpp/{test => standalone-tests}/HelloServer.dsp (100%) rename utilities/xmlrpcpp/{test => standalone-tests}/HelloServer.vcproj (100%) rename utilities/xmlrpcpp/{test => standalone-tests}/Makefile (100%) rename utilities/xmlrpcpp/{test => standalone-tests}/TestBase64Client.cpp (100%) rename utilities/xmlrpcpp/{test => standalone-tests}/TestBase64Client.dsp (100%) rename utilities/xmlrpcpp/{test => standalone-tests}/TestBase64Client.vcproj (100%) rename utilities/xmlrpcpp/{test => standalone-tests}/TestBase64Server.cpp (100%) rename utilities/xmlrpcpp/{test => standalone-tests}/TestBase64Server.dsp (100%) rename utilities/xmlrpcpp/{test => standalone-tests}/TestBase64Server.vcproj (100%) rename utilities/xmlrpcpp/{test => standalone-tests}/TestValues.cpp (100%) rename utilities/xmlrpcpp/{test => standalone-tests}/TestValues.dsp (100%) rename utilities/xmlrpcpp/{test => standalone-tests}/TestValues.vcproj (100%) rename utilities/xmlrpcpp/{test => standalone-tests}/TestValuesWin32.cpp (100%) rename utilities/xmlrpcpp/{test => standalone-tests}/TestXml.cpp (100%) rename utilities/xmlrpcpp/{test => standalone-tests}/TestXml.dsp (100%) rename utilities/xmlrpcpp/{test => standalone-tests}/TestXml.vcproj (100%) rename utilities/xmlrpcpp/{test => standalone-tests}/Validator.cpp (100%) rename utilities/xmlrpcpp/{test => standalone-tests}/Validator.dsp (100%) rename utilities/xmlrpcpp/{test => standalone-tests}/Validator.vcproj (100%) rename utilities/xmlrpcpp/{test => standalone-tests}/arrayOfStructsTest.xml (100%) rename utilities/xmlrpcpp/{test => standalone-tests}/bool_test.cpp (100%) rename utilities/xmlrpcpp/{test => standalone-tests}/countTheEntities.xml (100%) rename utilities/xmlrpcpp/{test => standalone-tests}/easyStructTest.xml (100%) rename utilities/xmlrpcpp/{test => standalone-tests}/echo.xml (100%) rename utilities/xmlrpcpp/{test => standalone-tests}/echoStructTest.xml (100%) rename utilities/xmlrpcpp/{test => standalone-tests}/pngnow.png (100%) rename utilities/xmlrpcpp/{test => standalone-tests}/port_zero_server.cpp (100%) create mode 100644 utilities/xmlrpcpp/test/CMakeLists.txt create mode 100644 utilities/xmlrpcpp/test/xmlrpcvalue_base64.cpp diff --git a/utilities/xmlrpcpp/CMakeLists.txt b/utilities/xmlrpcpp/CMakeLists.txt index 8112da8873..f06350019d 100644 --- a/utilities/xmlrpcpp/CMakeLists.txt +++ b/utilities/xmlrpcpp/CMakeLists.txt @@ -52,3 +52,7 @@ install(TARGETS xmlrpcpp ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} RUNTIME DESTINATION ${CATKIN_GLOBAL_BIN_DESTINATION}) + +if (CATKIN_ENABLE_TESTING) + add_subdirectory(test) +endif() diff --git a/utilities/xmlrpcpp/test/.cvsignore b/utilities/xmlrpcpp/standalone-tests/.cvsignore similarity index 100% rename from utilities/xmlrpcpp/test/.cvsignore rename to utilities/xmlrpcpp/standalone-tests/.cvsignore diff --git a/utilities/xmlrpcpp/test/FileClient.cpp b/utilities/xmlrpcpp/standalone-tests/FileClient.cpp similarity index 100% rename from utilities/xmlrpcpp/test/FileClient.cpp rename to utilities/xmlrpcpp/standalone-tests/FileClient.cpp diff --git a/utilities/xmlrpcpp/test/FileClient.dsp b/utilities/xmlrpcpp/standalone-tests/FileClient.dsp similarity index 100% rename from utilities/xmlrpcpp/test/FileClient.dsp rename to utilities/xmlrpcpp/standalone-tests/FileClient.dsp diff --git a/utilities/xmlrpcpp/test/FileClient.vcproj b/utilities/xmlrpcpp/standalone-tests/FileClient.vcproj similarity index 100% rename from utilities/xmlrpcpp/test/FileClient.vcproj rename to utilities/xmlrpcpp/standalone-tests/FileClient.vcproj diff --git a/utilities/xmlrpcpp/test/HelloClient.cpp b/utilities/xmlrpcpp/standalone-tests/HelloClient.cpp similarity index 100% rename from utilities/xmlrpcpp/test/HelloClient.cpp rename to utilities/xmlrpcpp/standalone-tests/HelloClient.cpp diff --git a/utilities/xmlrpcpp/test/HelloClient.dsp b/utilities/xmlrpcpp/standalone-tests/HelloClient.dsp similarity index 100% rename from utilities/xmlrpcpp/test/HelloClient.dsp rename to utilities/xmlrpcpp/standalone-tests/HelloClient.dsp diff --git a/utilities/xmlrpcpp/test/HelloClient.vcproj b/utilities/xmlrpcpp/standalone-tests/HelloClient.vcproj similarity index 100% rename from utilities/xmlrpcpp/test/HelloClient.vcproj rename to utilities/xmlrpcpp/standalone-tests/HelloClient.vcproj diff --git a/utilities/xmlrpcpp/test/HelloServer.cpp b/utilities/xmlrpcpp/standalone-tests/HelloServer.cpp similarity index 100% rename from utilities/xmlrpcpp/test/HelloServer.cpp rename to utilities/xmlrpcpp/standalone-tests/HelloServer.cpp diff --git a/utilities/xmlrpcpp/test/HelloServer.dsp b/utilities/xmlrpcpp/standalone-tests/HelloServer.dsp similarity index 100% rename from utilities/xmlrpcpp/test/HelloServer.dsp rename to utilities/xmlrpcpp/standalone-tests/HelloServer.dsp diff --git a/utilities/xmlrpcpp/test/HelloServer.vcproj b/utilities/xmlrpcpp/standalone-tests/HelloServer.vcproj similarity index 100% rename from utilities/xmlrpcpp/test/HelloServer.vcproj rename to utilities/xmlrpcpp/standalone-tests/HelloServer.vcproj diff --git a/utilities/xmlrpcpp/test/Makefile b/utilities/xmlrpcpp/standalone-tests/Makefile similarity index 100% rename from utilities/xmlrpcpp/test/Makefile rename to utilities/xmlrpcpp/standalone-tests/Makefile diff --git a/utilities/xmlrpcpp/test/TestBase64Client.cpp b/utilities/xmlrpcpp/standalone-tests/TestBase64Client.cpp similarity index 100% rename from utilities/xmlrpcpp/test/TestBase64Client.cpp rename to utilities/xmlrpcpp/standalone-tests/TestBase64Client.cpp diff --git a/utilities/xmlrpcpp/test/TestBase64Client.dsp b/utilities/xmlrpcpp/standalone-tests/TestBase64Client.dsp similarity index 100% rename from utilities/xmlrpcpp/test/TestBase64Client.dsp rename to utilities/xmlrpcpp/standalone-tests/TestBase64Client.dsp diff --git a/utilities/xmlrpcpp/test/TestBase64Client.vcproj b/utilities/xmlrpcpp/standalone-tests/TestBase64Client.vcproj similarity index 100% rename from utilities/xmlrpcpp/test/TestBase64Client.vcproj rename to utilities/xmlrpcpp/standalone-tests/TestBase64Client.vcproj diff --git a/utilities/xmlrpcpp/test/TestBase64Server.cpp b/utilities/xmlrpcpp/standalone-tests/TestBase64Server.cpp similarity index 100% rename from utilities/xmlrpcpp/test/TestBase64Server.cpp rename to utilities/xmlrpcpp/standalone-tests/TestBase64Server.cpp diff --git a/utilities/xmlrpcpp/test/TestBase64Server.dsp b/utilities/xmlrpcpp/standalone-tests/TestBase64Server.dsp similarity index 100% rename from utilities/xmlrpcpp/test/TestBase64Server.dsp rename to utilities/xmlrpcpp/standalone-tests/TestBase64Server.dsp diff --git a/utilities/xmlrpcpp/test/TestBase64Server.vcproj b/utilities/xmlrpcpp/standalone-tests/TestBase64Server.vcproj similarity index 100% rename from utilities/xmlrpcpp/test/TestBase64Server.vcproj rename to utilities/xmlrpcpp/standalone-tests/TestBase64Server.vcproj diff --git a/utilities/xmlrpcpp/test/TestValues.cpp b/utilities/xmlrpcpp/standalone-tests/TestValues.cpp similarity index 100% rename from utilities/xmlrpcpp/test/TestValues.cpp rename to utilities/xmlrpcpp/standalone-tests/TestValues.cpp diff --git a/utilities/xmlrpcpp/test/TestValues.dsp b/utilities/xmlrpcpp/standalone-tests/TestValues.dsp similarity index 100% rename from utilities/xmlrpcpp/test/TestValues.dsp rename to utilities/xmlrpcpp/standalone-tests/TestValues.dsp diff --git a/utilities/xmlrpcpp/test/TestValues.vcproj b/utilities/xmlrpcpp/standalone-tests/TestValues.vcproj similarity index 100% rename from utilities/xmlrpcpp/test/TestValues.vcproj rename to utilities/xmlrpcpp/standalone-tests/TestValues.vcproj diff --git a/utilities/xmlrpcpp/test/TestValuesWin32.cpp b/utilities/xmlrpcpp/standalone-tests/TestValuesWin32.cpp similarity index 100% rename from utilities/xmlrpcpp/test/TestValuesWin32.cpp rename to utilities/xmlrpcpp/standalone-tests/TestValuesWin32.cpp diff --git a/utilities/xmlrpcpp/test/TestXml.cpp b/utilities/xmlrpcpp/standalone-tests/TestXml.cpp similarity index 100% rename from utilities/xmlrpcpp/test/TestXml.cpp rename to utilities/xmlrpcpp/standalone-tests/TestXml.cpp diff --git a/utilities/xmlrpcpp/test/TestXml.dsp b/utilities/xmlrpcpp/standalone-tests/TestXml.dsp similarity index 100% rename from utilities/xmlrpcpp/test/TestXml.dsp rename to utilities/xmlrpcpp/standalone-tests/TestXml.dsp diff --git a/utilities/xmlrpcpp/test/TestXml.vcproj b/utilities/xmlrpcpp/standalone-tests/TestXml.vcproj similarity index 100% rename from utilities/xmlrpcpp/test/TestXml.vcproj rename to utilities/xmlrpcpp/standalone-tests/TestXml.vcproj diff --git a/utilities/xmlrpcpp/test/Validator.cpp b/utilities/xmlrpcpp/standalone-tests/Validator.cpp similarity index 100% rename from utilities/xmlrpcpp/test/Validator.cpp rename to utilities/xmlrpcpp/standalone-tests/Validator.cpp diff --git a/utilities/xmlrpcpp/test/Validator.dsp b/utilities/xmlrpcpp/standalone-tests/Validator.dsp similarity index 100% rename from utilities/xmlrpcpp/test/Validator.dsp rename to utilities/xmlrpcpp/standalone-tests/Validator.dsp diff --git a/utilities/xmlrpcpp/test/Validator.vcproj b/utilities/xmlrpcpp/standalone-tests/Validator.vcproj similarity index 100% rename from utilities/xmlrpcpp/test/Validator.vcproj rename to utilities/xmlrpcpp/standalone-tests/Validator.vcproj diff --git a/utilities/xmlrpcpp/test/arrayOfStructsTest.xml b/utilities/xmlrpcpp/standalone-tests/arrayOfStructsTest.xml similarity index 100% rename from utilities/xmlrpcpp/test/arrayOfStructsTest.xml rename to utilities/xmlrpcpp/standalone-tests/arrayOfStructsTest.xml diff --git a/utilities/xmlrpcpp/test/bool_test.cpp b/utilities/xmlrpcpp/standalone-tests/bool_test.cpp similarity index 100% rename from utilities/xmlrpcpp/test/bool_test.cpp rename to utilities/xmlrpcpp/standalone-tests/bool_test.cpp diff --git a/utilities/xmlrpcpp/test/countTheEntities.xml b/utilities/xmlrpcpp/standalone-tests/countTheEntities.xml similarity index 100% rename from utilities/xmlrpcpp/test/countTheEntities.xml rename to utilities/xmlrpcpp/standalone-tests/countTheEntities.xml diff --git a/utilities/xmlrpcpp/test/easyStructTest.xml b/utilities/xmlrpcpp/standalone-tests/easyStructTest.xml similarity index 100% rename from utilities/xmlrpcpp/test/easyStructTest.xml rename to utilities/xmlrpcpp/standalone-tests/easyStructTest.xml diff --git a/utilities/xmlrpcpp/test/echo.xml b/utilities/xmlrpcpp/standalone-tests/echo.xml similarity index 100% rename from utilities/xmlrpcpp/test/echo.xml rename to utilities/xmlrpcpp/standalone-tests/echo.xml diff --git a/utilities/xmlrpcpp/test/echoStructTest.xml b/utilities/xmlrpcpp/standalone-tests/echoStructTest.xml similarity index 100% rename from utilities/xmlrpcpp/test/echoStructTest.xml rename to utilities/xmlrpcpp/standalone-tests/echoStructTest.xml diff --git a/utilities/xmlrpcpp/test/pngnow.png b/utilities/xmlrpcpp/standalone-tests/pngnow.png similarity index 100% rename from utilities/xmlrpcpp/test/pngnow.png rename to utilities/xmlrpcpp/standalone-tests/pngnow.png diff --git a/utilities/xmlrpcpp/test/port_zero_server.cpp b/utilities/xmlrpcpp/standalone-tests/port_zero_server.cpp similarity index 100% rename from utilities/xmlrpcpp/test/port_zero_server.cpp rename to utilities/xmlrpcpp/standalone-tests/port_zero_server.cpp diff --git a/utilities/xmlrpcpp/test/CMakeLists.txt b/utilities/xmlrpcpp/test/CMakeLists.txt new file mode 100644 index 0000000000..bb3a54093c --- /dev/null +++ b/utilities/xmlrpcpp/test/CMakeLists.txt @@ -0,0 +1,2 @@ +catkin_add_gtest(xmlrpcvalue_base64 xmlrpcvalue_base64.cpp) +target_link_libraries(xmlrpcvalue_base64 xmlrpcpp) diff --git a/utilities/xmlrpcpp/test/xmlrpcvalue_base64.cpp b/utilities/xmlrpcpp/test/xmlrpcvalue_base64.cpp new file mode 100644 index 0000000000..6463687e41 --- /dev/null +++ b/utilities/xmlrpcpp/test/xmlrpcvalue_base64.cpp @@ -0,0 +1,150 @@ +#include +#include "../include/xmlrpcpp/XmlRpcValue.h" + +#include +#include +#include + +int main(int argc, char **argv) +{ + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} + +namespace XmlRpc +{ + + XmlRpcValue base64Value(std::string const & data) + { + return XmlRpcValue(const_cast(&data[0]), data.size()); + } + + XmlRpcValue fromXml(std::string const & data) + { + int offset = 0; + return XmlRpcValue(data, &offset); + } + + void removeNewlines(std::string & data) + { + data.erase(std::remove(data.begin(), data.end(), '\n'), data.end()); + } + + void assertEncodeDecode(std::string const & raw, std::string const & base64) + { + XmlRpcValue value = base64Value(raw); + std::string xml ="" + base64 + ""; + XmlRpcValue parsed_value = fromXml(xml); + std::string generated_xml = value.toXml(); + removeNewlines(generated_xml); + + std::stringstream buffer; + value.write(buffer); + std::string streamed = buffer.str(); + removeNewlines(streamed); + ASSERT_EQ(streamed, base64); + + ASSERT_EQ(generated_xml, "" + base64 + ""); + ASSERT_EQ(parsed_value, value); + } + + + TEST(xmlrpcvalue_base64, empty_string) + { + assertEncodeDecode("", ""); + } + + TEST(xmlrpcvalue_base64, hello_world) + { + assertEncodeDecode("Hello World!", "SGVsbG8gV29ybGQh"); + assertEncodeDecode("Hello World!\n", "SGVsbG8gV29ybGQhCg=="); + } + + TEST(xmlrpcvalue_base64, random) + { + assertEncodeDecode( + std::string("\261", 1), + "sQ==" + ); + assertEncodeDecode( + std::string("\341\370", 2), + "4fg=" + ); + assertEncodeDecode( + std::string("\206\262J", 3), + "hrJK" + ); + assertEncodeDecode( + std::string("|5Q%", 4), + "fDVRJQ==" + ); + assertEncodeDecode( + std::string("5\220,+X", 5), + "NZAsK1g=" + ); + assertEncodeDecode( + std::string("\247\342\007M@\270", 6), + "p+IHTUC4" + ); + assertEncodeDecode( + std::string("\012\247e\013;\232*", 7), + "CqdlCzuaKg==" + ); + assertEncodeDecode( + std::string("U\374\336w\351-\2503", 8), + "Vfzed+ktqDM=" + ); + assertEncodeDecode( + std::string("\264\204`\310\001\306\253g\026", 9), + "tIRgyAHGq2cW" + ); + assertEncodeDecode( + std::string("\224\307\217\336|J^\223\237v", 10), + "lMeP3nxKXpOfdg==" + ); + assertEncodeDecode( + std::string("~%\305\024\264P)\206\224\247N", 11), + "fiXFFLRQKYaUp04=" + ); + assertEncodeDecode( + std::string("-4\355\215Q|\367\332j\013\027\006", 12), + "LTTtjVF899pqCxcG" + ); + assertEncodeDecode( + std::string("\026Q\304\204\244s%\203\023?\364\320\005", 13), + "FlHEhKRzJYMTP/TQBQ==" + ); + assertEncodeDecode( + std::string("G0\306B\251\351;mwM\312i(\000", 14), + "RzDGQqnpO213TcppKAA=" + ); + assertEncodeDecode( + std::string("\031kpC)[t\205\026\230\343S\367\016\263", 15), + "GWtwQylbdIUWmONT9w6z" + ); + assertEncodeDecode( + std::string("B&\134a\013\246u^V\001\260a\247\231}U\3278\367=G\317g\020{\277\042\373", 28), + "QiZcYQumdV5WAbBhp5l9Vdc49z1Hz2cQe78i+w==" + ); + assertEncodeDecode( + std::string("[>\303\210`\270o\023FJ\004r\360\361\357\2517\345\204|\245\267P \247V\251v\025", 29), + "Wz7DiGC4bxNGSgRy8PHvqTflhHylt1Agp1apdhU=" + ); + assertEncodeDecode( + std::string("\264\245\360=\273E%8\023\3138\227k\222WS\227uf\314\345Y\031\365Q\024\331.\210&", 30), + "tKXwPbtFJTgTyziXa5JXU5d1ZszlWRn1URTZLogm" + ); + assertEncodeDecode( + std::string("II\036\326\353\232T\221/\021\3265F}\2647A)O\2302CLY?\367O\261E\246\332\376\333\230\343\326_\373\303\225\343\351\354[\326~\264\034\305\035V\227\034\331[\012\263Y", 58), + "SUke1uuaVJEvEdY1Rn20N0EpT5gyQ0xZP/dPsUWm2v7bmOPWX/vDlePp7FvWfrQcxR1WlxzZWwqzWQ==" + ); + assertEncodeDecode( + std::string("\353\317\000-\333\230\2701\251\310&J\225\347+\221q\245tb\336\225\350\323\310\327*q\261&;\2448\033X\346\277\245GM\216Oz\365\025K1\341w\230\277\272*\365\343\204\376\334E", 59), + "688ALduYuDGpyCZKlecrkXGldGLelejTyNcqcbEmO6Q4G1jmv6VHTY5PevUVSzHhd5i/uir144T+3EU=" + ); + assertEncodeDecode( + std::string("\235\232\352\362\304\351n\244\227\220\202hh\226\346\271\042\021d\362c\267\260\310`\000\034\247\215\350\013;#2\204(^_\333w\2233\374\337\205\253y\372\352\305F-\200v\034\331\216\205\011", 60), + "nZrq8sTpbqSXkIJoaJbmuSIRZPJjt7DIYAAcp43oCzsjMoQoXl/bd5Mz/N+Fq3n66sVGLX+AdhzZjoUJ" + ); + } +} From 19dc88e38a2d58085307d4c5e2dac3d281ff6fe6 Mon Sep 17 00:00:00 2001 From: Maarten de Vries Date: Tue, 18 Jul 2017 23:51:50 +0200 Subject: [PATCH 3/3] Add a base64.h with #error explaining why it is removed. --- utilities/xmlrpcpp/include/xmlrpcpp/base64.h | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 utilities/xmlrpcpp/include/xmlrpcpp/base64.h diff --git a/utilities/xmlrpcpp/include/xmlrpcpp/base64.h b/utilities/xmlrpcpp/include/xmlrpcpp/base64.h new file mode 100644 index 0000000000..f51244cfc4 --- /dev/null +++ b/utilities/xmlrpcpp/include/xmlrpcpp/base64.h @@ -0,0 +1,3 @@ +#error This header was removed due to licensing issues. \ +Please use a dedicated base64 library if you need one for your own project. \ +See https://github.com/ros/ros_comm/pull/1046 for more details.