RDKit: StreamOps.h Source File

| RDKit Open-source cheminformatics and machine learning.

- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

StreamOps.h
Go to the documentation of this file.
1 //
2 // Copyright (C) 2002-2008 Greg Landrum and Rational Discovery LLC
3 //
4 // @@ All Rights Reserved @@
5 // This file is part of the RDKit.
6 // The contents are covered by the terms of the BSD license
7 // which is included in the file license.txt, found at the root
8 // of the RDKit source tree.
9 //
10 //
11 #ifndef _RD_STREAMOPS_H
12 #define _RD_STREAMOPS_H
13
14 #include "types.h"
15 #include <string>
16 #include <sstream>
17 #include <iostream>
18 #include <boost/cstdint.hpp>
19 #include <boost/detail/endian.hpp>
20
21 namespace RDKit {
22 // this code block for handling endian problems is from :
23 // http://stackoverflow.com/questions/105252/how-do-i-convert-between-big-endian-and-little-endian-values-in-c
24 enum EEndian {
25 LITTLE_ENDIAN_ORDER,
26 BIG_ENDIAN_ORDER,
27 #if defined(BOOST_LITTLE_ENDIAN)
28 HOST_ENDIAN_ORDER = LITTLE_ENDIAN_ORDER
29 #elif defined(BOOST_BIG_ENDIAN)
30 HOST_ENDIAN_ORDER = BIG_ENDIAN_ORDER
31 #else
32 #error "Failed to determine the system endian value"
33 #endif
34 };
35
36 // this function swap the bytes of values given it's size as a template
37 // parameter (could sizeof be used?).
38 template <class T, unsigned int size>
39 inline T SwapBytes(T value) {
40 union {
41 T value;
42 char bytes[size];
43 } in, out;
44
45 in.value = value;
46
47 for (unsigned int i = 0; i < size / 2; ++i) {
48 out.bytes[i] = in.bytes[size - 1 - i];
49 out.bytes[size - 1 - i] = in.bytes[i];
50 }
51
52 return out.value;
53 }
54
55 // Here is the function you will use. Again there is two compile-time assertion
56 // that use the boost librarie. You could probably comment them out, but if you
57 // do be cautious not to use this function for anything else than integers
58 // types. This function need to be calles like this :
59 //
60 // int x = someValue;
61 // int i = EndianSwapBytes<HOST_ENDIAN_ORDER, BIG_ENDIAN_ORDER>(x);
62 //
63 template <EEndian from, EEndian to, class T>
64 inline T EndianSwapBytes(T value) {
65 // A : La donnée à swapper à une taille de 2, 4 ou 8 octets
66 BOOST_STATIC_ASSERT(sizeof(T) == 1 || sizeof(T) == 2 || sizeof(T) == 4 ||
67 sizeof(T) == 8);
68 if (sizeof(T) == 1) return value;
69
70 // A : La donnée à swapper est d'un type arithmetic
71 // BOOST_STATIC_ASSERT(boost::is_arithmetic<T>::value);
72
73 // Si from et to sont du même type on ne swap pas.
74 if (from == to) return value;
75
76 return SwapBytes<T, sizeof(T)>(value);
77 }
78 template <EEndian from, EEndian to>
79 inline char EndianSwapBytes(char value) {
80 return value;
81 }
82 template <EEndian from, EEndian to>
83 inline unsigned char EndianSwapBytes(unsigned char value) {
84 return value;
85 }
86 template <EEndian from, EEndian to>
87 inline signed char EndianSwapBytes(signed char value) {
88 return value;
89 }
90 // --------------------------------------
91
92 //! Packs an integer and outputs it to a stream
93 inline void appendPackedIntToStream(std::stringstream &ss,
94 boost::uint32_t num) {
95 int nbytes, bix;
96 unsigned int val, res;
97 char tc;
98
99 res = num;
100 while (1) {
101 if (res < (1 << 7)) {
102 val = (res << 1);
103 nbytes = 1;
104 break;
105 }
106 res -= (1 << 7);
107 if (res < (1 << 14)) {
108 val = ((res << 2) | 1);
109 nbytes = 2;
110 break;
111 }
112 res -= (1 << 14);
113 if (res < (1 << 21)) {
114 val = ((res << 3) | 3);
115 nbytes = 3;
116 break;
117 }
118 res -= (1 << 21);
119 if (res < (1 << 29)) {
120 val = ((res << 3) | 7);
121 nbytes = 4;
122 break;
123 } else {
124 CHECK_INVARIANT(0, "ERROR: Integer too big to pack\n");
125 }
126 }
127 // val = EndianSwapBytes<HOST_ENDIAN_ORDER,LITTLE_ENDIAN_ORDER>(val);
128
129 for (bix = 0; bix < nbytes; bix++) {
130 tc = (char)(val & 255);
131 ss.write(&tc, 1);
132 val >>= 8;
133 }
134 }
135
136 //! Reads an integer from a stream in packed format and returns the result.
137 inline boost::uint32_t readPackedIntFromStream(std::stringstream &ss) {
138 boost::uint32_t val, num;
139 int shift, offset;
140 char tmp;
141 ss.read(&tmp, sizeof(tmp));
142 val = UCHAR(tmp);
143 offset = 0;
144 if ((val & 1) == 0) {
145 shift = 1;
146 } else if ((val & 3) == 1) {
147 ss.read((char *)&tmp, sizeof(tmp));
148 val |= (UCHAR(tmp) << 8);
149 shift = 2;
150 offset = (1 << 7);
151 } else if ((val & 7) == 3) {
152 ss.read((char *)&tmp, sizeof(tmp));
153 val |= (UCHAR(tmp) << 8);
154 ss.read((char *)&tmp, sizeof(tmp));
155 val |= (UCHAR(tmp) << 16);
156 shift = 3;
157 offset = (1 << 7) + (1 << 14);
158 } else {
159 ss.read((char *)&tmp, sizeof(tmp));
160 val |= (UCHAR(tmp) << 8);
161 ss.read((char *)&tmp, sizeof(tmp));
162 val |= (UCHAR(tmp) << 16);
163 ss.read((char *)&tmp, sizeof(tmp));
164 val |= (UCHAR(tmp) << 24);
165 shift = 3;
166 offset = (1 << 7) + (1 << 14) + (1 << 21);
167 }
168 num = (val >> shift) + offset;
169 // num = EndianSwapBytes<LITTLE_ENDIAN_ORDER,HOST_ENDIAN_ORDER>(num);
170 return num;
171 }
172
173 //! Reads an integer from a char * in packed format and returns the result.
174 //! The argument is advanced
175 inline boost::uint32_t pullPackedIntFromString(const char *&text) {
176 boost::uint32_t val, num;
177 int shift, offset;
178 char tmp;
179 tmp = *text;
180 text++;
181 val = UCHAR(tmp);
182 offset = 0;
183 if ((val & 1) == 0) {
184 shift = 1;
185 } else if ((val & 3) == 1) {
186 tmp = *text;
187 text++;
188 val |= (UCHAR(tmp) << 8);
189 shift = 2;
190 offset = (1 << 7);
191 } else if ((val & 7) == 3) {
192 tmp = *text;
193 text++;
194 val |= (UCHAR(tmp) << 8);
195 tmp = *text;
196 text++;
197 val |= (UCHAR(tmp) << 16);
198 shift = 3;
199 offset = (1 << 7) + (1 << 14);
200 } else {
201 tmp = *text;
202 text++;
203 val |= (UCHAR(tmp) << 8);
204 tmp = *text;
205 text++;
206 val |= (UCHAR(tmp) << 16);
207 tmp = *text;
208 text++;
209 val |= (UCHAR(tmp) << 24);
210 shift = 3;
211 offset = (1 << 7) + (1 << 14) + (1 << 21);
212 }
213 num = (val >> shift) + offset;
214 // num = EndianSwapBytes<LITTLE_ENDIAN_ORDER,HOST_ENDIAN_ORDER>(num);
215 return num;
216 }
217
218 //! does a binary write of an object to a stream
219 template <typename T>
220 void streamWrite(std::ostream &ss, const T &val) {
221 T tval = EndianSwapBytes<HOST_ENDIAN_ORDER, LITTLE_ENDIAN_ORDER>(val);
222 ss.write((const char *)&tval, sizeof(T));
223 }
224 //! does a binary read of an object from a stream
225 template <typename T>
226 void streamRead(std::istream &ss, T &loc) {
227 T tloc;
228 ss.read((char *)&tloc, sizeof(T));
229 loc = EndianSwapBytes<LITTLE_ENDIAN_ORDER, HOST_ENDIAN_ORDER>(tloc);
230 }
231
232 //! grabs the next line from an instream and returns it.
233 inline std::string getLine(std::istream *inStream) {
234 std::string res;
235 std::getline(*inStream, res);
236 if ((res.length() > 0) && (res[res.length() - 1] == '\r')) {
237 res.erase(res.length() - 1);
238 }
239 return res;
240 }
241 //! grabs the next line from an instream and returns it.
242 inline std::string getLine(std::istream &inStream) {
243 return getLine(&inStream);
244 }
245 }
246
247 #endif
types.h
RDKit::BIG_ENDIAN_ORDER
Definition: StreamOps.h:26
RDKit::EndianSwapBytes
T EndianSwapBytes(T value)
Definition: StreamOps.h:64
CHECK_INVARIANT
#define CHECK_INVARIANT(expr, mess)
Definition: Invariant.h:95
RDKit::UCHAR
unsigned char UCHAR
Definition: types.h:144
RDKit::EEndian
EEndian
Definition: StreamOps.h:24
RDKit::streamRead
void streamRead(std::istream &ss, T &loc)
does a binary read of an object from a stream
Definition: StreamOps.h:226
RDKit::readPackedIntFromStream
boost::uint32_t readPackedIntFromStream(std::stringstream &ss)
Reads an integer from a stream in packed format and returns the result.
Definition: StreamOps.h:137
RDKit::pullPackedIntFromString
boost::uint32_t pullPackedIntFromString(const char *&text)
Definition: StreamOps.h:175
RDKit::SwapBytes
T SwapBytes(T value)
Definition: StreamOps.h:39
RDKit
Includes a bunch of functionality for handling Atom and Bond queries.
Definition: Atom.h:28
RDKit::LITTLE_ENDIAN_ORDER
Definition: StreamOps.h:25
RDKit::streamWrite
void streamWrite(std::ostream &ss, const T &val)
does a binary write of an object to a stream
Definition: StreamOps.h:220
RDKit::getLine
std::string getLine(std::istream *inStream)
grabs the next line from an instream and returns it.
Definition: StreamOps.h:233
RDKit::appendPackedIntToStream
void appendPackedIntToStream(std::stringstream &ss, boost::uint32_t num)
Packs an integer and outputs it to a stream.
Definition: StreamOps.h:93