30 static const std::array<char, 64> encode_table{
31 'A',
'B',
'C',
'D',
'E',
'F',
'G',
'H',
'I',
'J',
'K',
'L',
'M',
32 'N',
'O',
'P',
'Q',
'R',
'S',
'T',
'U',
'V',
'W',
'X',
'Y',
'Z',
33 'a',
'b',
'c',
'd',
'e',
'f',
'g',
'h',
'i',
'j',
'k',
'l',
'm',
34 'n',
'o',
'p',
'q',
'r',
's',
't',
'u',
'v',
'w',
'x',
'y',
'z',
35 '0',
'1',
'2',
'3',
'4',
'5',
'6',
'7',
'8',
'9',
'+',
'/'};
37 "Requested index out of range. Input invalid");
38 return encode_table[index];
50 std::array<unsigned, 256> et_reversed{};
53 et_reversed.fill(256);
54 const unsigned n_chars_{64};
55 for (
unsigned i{}; i < n_chars_; i++) {
56 et_reversed[
static_cast<unsigned>(char_encode_table(i))] = i;
63 static const std::array<unsigned, 256> decode_table{
64 ReverseCharEncodeTable_()};
66 "Requested index out of range. Input invalid");
68 "Invalid decode type, this should never occur!");
69 return decode_table[index];
73 static bool isValidBase64String(
const std::string& s) {
75 bool is_valid{s.size() % 4 == 0};
77 return is_valid && std::all_of(s.begin(), s.end(), [](
const char& c) {
78 return isalnum(c) || c ==
'+' || c ==
'/' || c ==
'=';
89 const std::string delimiters(
" \n\t");
90 size_t first = s.find_first_not_of(delimiters);
91 if (std::string::npos == first) {
92 GISMO_ERROR(
"Empty string cannot be converted into data-vector");
94 size_t last = s.find_last_not_of(delimiters);
95 return s.substr(first, (last - first + 1));
107 const std::size_t& minimum_n_bytes_required) {
109 const std::size_t additional_padding_bytes =
110 (3 - minimum_n_bytes_required % 3) % 3;
113 const std::size_t number_of_groups =
114 (minimum_n_bytes_required + additional_padding_bytes) / 3;
117 std::string encoded_string;
118 encoded_string.reserve(number_of_groups * 4);
121 for (std::size_t i_group{}; i_group < number_of_groups; i_group++) {
122 const std::size_t buffer_index = i_group * 3;
123 std::array<ByteRepresentation, 3> buffer{};
124 buffer[0] = buffer_index < minimum_n_bytes_required
125 ? byte_vector_ptr[buffer_index + 0]
127 buffer[1] = buffer_index < minimum_n_bytes_required
128 ? byte_vector_ptr[buffer_index + 1]
130 buffer[2] = buffer_index < minimum_n_bytes_required
131 ? byte_vector_ptr[buffer_index + 2]
135 encoded_string.push_back(
136 char_encode_table(((buffer[0] & 0xfc) >> 2)));
137 encoded_string.push_back(char_encode_table(
138 ((buffer[0] & 0x03) << 4) + ((buffer[1] & 0xf0) >> 4)));
139 encoded_string.push_back(char_encode_table(
140 ((buffer[1] & 0x0f) << 2) + ((buffer[2] & 0xc0) >> 6)));
141 encoded_string.push_back(
142 char_encode_table(((buffer[2] & 0x3f) << 0)));
146 for (
size_t i = 0; i < additional_padding_bytes; ++i) {
147 encoded_string[number_of_groups * 4 - i - 1] =
'=';
152 isValidBase64String(encoded_string),
153 "Something went wrong in B64 encoding, please write an issue");
154 return encoded_string;
171 template <
typename BaseType,
typename TargetType>
175 const unsigned rows = result.rows();
176 const unsigned cols = result.cols();
178 if (base_vector.size() != (rows * cols)) {
180 "Input array has the wrong size or could not be converted");
184 for (
unsigned i = 0; i < rows; ++i) {
185 for (
unsigned j = 0; j < cols; ++j) {
187 static_cast<TargetType
>(base_vector[i * cols + j]);
200 template <
typename BaseType,
typename TargetType>
202 std::vector<TargetType>& result) {
203 std::transform(base_vector.cbegin(), base_vector.cend(),
204 std::back_inserter(result), [](
const BaseType& c) {
205 return static_cast<TargetType
>(c);
217 template <
typename BaseType>
218 static std::string
Encode(
const std::vector<BaseType>& data_vector) {
223 constexpr
const std::size_t length_of_entry{
sizeof(BaseType{})};
225 const std::size_t minimum_n_bytes_required =
226 length_of_entry * data_vector.size();
228 return Encode_(vector_as_bytes_ptr, minimum_n_bytes_required);
239 template <
typename BaseType>
241 const bool& row_wise =
true) {
243 "Encoding is unsafe for non-arithmetic types.");
247 if ((data_vector.cols() == 1) || (data_vector.rows() == 1) ||
253 constexpr
const std::size_t length_of_entry{
sizeof(BaseType{})};
255 const std::size_t minimum_n_bytes_required =
256 length_of_entry * data_vector.size();
258 return Encode_(vector_as_bytes_ptr, minimum_n_bytes_required);
263 std::vector<BaseType> copy_of_matrix;
264 copy_of_matrix.reserve(data_vector.rows() * data_vector.cols());
269 for (
index_t i = 0; i < data_vector.rows(); ++i) {
270 for (
index_t j = 0; j < data_vector.cols(); ++j) {
271 copy_of_matrix.push_back(data_vector(i, j));
275 for (
index_t j = 0; j < data_vector.cols(); ++j) {
276 for (
index_t i = 0; i < data_vector.rows(); ++i) {
277 copy_of_matrix.push_back(data_vector(i, j));
282 return Encode(copy_of_matrix);
294 template <
typename OutputType>
295 static std::vector<OutputType>
Decode(
const std::string& base64string) {
297 const std::string& base64string_trimmed = trimWhitespaces(base64string);
300 "Validity check failed");
303 const std::size_t number_of_groups{base64string_trimmed.size() / 4};
304 constexpr
const std::size_t length_of_entry{
sizeof(OutputType{})};
305 const std::size_t number_of_output_values{(number_of_groups * 3) /
307 std::vector<OutputType> return_value;
308 return_value.resize(number_of_output_values);
315 for (std::size_t i_group{}; i_group < number_of_groups; i_group++) {
316 const std::size_t buffer_index = i_group * 4;
317 std::array<unsigned, 4> buffer{};
318 for (
unsigned i{}; i < 4; i++) {
319 buffer[i] = base64string_trimmed[buffer_index + i] !=
'='
320 ? char_decode_table(static_cast<unsigned>(
321 base64string_trimmed[buffer_index + i]))
326 if (buffer[1] != 255) {
327 vector_as_bytes[i_group * 3] =
328 ((buffer[0] & 0x3f) << 2) + ((buffer[1] & 0x30) >> 4);
330 if (buffer[2] != 255) {
331 vector_as_bytes[i_group * 3 + 1] =
332 ((buffer[1] & 0x0f) << 4) + ((buffer[2] & 0x3c) >> 2);
334 if (buffer[3] != 255) {
335 vector_as_bytes[i_group * 3 + 2] =
336 ((buffer[2] & 0x03) << 6) + ((buffer[3] & 0x3f) >> 0);
354 template <
typename ScalarType>
356 const std::string& base_type_flag_,
360 std::none_of(base_type_flag_.begin(), base_type_flag_.end(),
362 "Format flag {ascii, b64float64, ...} must be all lowercase.");
365 if (std::is_integral<ScalarType>::value ^
366 (base_type_flag_.find(
"int") != std::string::npos)) {
368 "Conversions from integral to floating type and vice-versa is "
373 if (base_type_flag_ ==
"b64uint16") {
374 CopyIntoGsMatrix(Decode<uint16_t>(base64_string), result);
375 }
else if (base_type_flag_ ==
"b64uint32") {
376 CopyIntoGsMatrix(Decode<uint32_t>(base64_string), result);
377 }
else if (base_type_flag_ ==
"b64bint64") {
378 CopyIntoGsMatrix(Decode<uint64_t>(base64_string), result);
379 }
else if (base_type_flag_ ==
"b64int16") {
380 CopyIntoGsMatrix(Base64::Decode<int16_t>(base64_string), result);
381 }
else if (base_type_flag_ ==
"b64int32") {
382 CopyIntoGsMatrix(Base64::Decode<int32_t>(base64_string), result);
383 }
else if (base_type_flag_ ==
"b64int64") {
384 CopyIntoGsMatrix(Base64::Decode<int64_t>(base64_string), result);
385 }
else if (base_type_flag_ ==
"b64float32") {
386 CopyIntoGsMatrix(Base64::Decode<float>(base64_string), result);
387 }
else if (base_type_flag_ ==
"b64float64") {
388 CopyIntoGsMatrix(Base64::Decode<double>(base64_string), result);
390 GISMO_ERROR(
"Reading matrix from XML found unknown type");
406 template <
typename ScalarType>
408 const std::string& base_type_flag_,
409 std::vector<ScalarType>& result) {
412 std::none_of(base_type_flag_.begin(), base_type_flag_.end(),
414 "Format flag {ascii, b64float64, ...} must be all lowercase.");
417 if (std::is_integral<ScalarType>::value ^
418 (base_type_flag_.find(
"int") != std::string::npos)) {
420 "Conversions from integral to floating type and vice-versa is "
425 if (base_type_flag_ ==
"b64uint16") {
426 CopyIntoVector(Decode<uint16_t>(base64_string), result);
427 }
else if (base_type_flag_ ==
"b64uint32") {
428 CopyIntoVector(Decode<uint32_t>(base64_string), result);
429 }
else if (base_type_flag_ ==
"b64bint64") {
430 CopyIntoVector(Decode<uint64_t>(base64_string), result);
431 }
else if (base_type_flag_ ==
"b64int16") {
432 CopyIntoVector(Base64::Decode<int16_t>(base64_string), result);
433 }
else if (base_type_flag_ ==
"b64int32") {
434 CopyIntoVector(Base64::Decode<int32_t>(base64_string), result);
435 }
else if (base_type_flag_ ==
"b64int64") {
436 CopyIntoVector(Base64::Decode<int64_t>(base64_string), result);
437 }
else if (base_type_flag_ ==
"b64float32") {
438 CopyIntoVector(Base64::Decode<float>(base64_string), result);
439 }
else if (base_type_flag_ ==
"b64float64") {
440 CopyIntoVector(Base64::Decode<double>(base64_string), result);
442 GISMO_ERROR(
"Reading matrix from XML found unknown type");
static std::string trimWhitespaces(const std::string &s)
Trim trailing and preceding whitespaces.
Definition: gsBase64.h:88
Provides declaration of Matrix class.
static std::vector< OutputType > Decode(const std::string &base64string)
Reading a B64 string, transforming it into a vector of a specific type.
Definition: gsBase64.h:295
static const std::array< unsigned, 256 > ReverseCharEncodeTable_()
Reverse the encoding table in an array.
Definition: gsBase64.h:49
static void DecodeIntoGsType(const std::string &base64_string, const std::string &base_type_flag_, std::vector< ScalarType > &result)
Decode a string and copy into requested gismo Type.
Definition: gsBase64.h:407
static std::string Encode(const std::vector< BaseType > &data_vector)
Helper routine for std::vector data.
Definition: gsBase64.h:218
static void CopyIntoVector(const std::vector< BaseType > &base_vector, std::vector< TargetType > &result)
Cast a vector of a base type into a vector of TargetType.
Definition: gsBase64.h:201
static void DecodeIntoGsType(const std::string &base64_string, const std::string &base_type_flag_, gsMatrix< ScalarType > &result)
Decode a string and copy into requested gismo Type.
Definition: gsBase64.h:355
#define index_t
Definition: gsConfig.h:32
static char char_encode_table(const unsigned &index)
Look up table.
Definition: gsBase64.h:27
A matrix with arbitrary coefficient type and fixed or dynamic size.
Definition: gsMatrix.h:38
This file contains the debugging and messaging system of G+Smo.
#define GISMO_ASSERT(cond, message)
Definition: gsDebug.h:89
Encode for base64 export.
Definition: gsBase64.h:21
static std::string Encode(const gsMatrix< BaseType > &data_vector, const bool &row_wise=true)
Helper routine for gsMatrix Types (non-sparse)
Definition: gsBase64.h:240
static void CopyIntoGsMatrix(const std::vector< BaseType > &base_vector, gsMatrix< TargetType > &result)
Copy a read vector of type BaseType into a gsMatrix with ScalarType TargetType.
Definition: gsBase64.h:172
static unsigned char_decode_table(const unsigned &index)
Lookup Table for Decoding B64 string.
Definition: gsBase64.h:62
#define GISMO_ERROR(message)
Definition: gsDebug.h:118
static std::string Encode_(const ByteRepresentation *byte_vector_ptr, const std::size_t &minimum_n_bytes_required)
Actual encoding routine where byte-stream is transformed and encoded.
Definition: gsBase64.h:106
unsigned char ByteRepresentation
Alias for one byte type.
Definition: gsBase64.h:24