StreamOps.h

Go to the documentation of this file.
00001 //
00002 //  Copyright (C) 2002-2008 Greg Landrum and Rational Discovery LLC
00003 //
00004 //  @@ All Rights Reserved @@
00005 //  This file is part of the RDKit.
00006 //  The contents are covered by the terms of the BSD license
00007 //  which is included in the file license.txt, found at the root
00008 //  of the RDKit source tree.
00009 //
00010 //
00011 #ifndef _RD_STREAMOPS_H
00012 #define _RD_STREAMOPS_H
00013 
00014 #include "types.h"
00015 #include <string>
00016 #include <sstream>
00017 #include <iostream>
00018 #include <boost/cstdint.hpp>
00019 
00020 
00021 namespace RDKit{
00022     
00023   //! Packs an integer and outputs it to a stream
00024   inline void appendPackedIntToStream(std::stringstream &ss, boost::uint32_t num) {
00025     int nbytes, bix;
00026     unsigned int val, res;
00027     char tc;
00028     
00029     CHECK_INVARIANT(num >= 0, "");
00030     res = num;
00031     while (1) {
00032       if (res < (1<<7)) {
00033         val = (res<<1);
00034         nbytes = 1;
00035         break;
00036       }
00037       res -= (1<<7);
00038       if (res < (1<<14)) {
00039         val = ((res<<2) | 1);
00040         nbytes = 2;
00041         break;
00042       }
00043       res -= (1<<14);
00044       if (res < (1<<21)) {
00045         val = ((res<<3) | 3);
00046         nbytes = 3;
00047         break;
00048       }
00049       res -= (1<<21);
00050       if ( res < (1<<29)) {
00051         val = ((res<<3) | 7);
00052         nbytes = 4;
00053         break;
00054       }
00055       else {
00056         CHECK_INVARIANT(0, "ERROR: Integer to big to pack\n");
00057       }
00058     }
00059     
00060     for (bix = 0; bix < nbytes; bix++) {
00061       tc = (char) (val & 255);
00062       ss.write(&tc, 1);
00063       val >>= 8;
00064     }
00065   }
00066   
00067   //! Reads an integer from a stream in packed format and returns the result.
00068   inline boost::uint32_t readPackedIntFromStream(std::stringstream &ss) {
00069     boost::uint32_t val, num;
00070     int shift, offset;
00071     char tmp;
00072     ss.read(&tmp, sizeof(tmp));
00073     val = UCHAR(tmp);
00074     offset = 0;
00075     if ((val&1) == 0) {
00076       shift = 1;
00077     }
00078     else if ((val&3) == 1) {
00079       ss.read((char *)&tmp, sizeof(tmp));
00080       val |= (UCHAR(tmp) << 8);
00081       shift = 2;
00082       offset = (1<<7);
00083     }
00084     else if ((val&7) == 3) {
00085       ss.read((char *)&tmp, sizeof(tmp));
00086       val |= (UCHAR(tmp) << 8);
00087       ss.read((char *)&tmp, sizeof(tmp));
00088       val |= (UCHAR(tmp) << 16);
00089       shift = 3;
00090       offset = (1<<7) + (1<<14);
00091     }
00092     else {
00093       ss.read((char *)&tmp, sizeof(tmp));
00094       val |= (UCHAR(tmp) << 8);
00095       ss.read((char *)&tmp, sizeof(tmp));
00096       val |= (UCHAR(tmp) << 16);
00097       ss.read((char *)&tmp, sizeof(tmp));
00098       val |= (UCHAR(tmp) << 24);
00099       shift = 3;
00100       offset = (1<<7) + (1<<14) + (1<<21);
00101     }
00102     num = (val >> shift) + offset;
00103     return num;
00104   }
00105 
00106   //! Reads an integer from a char * in packed format and returns the result.
00107   //!  The argument is advanced
00108   inline boost::uint32_t pullPackedIntFromString(const char *&text) {
00109     boost::uint32_t val, num;
00110     int shift, offset;
00111     char tmp;
00112     tmp = *text;
00113     text++;
00114     val = UCHAR(tmp);
00115     offset = 0;
00116     if ((val&1) == 0) {
00117       shift = 1;
00118     }
00119     else if ((val&3) == 1) {
00120       tmp = *text;
00121       text++;
00122       val |= (UCHAR(tmp) << 8);
00123       shift = 2;
00124       offset = (1<<7);
00125     }
00126     else if ((val&7) == 3) {
00127       tmp = *text;
00128       text++;
00129       val |= (UCHAR(tmp) << 8);
00130       tmp = *text;
00131       text++;
00132       val |= (UCHAR(tmp) << 16);
00133       shift = 3;
00134       offset = (1<<7) + (1<<14);
00135     }
00136     else {
00137       tmp = *text;
00138       text++;
00139       val |= (UCHAR(tmp) << 8);
00140       tmp = *text;
00141       text++;
00142       val |= (UCHAR(tmp) << 16);
00143       tmp = *text;
00144       text++;
00145       val |= (UCHAR(tmp) << 24);
00146       shift = 3;
00147       offset = (1<<7) + (1<<14) + (1<<21);
00148     }
00149     num = (val >> shift) + offset;
00150     return num;
00151   }
00152   
00153   //! does a binary write of an object to a stream
00154   template <typename T>
00155     void streamWrite(std::ostream &ss,const T &val){
00156     ss.write((const char *)&val,sizeof(T));
00157   }
00158   //! does a binary read of an object from a stream
00159   template <typename T>
00160     void streamRead(std::istream &ss,T &loc){
00161     ss.read((char *)&loc,sizeof(T));
00162   }
00163  
00164   //! grabs the next line from an instream and returns it.
00165   inline std::string getLine(std::istream *inStream) {
00166     std::string res;
00167     std::getline(*inStream,res);
00168     if ((res.length() > 0) && (res[res.length()-1]=='\r')){
00169       res.erase(res.length()-1);
00170     }
00171     return res;
00172   }
00173   //! grabs the next line from an instream and returns it.
00174   inline std::string getLine(std::istream &inStream) {
00175     return getLine(&inStream);
00176   }
00177 }
00178 
00179 
00180 
00181 #endif