Home  · Classes  · Annotated Classes  · Modules  · Members  · Namespaces  · Related Pages

Base64.h

Go to the documentation of this file.
00001 // --------------------------------------------------------------------------
00002 //                   OpenMS -- Open-Source Mass Spectrometry
00003 // --------------------------------------------------------------------------
00004 // Copyright The OpenMS Team -- Eberhard Karls University Tuebingen,
00005 // ETH Zurich, and Freie Universitaet Berlin 2002-2012.
00006 //
00007 // This software is released under a three-clause BSD license:
00008 //  * Redistributions of source code must retain the above copyright
00009 //    notice, this list of conditions and the following disclaimer.
00010 //  * Redistributions in binary form must reproduce the above copyright
00011 //    notice, this list of conditions and the following disclaimer in the
00012 //    documentation and/or other materials provided with the distribution.
00013 //  * Neither the name of any author or any participating institution
00014 //    may be used to endorse or promote products derived from this software
00015 //    without specific prior written permission.
00016 // For a full list of authors, refer to the file AUTHORS.
00017 // --------------------------------------------------------------------------
00018 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00019 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00020 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00021 // ARE DISCLAIMED. IN NO EVENT SHALL ANY OF THE AUTHORS OR THE CONTRIBUTING
00022 // INSTITUTIONS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00023 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00024 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
00025 // OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
00026 // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
00027 // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
00028 // ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00029 //
00030 // --------------------------------------------------------------------------
00031 // $Maintainer: Andreas Bertsch $
00032 // $Authors: Marc Sturm $
00033 // --------------------------------------------------------------------------
00034 
00035 #ifndef OPENMS_FORMAT_BASE64_H
00036 #define OPENMS_FORMAT_BASE64_H
00037 
00038 #ifndef OPENMS_IS_BIG_ENDIAN
00039 #if defined OPENMS_BIG_ENDIAN
00040 #define OPENMS_IS_BIG_ENDIAN true
00041 #else
00042 #define OPENMS_IS_BIG_ENDIAN false
00043 #endif
00044 #endif
00045 
00046 #include <OpenMS/CONCEPT/Types.h>
00047 #include <OpenMS/CONCEPT/Exception.h>
00048 #include <OpenMS/DATASTRUCTURES/String.h>
00049 #include <algorithm>
00050 #include <iterator>
00051 #include <cmath>
00052 #include <vector>
00053 
00054 #include <QByteArray>
00055 #include <zlib.h>
00056 
00057 namespace OpenMS
00058 {
00064   class OPENMS_DLLAPI Base64
00065   {
00066 
00067 public:
00068 
00070     Base64();
00071 
00073     virtual ~Base64();
00074 
00076     enum ByteOrder
00077     {
00078       BYTEORDER_BIGENDIAN,                  
00079       BYTEORDER_LITTLEENDIAN            
00080     };
00081 
00089     template <typename FromType>
00090     void encode(std::vector<FromType> & in, ByteOrder to_byte_order, String & out, bool zlib_compression = false);
00091 
00099     template <typename ToType>
00100     void decode(const String & in, ByteOrder from_byte_order, std::vector<ToType> & out, bool zlib_compression = false);
00101 
00109     template <typename FromType>
00110     void encodeIntegers(std::vector<FromType> & in, ByteOrder to_byte_order, String & out, bool zlib_compression = false);
00111 
00119     template <typename ToType>
00120     void decodeIntegers(const String & in, ByteOrder from_byte_order, std::vector<ToType> & out, bool zlib_compression = false);
00121 
00129     void encodeStrings(std::vector<String> & in, String & out, bool zlib_compression = false);
00130 
00138     void decodeStrings(const String & in, std::vector<String> & out, bool zlib_compression = false);
00139 
00140 private:
00141 
00143     union Reinterpreter64_
00144     {
00145       DoubleReal f;
00146       Int64 i;
00147     };
00148 
00150     union Reinterpreter32_
00151     {
00152       Real f;
00153       Int32 i;
00154     };
00155 
00156     static const char encoder_[];
00157     static const char decoder_[];
00159     template <typename ToType>
00160     void decodeUncompressed_(const String & in, ByteOrder from_byte_order, std::vector<ToType> & out);
00161 
00163     template <typename ToType>
00164     void decodeCompressed_(const String & in, ByteOrder from_byte_order, std::vector<ToType> & out);
00165 
00167     template <typename ToType>
00168     void decodeIntegersUncompressed_(const String & in, ByteOrder from_byte_order, std::vector<ToType> & out);
00169 
00171     template <typename ToType>
00172     void decodeIntegersCompressed_(const String & in, ByteOrder from_byte_order, std::vector<ToType> & out);
00173   };
00174 
00176   inline Int32 endianize32(Int32 & n)
00177   {
00178     return ((n & 0xff) << 24) | ((n & 0xff00) << 8) | ((n & 0xff0000) >> 8) | ((n & 0xff000000) >> 24);
00179   }
00180 
00182   inline Int64 endianize64(Int64 & n)
00183   {
00184     return ((n & 0x00000000000000ffll) << 56) |
00185            ((n & 0x000000000000ff00ll) << 40) |
00186            ((n & 0x0000000000ff0000ll) << 24) |
00187            ((n & 0x00000000ff000000ll) << 8)  |
00188            ((n & 0x000000ff00000000ll) >> 8)  |
00189            ((n & 0x0000ff0000000000ll) >> 24) |
00190            ((n & 0x00ff000000000000ll) >> 40) |
00191            ((n & 0xff00000000000000ll) >> 56);
00192   }
00193 
00194   template <typename FromType>
00195   void Base64::encode(std::vector<FromType> & in, ByteOrder to_byte_order, String & out, bool zlib_compression)
00196   {
00197     out.clear();
00198     if (in.empty())
00199       return;
00200 
00201     //initialize
00202     const Size element_size = sizeof(FromType);
00203     const Size input_bytes = element_size * in.size();
00204     String compressed;
00205     Byte * it;
00206     Byte * end;
00207     //Change endianness if necessary
00208     if ((OPENMS_IS_BIG_ENDIAN && to_byte_order == Base64::BYTEORDER_LITTLEENDIAN) || (!OPENMS_IS_BIG_ENDIAN && to_byte_order == Base64::BYTEORDER_BIGENDIAN))
00209     {
00210       if (element_size == 4)
00211       {
00212         for (Size i = 0; i < in.size(); ++i)
00213         {
00214           Reinterpreter32_ tmp;
00215           tmp.f = in[i];
00216           tmp.i = endianize32(tmp.i);
00217           in[i] = tmp.f;
00218         }
00219       }
00220       else
00221       {
00222         for (Size i = 0; i < in.size(); ++i)
00223         {
00224           Reinterpreter64_ tmp;
00225           tmp.f = in[i];
00226           tmp.i = endianize64(tmp.i);
00227           in[i] = tmp.f;
00228         }
00229       }
00230     }
00231 
00232     //encode with compression
00233     if (zlib_compression)
00234     {
00235       unsigned long sourceLen =   (unsigned long)in.size();
00236       unsigned long compressed_length =       //compressBound((unsigned long)in.size());
00237                                         sourceLen + (sourceLen >> 12) + (sourceLen >> 14) + 11; // taken from zlib's compress.c, as we cannot use compressBound*
00238       //
00239       // (*) compressBound is not defined in the QtCore lib, which forces the linker under windows to link in our zlib.
00240       //     This leads to multiply defined symbols as compress() is then defined twice.
00241 
00242       int zlib_error;
00243       do
00244       {
00245         compressed.resize(compressed_length);
00246         zlib_error = compress(reinterpret_cast<Bytef *>(&compressed[0]), &compressed_length, reinterpret_cast<Bytef *>(&in[0]), (unsigned long)input_bytes);
00247 
00248         switch (zlib_error)
00249         {
00250         case Z_MEM_ERROR:
00251           throw Exception::OutOfMemory(__FILE__, __LINE__, __PRETTY_FUNCTION__, compressed_length);
00252           break;
00253 
00254         case Z_BUF_ERROR:
00255           compressed_length *= 2;
00256         }
00257       }
00258       while (zlib_error == Z_BUF_ERROR);
00259 
00260       if (zlib_error != Z_OK)
00261       {
00262         throw Exception::ConversionError(__FILE__, __LINE__, __PRETTY_FUNCTION__, "Compression error?");
00263       }
00264 
00265       String(compressed).swap(compressed);
00266       it = reinterpret_cast<Byte *>(&compressed[0]);
00267       end = it + compressed_length;
00268       out.resize((Size)ceil(compressed_length / 3.) * 4);     //resize output array in order to have enough space for all characters
00269     }
00270     //encode without compression
00271     else
00272     {
00273       out.resize((Size)ceil(input_bytes / 3.) * 4);     //resize output array in order to have enough space for all characters
00274       it = reinterpret_cast<Byte *>(&in[0]);
00275       end = it + input_bytes;
00276     }
00277 
00278     Byte * to = reinterpret_cast<Byte *>(&out[0]);
00279 
00280 
00281     Size written = 0;
00282 
00283     while (it != end)
00284     {
00285       Int int_24bit = 0;
00286       Int padding_count = 0;
00287 
00288       // construct 24-bit integer from 3 bytes
00289       for (Size i = 0; i < 3; i++)
00290       {
00291         if (it != end)
00292         {
00293           int_24bit |= *it++ << ((2 - i) * 8);
00294         }
00295         else
00296         {
00297           padding_count++;
00298         }
00299       }
00300 
00301       // write out 4 characters
00302       for (Int i = 3; i >= 0; i--)
00303       {
00304         to[i] = encoder_[int_24bit & 0x3F];
00305         int_24bit >>= 6;
00306       }
00307 
00308       // fixup for padding
00309       if (padding_count > 0)
00310         to[3] = '=';
00311       if (padding_count > 1)
00312         to[2] = '=';
00313 
00314       to += 4;
00315       written += 4;
00316     }
00317 
00318     out.resize(written);         //no more space is needed
00319   }
00320 
00321   template <typename ToType>
00322   void Base64::decode(const String & in, ByteOrder from_byte_order, std::vector<ToType> & out, bool zlib_compression)
00323   {
00324     if (zlib_compression)
00325     {
00326       decodeCompressed_(in, from_byte_order, out);
00327     }
00328     else
00329     {
00330       decodeUncompressed_(in, from_byte_order, out);
00331     }
00332   }
00333 
00334   template <typename ToType>
00335   void Base64::decodeCompressed_(const String & in, ByteOrder from_byte_order, std::vector<ToType> & out)
00336   {
00337     out.clear();
00338     if (in == "")
00339       return;
00340 
00341     void * byte_buffer;
00342     Size buffer_size;
00343     std::vector<unsigned char> binary;
00344     const Size element_size = sizeof(ToType);
00345 
00346     String decompressed;
00347 
00348     QByteArray qt_byte_array = QByteArray::fromRawData(in.c_str(), (int) in.size());
00349     QByteArray bazip = QByteArray::fromBase64(qt_byte_array);
00350     QByteArray czip;
00351     czip.resize(4);
00352     czip[0] = (bazip.size() & 0xff000000) >> 24;
00353     czip[1] = (bazip.size() & 0x00ff0000) >> 16;
00354     czip[2] = (bazip.size() & 0x0000ff00) >> 8;
00355     czip[3] = (bazip.size() & 0x000000ff);
00356     czip += bazip;
00357     QByteArray base64_uncompressed = qUncompress(czip);
00358 
00359     if (base64_uncompressed.isEmpty())
00360     {
00361       throw Exception::ConversionError(__FILE__, __LINE__, __PRETTY_FUNCTION__, "Decompression error?");
00362     }
00363     decompressed.resize(base64_uncompressed.size());
00364 
00365     std::copy(base64_uncompressed.begin(), base64_uncompressed.end(), decompressed.begin());
00366 
00367     byte_buffer = reinterpret_cast<void *>(&decompressed[0]);
00368     buffer_size = decompressed.size();
00369 
00370     //change endianness if necessary
00371     if ((OPENMS_IS_BIG_ENDIAN && from_byte_order == Base64::BYTEORDER_LITTLEENDIAN) || (!OPENMS_IS_BIG_ENDIAN && from_byte_order == Base64::BYTEORDER_BIGENDIAN))
00372     {
00373       if (element_size == 4)
00374       {
00375         const Real * float_buffer = reinterpret_cast<const Real *>(byte_buffer);
00376         if (buffer_size % element_size != 0)
00377           throw Exception::ConversionError(__FILE__, __LINE__, __PRETTY_FUNCTION__, "Bad BufferCount?");
00378         Size float_count = buffer_size / element_size;
00379         Int32 * p = reinterpret_cast<Int32 *>(byte_buffer);
00380         std::transform(p, p + float_count, p, endianize32);
00381         out.assign(float_buffer, float_buffer + float_count);
00382       }
00383       else
00384       {
00385         const DoubleReal * float_buffer = reinterpret_cast<const DoubleReal *>(byte_buffer);
00386 
00387         if (buffer_size % element_size != 0)
00388           throw Exception::ConversionError(__FILE__, __LINE__, __PRETTY_FUNCTION__, "Bad BufferCount?");
00389 
00390         Size float_count = buffer_size / element_size;
00391 
00392         Int64 * p = reinterpret_cast<Int64 *>(byte_buffer);
00393         std::transform(p, p + float_count, p, endianize64);
00394 
00395         out.resize(float_count);
00396         // do NOT use assign here, as it will give a lot of type conversion warnings on VS compiler
00397         for (Size i = 0; i < float_count; ++i)
00398         {
00399           out[i] = (ToType) * float_buffer;
00400           ++float_buffer;
00401         }
00402       }
00403     }
00404     else
00405     {
00406       if (element_size == 4)
00407       {
00408         const Real * float_buffer = reinterpret_cast<const Real *>(byte_buffer);
00409         if (buffer_size % element_size != 0)
00410           throw Exception::ConversionError(__FILE__, __LINE__, __PRETTY_FUNCTION__, "Bad BufferCount while decoding?");
00411 
00412         Size float_count = buffer_size / element_size;
00413         out.assign(float_buffer, float_buffer + float_count);
00414       }
00415       else
00416       {
00417         const DoubleReal * float_buffer = reinterpret_cast<const DoubleReal *>(byte_buffer);
00418 
00419         if (buffer_size % element_size != 0)
00420           throw Exception::ConversionError(__FILE__, __LINE__, __PRETTY_FUNCTION__, "Bad BufferCount while decoding?");
00421 
00422         Size float_count = buffer_size / element_size;
00423         out.resize(float_count);
00424         // do NOT use assign here, as it will give a lot of type conversion warnings on VS compiler
00425         for (Size i = 0; i < float_count; ++i)
00426         {
00427           out[i] = (ToType) * float_buffer;
00428           ++float_buffer;
00429         }
00430       }
00431     }
00432 
00433   }
00434 
00435   template <typename ToType>
00436   void Base64::decodeUncompressed_(const String & in, ByteOrder from_byte_order, std::vector<ToType> & out)
00437   {
00438     out.clear();
00439     if (in == "")
00440       return;
00441 
00442     Size src_size = in.size();
00443     // last one or two '=' are skipped if contained
00444     int padding = 0;
00445     if (in[src_size - 1] == '=')
00446       padding++;
00447     if (in[src_size - 2] == '=')
00448       padding++;
00449 
00450     src_size -= padding;
00451 
00452     register UInt a;
00453     register UInt b;
00454 
00455     UInt offset = 0;
00456     int inc = 1;
00457     UInt written = 0;
00458 
00459     const Size element_size = sizeof(ToType);
00460 
00461     // enough for either float or double
00462     char element[8] = "\x00\x00\x00\x00\x00\x00\x00";
00463 
00464     if ((OPENMS_IS_BIG_ENDIAN && from_byte_order == Base64::BYTEORDER_LITTLEENDIAN) || (!OPENMS_IS_BIG_ENDIAN && from_byte_order == Base64::BYTEORDER_BIGENDIAN))
00465     {
00466       offset = (element_size - 1);              // other endian
00467       inc = -1;
00468     }
00469     else
00470     {
00471       offset = 0;
00472       inc = 1;
00473     }
00474 
00475     //reserve enough space in the output vector
00476     out.reserve((UInt)(std::ceil((4.0 * src_size) / 3.0) + 6.0));
00477 
00478     // sort all read bytes correctly into a char[4] (double) or
00479     // char[8] (Real) and push_back when necessary.
00480     for (Size i = 0; i < src_size; i += 4)
00481     {
00482       // decode 4 Base64-Chars to 3 Byte
00483       a = decoder_[(int)in[i] - 43] - 62;
00484       b = decoder_[(int)in[i + 1] - 43] - 62;
00485       if (i + 1 >= src_size)
00486         b = 0;
00487       element[offset] = (unsigned char) ((a << 2) | (b >> 4));
00488       written++;
00489       offset = (offset + inc) % element_size;
00490 
00491       if (written % element_size == 0)
00492       {
00493         ToType * to_type = reinterpret_cast<ToType *>(&element[0]);
00494         out.push_back((*to_type));
00495         strcpy(element, "");
00496       }
00497 
00498       a = decoder_[(int)in[i + 2] - 43] - 62;
00499       if (i + 2 >= src_size)
00500         a = 0;
00501       element[offset] = (unsigned char) (((b & 15) << 4) | (a >> 2));
00502       written++;
00503       offset = (offset + inc) % element_size;
00504 
00505       if (written % element_size == 0)
00506       {
00507         ToType * to_type = reinterpret_cast<ToType *>(&element[0]);
00508         out.push_back((*to_type));
00509         strcpy(element, "");
00510       }
00511 
00512       b = decoder_[(int)in[i + 3] - 43] - 62;
00513       if (i + 3 >= src_size)
00514         b = 0;
00515       element[offset] = (unsigned char) (((a & 3) << 6) | b);
00516       written++;
00517       offset = (offset + inc) % element_size;
00518 
00519       if (written % element_size == 0)
00520       {
00521         ToType * to_type = reinterpret_cast<ToType *>(&element[0]);
00522         out.push_back((*to_type));
00523         strcpy(element, "");
00524       }
00525     }
00526   }
00527 
00528   template <typename FromType>
00529   void Base64::encodeIntegers(std::vector<FromType> & in, ByteOrder to_byte_order, String & out, bool zlib_compression)
00530   {
00531     out.clear();
00532     if (in.empty())
00533       return;
00534 
00535     //initialize
00536     const Size element_size = sizeof(FromType);
00537     const Size input_bytes = element_size * in.size();
00538     String compressed;
00539     Byte * it;
00540     Byte * end;
00541     //Change endianness if necessary
00542     if ((OPENMS_IS_BIG_ENDIAN && to_byte_order == Base64::BYTEORDER_LITTLEENDIAN) || (!OPENMS_IS_BIG_ENDIAN && to_byte_order == Base64::BYTEORDER_BIGENDIAN))
00543     {
00544       if (element_size == 4)
00545       {
00546         for (Size i = 0; i < in.size(); ++i)
00547         {
00548           Int32 tmp = in[i];
00549           tmp = endianize32(tmp);
00550           in[i] = tmp;
00551         }
00552       }
00553       else
00554       {
00555         for (Size i = 0; i < in.size(); ++i)
00556         {
00557           Int64 tmp = in[i];
00558           tmp = endianize64(tmp);
00559           in[i] = tmp;
00560         }
00561       }
00562     }
00563 
00564     //encode with compression (use Qt because of zlib support)
00565     if (zlib_compression)
00566     {
00567       unsigned long sourceLen =   (unsigned long)input_bytes;
00568       unsigned long compressed_length =       //compressBound((unsigned long)in.size());
00569                                         sourceLen + (sourceLen >> 12) + (sourceLen >> 14) + 11; // taken from zlib's compress.c, as we cannot use compressBound*
00570 
00571       compressed.resize(compressed_length);
00572       while (compress(reinterpret_cast<Bytef *>(&compressed[0]), &compressed_length, reinterpret_cast<Bytef *>(&in[0]), (unsigned long)input_bytes) != Z_OK)
00573       {
00574         compressed_length *= 2;
00575         compressed.reserve(compressed_length);
00576       }
00577 
00578 
00579       String(compressed).swap(compressed);
00580       it = reinterpret_cast<Byte *>(&compressed[0]);
00581       end = it + compressed_length;
00582       out.resize((Size)ceil(compressed_length / 3.) * 4);     //resize output array in order to have enough space for all characters
00583     }
00584     //encode without compression
00585     else
00586     {
00587       out.resize((Size)ceil(input_bytes / 3.) * 4);     //resize output array in order to have enough space for all characters
00588       it = reinterpret_cast<Byte *>(&in[0]);
00589       end = it + input_bytes;
00590     }
00591 
00592     Byte * to = reinterpret_cast<Byte *>(&out[0]);
00593 
00594 
00595     Size written = 0;
00596 
00597     while (it != end)
00598     {
00599       Int int_24bit = 0;
00600       Int padding_count = 0;
00601 
00602       // construct 24-bit integer from 3 bytes
00603       for (Size i = 0; i < 3; i++)
00604       {
00605         if (it != end)
00606         {
00607           int_24bit |= *it++ << ((2 - i) * 8);
00608         }
00609         else
00610         {
00611           padding_count++;
00612         }
00613       }
00614 
00615       // write out 4 characters
00616       for (Int i = 3; i >= 0; i--)
00617       {
00618         to[i] = encoder_[int_24bit & 0x3F];
00619         int_24bit >>= 6;
00620       }
00621 
00622       // fixup for padding
00623       if (padding_count > 0)
00624         to[3] = '=';
00625       if (padding_count > 1)
00626         to[2] = '=';
00627 
00628       to += 4;
00629       written += 4;
00630     }
00631 
00632     out.resize(written);         //no more space is needed
00633   }
00634 
00635   template <typename ToType>
00636   void Base64::decodeIntegers(const String & in, ByteOrder from_byte_order, std::vector<ToType> & out, bool zlib_compression)
00637   {
00638     if (zlib_compression)
00639     {
00640       decodeIntegersCompressed_(in, from_byte_order, out);
00641     }
00642     else
00643     {
00644       decodeIntegersUncompressed_(in, from_byte_order, out);
00645     }
00646   }
00647 
00648   template <typename ToType>
00649   void Base64::decodeIntegersCompressed_(const String & in, ByteOrder from_byte_order, std::vector<ToType> & out)
00650   {
00651     out.clear();
00652     if (in == "")
00653       return;
00654 
00655     void * byte_buffer;
00656     Size buffer_size;
00657     std::vector<unsigned char> binary;
00658     const Size element_size = sizeof(ToType);
00659 
00660     String decompressed;
00661 
00662     QByteArray qt_byte_array = QByteArray::fromRawData(in.c_str(), (int) in.size());
00663     QByteArray bazip = QByteArray::fromBase64(qt_byte_array);
00664     QByteArray czip;
00665     czip.resize(4);
00666     czip[0] = (bazip.size() & 0xff000000) >> 24;
00667     czip[1] = (bazip.size() & 0x00ff0000) >> 16;
00668     czip[2] = (bazip.size() | 0x00000800) >> 8;
00669     czip[3] = (bazip.size() & 0x000000ff);
00670     czip += bazip;
00671     QByteArray base64_uncompressed = qUncompress(czip);
00672     if (base64_uncompressed.isEmpty())
00673     {
00674       throw Exception::ConversionError(__FILE__, __LINE__, __PRETTY_FUNCTION__, "Decompression error?");
00675     }
00676     decompressed.resize(base64_uncompressed.size());
00677 
00678     std::copy(base64_uncompressed.begin(), base64_uncompressed.end(), decompressed.begin());
00679 
00680     byte_buffer = reinterpret_cast<void *>(&decompressed[0]);
00681     buffer_size = decompressed.size();
00682 
00683     //change endianness if necessary
00684     if ((OPENMS_IS_BIG_ENDIAN && from_byte_order == Base64::BYTEORDER_LITTLEENDIAN) || (!OPENMS_IS_BIG_ENDIAN && from_byte_order == Base64::BYTEORDER_BIGENDIAN))
00685     {
00686       if (element_size == 4)
00687       {
00688         const Int32 * float_buffer = reinterpret_cast<const Int32 *>(byte_buffer);
00689         if (buffer_size % element_size != 0)
00690           throw Exception::ConversionError(__FILE__, __LINE__, __PRETTY_FUNCTION__, "Bad BufferCount?");
00691         Size float_count = buffer_size / element_size;
00692         Int32 * p = reinterpret_cast<Int32 *>(byte_buffer);
00693         std::transform(p, p + float_count, p, endianize32);
00694 
00695         out.resize(float_count);
00696         // do NOT use assign here, as it will give a lot of type conversion warnings on VS compiler
00697         for (Size i = 0; i < float_count; ++i)
00698         {
00699           out[i] = (ToType) * float_buffer;
00700           ++float_buffer;
00701         }
00702       }
00703       else
00704       {
00705         const Int64 * float_buffer = reinterpret_cast<const Int64 *>(byte_buffer);
00706 
00707         if (buffer_size % element_size != 0)
00708           throw Exception::ConversionError(__FILE__, __LINE__, __PRETTY_FUNCTION__, "Bad BufferCount?");
00709 
00710         Size float_count = buffer_size / element_size;
00711 
00712         Int64 * p = reinterpret_cast<Int64 *>(byte_buffer);
00713         std::transform(p, p + float_count, p, endianize64);
00714 
00715         out.resize(float_count);
00716         // do NOT use assign here, as it will give a lot of type conversion warnings on VS compiler
00717         for (Size i = 0; i < float_count; ++i)
00718         {
00719           out[i] = (ToType) * float_buffer;
00720           ++float_buffer;
00721         }
00722       }
00723     }
00724     else
00725     {
00726       if (element_size == 4)
00727       {
00728         const Int * float_buffer = reinterpret_cast<const Int *>(byte_buffer);
00729         if (buffer_size % element_size != 0)
00730           throw Exception::ConversionError(__FILE__, __LINE__, __PRETTY_FUNCTION__, "Bad BufferCount while decoding?");
00731 
00732         Size float_count = buffer_size / element_size;
00733         out.resize(float_count);
00734         // do NOT use assign here, as it will give a lot of type conversion warnings on VS compiler
00735         for (Size i = 0; i < float_count; ++i)
00736         {
00737           out[i] = (ToType) * float_buffer;
00738           ++float_buffer;
00739         }
00740       }
00741       else
00742       {
00743         const Int64 * float_buffer = reinterpret_cast<const Int64 *>(byte_buffer);
00744 
00745         if (buffer_size % element_size != 0)
00746           throw Exception::ConversionError(__FILE__, __LINE__, __PRETTY_FUNCTION__, "Bad BufferCount while decoding?");
00747 
00748         Size float_count = buffer_size / element_size;
00749         out.resize(float_count);
00750         // do NOT use assign here, as it will give a lot of type conversion warnings on VS compiler
00751         for (Size i = 0; i < float_count; ++i)
00752         {
00753           out[i] = (ToType) * float_buffer;
00754           ++float_buffer;
00755         }
00756       }
00757     }
00758 
00759   }
00760 
00761   template <typename ToType>
00762   void Base64::decodeIntegersUncompressed_(const String & in, ByteOrder from_byte_order, std::vector<ToType> & out)
00763   {
00764     out.clear();
00765     if (in == "")
00766       return;
00767 
00768     Size src_size = in.size();
00769     // last one or two '=' are skipped if contained
00770     int padding = 0;
00771     if (in[src_size - 1] == '=')
00772       padding++;
00773     if (in[src_size - 2] == '=')
00774       padding++;
00775 
00776     src_size -= padding;
00777 
00778     register UInt a;
00779     register UInt b;
00780 
00781     UInt offset = 0;
00782     int inc = 1;
00783     UInt written = 0;
00784 
00785     const Size element_size = sizeof(ToType);
00786 
00787     // enough for either float or double
00788     char element[8] = "\x00\x00\x00\x00\x00\x00\x00";
00789 
00790     if ((OPENMS_IS_BIG_ENDIAN && from_byte_order == Base64::BYTEORDER_LITTLEENDIAN) || (!OPENMS_IS_BIG_ENDIAN && from_byte_order == Base64::BYTEORDER_BIGENDIAN))
00791     {
00792       offset = (element_size - 1);              // other endian
00793       inc = -1;
00794     }
00795     else
00796     {
00797       offset = 0;
00798       inc = 1;
00799     }
00800 
00801     //reserve enough space in the output vector
00802     out.reserve((UInt)(std::ceil((4.0 * src_size) / 3.0) + 6.0));
00803 
00804     // sort all read bytes correctly into a char[4] (double) or
00805     // char[8] (Real) and push_back when necessary.
00806     for (Size i = 0; i < src_size; i += 4)
00807     {
00808 //printf ("start: i=%d, offset %d\n", i, offset);
00809 
00810       // decode 4 Base64-Chars to 3 Byte
00811       a = decoder_[(int)in[i] - 43] - 62;
00812       b = decoder_[(int)in[i + 1] - 43] - 62;
00813       if (i + 1 >= src_size)
00814         b = 0;
00815       element[offset] = (unsigned char) ((a << 2) | (b >> 4));
00816       written++;
00817 //printf ("1: i=%d, offset %d, wrote %d\n", i, offset, element[offset]);
00818       offset = (offset + inc) % element_size;
00819 
00820       if (written % element_size == 0)
00821       {
00822         ToType float_value;
00823         if (element_size == 4)
00824         {
00825           Int32 * value = reinterpret_cast<Int32 *>(&element[0]);
00826           float_value = (ToType) * value;
00827         }
00828         else
00829         {
00830           Int64 * value = reinterpret_cast<Int64 *>(&element[0]);
00831           float_value = (ToType) * value;
00832         }
00833         out.push_back(float_value);
00834         strcpy(element, "");
00835       }
00836 
00837       a = decoder_[(int)in[i + 2] - 43] - 62;
00838       if (i + 2 >= src_size)
00839         a = 0;
00840       element[offset] = (unsigned char) (((b & 15) << 4) | (a >> 2));
00841       written++;
00842       offset = (offset + inc) % element_size;
00843 
00844       if (written % element_size == 0)
00845       {
00846         ToType float_value;
00847         if (element_size == 4)
00848         {
00849           Int32 * value = reinterpret_cast<Int32 *>(&element[0]);
00850           float_value = (ToType) * value;
00851         }
00852         else
00853         {
00854           Int64 * value = reinterpret_cast<Int64 *>(&element[0]);
00855           float_value = (ToType) * value;
00856         }
00857         out.push_back(float_value);
00858         strcpy(element, "");
00859       }
00860 
00861       b = decoder_[(int)in[i + 3] - 43] - 62;
00862       if (i + 3 >= src_size)
00863         b = 0;
00864       element[offset] = (unsigned char) (((a & 3) << 6) | b);
00865       written++;
00866       offset = (offset + inc) % element_size;
00867 
00868       if (written % element_size == 0)
00869       {
00870         ToType float_value;
00871         if (element_size == 4)
00872         {
00873           Int32 * value = reinterpret_cast<Int32 *>(&element[0]);
00874           float_value = (ToType) * value;
00875         }
00876         else
00877         {
00878           Int64 * value = reinterpret_cast<Int64 *>(&element[0]);
00879           float_value = (ToType) * value;
00880         }
00881         out.push_back(float_value);
00882         strcpy(element, "");
00883       }
00884     }
00885   }
00886 
00887 } //namespace OpenMS
00888 
00889 #endif /* OPENMS_FORMAT_BASE64_H */

OpenMS / TOPP release 1.10.0 Documentation generated on Thu Mar 7 2013 09:42:37 using doxygen 1.7.1