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  if (in == "")
452  return;
453 
454  Size src_size = in.size();
455  // last one or two '=' are skipped if contained
456  int padding = 0;
457  if (in[src_size - 1] == '=')
458  padding++;
459  if (in[src_size - 2] == '=')
460  padding++;
461 
462  src_size -= padding;
463 
464  register UInt a;
465  register UInt b;
466 
467  UInt offset = 0;
468  int inc = 1;
469  UInt written = 0;
470 
471  const Size element_size = sizeof(ToType);
472 
473  // enough for either float or double
474  char element[8] = "\x00\x00\x00\x00\x00\x00\x00";
475 
476  if ((OPENMS_IS_BIG_ENDIAN && from_byte_order == Base64::BYTEORDER_LITTLEENDIAN) || (!OPENMS_IS_BIG_ENDIAN && from_byte_order == Base64::BYTEORDER_BIGENDIAN))
477  {
478  offset = (element_size - 1); // other endian
479  inc = -1;
480  }
481  else
482  {
483  offset = 0;
484  inc = 1;
485  }
486 
487  //reserve enough space in the output vector
488  out.reserve((UInt)(std::ceil((4.0 * src_size) / 3.0) + 6.0));
489 
490  // sort all read bytes correctly into a char[4] (double) or
491  // char[8] (float) and push_back when necessary.
492  for (Size i = 0; i < src_size; i += 4)
493  {
494  // decode 4 Base64-Chars to 3 Byte
495  a = decoder_[(int)in[i] - 43] - 62;
496  b = decoder_[(int)in[i + 1] - 43] - 62;
497  if (i + 1 >= src_size)
498  b = 0;
499  element[offset] = (unsigned char) ((a << 2) | (b >> 4));
500  written++;
501  offset = (offset + inc) % element_size;
502 
503  if (written % element_size == 0)
504  {
505  ToType * to_type = reinterpret_cast<ToType *>(&element[0]);
506  out.push_back((*to_type));
507  strcpy(element, "");
508  }
509 
510  a = decoder_[(int)in[i + 2] - 43] - 62;
511  if (i + 2 >= src_size)
512  a = 0;
513  element[offset] = (unsigned char) (((b & 15) << 4) | (a >> 2));
514  written++;
515  offset = (offset + inc) % element_size;
516 
517  if (written % element_size == 0)
518  {
519  ToType * to_type = reinterpret_cast<ToType *>(&element[0]);
520  out.push_back((*to_type));
521  strcpy(element, "");
522  }
523 
524  b = decoder_[(int)in[i + 3] - 43] - 62;
525  if (i + 3 >= src_size)
526  b = 0;
527  element[offset] = (unsigned char) (((a & 3) << 6) | b);
528  written++;
529  offset = (offset + inc) % element_size;
530 
531  if (written % element_size == 0)
532  {
533  ToType * to_type = reinterpret_cast<ToType *>(&element[0]);
534  out.push_back((*to_type));
535  strcpy(element, "");
536  }
537  }
538  }
539 
540  template <typename FromType>
541  void Base64::encodeIntegers(std::vector<FromType> & in, ByteOrder to_byte_order, String & out, bool zlib_compression)
542  {
543  out.clear();
544  if (in.empty())
545  return;
546 
547  //initialize
548  const Size element_size = sizeof(FromType);
549  const Size input_bytes = element_size * in.size();
550  String compressed;
551  Byte * it;
552  Byte * end;
553  //Change endianness if necessary
555  {
556  if (element_size == 4)
557  {
558  for (Size i = 0; i < in.size(); ++i)
559  {
560  Int32 tmp = in[i];
561  tmp = endianize32(tmp);
562  in[i] = tmp;
563  }
564  }
565  else
566  {
567  for (Size i = 0; i < in.size(); ++i)
568  {
569  Int64 tmp = in[i];
570  tmp = endianize64(tmp);
571  in[i] = tmp;
572  }
573  }
574  }
575 
576  //encode with compression (use Qt because of zlib support)
577  if (zlib_compression)
578  {
579  unsigned long sourceLen = (unsigned long)input_bytes;
580  unsigned long compressed_length = //compressBound((unsigned long)in.size());
581  sourceLen + (sourceLen >> 12) + (sourceLen >> 14) + 11; // taken from zlib's compress.c, as we cannot use compressBound*
582 
583  compressed.resize(compressed_length);
584  while (compress(reinterpret_cast<Bytef *>(&compressed[0]), &compressed_length, reinterpret_cast<Bytef *>(&in[0]), (unsigned long)input_bytes) != Z_OK)
585  {
586  compressed_length *= 2;
587  compressed.reserve(compressed_length);
588  }
589 
590 
591  String(compressed).swap(compressed);
592  it = reinterpret_cast<Byte *>(&compressed[0]);
593  end = it + compressed_length;
594  out.resize((Size)ceil(compressed_length / 3.) * 4); //resize output array in order to have enough space for all characters
595  }
596  //encode without compression
597  else
598  {
599  out.resize((Size)ceil(input_bytes / 3.) * 4); //resize output array in order to have enough space for all characters
600  it = reinterpret_cast<Byte *>(&in[0]);
601  end = it + input_bytes;
602  }
603 
604  Byte * to = reinterpret_cast<Byte *>(&out[0]);
605 
606 
607  Size written = 0;
608 
609  while (it != end)
610  {
611  Int int_24bit = 0;
612  Int padding_count = 0;
613 
614  // construct 24-bit integer from 3 bytes
615  for (Size i = 0; i < 3; i++)
616  {
617  if (it != end)
618  {
619  int_24bit |= *it++ << ((2 - i) * 8);
620  }
621  else
622  {
623  padding_count++;
624  }
625  }
626 
627  // write out 4 characters
628  for (Int i = 3; i >= 0; i--)
629  {
630  to[i] = encoder_[int_24bit & 0x3F];
631  int_24bit >>= 6;
632  }
633 
634  // fixup for padding
635  if (padding_count > 0)
636  to[3] = '=';
637  if (padding_count > 1)
638  to[2] = '=';
639 
640  to += 4;
641  written += 4;
642  }
643 
644  out.resize(written); //no more space is needed
645  }
646 
647  template <typename ToType>
648  void Base64::decodeIntegers(const String & in, ByteOrder from_byte_order, std::vector<ToType> & out, bool zlib_compression)
649  {
650  if (zlib_compression)
651  {
652  decodeIntegersCompressed_(in, from_byte_order, out);
653  }
654  else
655  {
656  decodeIntegersUncompressed_(in, from_byte_order, out);
657  }
658  }
659 
660  template <typename ToType>
661  void Base64::decodeIntegersCompressed_(const String & in, ByteOrder from_byte_order, std::vector<ToType> & out)
662  {
663  out.clear();
664  if (in == "")
665  return;
666 
667  void * byte_buffer;
668  Size buffer_size;
669  std::vector<unsigned char> binary;
670  const Size element_size = sizeof(ToType);
671 
672  String decompressed;
673 
674  QByteArray qt_byte_array = QByteArray::fromRawData(in.c_str(), (int) in.size());
675  QByteArray bazip = QByteArray::fromBase64(qt_byte_array);
676  QByteArray czip;
677  czip.resize(4);
678  czip[0] = (bazip.size() & 0xff000000) >> 24;
679  czip[1] = (bazip.size() & 0x00ff0000) >> 16;
680  czip[2] = (bazip.size() & 0x0000ff00) >> 8;
681  czip[3] = (bazip.size() & 0x000000ff);
682  czip += bazip;
683  QByteArray base64_uncompressed = qUncompress(czip);
684  if (base64_uncompressed.isEmpty())
685  {
686  throw Exception::ConversionError(__FILE__, __LINE__, __PRETTY_FUNCTION__, "Decompression error?");
687  }
688  decompressed.resize(base64_uncompressed.size());
689 
690  std::copy(base64_uncompressed.begin(), base64_uncompressed.end(), decompressed.begin());
691 
692  byte_buffer = reinterpret_cast<void *>(&decompressed[0]);
693  buffer_size = decompressed.size();
694 
695  //change endianness if necessary
696  if ((OPENMS_IS_BIG_ENDIAN && from_byte_order == Base64::BYTEORDER_LITTLEENDIAN) || (!OPENMS_IS_BIG_ENDIAN && from_byte_order == Base64::BYTEORDER_BIGENDIAN))
697  {
698  if (element_size == 4)
699  {
700  const Int32 * float_buffer = reinterpret_cast<const Int32 *>(byte_buffer);
701  if (buffer_size % element_size != 0)
702  throw Exception::ConversionError(__FILE__, __LINE__, __PRETTY_FUNCTION__, "Bad BufferCount?");
703  Size float_count = buffer_size / element_size;
704  Int32 * p = reinterpret_cast<Int32 *>(byte_buffer);
705  std::transform(p, p + float_count, p, endianize32);
706 
707  out.resize(float_count);
708  // do NOT use assign here, as it will give a lot of type conversion warnings on VS compiler
709  for (Size i = 0; i < float_count; ++i)
710  {
711  out[i] = (ToType) * float_buffer;
712  ++float_buffer;
713  }
714  }
715  else
716  {
717  const Int64 * float_buffer = reinterpret_cast<const Int64 *>(byte_buffer);
718 
719  if (buffer_size % element_size != 0)
720  throw Exception::ConversionError(__FILE__, __LINE__, __PRETTY_FUNCTION__, "Bad BufferCount?");
721 
722  Size float_count = buffer_size / element_size;
723 
724  Int64 * p = reinterpret_cast<Int64 *>(byte_buffer);
725  std::transform(p, p + float_count, p, endianize64);
726 
727  out.resize(float_count);
728  // do NOT use assign here, as it will give a lot of type conversion warnings on VS compiler
729  for (Size i = 0; i < float_count; ++i)
730  {
731  out[i] = (ToType) * float_buffer;
732  ++float_buffer;
733  }
734  }
735  }
736  else
737  {
738  if (element_size == 4)
739  {
740  const Int * float_buffer = reinterpret_cast<const Int *>(byte_buffer);
741  if (buffer_size % element_size != 0)
742  throw Exception::ConversionError(__FILE__, __LINE__, __PRETTY_FUNCTION__, "Bad BufferCount while decoding?");
743 
744  Size float_count = buffer_size / element_size;
745  out.resize(float_count);
746  // do NOT use assign here, as it will give a lot of type conversion warnings on VS compiler
747  for (Size i = 0; i < float_count; ++i)
748  {
749  out[i] = (ToType) * float_buffer;
750  ++float_buffer;
751  }
752  }
753  else
754  {
755  const Int64 * float_buffer = reinterpret_cast<const Int64 *>(byte_buffer);
756 
757  if (buffer_size % element_size != 0)
758  throw Exception::ConversionError(__FILE__, __LINE__, __PRETTY_FUNCTION__, "Bad BufferCount while decoding?");
759 
760  Size float_count = buffer_size / element_size;
761  out.resize(float_count);
762  // do NOT use assign here, as it will give a lot of type conversion warnings on VS compiler
763  for (Size i = 0; i < float_count; ++i)
764  {
765  out[i] = (ToType) * float_buffer;
766  ++float_buffer;
767  }
768  }
769  }
770 
771  }
772 
773  template <typename ToType>
774  void Base64::decodeIntegersUncompressed_(const String & in, ByteOrder from_byte_order, std::vector<ToType> & out)
775  {
776  out.clear();
777  if (in == "")
778  return;
779 
780  Size src_size = in.size();
781  // last one or two '=' are skipped if contained
782  int padding = 0;
783  if (in[src_size - 1] == '=')
784  padding++;
785  if (in[src_size - 2] == '=')
786  padding++;
787 
788  src_size -= padding;
789 
790  register UInt a;
791  register UInt b;
792 
793  UInt offset = 0;
794  int inc = 1;
795  UInt written = 0;
796 
797  const Size element_size = sizeof(ToType);
798 
799  // enough for either float or double
800  char element[8] = "\x00\x00\x00\x00\x00\x00\x00";
801 
802  if ((OPENMS_IS_BIG_ENDIAN && from_byte_order == Base64::BYTEORDER_LITTLEENDIAN) || (!OPENMS_IS_BIG_ENDIAN && from_byte_order == Base64::BYTEORDER_BIGENDIAN))
803  {
804  offset = (element_size - 1); // other endian
805  inc = -1;
806  }
807  else
808  {
809  offset = 0;
810  inc = 1;
811  }
812 
813  //reserve enough space in the output vector
814  out.reserve((UInt)(std::ceil((4.0 * src_size) / 3.0) + 6.0));
815 
816  // sort all read bytes correctly into a char[4] (double) or
817  // char[8] (float) and push_back when necessary.
818  for (Size i = 0; i < src_size; i += 4)
819  {
820 //printf ("start: i=%d, offset %d\n", i, offset);
821 
822  // decode 4 Base64-Chars to 3 Byte
823  a = decoder_[(int)in[i] - 43] - 62;
824  b = decoder_[(int)in[i + 1] - 43] - 62;
825  if (i + 1 >= src_size)
826  b = 0;
827  element[offset] = (unsigned char) ((a << 2) | (b >> 4));
828  written++;
829 //printf ("1: i=%d, offset %d, wrote %d\n", i, offset, element[offset]);
830  offset = (offset + inc) % element_size;
831 
832  if (written % element_size == 0)
833  {
834  ToType float_value;
835  if (element_size == 4)
836  {
837  Int32 * value = reinterpret_cast<Int32 *>(&element[0]);
838  float_value = (ToType) * value;
839  }
840  else
841  {
842  Int64 * value = reinterpret_cast<Int64 *>(&element[0]);
843  float_value = (ToType) * value;
844  }
845  out.push_back(float_value);
846  strcpy(element, "");
847  }
848 
849  a = decoder_[(int)in[i + 2] - 43] - 62;
850  if (i + 2 >= src_size)
851  a = 0;
852  element[offset] = (unsigned char) (((b & 15) << 4) | (a >> 2));
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  b = decoder_[(int)in[i + 3] - 43] - 62;
874  if (i + 3 >= src_size)
875  b = 0;
876  element[offset] = (unsigned char) (((a & 3) << 6) | b);
877  written++;
878  offset = (offset + inc) % element_size;
879 
880  if (written % element_size == 0)
881  {
882  ToType float_value;
883  if (element_size == 4)
884  {
885  Int32 * value = reinterpret_cast<Int32 *>(&element[0]);
886  float_value = (ToType) * value;
887  }
888  else
889  {
890  Int64 * value = reinterpret_cast<Int64 *>(&element[0]);
891  float_value = (ToType) * value;
892  }
893  out.push_back(float_value);
894  strcpy(element, "");
895  }
896  }
897  }
898 
899 } //namespace OpenMS
900 
901 #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:774
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:541
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:648
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:661
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 Sat May 16 2015 16:13:14 using doxygen 1.8.9.1