Home  · Classes  · Annotated Classes  · Modules  · Members  · Namespaces  · Related Pages
Base64.h
Go to the documentation of this file.
1 // --------------------------------------------------------------------------
2 // OpenMS -- Open-Source Mass Spectrometry
3 // --------------------------------------------------------------------------
4 // Copyright The OpenMS Team -- Eberhard Karls University Tuebingen,
5 // ETH Zurich, and Freie Universitaet Berlin 2002-2015.
6 //
7 // This software is released under a three-clause BSD license:
8 // * Redistributions of source code must retain the above copyright
9 // notice, this list of conditions and the following disclaimer.
10 // * Redistributions in binary form must reproduce the above copyright
11 // notice, this list of conditions and the following disclaimer in the
12 // documentation and/or other materials provided with the distribution.
13 // * Neither the name of any author or any participating institution
14 // may be used to endorse or promote products derived from this software
15 // without specific prior written permission.
16 // For a full list of authors, refer to the file AUTHORS.
17 // --------------------------------------------------------------------------
18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 // ARE DISCLAIMED. IN NO EVENT SHALL ANY OF THE AUTHORS OR THE CONTRIBUTING
22 // INSTITUTIONS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
23 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
25 // OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26 // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
27 // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
28 // ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 //
30 // --------------------------------------------------------------------------
31 // $Maintainer: Andreas Bertsch $
32 // $Authors: Marc Sturm $
33 // --------------------------------------------------------------------------
34 
35 #ifndef OPENMS_FORMAT_BASE64_H
36 #define OPENMS_FORMAT_BASE64_H
37 
38 #ifndef OPENMS_IS_BIG_ENDIAN
39 #if defined OPENMS_BIG_ENDIAN
40 #define OPENMS_IS_BIG_ENDIAN true
41 #else
42 #define OPENMS_IS_BIG_ENDIAN false
43 #endif
44 #endif
45 
46 #include <OpenMS/CONCEPT/Types.h>
49 #include <algorithm>
50 #include <iterator>
51 #include <cmath>
52 #include <vector>
53 
54 #include <QByteArray>
55 #include <zlib.h>
56 
57 namespace OpenMS
58 {
64  class OPENMS_DLLAPI Base64
65  {
66 
67 public:
68 
70  Base64();
71 
73  virtual ~Base64();
74 
76  enum ByteOrder
77  {
79  BYTEORDER_LITTLEENDIAN
80  };
81 
89  template <typename FromType>
90  void encode(std::vector<FromType> & in, ByteOrder to_byte_order, String & out, bool zlib_compression = false);
91 
97  template <typename ToType>
98  void decode(const String & in, ByteOrder from_byte_order, std::vector<ToType> & out, bool zlib_compression = false);
99 
107  template <typename FromType>
108  void encodeIntegers(std::vector<FromType> & in, ByteOrder to_byte_order, String & out, bool zlib_compression = false);
109 
115  template <typename ToType>
116  void decodeIntegers(const String & in, ByteOrder from_byte_order, std::vector<ToType> & out, bool zlib_compression = false);
117 
130  void encodeStrings(const std::vector<String> & in, String & out, bool zlib_compression = false, bool append_null_byte = true);
131 
141  void decodeStrings(const String & in, std::vector<String> & out, bool zlib_compression = false);
142 
150  void decodeSingleString(const String & in, QByteArray & base64_uncompressed, bool zlib_compression);
151 
152 private:
153 
156  {
157  double f;
159  };
160 
163  {
164  float f;
166  };
167 
168  static const char encoder_[];
169  static const char decoder_[];
171  template <typename ToType>
172  void decodeUncompressed_(const String & in, ByteOrder from_byte_order, std::vector<ToType> & out);
173 
175  template <typename ToType>
176  void decodeCompressed_(const String & in, ByteOrder from_byte_order, std::vector<ToType> & out);
177 
179  template <typename ToType>
180  void decodeIntegersUncompressed_(const String & in, ByteOrder from_byte_order, std::vector<ToType> & out);
181 
183  template <typename ToType>
184  void decodeIntegersCompressed_(const String & in, ByteOrder from_byte_order, std::vector<ToType> & out);
185  };
186 
188  inline Int32 endianize32(Int32 & n)
189  {
190  return ((n & 0xff) << 24) | ((n & 0xff00) << 8) | ((n & 0xff0000) >> 8) | ((n & 0xff000000) >> 24);
191  }
192 
194  inline Int64 endianize64(Int64 & n)
195  {
196  return ((n & 0x00000000000000ffll) << 56) |
197  ((n & 0x000000000000ff00ll) << 40) |
198  ((n & 0x0000000000ff0000ll) << 24) |
199  ((n & 0x00000000ff000000ll) << 8) |
200  ((n & 0x000000ff00000000ll) >> 8) |
201  ((n & 0x0000ff0000000000ll) >> 24) |
202  ((n & 0x00ff000000000000ll) >> 40) |
203  ((n & 0xff00000000000000ll) >> 56);
204  }
205 
206  template <typename FromType>
207  void Base64::encode(std::vector<FromType> & in, ByteOrder to_byte_order, String & out, bool zlib_compression)
208  {
209  out.clear();
210  if (in.empty())
211  return;
212 
213  //initialize
214  const Size element_size = sizeof(FromType);
215  const Size input_bytes = element_size * in.size();
216  String compressed;
217  Byte * it;
218  Byte * end;
219  //Change endianness if necessary
221  {
222  if (element_size == 4)
223  {
224  for (Size i = 0; i < in.size(); ++i)
225  {
226  Reinterpreter32_ tmp;
227  tmp.f = in[i];
228  tmp.i = endianize32(tmp.i);
229  in[i] = tmp.f;
230  }
231  }
232  else
233  {
234  for (Size i = 0; i < in.size(); ++i)
235  {
236  Reinterpreter64_ tmp;
237  tmp.f = in[i];
238  tmp.i = endianize64(tmp.i);
239  in[i] = tmp.f;
240  }
241  }
242  }
243 
244  //encode with compression
245  if (zlib_compression)
246  {
247  unsigned long sourceLen = (unsigned long)in.size();
248  unsigned long compressed_length = //compressBound((unsigned long)in.size());
249  sourceLen + (sourceLen >> 12) + (sourceLen >> 14) + 11; // taken from zlib's compress.c, as we cannot use compressBound*
250  //
251  // (*) compressBound is not defined in the QtCore lib, which forces the linker under windows to link in our zlib.
252  // This leads to multiply defined symbols as compress() is then defined twice.
253 
254  int zlib_error;
255  do
256  {
257  compressed.resize(compressed_length);
258  zlib_error = compress(reinterpret_cast<Bytef *>(&compressed[0]), &compressed_length, reinterpret_cast<Bytef *>(&in[0]), (unsigned long)input_bytes);
259 
260  switch (zlib_error)
261  {
262  case Z_MEM_ERROR:
263  throw Exception::OutOfMemory(__FILE__, __LINE__, __PRETTY_FUNCTION__, compressed_length);
264  break;
265 
266  case Z_BUF_ERROR:
267  compressed_length *= 2;
268  }
269  }
270  while (zlib_error == Z_BUF_ERROR);
271 
272  if (zlib_error != Z_OK)
273  {
274  throw Exception::ConversionError(__FILE__, __LINE__, __PRETTY_FUNCTION__, "Compression error?");
275  }
276 
277  String(compressed).swap(compressed);
278  it = reinterpret_cast<Byte *>(&compressed[0]);
279  end = it + compressed_length;
280  out.resize((Size)ceil(compressed_length / 3.) * 4); //resize output array in order to have enough space for all characters
281  }
282  //encode without compression
283  else
284  {
285  out.resize((Size)ceil(input_bytes / 3.) * 4); //resize output array in order to have enough space for all characters
286  it = reinterpret_cast<Byte *>(&in[0]);
287  end = it + input_bytes;
288  }
289 
290  Byte * to = reinterpret_cast<Byte *>(&out[0]);
291 
292 
293  Size written = 0;
294 
295  while (it != end)
296  {
297  Int int_24bit = 0;
298  Int padding_count = 0;
299 
300  // construct 24-bit integer from 3 bytes
301  for (Size i = 0; i < 3; i++)
302  {
303  if (it != end)
304  {
305  int_24bit |= *it++ << ((2 - i) * 8);
306  }
307  else
308  {
309  padding_count++;
310  }
311  }
312 
313  // write out 4 characters
314  for (Int i = 3; i >= 0; i--)
315  {
316  to[i] = encoder_[int_24bit & 0x3F];
317  int_24bit >>= 6;
318  }
319 
320  // fixup for padding
321  if (padding_count > 0)
322  to[3] = '=';
323  if (padding_count > 1)
324  to[2] = '=';
325 
326  to += 4;
327  written += 4;
328  }
329 
330  out.resize(written); //no more space is needed
331  }
332 
333  template <typename ToType>
334  void Base64::decode(const String & in, ByteOrder from_byte_order, std::vector<ToType> & out, bool zlib_compression)
335  {
336  if (zlib_compression)
337  {
338  decodeCompressed_(in, from_byte_order, out);
339  }
340  else
341  {
342  decodeUncompressed_(in, from_byte_order, out);
343  }
344  }
345 
346  template <typename ToType>
347  void Base64::decodeCompressed_(const String & in, ByteOrder from_byte_order, std::vector<ToType> & out)
348  {
349  out.clear();
350  if (in == "")
351  return;
352 
353  void * byte_buffer;
354  Size buffer_size;
355  std::vector<unsigned char> binary;
356  const Size element_size = sizeof(ToType);
357 
358  String decompressed;
359 
360  QByteArray qt_byte_array = QByteArray::fromRawData(in.c_str(), (int) in.size());
361  QByteArray bazip = QByteArray::fromBase64(qt_byte_array);
362  QByteArray czip;
363  czip.resize(4);
364  czip[0] = (bazip.size() & 0xff000000) >> 24;
365  czip[1] = (bazip.size() & 0x00ff0000) >> 16;
366  czip[2] = (bazip.size() & 0x0000ff00) >> 8;
367  czip[3] = (bazip.size() & 0x000000ff);
368  czip += bazip;
369  QByteArray base64_uncompressed = qUncompress(czip);
370 
371  if (base64_uncompressed.isEmpty())
372  {
373  throw Exception::ConversionError(__FILE__, __LINE__, __PRETTY_FUNCTION__, "Decompression error?");
374  }
375  decompressed.resize(base64_uncompressed.size());
376 
377  std::copy(base64_uncompressed.begin(), base64_uncompressed.end(), decompressed.begin());
378 
379  byte_buffer = reinterpret_cast<void *>(&decompressed[0]);
380  buffer_size = decompressed.size();
381 
382  //change endianness if necessary
383  if ((OPENMS_IS_BIG_ENDIAN && from_byte_order == Base64::BYTEORDER_LITTLEENDIAN) || (!OPENMS_IS_BIG_ENDIAN && from_byte_order == Base64::BYTEORDER_BIGENDIAN))
384  {
385  if (element_size == 4)
386  {
387  const float * float_buffer = reinterpret_cast<const float *>(byte_buffer);
388  if (buffer_size % element_size != 0)
389  throw Exception::ConversionError(__FILE__, __LINE__, __PRETTY_FUNCTION__, "Bad BufferCount?");
390  Size float_count = buffer_size / element_size;
391  Int32 * p = reinterpret_cast<Int32 *>(byte_buffer);
392  std::transform(p, p + float_count, p, endianize32);
393  out.assign(float_buffer, float_buffer + float_count);
394  }
395  else
396  {
397  const double * float_buffer = reinterpret_cast<const double *>(byte_buffer);
398 
399  if (buffer_size % element_size != 0)
400  throw Exception::ConversionError(__FILE__, __LINE__, __PRETTY_FUNCTION__, "Bad BufferCount?");
401 
402  Size float_count = buffer_size / element_size;
403 
404  Int64 * p = reinterpret_cast<Int64 *>(byte_buffer);
405  std::transform(p, p + float_count, p, endianize64);
406 
407  out.resize(float_count);
408  // do NOT use assign here, as it will give a lot of type conversion warnings on VS compiler
409  for (Size i = 0; i < float_count; ++i)
410  {
411  out[i] = (ToType) * float_buffer;
412  ++float_buffer;
413  }
414  }
415  }
416  else
417  {
418  if (element_size == 4)
419  {
420  const float * float_buffer = reinterpret_cast<const float *>(byte_buffer);
421  if (buffer_size % element_size != 0)
422  throw Exception::ConversionError(__FILE__, __LINE__, __PRETTY_FUNCTION__, "Bad BufferCount while decoding?");
423 
424  Size float_count = buffer_size / element_size;
425  out.assign(float_buffer, float_buffer + float_count);
426  }
427  else
428  {
429  const double * float_buffer = reinterpret_cast<const double *>(byte_buffer);
430 
431  if (buffer_size % element_size != 0)
432  throw Exception::ConversionError(__FILE__, __LINE__, __PRETTY_FUNCTION__, "Bad BufferCount while decoding?");
433 
434  Size float_count = buffer_size / element_size;
435  out.resize(float_count);
436  // do NOT use assign here, as it will give a lot of type conversion warnings on VS compiler
437  for (Size i = 0; i < float_count; ++i)
438  {
439  out[i] = (ToType) * float_buffer;
440  ++float_buffer;
441  }
442  }
443  }
444 
445  }
446 
447  template <typename ToType>
448  void Base64::decodeUncompressed_(const String & in, ByteOrder from_byte_order, std::vector<ToType> & out)
449  {
450  out.clear();
451 
452  // The length of a base64 string is a always a multiple of 4 (always 3
453  // bytes are encoded as 4 characters)
454  if (in.size() < 4)
455  {
456  return;
457  }
458 
459  Size src_size = in.size();
460  // last one or two '=' are skipped if contained
461  int padding = 0;
462  if (in[src_size - 1] == '=') padding++;
463  if (in[src_size - 2] == '=') padding++;
464 
465  src_size -= padding;
466 
467  register UInt a;
468  register UInt b;
469 
470  UInt offset = 0;
471  int inc = 1;
472  UInt written = 0;
473 
474  const Size element_size = sizeof(ToType);
475 
476  // enough for either float or double
477  char element[8] = "\x00\x00\x00\x00\x00\x00\x00";
478 
479  if ((OPENMS_IS_BIG_ENDIAN && from_byte_order == Base64::BYTEORDER_LITTLEENDIAN) || (!OPENMS_IS_BIG_ENDIAN && from_byte_order == Base64::BYTEORDER_BIGENDIAN))
480  {
481  offset = (element_size - 1); // other endian
482  inc = -1;
483  }
484  else
485  {
486  offset = 0;
487  inc = 1;
488  }
489 
490  //reserve enough space in the output vector
491  out.reserve((UInt)(std::ceil((4.0 * src_size) / 3.0) + 6.0));
492 
493  // sort all read bytes correctly into a char[4] (double) or
494  // char[8] (float) and push_back when necessary.
495  for (Size i = 0; i < src_size; i += 4)
496  {
497  // decode 4 Base64-Chars to 3 Byte
498  // -------------------------------
499 
500  // decode the first two chars
501  a = decoder_[(int)in[i] - 43] - 62;
502  b = decoder_[(int)in[i + 1] - 43] - 62;
503  if (i + 1 >= src_size)
504  {
505  b = 0;
506  }
507  // write first byte (6 bits from a and 2 highest bits from b)
508  element[offset] = (unsigned char) ((a << 2) | (b >> 4));
509  written++;
510  offset = (offset + inc) % element_size;
511 
512  if (written % element_size == 0)
513  {
514  ToType * to_type = reinterpret_cast<ToType *>(&element[0]);
515  out.push_back((*to_type));
516  strcpy(element, "");
517  }
518 
519  // decode the third char
520  a = decoder_[(int)in[i + 2] - 43] - 62;
521  if (i + 2 >= src_size)
522  {
523  a = 0;
524  }
525  // write second byte (4 lowest bits from b and 4 highest bits from a)
526  element[offset] = (unsigned char) (((b & 15) << 4) | (a >> 2));
527  written++;
528  offset = (offset + inc) % element_size;
529 
530  if (written % element_size == 0)
531  {
532  ToType * to_type = reinterpret_cast<ToType *>(&element[0]);
533  out.push_back((*to_type));
534  strcpy(element, "");
535  }
536 
537  // decode the fourth char
538  b = decoder_[(int)in[i + 3] - 43] - 62;
539  if (i + 3 >= src_size)
540  {
541  b = 0;
542  }
543  // write third byte (2 lowest bits from a and 6 bits from b)
544  element[offset] = (unsigned char) (((a & 3) << 6) | b);
545  written++;
546  offset = (offset + inc) % element_size;
547 
548  if (written % element_size == 0)
549  {
550  ToType * to_type = reinterpret_cast<ToType *>(&element[0]);
551  out.push_back((*to_type));
552  strcpy(element, "");
553  }
554  }
555  }
556 
557  template <typename FromType>
558  void Base64::encodeIntegers(std::vector<FromType> & in, ByteOrder to_byte_order, String & out, bool zlib_compression)
559  {
560  out.clear();
561  if (in.empty())
562  return;
563 
564  //initialize
565  const Size element_size = sizeof(FromType);
566  const Size input_bytes = element_size * in.size();
567  String compressed;
568  Byte * it;
569  Byte * end;
570  //Change endianness if necessary
572  {
573  if (element_size == 4)
574  {
575  for (Size i = 0; i < in.size(); ++i)
576  {
577  Int32 tmp = in[i];
578  tmp = endianize32(tmp);
579  in[i] = tmp;
580  }
581  }
582  else
583  {
584  for (Size i = 0; i < in.size(); ++i)
585  {
586  Int64 tmp = in[i];
587  tmp = endianize64(tmp);
588  in[i] = tmp;
589  }
590  }
591  }
592 
593  //encode with compression (use Qt because of zlib support)
594  if (zlib_compression)
595  {
596  unsigned long sourceLen = (unsigned long)input_bytes;
597  unsigned long compressed_length = //compressBound((unsigned long)in.size());
598  sourceLen + (sourceLen >> 12) + (sourceLen >> 14) + 11; // taken from zlib's compress.c, as we cannot use compressBound*
599 
600  compressed.resize(compressed_length);
601  while (compress(reinterpret_cast<Bytef *>(&compressed[0]), &compressed_length, reinterpret_cast<Bytef *>(&in[0]), (unsigned long)input_bytes) != Z_OK)
602  {
603  compressed_length *= 2;
604  compressed.reserve(compressed_length);
605  }
606 
607 
608  String(compressed).swap(compressed);
609  it = reinterpret_cast<Byte *>(&compressed[0]);
610  end = it + compressed_length;
611  out.resize((Size)ceil(compressed_length / 3.) * 4); //resize output array in order to have enough space for all characters
612  }
613  //encode without compression
614  else
615  {
616  out.resize((Size)ceil(input_bytes / 3.) * 4); //resize output array in order to have enough space for all characters
617  it = reinterpret_cast<Byte *>(&in[0]);
618  end = it + input_bytes;
619  }
620 
621  Byte * to = reinterpret_cast<Byte *>(&out[0]);
622 
623 
624  Size written = 0;
625 
626  while (it != end)
627  {
628  Int int_24bit = 0;
629  Int padding_count = 0;
630 
631  // construct 24-bit integer from 3 bytes
632  for (Size i = 0; i < 3; i++)
633  {
634  if (it != end)
635  {
636  int_24bit |= *it++ << ((2 - i) * 8);
637  }
638  else
639  {
640  padding_count++;
641  }
642  }
643 
644  // write out 4 characters
645  for (Int i = 3; i >= 0; i--)
646  {
647  to[i] = encoder_[int_24bit & 0x3F];
648  int_24bit >>= 6;
649  }
650 
651  // fixup for padding
652  if (padding_count > 0)
653  to[3] = '=';
654  if (padding_count > 1)
655  to[2] = '=';
656 
657  to += 4;
658  written += 4;
659  }
660 
661  out.resize(written); //no more space is needed
662  }
663 
664  template <typename ToType>
665  void Base64::decodeIntegers(const String & in, ByteOrder from_byte_order, std::vector<ToType> & out, bool zlib_compression)
666  {
667  if (zlib_compression)
668  {
669  decodeIntegersCompressed_(in, from_byte_order, out);
670  }
671  else
672  {
673  decodeIntegersUncompressed_(in, from_byte_order, out);
674  }
675  }
676 
677  template <typename ToType>
678  void Base64::decodeIntegersCompressed_(const String & in, ByteOrder from_byte_order, std::vector<ToType> & out)
679  {
680  out.clear();
681  if (in == "")
682  return;
683 
684  void * byte_buffer;
685  Size buffer_size;
686  std::vector<unsigned char> binary;
687  const Size element_size = sizeof(ToType);
688 
689  String decompressed;
690 
691  QByteArray qt_byte_array = QByteArray::fromRawData(in.c_str(), (int) in.size());
692  QByteArray bazip = QByteArray::fromBase64(qt_byte_array);
693  QByteArray czip;
694  czip.resize(4);
695  czip[0] = (bazip.size() & 0xff000000) >> 24;
696  czip[1] = (bazip.size() & 0x00ff0000) >> 16;
697  czip[2] = (bazip.size() & 0x0000ff00) >> 8;
698  czip[3] = (bazip.size() & 0x000000ff);
699  czip += bazip;
700  QByteArray base64_uncompressed = qUncompress(czip);
701  if (base64_uncompressed.isEmpty())
702  {
703  throw Exception::ConversionError(__FILE__, __LINE__, __PRETTY_FUNCTION__, "Decompression error?");
704  }
705  decompressed.resize(base64_uncompressed.size());
706 
707  std::copy(base64_uncompressed.begin(), base64_uncompressed.end(), decompressed.begin());
708 
709  byte_buffer = reinterpret_cast<void *>(&decompressed[0]);
710  buffer_size = decompressed.size();
711 
712  //change endianness if necessary
713  if ((OPENMS_IS_BIG_ENDIAN && from_byte_order == Base64::BYTEORDER_LITTLEENDIAN) || (!OPENMS_IS_BIG_ENDIAN && from_byte_order == Base64::BYTEORDER_BIGENDIAN))
714  {
715  if (element_size == 4)
716  {
717  const Int32 * float_buffer = reinterpret_cast<const Int32 *>(byte_buffer);
718  if (buffer_size % element_size != 0)
719  throw Exception::ConversionError(__FILE__, __LINE__, __PRETTY_FUNCTION__, "Bad BufferCount?");
720  Size float_count = buffer_size / element_size;
721  Int32 * p = reinterpret_cast<Int32 *>(byte_buffer);
722  std::transform(p, p + float_count, p, endianize32);
723 
724  out.resize(float_count);
725  // do NOT use assign here, as it will give a lot of type conversion warnings on VS compiler
726  for (Size i = 0; i < float_count; ++i)
727  {
728  out[i] = (ToType) * float_buffer;
729  ++float_buffer;
730  }
731  }
732  else
733  {
734  const Int64 * float_buffer = reinterpret_cast<const Int64 *>(byte_buffer);
735 
736  if (buffer_size % element_size != 0)
737  throw Exception::ConversionError(__FILE__, __LINE__, __PRETTY_FUNCTION__, "Bad BufferCount?");
738 
739  Size float_count = buffer_size / element_size;
740 
741  Int64 * p = reinterpret_cast<Int64 *>(byte_buffer);
742  std::transform(p, p + float_count, p, endianize64);
743 
744  out.resize(float_count);
745  // do NOT use assign here, as it will give a lot of type conversion warnings on VS compiler
746  for (Size i = 0; i < float_count; ++i)
747  {
748  out[i] = (ToType) * float_buffer;
749  ++float_buffer;
750  }
751  }
752  }
753  else
754  {
755  if (element_size == 4)
756  {
757  const Int * float_buffer = reinterpret_cast<const Int *>(byte_buffer);
758  if (buffer_size % element_size != 0)
759  throw Exception::ConversionError(__FILE__, __LINE__, __PRETTY_FUNCTION__, "Bad BufferCount while decoding?");
760 
761  Size float_count = buffer_size / element_size;
762  out.resize(float_count);
763  // do NOT use assign here, as it will give a lot of type conversion warnings on VS compiler
764  for (Size i = 0; i < float_count; ++i)
765  {
766  out[i] = (ToType) * float_buffer;
767  ++float_buffer;
768  }
769  }
770  else
771  {
772  const Int64 * float_buffer = reinterpret_cast<const Int64 *>(byte_buffer);
773 
774  if (buffer_size % element_size != 0)
775  throw Exception::ConversionError(__FILE__, __LINE__, __PRETTY_FUNCTION__, "Bad BufferCount while decoding?");
776 
777  Size float_count = buffer_size / element_size;
778  out.resize(float_count);
779  // do NOT use assign here, as it will give a lot of type conversion warnings on VS compiler
780  for (Size i = 0; i < float_count; ++i)
781  {
782  out[i] = (ToType) * float_buffer;
783  ++float_buffer;
784  }
785  }
786  }
787 
788  }
789 
790  template <typename ToType>
791  void Base64::decodeIntegersUncompressed_(const String & in, ByteOrder from_byte_order, std::vector<ToType> & out)
792  {
793  out.clear();
794 
795  // The length of a base64 string is a always a multiple of 4 (always 3
796  // bytes are encoded as 4 characters)
797  if (in.size() < 4)
798  {
799  return;
800  }
801 
802  Size src_size = in.size();
803  // last one or two '=' are skipped if contained
804  int padding = 0;
805  if (in[src_size - 1] == '=') padding++;
806  if (in[src_size - 2] == '=') padding++;
807 
808  src_size -= padding;
809 
810  register UInt a;
811  register UInt b;
812 
813  UInt offset = 0;
814  int inc = 1;
815  UInt written = 0;
816 
817  const Size element_size = sizeof(ToType);
818 
819  // enough for either float or double
820  char element[8] = "\x00\x00\x00\x00\x00\x00\x00";
821 
822  if ((OPENMS_IS_BIG_ENDIAN && from_byte_order == Base64::BYTEORDER_LITTLEENDIAN) || (!OPENMS_IS_BIG_ENDIAN && from_byte_order == Base64::BYTEORDER_BIGENDIAN))
823  {
824  offset = (element_size - 1); // other endian
825  inc = -1;
826  }
827  else
828  {
829  offset = 0;
830  inc = 1;
831  }
832 
833  //reserve enough space in the output vector
834  out.reserve((UInt)(std::ceil((4.0 * src_size) / 3.0) + 6.0));
835 
836  // sort all read bytes correctly into a char[4] (double) or
837  // char[8] (float) and push_back when necessary.
838  for (Size i = 0; i < src_size; i += 4)
839  {
840 
841  // decode 4 Base64-Chars to 3 Byte
842  // -------------------------------
843 
844  // decode the first two chars
845  a = decoder_[(int)in[i] - 43] - 62;
846  b = decoder_[(int)in[i + 1] - 43] - 62;
847  if (i + 1 >= src_size)
848  {
849  b = 0;
850  }
851  // write first byte (6 bits from a and 2 highest bits from b)
852  element[offset] = (unsigned char) ((a << 2) | (b >> 4));
853  written++;
854  offset = (offset + inc) % element_size;
855 
856  if (written % element_size == 0)
857  {
858  ToType float_value;
859  if (element_size == 4)
860  {
861  Int32 * value = reinterpret_cast<Int32 *>(&element[0]);
862  float_value = (ToType) * value;
863  }
864  else
865  {
866  Int64 * value = reinterpret_cast<Int64 *>(&element[0]);
867  float_value = (ToType) * value;
868  }
869  out.push_back(float_value);
870  strcpy(element, "");
871  }
872 
873  // decode the third char
874  a = decoder_[(int)in[i + 2] - 43] - 62;
875  if (i + 2 >= src_size)
876  {
877  a = 0;
878  }
879  // write second byte (4 lowest bits from b and 4 highest bits from a)
880  element[offset] = (unsigned char) (((b & 15) << 4) | (a >> 2));
881  written++;
882  offset = (offset + inc) % element_size;
883 
884  if (written % element_size == 0)
885  {
886  ToType float_value;
887  if (element_size == 4)
888  {
889  Int32 * value = reinterpret_cast<Int32 *>(&element[0]);
890  float_value = (ToType) * value;
891  }
892  else
893  {
894  Int64 * value = reinterpret_cast<Int64 *>(&element[0]);
895  float_value = (ToType) * value;
896  }
897  out.push_back(float_value);
898  strcpy(element, "");
899  }
900 
901  // decode the fourth char
902  b = decoder_[(int)in[i + 3] - 43] - 62;
903  if (i + 3 >= src_size)
904  {
905  b = 0;
906  }
907  // write third byte (2 lowest bits from a and 6 bits from b)
908  element[offset] = (unsigned char) (((a & 3) << 6) | b);
909  written++;
910  offset = (offset + inc) % element_size;
911 
912  if (written % element_size == 0)
913  {
914  ToType float_value;
915  if (element_size == 4)
916  {
917  Int32 * value = reinterpret_cast<Int32 *>(&element[0]);
918  float_value = (ToType) * value;
919  }
920  else
921  {
922  Int64 * value = reinterpret_cast<Int64 *>(&element[0]);
923  float_value = (ToType) * value;
924  }
925  out.push_back(float_value);
926  strcpy(element, "");
927  }
928  }
929  }
930 
931 } //namespace OpenMS
932 
933 #endif /* OPENMS_FORMAT_BASE64_H */
Big endian type.
Definition: Base64.h:78
A more convenient string class.
Definition: String.h:57
Class to encode and decode Base64.
Definition: Base64.h:64
Little endian type.
Definition: Base64.h:79
Main OpenMS namespace.
Definition: FeatureDeconvolution.h:47
float f
Definition: Base64.h:164
void decodeIntegersUncompressed_(const String &in, ByteOrder from_byte_order, std::vector< ToType > &out)
Decodes a Base64 string to a vector of integer numbers.
Definition: Base64.h:791
void encodeIntegers(std::vector< FromType > &in, ByteOrder to_byte_order, String &out, bool zlib_compression=false)
Encodes a vector of integer point numbers to a Base64 string.
Definition: Base64.h:558
ByteOrder
Byte order type.
Definition: Base64.h:76
Internal class needed for type-punning.
Definition: Base64.h:162
void decodeIntegers(const String &in, ByteOrder from_byte_order, std::vector< ToType > &out, bool zlib_compression=false)
Decodes a Base64 string to a vector of integer numbers.
Definition: Base64.h:665
OPENMS_INT32_TYPE Int32
Signed integer type (32bit)
Definition: Types.h:57
double f
Definition: Base64.h:157
void decodeIntegersCompressed_(const String &in, ByteOrder from_byte_order, std::vector< ToType > &out)
Decodes a compressed Base64 string to a vector of integer numbers.
Definition: Base64.h:678
Int64 i
Definition: Base64.h:158
Invalid conversion exception.
Definition: Exception.h:363
Int32 i
Definition: Base64.h:165
Out of memory exception.
Definition: Exception.h:472
void decodeUncompressed_(const String &in, ByteOrder from_byte_order, std::vector< ToType > &out)
Decodes a Base64 string to a vector of floating point numbers.
Definition: Base64.h:448
#define OPENMS_IS_BIG_ENDIAN
Definition: Base64.h:42
static const char decoder_[]
Definition: Base64.h:169
static const char encoder_[]
Definition: Base64.h:168
OPENMS_INT64_TYPE Int64
Signed integer type (64bit)
Definition: Types.h:64
OPENMS_BYTE_TYPE Byte
Byte type.
Definition: Types.h:105
void encode(std::vector< FromType > &in, ByteOrder to_byte_order, String &out, bool zlib_compression=false)
Encodes a vector of floating point numbers to a Base64 string.
Definition: Base64.h:207
Int64 endianize64(Int64 &n)
Endianizes a 64 bit type from big endian to little endian and vice versa.
Definition: Base64.h:194
Internal class needed for type-punning.
Definition: Base64.h:155
Int32 endianize32(Int32 &n)
Endianizes a 32 bit type from big endian to little endian and vice versa.
Definition: Base64.h:188
int Int
Signed integer type.
Definition: Types.h:96
void decode(const String &in, ByteOrder from_byte_order, std::vector< ToType > &out, bool zlib_compression=false)
Decodes a Base64 string to a vector of floating point numbers.
Definition: Base64.h:334
void decodeCompressed_(const String &in, ByteOrder from_byte_order, std::vector< ToType > &out)
Decodes a compressed Base64 string to a vector of floating point numbers.
Definition: Base64.h:347

OpenMS / TOPP release 2.0.0 Documentation generated on Tue Aug 25 2015 05:53:44 using doxygen 1.8.9.1