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-2013.
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 
99  template <typename ToType>
100  void decode(const String & in, ByteOrder from_byte_order, std::vector<ToType> & out, bool zlib_compression = false);
101 
109  template <typename FromType>
110  void encodeIntegers(std::vector<FromType> & in, ByteOrder to_byte_order, String & out, bool zlib_compression = false);
111 
119  template <typename ToType>
120  void decodeIntegers(const String & in, ByteOrder from_byte_order, std::vector<ToType> & out, bool zlib_compression = false);
121 
129  void encodeStrings(std::vector<String> & in, String & out, bool zlib_compression = false);
130 
138  void decodeStrings(const String & in, std::vector<String> & out, bool zlib_compression = false);
139 
140 private:
141 
144  {
147  };
148 
151  {
154  };
155 
156  static const char encoder_[];
157  static const char decoder_[];
159  template <typename ToType>
160  void decodeUncompressed_(const String & in, ByteOrder from_byte_order, std::vector<ToType> & out);
161 
163  template <typename ToType>
164  void decodeCompressed_(const String & in, ByteOrder from_byte_order, std::vector<ToType> & out);
165 
167  template <typename ToType>
168  void decodeIntegersUncompressed_(const String & in, ByteOrder from_byte_order, std::vector<ToType> & out);
169 
171  template <typename ToType>
172  void decodeIntegersCompressed_(const String & in, ByteOrder from_byte_order, std::vector<ToType> & out);
173  };
174 
176  inline Int32 endianize32(Int32 & n)
177  {
178  return ((n & 0xff) << 24) | ((n & 0xff00) << 8) | ((n & 0xff0000) >> 8) | ((n & 0xff000000) >> 24);
179  }
180 
182  inline Int64 endianize64(Int64 & n)
183  {
184  return ((n & 0x00000000000000ffll) << 56) |
185  ((n & 0x000000000000ff00ll) << 40) |
186  ((n & 0x0000000000ff0000ll) << 24) |
187  ((n & 0x00000000ff000000ll) << 8) |
188  ((n & 0x000000ff00000000ll) >> 8) |
189  ((n & 0x0000ff0000000000ll) >> 24) |
190  ((n & 0x00ff000000000000ll) >> 40) |
191  ((n & 0xff00000000000000ll) >> 56);
192  }
193 
194  template <typename FromType>
195  void Base64::encode(std::vector<FromType> & in, ByteOrder to_byte_order, String & out, bool zlib_compression)
196  {
197  out.clear();
198  if (in.empty())
199  return;
200 
201  //initialize
202  const Size element_size = sizeof(FromType);
203  const Size input_bytes = element_size * in.size();
204  String compressed;
205  Byte * it;
206  Byte * end;
207  //Change endianness if necessary
209  {
210  if (element_size == 4)
211  {
212  for (Size i = 0; i < in.size(); ++i)
213  {
214  Reinterpreter32_ tmp;
215  tmp.f = in[i];
216  tmp.i = endianize32(tmp.i);
217  in[i] = tmp.f;
218  }
219  }
220  else
221  {
222  for (Size i = 0; i < in.size(); ++i)
223  {
224  Reinterpreter64_ tmp;
225  tmp.f = in[i];
226  tmp.i = endianize64(tmp.i);
227  in[i] = tmp.f;
228  }
229  }
230  }
231 
232  //encode with compression
233  if (zlib_compression)
234  {
235  unsigned long sourceLen = (unsigned long)in.size();
236  unsigned long compressed_length = //compressBound((unsigned long)in.size());
237  sourceLen + (sourceLen >> 12) + (sourceLen >> 14) + 11; // taken from zlib's compress.c, as we cannot use compressBound*
238  //
239  // (*) compressBound is not defined in the QtCore lib, which forces the linker under windows to link in our zlib.
240  // This leads to multiply defined symbols as compress() is then defined twice.
241 
242  int zlib_error;
243  do
244  {
245  compressed.resize(compressed_length);
246  zlib_error = compress(reinterpret_cast<Bytef *>(&compressed[0]), &compressed_length, reinterpret_cast<Bytef *>(&in[0]), (unsigned long)input_bytes);
247 
248  switch (zlib_error)
249  {
250  case Z_MEM_ERROR:
251  throw Exception::OutOfMemory(__FILE__, __LINE__, __PRETTY_FUNCTION__, compressed_length);
252  break;
253 
254  case Z_BUF_ERROR:
255  compressed_length *= 2;
256  }
257  }
258  while (zlib_error == Z_BUF_ERROR);
259 
260  if (zlib_error != Z_OK)
261  {
262  throw Exception::ConversionError(__FILE__, __LINE__, __PRETTY_FUNCTION__, "Compression error?");
263  }
264 
265  String(compressed).swap(compressed);
266  it = reinterpret_cast<Byte *>(&compressed[0]);
267  end = it + compressed_length;
268  out.resize((Size)ceil(compressed_length / 3.) * 4); //resize output array in order to have enough space for all characters
269  }
270  //encode without compression
271  else
272  {
273  out.resize((Size)ceil(input_bytes / 3.) * 4); //resize output array in order to have enough space for all characters
274  it = reinterpret_cast<Byte *>(&in[0]);
275  end = it + input_bytes;
276  }
277 
278  Byte * to = reinterpret_cast<Byte *>(&out[0]);
279 
280 
281  Size written = 0;
282 
283  while (it != end)
284  {
285  Int int_24bit = 0;
286  Int padding_count = 0;
287 
288  // construct 24-bit integer from 3 bytes
289  for (Size i = 0; i < 3; i++)
290  {
291  if (it != end)
292  {
293  int_24bit |= *it++ << ((2 - i) * 8);
294  }
295  else
296  {
297  padding_count++;
298  }
299  }
300 
301  // write out 4 characters
302  for (Int i = 3; i >= 0; i--)
303  {
304  to[i] = encoder_[int_24bit & 0x3F];
305  int_24bit >>= 6;
306  }
307 
308  // fixup for padding
309  if (padding_count > 0)
310  to[3] = '=';
311  if (padding_count > 1)
312  to[2] = '=';
313 
314  to += 4;
315  written += 4;
316  }
317 
318  out.resize(written); //no more space is needed
319  }
320 
321  template <typename ToType>
322  void Base64::decode(const String & in, ByteOrder from_byte_order, std::vector<ToType> & out, bool zlib_compression)
323  {
324  if (zlib_compression)
325  {
326  decodeCompressed_(in, from_byte_order, out);
327  }
328  else
329  {
330  decodeUncompressed_(in, from_byte_order, out);
331  }
332  }
333 
334  template <typename ToType>
335  void Base64::decodeCompressed_(const String & in, ByteOrder from_byte_order, std::vector<ToType> & out)
336  {
337  out.clear();
338  if (in == "")
339  return;
340 
341  void * byte_buffer;
342  Size buffer_size;
343  std::vector<unsigned char> binary;
344  const Size element_size = sizeof(ToType);
345 
346  String decompressed;
347 
348  QByteArray qt_byte_array = QByteArray::fromRawData(in.c_str(), (int) in.size());
349  QByteArray bazip = QByteArray::fromBase64(qt_byte_array);
350  QByteArray czip;
351  czip.resize(4);
352  czip[0] = (bazip.size() & 0xff000000) >> 24;
353  czip[1] = (bazip.size() & 0x00ff0000) >> 16;
354  czip[2] = (bazip.size() & 0x0000ff00) >> 8;
355  czip[3] = (bazip.size() & 0x000000ff);
356  czip += bazip;
357  QByteArray base64_uncompressed = qUncompress(czip);
358 
359  if (base64_uncompressed.isEmpty())
360  {
361  throw Exception::ConversionError(__FILE__, __LINE__, __PRETTY_FUNCTION__, "Decompression error?");
362  }
363  decompressed.resize(base64_uncompressed.size());
364 
365  std::copy(base64_uncompressed.begin(), base64_uncompressed.end(), decompressed.begin());
366 
367  byte_buffer = reinterpret_cast<void *>(&decompressed[0]);
368  buffer_size = decompressed.size();
369 
370  //change endianness if necessary
371  if ((OPENMS_IS_BIG_ENDIAN && from_byte_order == Base64::BYTEORDER_LITTLEENDIAN) || (!OPENMS_IS_BIG_ENDIAN && from_byte_order == Base64::BYTEORDER_BIGENDIAN))
372  {
373  if (element_size == 4)
374  {
375  const Real * float_buffer = reinterpret_cast<const Real *>(byte_buffer);
376  if (buffer_size % element_size != 0)
377  throw Exception::ConversionError(__FILE__, __LINE__, __PRETTY_FUNCTION__, "Bad BufferCount?");
378  Size float_count = buffer_size / element_size;
379  Int32 * p = reinterpret_cast<Int32 *>(byte_buffer);
380  std::transform(p, p + float_count, p, endianize32);
381  out.assign(float_buffer, float_buffer + float_count);
382  }
383  else
384  {
385  const DoubleReal * float_buffer = reinterpret_cast<const DoubleReal *>(byte_buffer);
386 
387  if (buffer_size % element_size != 0)
388  throw Exception::ConversionError(__FILE__, __LINE__, __PRETTY_FUNCTION__, "Bad BufferCount?");
389 
390  Size float_count = buffer_size / element_size;
391 
392  Int64 * p = reinterpret_cast<Int64 *>(byte_buffer);
393  std::transform(p, p + float_count, p, endianize64);
394 
395  out.resize(float_count);
396  // do NOT use assign here, as it will give a lot of type conversion warnings on VS compiler
397  for (Size i = 0; i < float_count; ++i)
398  {
399  out[i] = (ToType) * float_buffer;
400  ++float_buffer;
401  }
402  }
403  }
404  else
405  {
406  if (element_size == 4)
407  {
408  const Real * float_buffer = reinterpret_cast<const Real *>(byte_buffer);
409  if (buffer_size % element_size != 0)
410  throw Exception::ConversionError(__FILE__, __LINE__, __PRETTY_FUNCTION__, "Bad BufferCount while decoding?");
411 
412  Size float_count = buffer_size / element_size;
413  out.assign(float_buffer, float_buffer + float_count);
414  }
415  else
416  {
417  const DoubleReal * float_buffer = reinterpret_cast<const DoubleReal *>(byte_buffer);
418 
419  if (buffer_size % element_size != 0)
420  throw Exception::ConversionError(__FILE__, __LINE__, __PRETTY_FUNCTION__, "Bad BufferCount while decoding?");
421 
422  Size float_count = buffer_size / element_size;
423  out.resize(float_count);
424  // do NOT use assign here, as it will give a lot of type conversion warnings on VS compiler
425  for (Size i = 0; i < float_count; ++i)
426  {
427  out[i] = (ToType) * float_buffer;
428  ++float_buffer;
429  }
430  }
431  }
432 
433  }
434 
435  template <typename ToType>
436  void Base64::decodeUncompressed_(const String & in, ByteOrder from_byte_order, std::vector<ToType> & out)
437  {
438  out.clear();
439  if (in == "")
440  return;
441 
442  Size src_size = in.size();
443  // last one or two '=' are skipped if contained
444  int padding = 0;
445  if (in[src_size - 1] == '=')
446  padding++;
447  if (in[src_size - 2] == '=')
448  padding++;
449 
450  src_size -= padding;
451 
452  register UInt a;
453  register UInt b;
454 
455  UInt offset = 0;
456  int inc = 1;
457  UInt written = 0;
458 
459  const Size element_size = sizeof(ToType);
460 
461  // enough for either float or double
462  char element[8] = "\x00\x00\x00\x00\x00\x00\x00";
463 
464  if ((OPENMS_IS_BIG_ENDIAN && from_byte_order == Base64::BYTEORDER_LITTLEENDIAN) || (!OPENMS_IS_BIG_ENDIAN && from_byte_order == Base64::BYTEORDER_BIGENDIAN))
465  {
466  offset = (element_size - 1); // other endian
467  inc = -1;
468  }
469  else
470  {
471  offset = 0;
472  inc = 1;
473  }
474 
475  //reserve enough space in the output vector
476  out.reserve((UInt)(std::ceil((4.0 * src_size) / 3.0) + 6.0));
477 
478  // sort all read bytes correctly into a char[4] (double) or
479  // char[8] (Real) and push_back when necessary.
480  for (Size i = 0; i < src_size; i += 4)
481  {
482  // decode 4 Base64-Chars to 3 Byte
483  a = decoder_[(int)in[i] - 43] - 62;
484  b = decoder_[(int)in[i + 1] - 43] - 62;
485  if (i + 1 >= src_size)
486  b = 0;
487  element[offset] = (unsigned char) ((a << 2) | (b >> 4));
488  written++;
489  offset = (offset + inc) % element_size;
490 
491  if (written % element_size == 0)
492  {
493  ToType * to_type = reinterpret_cast<ToType *>(&element[0]);
494  out.push_back((*to_type));
495  strcpy(element, "");
496  }
497 
498  a = decoder_[(int)in[i + 2] - 43] - 62;
499  if (i + 2 >= src_size)
500  a = 0;
501  element[offset] = (unsigned char) (((b & 15) << 4) | (a >> 2));
502  written++;
503  offset = (offset + inc) % element_size;
504 
505  if (written % element_size == 0)
506  {
507  ToType * to_type = reinterpret_cast<ToType *>(&element[0]);
508  out.push_back((*to_type));
509  strcpy(element, "");
510  }
511 
512  b = decoder_[(int)in[i + 3] - 43] - 62;
513  if (i + 3 >= src_size)
514  b = 0;
515  element[offset] = (unsigned char) (((a & 3) << 6) | b);
516  written++;
517  offset = (offset + inc) % element_size;
518 
519  if (written % element_size == 0)
520  {
521  ToType * to_type = reinterpret_cast<ToType *>(&element[0]);
522  out.push_back((*to_type));
523  strcpy(element, "");
524  }
525  }
526  }
527 
528  template <typename FromType>
529  void Base64::encodeIntegers(std::vector<FromType> & in, ByteOrder to_byte_order, String & out, bool zlib_compression)
530  {
531  out.clear();
532  if (in.empty())
533  return;
534 
535  //initialize
536  const Size element_size = sizeof(FromType);
537  const Size input_bytes = element_size * in.size();
538  String compressed;
539  Byte * it;
540  Byte * end;
541  //Change endianness if necessary
543  {
544  if (element_size == 4)
545  {
546  for (Size i = 0; i < in.size(); ++i)
547  {
548  Int32 tmp = in[i];
549  tmp = endianize32(tmp);
550  in[i] = tmp;
551  }
552  }
553  else
554  {
555  for (Size i = 0; i < in.size(); ++i)
556  {
557  Int64 tmp = in[i];
558  tmp = endianize64(tmp);
559  in[i] = tmp;
560  }
561  }
562  }
563 
564  //encode with compression (use Qt because of zlib support)
565  if (zlib_compression)
566  {
567  unsigned long sourceLen = (unsigned long)input_bytes;
568  unsigned long compressed_length = //compressBound((unsigned long)in.size());
569  sourceLen + (sourceLen >> 12) + (sourceLen >> 14) + 11; // taken from zlib's compress.c, as we cannot use compressBound*
570 
571  compressed.resize(compressed_length);
572  while (compress(reinterpret_cast<Bytef *>(&compressed[0]), &compressed_length, reinterpret_cast<Bytef *>(&in[0]), (unsigned long)input_bytes) != Z_OK)
573  {
574  compressed_length *= 2;
575  compressed.reserve(compressed_length);
576  }
577 
578 
579  String(compressed).swap(compressed);
580  it = reinterpret_cast<Byte *>(&compressed[0]);
581  end = it + compressed_length;
582  out.resize((Size)ceil(compressed_length / 3.) * 4); //resize output array in order to have enough space for all characters
583  }
584  //encode without compression
585  else
586  {
587  out.resize((Size)ceil(input_bytes / 3.) * 4); //resize output array in order to have enough space for all characters
588  it = reinterpret_cast<Byte *>(&in[0]);
589  end = it + input_bytes;
590  }
591 
592  Byte * to = reinterpret_cast<Byte *>(&out[0]);
593 
594 
595  Size written = 0;
596 
597  while (it != end)
598  {
599  Int int_24bit = 0;
600  Int padding_count = 0;
601 
602  // construct 24-bit integer from 3 bytes
603  for (Size i = 0; i < 3; i++)
604  {
605  if (it != end)
606  {
607  int_24bit |= *it++ << ((2 - i) * 8);
608  }
609  else
610  {
611  padding_count++;
612  }
613  }
614 
615  // write out 4 characters
616  for (Int i = 3; i >= 0; i--)
617  {
618  to[i] = encoder_[int_24bit & 0x3F];
619  int_24bit >>= 6;
620  }
621 
622  // fixup for padding
623  if (padding_count > 0)
624  to[3] = '=';
625  if (padding_count > 1)
626  to[2] = '=';
627 
628  to += 4;
629  written += 4;
630  }
631 
632  out.resize(written); //no more space is needed
633  }
634 
635  template <typename ToType>
636  void Base64::decodeIntegers(const String & in, ByteOrder from_byte_order, std::vector<ToType> & out, bool zlib_compression)
637  {
638  if (zlib_compression)
639  {
640  decodeIntegersCompressed_(in, from_byte_order, out);
641  }
642  else
643  {
644  decodeIntegersUncompressed_(in, from_byte_order, out);
645  }
646  }
647 
648  template <typename ToType>
649  void Base64::decodeIntegersCompressed_(const String & in, ByteOrder from_byte_order, std::vector<ToType> & out)
650  {
651  out.clear();
652  if (in == "")
653  return;
654 
655  void * byte_buffer;
656  Size buffer_size;
657  std::vector<unsigned char> binary;
658  const Size element_size = sizeof(ToType);
659 
660  String decompressed;
661 
662  QByteArray qt_byte_array = QByteArray::fromRawData(in.c_str(), (int) in.size());
663  QByteArray bazip = QByteArray::fromBase64(qt_byte_array);
664  QByteArray czip;
665  czip.resize(4);
666  czip[0] = (bazip.size() & 0xff000000) >> 24;
667  czip[1] = (bazip.size() & 0x00ff0000) >> 16;
668  czip[2] = (bazip.size() | 0x00000800) >> 8;
669  czip[3] = (bazip.size() & 0x000000ff);
670  czip += bazip;
671  QByteArray base64_uncompressed = qUncompress(czip);
672  if (base64_uncompressed.isEmpty())
673  {
674  throw Exception::ConversionError(__FILE__, __LINE__, __PRETTY_FUNCTION__, "Decompression error?");
675  }
676  decompressed.resize(base64_uncompressed.size());
677 
678  std::copy(base64_uncompressed.begin(), base64_uncompressed.end(), decompressed.begin());
679 
680  byte_buffer = reinterpret_cast<void *>(&decompressed[0]);
681  buffer_size = decompressed.size();
682 
683  //change endianness if necessary
684  if ((OPENMS_IS_BIG_ENDIAN && from_byte_order == Base64::BYTEORDER_LITTLEENDIAN) || (!OPENMS_IS_BIG_ENDIAN && from_byte_order == Base64::BYTEORDER_BIGENDIAN))
685  {
686  if (element_size == 4)
687  {
688  const Int32 * float_buffer = reinterpret_cast<const Int32 *>(byte_buffer);
689  if (buffer_size % element_size != 0)
690  throw Exception::ConversionError(__FILE__, __LINE__, __PRETTY_FUNCTION__, "Bad BufferCount?");
691  Size float_count = buffer_size / element_size;
692  Int32 * p = reinterpret_cast<Int32 *>(byte_buffer);
693  std::transform(p, p + float_count, p, endianize32);
694 
695  out.resize(float_count);
696  // do NOT use assign here, as it will give a lot of type conversion warnings on VS compiler
697  for (Size i = 0; i < float_count; ++i)
698  {
699  out[i] = (ToType) * float_buffer;
700  ++float_buffer;
701  }
702  }
703  else
704  {
705  const Int64 * float_buffer = reinterpret_cast<const Int64 *>(byte_buffer);
706 
707  if (buffer_size % element_size != 0)
708  throw Exception::ConversionError(__FILE__, __LINE__, __PRETTY_FUNCTION__, "Bad BufferCount?");
709 
710  Size float_count = buffer_size / element_size;
711 
712  Int64 * p = reinterpret_cast<Int64 *>(byte_buffer);
713  std::transform(p, p + float_count, p, endianize64);
714 
715  out.resize(float_count);
716  // do NOT use assign here, as it will give a lot of type conversion warnings on VS compiler
717  for (Size i = 0; i < float_count; ++i)
718  {
719  out[i] = (ToType) * float_buffer;
720  ++float_buffer;
721  }
722  }
723  }
724  else
725  {
726  if (element_size == 4)
727  {
728  const Int * float_buffer = reinterpret_cast<const Int *>(byte_buffer);
729  if (buffer_size % element_size != 0)
730  throw Exception::ConversionError(__FILE__, __LINE__, __PRETTY_FUNCTION__, "Bad BufferCount while decoding?");
731 
732  Size float_count = buffer_size / element_size;
733  out.resize(float_count);
734  // do NOT use assign here, as it will give a lot of type conversion warnings on VS compiler
735  for (Size i = 0; i < float_count; ++i)
736  {
737  out[i] = (ToType) * float_buffer;
738  ++float_buffer;
739  }
740  }
741  else
742  {
743  const Int64 * float_buffer = reinterpret_cast<const Int64 *>(byte_buffer);
744 
745  if (buffer_size % element_size != 0)
746  throw Exception::ConversionError(__FILE__, __LINE__, __PRETTY_FUNCTION__, "Bad BufferCount while decoding?");
747 
748  Size float_count = buffer_size / element_size;
749  out.resize(float_count);
750  // do NOT use assign here, as it will give a lot of type conversion warnings on VS compiler
751  for (Size i = 0; i < float_count; ++i)
752  {
753  out[i] = (ToType) * float_buffer;
754  ++float_buffer;
755  }
756  }
757  }
758 
759  }
760 
761  template <typename ToType>
762  void Base64::decodeIntegersUncompressed_(const String & in, ByteOrder from_byte_order, std::vector<ToType> & out)
763  {
764  out.clear();
765  if (in == "")
766  return;
767 
768  Size src_size = in.size();
769  // last one or two '=' are skipped if contained
770  int padding = 0;
771  if (in[src_size - 1] == '=')
772  padding++;
773  if (in[src_size - 2] == '=')
774  padding++;
775 
776  src_size -= padding;
777 
778  register UInt a;
779  register UInt b;
780 
781  UInt offset = 0;
782  int inc = 1;
783  UInt written = 0;
784 
785  const Size element_size = sizeof(ToType);
786 
787  // enough for either float or double
788  char element[8] = "\x00\x00\x00\x00\x00\x00\x00";
789 
790  if ((OPENMS_IS_BIG_ENDIAN && from_byte_order == Base64::BYTEORDER_LITTLEENDIAN) || (!OPENMS_IS_BIG_ENDIAN && from_byte_order == Base64::BYTEORDER_BIGENDIAN))
791  {
792  offset = (element_size - 1); // other endian
793  inc = -1;
794  }
795  else
796  {
797  offset = 0;
798  inc = 1;
799  }
800 
801  //reserve enough space in the output vector
802  out.reserve((UInt)(std::ceil((4.0 * src_size) / 3.0) + 6.0));
803 
804  // sort all read bytes correctly into a char[4] (double) or
805  // char[8] (Real) and push_back when necessary.
806  for (Size i = 0; i < src_size; i += 4)
807  {
808 //printf ("start: i=%d, offset %d\n", i, offset);
809 
810  // decode 4 Base64-Chars to 3 Byte
811  a = decoder_[(int)in[i] - 43] - 62;
812  b = decoder_[(int)in[i + 1] - 43] - 62;
813  if (i + 1 >= src_size)
814  b = 0;
815  element[offset] = (unsigned char) ((a << 2) | (b >> 4));
816  written++;
817 //printf ("1: i=%d, offset %d, wrote %d\n", i, offset, element[offset]);
818  offset = (offset + inc) % element_size;
819 
820  if (written % element_size == 0)
821  {
822  ToType float_value;
823  if (element_size == 4)
824  {
825  Int32 * value = reinterpret_cast<Int32 *>(&element[0]);
826  float_value = (ToType) * value;
827  }
828  else
829  {
830  Int64 * value = reinterpret_cast<Int64 *>(&element[0]);
831  float_value = (ToType) * value;
832  }
833  out.push_back(float_value);
834  strcpy(element, "");
835  }
836 
837  a = decoder_[(int)in[i + 2] - 43] - 62;
838  if (i + 2 >= src_size)
839  a = 0;
840  element[offset] = (unsigned char) (((b & 15) << 4) | (a >> 2));
841  written++;
842  offset = (offset + inc) % element_size;
843 
844  if (written % element_size == 0)
845  {
846  ToType float_value;
847  if (element_size == 4)
848  {
849  Int32 * value = reinterpret_cast<Int32 *>(&element[0]);
850  float_value = (ToType) * value;
851  }
852  else
853  {
854  Int64 * value = reinterpret_cast<Int64 *>(&element[0]);
855  float_value = (ToType) * value;
856  }
857  out.push_back(float_value);
858  strcpy(element, "");
859  }
860 
861  b = decoder_[(int)in[i + 3] - 43] - 62;
862  if (i + 3 >= src_size)
863  b = 0;
864  element[offset] = (unsigned char) (((a & 3) << 6) | b);
865  written++;
866  offset = (offset + inc) % element_size;
867 
868  if (written % element_size == 0)
869  {
870  ToType float_value;
871  if (element_size == 4)
872  {
873  Int32 * value = reinterpret_cast<Int32 *>(&element[0]);
874  float_value = (ToType) * value;
875  }
876  else
877  {
878  Int64 * value = reinterpret_cast<Int64 *>(&element[0]);
879  float_value = (ToType) * value;
880  }
881  out.push_back(float_value);
882  strcpy(element, "");
883  }
884  }
885  }
886 
887 } //namespace OpenMS
888 
889 #endif /* OPENMS_FORMAT_BASE64_H */
Big endian type.
Definition: Base64.h:78
float Real
Real type.
Definition: Types.h:109
A more convenient string class.
Definition: String.h:56
Class to encode and decode Base64.
Definition: Base64.h:64
Little endian type.
Definition: Base64.h:79
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:762
Real f
Definition: Base64.h:152
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:529
ByteOrder
Byte order type.
Definition: Base64.h:76
Internal class needed for type-punning.
Definition: Base64.h:150
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:636
OPENMS_INT32_TYPE Int32
Signed integer type (32bit)
Definition: Types.h:61
DoubleReal f
Definition: Base64.h:145
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:649
Int64 i
Definition: Base64.h:146
Invalid conversion exception.
Definition: Exception.h:363
Int32 i
Definition: Base64.h:153
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:436
#define OPENMS_IS_BIG_ENDIAN
Definition: Base64.h:42
static const char decoder_[]
Definition: Base64.h:157
size_t Size
Size type e.g. used as variable which can hold result of size()
Definition: Types.h:144
static const char encoder_[]
Definition: Base64.h:156
OPENMS_INT64_TYPE Int64
Signed integer type (64bit)
Definition: Types.h:68
OPENMS_BYTE_TYPE Byte
Byte type.
Definition: Types.h:128
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:195
Int64 endianize64(Int64 &n)
Endianizes a 64 bit type from big endian to little endian and vice versa.
Definition: Base64.h:182
Internal class needed for type-punning.
Definition: Base64.h:143
Int32 endianize32(Int32 &n)
Endianizes a 32 bit type from big endian to little endian and vice versa.
Definition: Base64.h:176
int Int
Signed integer type.
Definition: Types.h:100
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:322
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:335

OpenMS / TOPP release 1.11.1 Documentation generated on Thu Nov 14 2013 11:19:11 using doxygen 1.8.5