#include <stdexcept>
#include <algorithm>
#include <cmath> // for round()
+#include <climits>
#include <wchar.h>
#include <stdlib.h>
#include <boost/numeric/conversion/cast.hpp>
#include <boost/foreach.hpp>
+#include <boost/assert.hpp>
+#include <boost/shared_ptr.hpp>
+#include <openssl/bio.h>
+#include <openssl/evp.h>
+
#include <stringfunc.hxx>
using namespace std;
return result;
} // eo join_string(const std::vector< std::string >&,const std::string&)
+std::string join_string (
+ const char *const parts[], /* assumed NULL-terminated */
+ const std::string& delimiter
+)
+{
+ std::string result;
+
+ if (parts != NULL)
+ {
+ const char *const *cur = parts;
+
+ if (*cur != NULL) {
+ result = std::string (*cur);
+
+ while (*++cur != NULL) {
+ result += delimiter;
+ result += std::string (*cur);
+ }
+ }
+ }
+
+ return result;
+}
+
/*
} // eo convert_hex_to_binary(const std::string&)
+static list<string>& alloc_template_starts()
+{
+ static list<string> result;
+ if (result.empty())
+ {
+ result.push_back("std::list");
+ result.push_back("std::vector");
+ }
+ return result;
+}
+
+string shorten_stl_types(const string &input)
+{
+ string output = input;
+
+ // first: replace fixed string for std::string
+ replace_all(output, "std::basic_string<char, std::char_traits<char>, std::allocator<char> >",
+ "std::string");
+
+ // loop over list/vector/... that have an allocator, e.g.
+ // std::list< some_type_here, std::allocator<some_type_here> >
+ string::size_type start, comma, end, len, start_text_len;
+ int n_open_brackets;
+ string allocator_text;
+ BOOST_FOREACH(const string &start_text, alloc_template_starts())
+ {
+ start = 0;
+ comma = 0;
+ end = 0;
+ start_text_len = start_text.length();
+ while( (start=output.find(start_text+"<", start)) != string::npos )
+ {
+ len = output.length();
+ start += start_text_len+1; // start next iter and tests here after opening bracket
+
+ // now comes the tricky part: find matching ',' and the closing '>' even if "subtype" is template again
+ comma = start;
+ n_open_brackets = 1; // the bracket right after start_text counts as first
+ while (comma < len && n_open_brackets > 0)
+ {
+ if (output[comma] == ',' && n_open_brackets == 1)
+ break;
+ else if (output[comma] == '<')
+ ++n_open_brackets;
+ else if (output[comma] == '>')
+ --n_open_brackets;
+ ++comma;
+ }
+ end = comma+1;
+ while (end < len && n_open_brackets > 0)
+ {
+ if (output[end] == '<')
+ ++n_open_brackets;
+ else if (output[end] == '>')
+ {
+ --n_open_brackets;
+ if (n_open_brackets == 0)
+ break; // do not increment end
+ }
+ ++end;
+ }
+
+ // check that start < comma < end < len && n_open_brackets == 0
+ if (start >= comma || comma >= end || end >= len || n_open_brackets != 0)
+ continue; // input seems to be of unexpected form
+
+ // check that type in allocator is same as until comma
+ string type = output.substr(start, comma-start);
+ if (type[type.length()-1] == '>')
+ allocator_text = string("std::allocator<") + type + " > ";
+ else
+ allocator_text = string("std::allocator<") + type + "> ";
+ if (output.substr(comma+2, end-comma-2) == allocator_text)
+ output.replace(comma+2, end-comma-2, "_alloc_");
+ }
+ }
+
+ return output;
+}
+
+typedef boost::shared_ptr<BIO> BIO_Ptr;
+
+/**
+* @brief Converts openssl generic input/output to std::string
+*
+* Code adapted from keymakerd.
+*
+* @param bio Openssl's generic input/output
+* @return :string STL string
+**/
+static std::string _convert_BIO_to_string(BIO *input)
+{
+ std::string rtn;
+
+ char *output = NULL;
+ long written = BIO_get_mem_data(input, &output);
+ if (written <= 0 || output == NULL)
+ return rtn;
+
+ rtn.assign(output, written); //lint !e534 !e732
+ return rtn;
+} //lint !e1764
+
+/**
+ * @brief base64 encode a string using OpenSSL base64 functions
+ *
+ * Data size limit is 2GB on 32 bit (LONG_MAX)
+ *
+ * @param input String to encode
+ * @param one_line Encode all data as one line, no wrapping with line feeds
+ * @return base64 encoded string
+ */
+std::string base64_encode(const std::string &input, bool one_line)
+{
+ // check for empty buffer
+ if (input.empty())
+ return input;
+
+ // safety check to ensure our check afer BIO_write() works
+ if (input.size() >= LONG_MAX)
+ throw runtime_error("base64 encode: Too much data");
+
+ // setup encoder. Note: BIO_free_all frees both BIOs.
+ BIO_Ptr base64_encoder(BIO_new(BIO_f_base64()), BIO_free_all);
+ BIO *encoder_bio = base64_encoder.get();
+ if (one_line)
+ BIO_set_flags(encoder_bio, BIO_FLAGS_BASE64_NO_NL);
+
+ // chain output buffer and encoder together
+ BIO *encoded_result = BIO_new(BIO_s_mem());
+ BIO_push(encoder_bio, encoded_result);
+
+ // encode
+ long written = BIO_write(encoder_bio, input.c_str(), input.size());
+ if ((unsigned)written != input.size())
+ {
+ ostringstream out;
+ out << "base64 encoding failed: input size: "
+ << input.size() << " vs. output size: " << written;
+ throw runtime_error(out.str());
+ }
+ if (BIO_flush(encoder_bio) != 1)
+ throw runtime_error("base64 encode: BIO_flush() failed");
+
+ return _convert_BIO_to_string(encoded_result);
+}
+
+/**
+ * @brief base64 decode a string using OpenSSL base64 functions
+ *
+ * @param input String to decode
+ * @param one_line Expect all base64 data in one line. Input with line feeds will fail.
+ * @return base64 decoded string
+ */
+std::string base64_decode(const std::string &input, bool one_line)
+{
+ // check for empty buffer
+ if (input.empty())
+ return input;
+
+ // safety check for BIO_new_mem_buf()
+ if (input.size() >= INT_MAX)
+ throw runtime_error("base64 decode: Too much data");
+
+ // setup encoder. Note: BIO_free_all frees both BIOs.
+ BIO_Ptr base64_decoder(BIO_new(BIO_f_base64()), BIO_free_all);
+ BIO *bio_base64 = base64_decoder.get();
+ if (one_line)
+ BIO_set_flags(bio_base64, BIO_FLAGS_BASE64_NO_NL);
+
+ // chain input buffer and decoder together
+ BIO *bio_input = BIO_new_mem_buf((void*)input.c_str(), input.size());
+ bio_input = BIO_push(bio_base64, bio_input);
+
+ BIO_Ptr decoded_result(BIO_new(BIO_s_mem()), BIO_free_all);
+ BIO *bio_decoded = decoded_result.get();
+ const int convbuf_size = 512;
+ char convbuf[convbuf_size];
+
+ long read_bytes = 0;
+ while((read_bytes = BIO_read(bio_input, convbuf, convbuf_size)) > 0)
+ {
+ BOOST_ASSERT(read_bytes <= convbuf_size);
+ long written_bytes = BIO_write(bio_decoded, convbuf, read_bytes);
+ if (written_bytes != read_bytes)
+ {
+ ostringstream out;
+ out << "base64 decoding failed: read_bytes: "
+ << read_bytes << " vs. written_bytes: " << written_bytes;
+ throw runtime_error(out.str());
+ }
+ }
+ if (read_bytes == -2 || read_bytes == -1)
+ throw runtime_error("base64 decode: Error during decoding");
+
+ return _convert_BIO_to_string(bio_decoded);
+}
+
} // eo namespace I2n
};
-long double rounding_upwards(
+static long double rounding_upwards(
const long double number,
const int rounding_multiplier
)