7
static int SSINT = 0x00000001;
8
static unsigned char *SSTPTR = (unsigned char*)&SSINT;
9
bool SSwabInt = (SSTPTR[0]!=0);
10
static const int TMPSIZE = sizeof(double);
12
/******************** reading generic binary data *************************/
13
unsigned int OB_io_read_binary(char* ccc, char *x, unsigned int size, unsigned int count)
15
if (x == NULL || size == 0)
20
memcpy(x, ccc, count);
25
unsigned int sz = size * count;
31
unsigned char c, tmp[TMPSIZE];
33
for ( i = 0 ; i < sz ; i += size )
35
memcpy(tmp, &ccc[i], size);
36
for (j = 0, k = size - 1 ; j < k ; j++, k--) {
37
c = tmp[j]; tmp[j] = tmp[k]; tmp[k] = c;
39
memcpy(&x[i], tmp, size);
45
unsigned int OB_io_read_binary(istream& ifs, char *x, unsigned int size, unsigned int count)
47
if (x == NULL || size == 0)
57
unsigned int sz = size * count;
63
unsigned char c, tmp[TMPSIZE];
65
for ( i = 0 ; i < count ; i++ )
67
ifs.read((char*)&tmp[0], size);
68
for (j = 0, k = size - 1 ; j < k ; j++, k--) {
69
c = tmp[j]; tmp[j] = tmp[k]; tmp[k] = c;
71
memcpy(&x[i*size], tmp, size);
78
/******************** writing generic binary data *************************/
79
unsigned int OB_io_write_binary(char *ccc, const char *x, unsigned int size, unsigned int count)
81
if (x == NULL || size == 0)
86
memcpy(ccc, x, count);
91
unsigned int sz = size * count;
97
unsigned char c, tmp[TMPSIZE];
99
for (i = 0 ; i < sz ; i += size)
101
memcpy(tmp, &x[i], size);
102
for (j = 0, k = size - 1 ; j < k ; j++, k-- ) {
103
c = tmp[j]; tmp[j] = tmp[k]; tmp[k] = c;
105
memcpy(&ccc[i], tmp, size);
111
unsigned int OB_io_write_binary(ostream &ofs, const char *x, unsigned int size, unsigned int count)
113
if (x == NULL || size == 0)
123
unsigned int sz = size * count;
129
unsigned char c, tmp[TMPSIZE];
131
for (i = 0 ; i < sz ; i += size)
133
memcpy(tmp, &x[i], size);
134
for (j = 0, k = size - 1 ; j < k ; j++, k-- ) {
135
c = tmp[j]; tmp[j] = tmp[k]; tmp[k] = c;
137
ofs.write((char*)&tmp[0], size);
144
/**********************reading STL strings****************************/
146
unsigned int OB_io_read_binary(char* ccc, string& str)
149
unsigned int i = 0, idx = 0;
151
idx += OB_io_read_binary(ccc, (char*) &i, sizeof(unsigned int), 1);
152
buffer = new char[i+1];
153
idx += OB_io_read_binary(&ccc[idx], buffer, sizeof(char), i);
162
unsigned int OB_io_read_binary(istream& ifs, string& str)
165
unsigned int i = 0, idx = 0;
167
idx += OB_io_read_binary(ifs, (char*) &i, sizeof(unsigned int), 1);
168
buffer = new char[i+1];
169
idx += OB_io_read_binary(ifs, buffer, sizeof(char), i);
179
/******************** writing STL strings *************************/
181
unsigned int OB_io_write_binary(char* ccc, const string& str)
183
unsigned int idx = 0, size = str.size();
185
idx += OB_io_write_binary(ccc, (char*) &size, sizeof(unsigned int), 1);
186
idx += OB_io_write_binary(&ccc[idx], str.c_str(), sizeof(char), size);
190
unsigned int OB_io_write_binary(ostream& ofs, const string& str)
192
unsigned int idx = 0, size = str.size();
194
idx += OB_io_write_binary(ofs, (char*) &size, sizeof(unsigned int), 1);
195
idx += OB_io_write_binary(ofs, str.c_str(), sizeof(char), size);
200
/******************* writing compressed data *************************/
202
**\fn OB_io_write_binary_compressed(char*ccc, unsigned int *x, unsigned int NumBits, unsigned int NumInts)
203
**\brief Writes an unsigned interger array out in a platform independed
204
**compressed binary format.
205
**\param ccc A character array that the binary is written to
206
**\param x An unsigned integer array to be written to ccc.
207
**\param NumBits The number of bits that will be used to store
208
**each unsigned integer. The largest value in x must be less than
210
**\param NumInts The number of integers in x
211
**\return The number of bytes written to ccc. This value should
212
**always be 1+(NumBits*NumInts)/8 (integer division).
214
unsigned int OB_io_write_binary_compressed(char*ccc, unsigned int *x, unsigned int NumBits, unsigned int NumInts)
216
//If there are no values or x is NULL do nothing
217
if (!NumInts || x==NULL) return 0;
219
//If 32 or more bits are specified simply write uncompressed
220
if (NumBits >=32) return OB_io_write_binary(ccc,(const char*) x, sizeof(unsigned int), NumInts);
222
bool swap = !SSwabInt;
223
unsigned int bitarraysize = 1+(NumBits*NumInts)/8;
224
unsigned char *cc = (unsigned char*) ccc;
226
for (i=0 ; i<bitarraysize ; i++) cc[i] = 0;
227
unsigned char mask1[8],mask2[8];
236
for (i=0 ; i<8 ; i++) mask1[i] = ~mask2[i];
237
unsigned int bitshift=0;
238
unsigned int bytes=0;
240
unsigned char *cptr = (unsigned char*)&value;
241
for (i=0 ; i<NumInts ; i++) {
243
cptr[0] = ((unsigned char*)(&x[i]))[3];
244
cptr[1] = ((unsigned char*)(&x[i]))[2];
245
cptr[2] = ((unsigned char*)(&x[i]))[1];
246
cptr[3] = ((unsigned char*)(&x[i]))[0];
249
for (j=0 ; j<NumBits/8 ; j++) {
250
cc[bytes+0+j] |= (cptr[j]<<(bitshift ))&mask1[bitshift];
251
cc[bytes+1+j] |= (cptr[j]>>(8-bitshift))&mask2[bitshift];
253
cc[bytes+0+j] |= (cptr[j]<<(bitshift ))&mask1[bitshift];
254
if ((bitshift + NumBits%8) > 7) cc[bytes+1+j] |= (cptr[j]>>(8-bitshift))&mask2[bitshift];
256
while (bitshift > 7) {bitshift-=8; bytes++;}
261
**\fn OB_io_write_binary_compressed(ostream& ostr, unsigned int *x, unsigned int NumBits, unsigned int NumInts)
262
**\brief Writes an unsigned interger array out in a platform independed
263
**compressed binary format.
264
**\param ostr An output stream that the binary is written to
265
**\param x An unsigned integer array to be written to ostr.
266
**\param NumBits The number of bits that will be used to store
267
**each unsigned integer. The largest value in x must be less than
269
**\param NumInts The number of integers in x
270
**\return The number of bytes written to ostr. This value should
271
**always be 1+(NumBits*NumInts)/8 (integer division).
273
unsigned int OB_io_write_binary_compressed(ostream& ostr, unsigned int *x, unsigned int NumBits, unsigned int NumInts)
275
//If there are no values or x is NULL do nothing
276
if (!NumInts || x==NULL) return 0;
278
//If 32 or more bits are specified simply write uncompressed
279
if (NumBits >=32) return OB_io_write_binary(ostr,(const char*) x, sizeof(unsigned int), NumInts);
281
unsigned int bitarraysize = 1+(NumBits*NumInts)/8;
282
char *cc = new char [bitarraysize];
283
unsigned int idx = OB_io_write_binary_compressed(cc,x,NumBits,NumInts);
284
ostr.write(cc,bitarraysize);
290
**\fn OB_io_write_binary_compressed(char*ccc, float *x, unsigned int NumBits, unsigned int Nfloats)
291
**\brief Writes a float array out in a platform independed
292
**compressed binary format.
293
**\param ccc A character array that the binary is written to
294
**\param x A float array to be written to ccc.
295
**\param NumBits The number of bits that will be used to store
296
**each unsigned integer. The lost of resolution of the float
297
**values depends directly on how many bits are used.
298
**\param Nfloats The number of floats in x.
299
**\return The number of bytes written to ccc. This value should
300
**always be 9+(NumBits*NumInts)/8 (integer division).
301
**\par Compression Info
302
**There is a loss of resolution of the floats using this routine.
303
**The greater the value of NumBits and the smaller the range of values
304
**in x, the smaller the loss of resolution. The function
305
**OB_io_util_calc_NumBits(float *x, unsigned int N, float res)
306
**will calculate how many bits are required for a given resolution and
309
unsigned int OB_io_write_binary_compressed(char*ccc, float *x, unsigned int NumBits, unsigned int Nfloats)
313
//If there are no values of x is NULL do nothing
314
if (!Nfloats || x==NULL) return 0;
316
//If 32 or more bits are specified simply write uncompressed
317
if (NumBits >=32) return OB_io_write_binary(&ccc[idx],(const char*) x, sizeof(unsigned int), Nfloats);
325
for (i=0 ; i<Nfloats ; i++) {
326
if (x[i] > max) max = x[i];
327
if (x[i] < min) min = x[i];
329
idx += OB_io_write_binary(&ccc[idx],(const char*)&max,sizeof(float),1);
330
idx += OB_io_write_binary(&ccc[idx],(const char*)&min,sizeof(float),1);
332
//Integerize values and write out
333
unsigned int maxint = (unsigned int) 0;
334
for (i=0 ; i<NumBits ; i++) maxint |= ((unsigned int)1)<<i;
335
unsigned int *ix = new unsigned int [Nfloats];
337
for (i=0 ; i<Nfloats ; i++)
338
ix[i] = (unsigned int) (((float)maxint*((x[i]-min)/(max-min))) + 0.499999999f);
340
else for (i=0 ; i<Nfloats ; i++) ix[i] = (unsigned int) 0;
341
idx += OB_io_write_binary_compressed(&ccc[idx],ix,NumBits,Nfloats);
347
**\fn OB_io_write_binary_compressed(ostream& ostr, float *x, unsigned int NumBits, unsigned int Nfloats)
348
**\brief Writes a float array out in a platform independed
349
**compressed binary format.
350
**\param ostr A character array that the binary is written to
351
**\param x A float array to be written to ostr.
352
**\param NumBits The number of bits that will be used to store
353
**each unsigned integer. The lost of resolution of the float
354
**values depends directly on how many bits are used.
355
**\param Nfloats The number of floats in x.
356
**\return The number of bytes written to ccc. This value should
357
**always be 9+(NumBits*NumInts)/8 (integer division).
358
**\par Compression Info
359
**There is a loss of resolution of the floats using this routine.
360
**The greater the value of NumBits and the smaller the range of values
361
**in x, the smaller the loss of resolution. The function
362
**OB_io_util_calc_NumBits(float *x, unsigned int N, float res)
363
**will calculate how many bits are required for a given resolution and
366
unsigned int OB_io_write_binary_compressed(ostream& ostr, float *x, unsigned int NumBits, unsigned int Nfloats)
370
//If there are no values of x is NULL do nothing
371
if (!Nfloats || x==NULL) return 0;
373
//If 32 or more bits are specified simply write uncompressed
374
if (NumBits >=32) return OB_io_write_binary(ostr,(const char*) x, sizeof(unsigned int), Nfloats);
380
for (i=0 ; i<Nfloats ; i++) {
381
if (x[i] > max) max = x[i];
382
if (x[i] < min) min = x[i];
384
idx += OB_io_write_binary(ostr,(const char*)&max,sizeof(float),1);
385
idx += OB_io_write_binary(ostr,(const char*)&min,sizeof(float),1);
387
//Integerize values and write out
388
unsigned int maxint = (unsigned int) 0;
389
for (i=0 ; i<NumBits ; i++) maxint |= ((unsigned int)1)<<i;
390
unsigned int *ix = new unsigned int [Nfloats];
392
for (i=0 ; i<Nfloats ; i++)
393
ix[i] = (unsigned int) (((float)maxint*((x[i]-min)/(max-min))) + 0.499999999f);
395
else for (i=0 ; i<Nfloats ; i++) ix[i] = (unsigned int) 0;
396
idx += OB_io_write_binary_compressed(ostr,ix,NumBits,Nfloats);
403
/******************* reading compressed data *************************/
405
**\fn OB_io_read_binary_compressed(char*ccc, unsigned int *x, unsigned int NumBits, unsigned int NumInts)
406
**\brief Reads compressed binary data that was written with either
407
**OB_io_write_binary_compressed(char*ccc, unsigned int *x, unsigned int NumBits, unsigned int NumInts)
409
**OB_io_write_binary_compressed(ostream& ostr, unsigned int *x, unsigned int NumBits, unsigned int NumInts)
410
**\param ccc A character array the binary is being read from
411
**\param x An array of unsigned ints the binary data will be extracted to
412
**\param NumBits The number of bits used to store each unsigned integer
413
**\param NumInts The number of integers stored in ccc
414
**\return The number of bytes read from ccc. This value should
415
**always be 1+(NumBits*NumInts)/8 (integer division).
417
unsigned int OB_io_read_binary_compressed(char*ccc, unsigned int *x, unsigned int NumBits, unsigned int NumInts)
419
//If there are no values or x is NULL do nothing
420
if (!NumInts || x==NULL) return 0;
422
//If 32 or more bits are specified simply read uncompressed
423
if (NumBits >=32) return OB_io_read_binary(ccc,(char*) x, sizeof(unsigned int), NumInts);
426
bool swap = !SSwabInt;
427
unsigned int bitarraysize = 1+(NumBits*NumInts)/8;
428
unsigned char *cc = (unsigned char*) ccc;
430
unsigned int mask = (unsigned int) 0;
431
for (i=0 ; i<NumBits ; i++) mask |= ((unsigned int) 1) << i;
432
unsigned char mask1[8],mask2[8];
441
for (i=0 ; i<8 ; i++) mask2[i] = ~mask1[i];
442
unsigned int bitshift=0;
443
unsigned int bytes=0;
445
unsigned char *cptr = (unsigned char*)&value;
446
for (i=0 ; i<NumInts ; i++) {
447
value = (unsigned int) 0;
448
for (j=0 ; j<NumBits/8 ; j++) {
449
cptr[j] = (cc[bytes+0+j]>>( bitshift))&mask1[bitshift];
450
cptr[j] |= (cc[bytes+1+j]<<(8-bitshift))&mask2[bitshift];
452
cptr[j] = (cc[bytes+0+j]>>( bitshift))&mask1[bitshift];
453
if ((bitshift + NumBits%8) > 7) cptr[j] |= (cc[bytes+1+j]<<(8-bitshift))&mask2[bitshift];
456
while (bitshift > 7) {bitshift-=8; bytes++;}
458
((unsigned char*)(&x[i]))[3] = cptr[0];
459
((unsigned char*)(&x[i]))[2] = cptr[1];
460
((unsigned char*)(&x[i]))[1] = cptr[2];
461
((unsigned char*)(&x[i]))[0] = cptr[3];
471
**\fn OB_io_read_binary_compressed(istream& istr, unsigned int *x, unsigned int NumBits, unsigned int NumInts)
472
**\brief Reads compressed binary data that was written with either
473
**OB_io_write_binary_compressed(char*ccc, unsigned int *x, unsigned int NumBits, unsigned int NumInts)
475
**OB_io_write_binary_compressed(ostream& ostr, unsigned int *x, unsigned int NumBits, unsigned int NumInts)
476
**\param istr An input file stream the binary is being read from
477
**\param x An array of unsigned ints the binary data will be extracted to
478
**\param NumBits The number of bits used to store each unsigned integer
479
**\param NumInts The number of integers stored in istr
480
**\return The number of bytes read from istr. This value should
481
**always be 1+(NumBits*NumInts)/8 (integer division).
483
unsigned int OB_io_read_binary_compressed(istream& istr, unsigned int *x, unsigned int NumBits, unsigned int NumInts)
485
//If there are no values or x is NULL do nothing
486
if (!NumInts || x==NULL) return 0;
488
//If 32 or more bits are specified simply read uncompressed
489
if (NumBits >=32) return OB_io_read_binary(istr,(char*) x, sizeof(unsigned int), NumInts);
491
unsigned int bitarraysize = 1+(NumBits*NumInts)/8;
492
char *cc = new char [bitarraysize];
493
istr.read(cc,bitarraysize);
494
unsigned int idx = OB_io_read_binary_compressed(cc,x,NumBits,NumInts);
500
**\fn OB_io_read_binary_compressed(char*ccc, float *x, unsigned int NumBits, unsigned int Nfloats)
501
**\brief Reads compressed binary data that was written with either
502
**OB_io_write_binary_compressed(char*ccc, float *x, unsigned int NumBits, unsigned int NumInts)
504
**OB_io_write_binary_compressed(ostream& ostr, float *x, unsigned int NumBits, unsigned int NumInts)
505
**\param ccc A character array the binary is being read from
506
**\param x An array of floats the binary data will be extracted to
507
**\param NumBits The number of bits used to store each float
508
**\param Nfloats The number of floats to be read
509
**\return The number of bytes read from ccc. This value should
510
**always be 1+(NumBits*NumInts)/8 (integer division).
512
unsigned int OB_io_read_binary_compressed(char*ccc, float *x, unsigned int NumBits, unsigned int Nfloats)
516
//If there are no values or x is NULL do nothing
517
if (!Nfloats || x==NULL) return 0;
519
//If 32 or more bits are specified simply write uncompressed
520
if (NumBits >=32) return OB_io_read_binary(&ccc[idx],(char*) x, sizeof(unsigned int), Nfloats);
525
idx += OB_io_read_binary(&ccc[idx],(char*)&max,sizeof(float),1);
526
idx += OB_io_read_binary(&ccc[idx],(char*)&min,sizeof(float),1);
530
unsigned int maxint = (unsigned int) 0;
531
for (i=0 ; i<NumBits ; i++) maxint |= ((unsigned int)1)<<i;
532
unsigned int *ix = new unsigned int [Nfloats];
533
idx += OB_io_read_binary_compressed(&ccc[idx],ix,NumBits,Nfloats);
534
for (i=0 ; i<Nfloats ; i++) x[i] = (max-min)*((float)ix[i]/(float)maxint)+min;
541
**\fn OB_io_read_binary_compressed(istream& istr, float *x, unsigned int NumBits, unsigned int Nfloats)
542
**\brief Reads compressed binary data that was written with either
543
**OB_io_write_binary_compressed(char*ccc, float *x, unsigned int NumBits, unsigned int NumInts)
545
**OB_io_write_binary_compressed(ostream& ostr, float *x, unsigned int NumBits, unsigned int NumInts)
546
**\param istr An input stream the binary is being read from
547
**\param x An array of floats the binary data will be extracted to
548
**\param NumBits The number of bits used to store each float
549
**\param Nfloats The number of float values to be read
550
**\return The number of bytes read from istr. This value should
551
**always be 1+(NumBits*NumInts)/8 (integer division).
553
unsigned int OB_io_read_binary_compressed(istream& istr, float *x, unsigned int NumBits, unsigned int Nfloats)
557
//If there are no values or x is NULL do nothing
558
if (!Nfloats || x==NULL) return 0;
560
//If 32 or more bits are specified simply write uncompressed
561
if (NumBits >=32) return OB_io_read_binary(istr,(char*) x, sizeof(unsigned int), Nfloats);
566
idx += OB_io_read_binary(istr,(char*)&max,sizeof(float),1);
567
idx += OB_io_read_binary(istr,(char*)&min,sizeof(float),1);
571
unsigned int maxint = (unsigned int) 0;
572
for (i=0 ; i<NumBits ; i++) maxint |= ((unsigned int)1)<<i;
573
unsigned int *ix = new unsigned int [Nfloats];
574
idx += OB_io_read_binary_compressed(istr,ix,NumBits,Nfloats);
575
for (i=0 ; i<Nfloats ; i++) x[i] = (max-min)*((float)ix[i]/(float)maxint)+min;
583
**\fn OB_io_util_calc_NumBits(unsigned int *x, unsigned int N)
584
**\param x an unsigned integer array
585
**\paran N The number of values in the unsigned integer array x.
586
**\return The number of bits per value required to store the
587
**unsigned integer values in x with the
588
**OB_io_write_binary_compressed(char*ccc, unsigned int *x, unsigned int NumBits, unsigned int NumInts)
590
**OB_io_write_binary_compressed(ostream& ostr, unsigned int *x, unsigned int NumBits, unsigned int NumInts)
593
unsigned int OB_io_util_calc_NumBits(unsigned int *x, unsigned int N)
598
for (i=0 ; i<N ; i++) if (x[i] > max) max = x[i];
599
unsigned int mmax=(unsigned int) 0;
600
for (i=0 ; i<32 && max > mmax ; i++) mmax |= ((unsigned int)1)<<i;
605
**\fn OB_io_util_calc_NumBits(float *x, unsigned int N, float res)
606
**\param x A float array
607
**\param N The number of values in the float array x.
608
**\param The resolution desired.
609
**\returns The number of bits per value required to store float
610
**the float values in x at a resolution of res (or better) with the
611
**OB_io_write_binary_compressed(char*ccc, float *x, unsigned int NumBits, unsigned int Nfloats)
613
**OB_io_write_binary_compressed(istream& istr, float *x, unsigned int NumBits, unsigned int Nfloats)
616
unsigned int OB_io_util_calc_NumBits(float *x, unsigned int N, float res)
624
for (i=0 ; i<N ; i++) {
625
if (x[i] > max) max = x[i];
626
if (x[i] < min) min = x[i];
629
unsigned int imax = (unsigned int) ((max-min)/res+0.5f);
630
unsigned int mmax=(unsigned int) 0;
631
for (i=0 ; i<32 && imax > mmax ; i++) mmax |= ((unsigned int)1)<<i;
636
/******************* Writing OBBinaryIO objects ************************/
637
ostream& operator<<(ostream& ostr, const OBBinaryIO& obj)
639
unsigned int size = obj.BinarySize();
640
OB_io_write_binary(ostr,(const char*)&size,sizeof(unsigned int),1);
641
obj.WriteBinary(ostr);
644
istream& operator>>(istream& istr, OBBinaryIO& obj)
647
OB_io_read_binary(istr,(char*)&size,sizeof(unsigned int),1);
649
size2 = obj.ReadBinary(istr);
651
cerr << "WARNING operator>>(istream& istr, OBBinaryIO& obj) " << endl;
652
cerr << "Record size (" << size << ") is not equal to number of bytes read (" << size2 << ")" << endl;
658
}// End namespace OpenBabel