source: trunk/Mars/mcore/fits.h@ 15593

Last change on this file since 15593 was 15364, checked in by tbretz, 12 years ago
Implemented the possibility to stream the input file immediately also to an output file while reading.
File size: 26.1 KB
Line 
1#ifndef MARS_fits
2#define MARS_fits
3
4#ifdef __CINT__
5#define int8_t Char_t
6#define int16_t Short_t
7#define int32_t Int_t
8#define int64_t Long64_t
9#define uint8_t UChar_t
10#define uint16_t UShort_t
11#define uint32_t UInt_t
12#define uint64_t ULong64_t
13#else
14#include <stdint.h>
15#endif
16
17#include <map>
18#include <string>
19#include <fstream>
20#include <sstream>
21#include <algorithm>
22
23#ifdef __EXCEPTIONS
24#include <stdexcept>
25#endif
26
27#ifdef __CINT__
28#define off_t size_t
29#endif
30
31#if !defined(__MARS__) && !defined(__CINT__)
32#include <unordered_map>
33#endif
34
35#ifndef __MARS__
36#include <vector>
37#include <iomanip>
38#include <iostream>
39#define gLog cerr
40#define ___err___ ""
41#define ___warn___ ""
42#define ___all___ ""
43#else
44#include "MLog.h"
45#include "MLogManip.h"
46#define ___err___ err
47#define ___warn___ warn
48#define ___all___ all
49#endif
50
51#if defined(HAVE_ZLIB) || defined(__CINT__)
52#include "izstream.h"
53#else
54#include <fstream>
55#define izstream ifstream
56#warning Support for zipped FITS files disabled.
57#endif
58
59#include "checksum.h"
60
61#ifndef __MARS__
62namespace std
63{
64#else
65using namespace std;
66#endif
67
68class fits : public izstream
69{
70public:
71 struct Entry
72 {
73 char type;
74 string value;
75 string comment;
76
77 template<typename T>
78 T Get() const
79 {
80 T t;
81
82 istringstream str(value);
83 str >> t;
84
85 return t;
86 }
87 };
88
89 struct Table
90 {
91 off_t offset;
92
93 string name;
94 size_t bytes_per_row;
95 size_t num_rows;
96 size_t num_cols;
97
98 struct Column
99 {
100 size_t offset;
101 size_t num;
102 size_t size;
103 char type;
104 string unit;
105 };
106
107 typedef map<string, Entry> Keys;
108 typedef map<string, Column> Columns;
109
110 Columns cols;
111 Keys keys;
112
113 int64_t datasum;
114
115 string Trim(const string &str, char c=' ') const
116 {
117 // Trim Both leading and trailing spaces
118 const size_t pstart = str.find_first_not_of(c); // Find the first character position after excluding leading blank spaces
119 const size_t pend = str.find_last_not_of(c); // Find the first character position from reverse af
120
121 // if all spaces or empty return an empty string
122 if (string::npos==pstart || string::npos==pend)
123 return string();
124
125 return str.substr(pstart, pend-pstart+1);
126 }
127
128 bool Check(const string &key, char type, const string &value="") const
129 {
130 const Keys::const_iterator it = keys.find(key);
131 if (it==keys.end())
132 {
133 ostringstream str;
134 str << "Key '" << key << "' not found.";
135#ifdef __EXCEPTIONS
136 throw runtime_error(str.str());
137#else
138 gLog << ___err___ << "ERROR - " << str.str() << endl;
139 return false;
140#endif
141 }
142
143 if (it->second.type!=type)
144 {
145 ostringstream str;
146 str << "Wrong type for key '" << key << "': expected " << type << ", found " << it->second.type << ".";
147#ifdef __EXCEPTIONS
148 throw runtime_error(str.str());
149#else
150 gLog << ___err___ << "ERROR - " << str.str() << endl;
151 return false;
152#endif
153 }
154
155 if (!value.empty() && it->second.value!=value)
156 {
157 ostringstream str;
158 str << "Wrong value for key '" << key << "': expected " << value << ", found " << it->second.value << ".";
159#ifdef __EXCEPTIONS
160 throw runtime_error(str.str());
161#else
162 gLog << ___err___ << "ERROR - " << str.str() << endl;
163 return false;
164#endif
165 }
166
167 return true;
168 }
169
170 Keys ParseBlock(const vector<string> &vec) const
171 {
172 map<string,Entry> rc;
173
174 for (unsigned int i=0; i<vec.size(); i++)
175 {
176 const string key = Trim(vec[i].substr(0,8));
177 // Keywords without a value, like COMMENT / HISTORY
178 if (vec[i].substr(8,2)!="= ")
179 continue;
180
181 char type = 0;
182
183 string com;
184 string val = Trim(vec[i].substr(10));
185 if (val[0]=='\'')
186 {
187 // First skip all '' in the string
188 size_t p = 1;
189 while (1)
190 {
191 const size_t pp = val.find_first_of('\'', p);
192 if (pp==string::npos)
193 break;
194
195 p = val[pp+1]=='\'' ? pp+2 : pp+1;
196 }
197
198 // Now find the comment
199 const size_t ppp = val.find_first_of('/', p);
200
201 // Set value, comment and type
202 com = ppp==string::npos ? "" : Trim(val.substr(ppp+1));
203 val = Trim(val.substr(1, p-2));
204 type = 'T';
205 }
206 else
207 {
208 const size_t p = val.find_first_of('/');
209
210 com = Trim(val.substr(p+2));
211 val = Trim(val.substr(0, p));
212
213 if (val.empty() || val.find_first_of('T')!=string::npos || val.find_first_of('F')!=string::npos)
214 type = 'B';
215 else
216 type = val.find_last_of('.')==string::npos ? 'I' : 'F';
217 }
218
219 const Entry e = { type, val, com };
220 rc[key] = e;
221 }
222
223 return rc;
224 }
225
226 Table() : offset(0) { }
227 Table(const vector<string> &vec, off_t off) :
228 offset(off), keys(ParseBlock(vec))
229 {
230 if (!Check("XTENSION", 'T', "BINTABLE") ||
231 !Check("NAXIS", 'I', "2") ||
232 !Check("BITPIX", 'I', "8") ||
233 !Check("PCOUNT", 'I', "0") ||
234 !Check("GCOUNT", 'I', "1") ||
235 !Check("EXTNAME", 'T') ||
236 !Check("NAXIS1", 'I') ||
237 !Check("NAXIS2", 'I') ||
238 !Check("TFIELDS", 'I'))
239 return;
240
241 bytes_per_row = Get<size_t>("NAXIS1");
242 num_rows = Get<size_t>("NAXIS2");
243 num_cols = Get<size_t>("TFIELDS");
244 datasum = Get<int64_t>("DATASUM", -1);
245
246 size_t bytes = 0;
247 for (size_t i=1; i<=num_cols; i++)
248 {
249 ostringstream num;
250 num << i;
251
252 if (!Check("TTYPE"+num.str(), 'T') ||
253 !Check("TFORM"+num.str(), 'T'))
254 return;
255
256 const string id = Get<string>("TTYPE"+num.str());
257 const string fmt = Get<string>("TFORM"+num.str());
258 const string unit = Get<string>("TUNIT"+num.str(), "");
259
260 istringstream sin(fmt);
261 int n = 0;
262 sin >> n;
263 if (!sin)
264 n = 1;
265
266 const char type = fmt[fmt.length()-1];
267
268 size_t size = 0;
269 switch (type)
270 {
271 // We could use negative values to mark floats
272 // otheriwse we could just cast them to int64_t?
273 case 'L': // logical
274 case 'A': // char
275 case 'B': size = 1; break; // byte
276 case 'I': size = 2; break; // short
277 case 'J': size = 4; break; // int
278 case 'K': size = 8; break; // long long
279 case 'E': size = 4; break; // float
280 case 'D': size = 8; break; // double
281 // case 'X': size = n; break; // bits (n=number of bytes needed to contain all bits)
282 // case 'C': size = 8; break; // complex float
283 // case 'M': size = 16; break; // complex double
284 // case 'P': size = 8; break; // array descriptor (32bit)
285 // case 'Q': size = 16; break; // array descriptor (64bit)
286 default:
287 {
288 ostringstream str;
289 str << "FITS format TFORM='" << fmt << "' not yet supported.";
290#ifdef __EXCEPTIONS
291 throw runtime_error(str.str());
292#else
293 gLog << ___err___ << "ERROR - " << str.str() << endl;
294 return;
295#endif
296 }
297 }
298
299 const Table::Column col = { bytes, n, size, type, unit };
300
301 cols[id] = col;
302 bytes += n*size;
303 }
304
305 if (bytes!=bytes_per_row)
306 {
307#ifdef __EXCEPTIONS
308 throw runtime_error("Column size mismatch");
309#else
310 gLog << ___err___ << "ERROR - Column size mismatch" << endl;
311 return;
312#endif
313 }
314
315 name = Get<string>("EXTNAME");
316 }
317
318 void PrintKeys(bool display_all=false) const
319 {
320 for (Keys::const_iterator it=keys.begin(); it!=keys.end(); it++)
321 {
322 if (!display_all &&
323 (it->first.substr(0, 6)=="TTYPE" ||
324 it->first.substr(0, 6)=="TFORM" ||
325 it->first.substr(0, 6)=="TUNIT" ||
326 it->first=="TFIELDS" ||
327 it->first=="XTENSION" ||
328 it->first=="NAXIS" ||
329 it->first=="BITPIX" ||
330 it->first=="PCOUNT" ||
331 it->first=="GCOUNT")
332 )
333 continue;
334
335 gLog << ___all___ << setw(2) << it->second.type << '|' << it->first << '=' << it->second.value << '/' << it->second.comment << '|' << endl;
336 }}
337
338 void PrintColumns() const
339 {
340 typedef map<pair<size_t, string>, Column> Sorted;
341
342 Sorted sorted;
343
344 for (Columns::const_iterator it=cols.begin(); it!=cols.end(); it++)
345 sorted[make_pair(it->second.offset, it->first)] = it->second;
346
347 for (Sorted::const_iterator it=sorted.begin(); it!=sorted.end(); it++)
348 {
349 gLog << ___all___ << setw(6) << it->second.offset << "| ";
350 gLog << it->second.num << 'x';
351 switch (it->second.type)
352 {
353 case 'A': gLog << "char(8)"; break;
354 case 'L': gLog << "bool(8)"; break;
355 case 'B': gLog << "byte(8)"; break;
356 case 'I': gLog << "short(16)"; break;
357 case 'J': gLog << "int(32)"; break;
358 case 'K': gLog << "int(64)"; break;
359 case 'E': gLog << "float(32)"; break;
360 case 'D': gLog << "double(64)"; break;
361 }
362 gLog << ": " << it->first.second << " [" << it->second.unit << "]" << endl;
363 }
364 }
365
366 operator bool() const { return !name.empty(); }
367
368 bool HasKey(const string &key) const
369 {
370 return keys.find(key)!=keys.end();
371 }
372
373 bool HasColumn(const string& col) const
374 {
375 return cols.find(col)!=cols.end();
376 }
377
378 const Columns &GetColumns() const
379 {
380 return cols;
381 }
382
383 const Keys &GetKeys() const
384 {
385 return keys;
386 }
387
388 // Values of keys are always signed
389 template<typename T>
390 T Get(const string &key) const
391 {
392 const map<string,Entry>::const_iterator it = keys.find(key);
393 if (it==keys.end())
394 {
395 ostringstream str;
396 str << "Key '" << key << "' not found." << endl;
397#ifdef __EXCEPTIONS
398 throw runtime_error(str.str());
399#else
400 gLog << ___err___ << "ERROR - " << str.str() << endl;
401 return T();
402#endif
403 }
404 return it->second.Get<T>();
405 }
406
407 // Values of keys are always signed
408 template<typename T>
409 T Get(const string &key, const T &deflt) const
410 {
411 const map<string,Entry>::const_iterator it = keys.find(key);
412 return it==keys.end() ? deflt :it->second.Get<T>();
413 }
414
415 size_t GetN(const string &key) const
416 {
417 const Columns::const_iterator it = cols.find(key);
418 return it==cols.end() ? 0 : it->second.num;
419 }
420 };
421
422private:
423 ofstream fCopy;
424
425 Table fTable;
426
427 typedef pair<void*, Table::Column> Address;
428 typedef vector<Address> Addresses;
429 //map<void*, Table::Column> fAddresses;
430 Addresses fAddresses;
431
432#if defined(__MARS__) || defined(__CINT__)
433 typedef map<string, void*> Pointers;
434#else
435 typedef unordered_map<string, void*> Pointers;
436#endif
437 Pointers fPointers;
438
439 vector<vector<char>> fGarbage;
440
441 vector<char> fBufferRow;
442 vector<char> fBufferDat;
443
444 size_t fRow;
445
446 Checksum fChkHeader;
447 Checksum fChkData;
448
449 bool ReadBlock(vector<string> &vec)
450 {
451 int endtag = 0;
452 for (int i=0; i<36; i++)
453 {
454 char c[81];
455 c[80] = 0;
456 read(c, 80);
457 if (!good())
458 break;
459
460 fChkHeader.add(c, 80);
461
462// if (c[0]==0)
463// return vector<string>();
464
465 string str(c);
466
467// if (!str.empty())
468// cout << setw(2) << i << "|" << str << "|" << (endtag?'-':'+') << endl;
469
470 if (endtag==2 || str=="END ")
471 {
472 endtag = 2; // valid END tag found
473 continue;
474 }
475
476 if (endtag==1 || str==" ")
477 {
478 endtag = 1; // end tag not found, but expected to be there
479 continue;
480 }
481
482 vec.push_back(str);
483 }
484
485 // Make sure that no empty vector is returned
486 if (endtag && vec.size()%36==0)
487 vec.push_back(string("END = '' / "));
488
489 return endtag==2;
490 }
491
492 string Compile(const string &key, int16_t i=-1)
493 {
494 if (i<0)
495 return key;
496
497 ostringstream str;
498 str << key << i;
499 return str.str();
500 }
501
502 void Constructor(const string &fname, string fout, bool force)
503 {
504 char simple[10];
505 read(simple, 10);
506 if (!good())
507 return;
508
509 if (memcmp(simple, "SIMPLE = ", 10))
510 {
511 clear(rdstate()|ios::badbit);
512#ifdef __EXCEPTIONS
513 throw runtime_error("File is not a FITS file.");
514#else
515 gLog << ___err___ << "ERROR - File is not a FITS file." << endl;
516 return;
517#endif
518 }
519
520 seekg(0);
521
522 while (good())
523 {
524 vector<string> block;
525 while (1)
526 {
527 // FIXME: Set limit on memory consumption
528 const int rc = ReadBlock(block);
529 if (!good())
530 {
531 clear(rdstate()|ios::badbit);
532#ifdef __EXCEPTIONS
533 throw runtime_error("FITS file corrupted.");
534#else
535 gLog << ___err___ << "ERROR - FITS file corrupted." << endl;
536 return;
537#endif
538 }
539
540 if (block.size()%36)
541 {
542 if (!rc && !force)
543 {
544 clear(rdstate()|ios::badbit);
545#ifdef __EXCEPTIONS
546 throw runtime_error("END keyword missing in FITS header.");
547#else
548 gLog << ___err___ << "ERROR - END keyword missing in FITS file... file might be corrupted." << endl;
549 return;
550#endif
551 }
552 break;
553 }
554 }
555
556 if (block.size()==0)
557 break;
558
559 if (block[0].substr(0, 9)=="SIMPLE =")
560 {
561 fChkHeader.reset();
562 continue;
563 }
564
565 if (block[0].substr(0, 9)=="XTENSION=")
566 {
567 // FIXME: Check for table name
568
569 fTable = Table(block, tellg());
570 fRow = (size_t)-1;
571
572 //fTable.PrintKeys();
573
574 if (!fTable)
575 {
576 clear(rdstate()|ios::badbit);
577 return;
578 }
579
580 fBufferRow.resize(fTable.bytes_per_row + 8-fTable.bytes_per_row%4);
581 fBufferDat.resize(fTable.bytes_per_row);
582
583 /*
584 // Next table should start at:
585 const size_t size = fTable.bytes_per_row*fTable.num_rows;
586 const size_t blks = size/(36*80);
587 const size_t rest = size%(36*80);
588
589 seekg((blks+(rest>0?1:0))*(36*80), ios::cur);
590 if (!good())
591 gLog << ___err___ << "File seems to be incomplete (less data than expected from header)." << endl;
592
593 fRow = fTable.num_rows;
594 */
595
596 break;
597 }
598 }
599
600 if (fout.empty())
601 return;
602
603 if (*fout.rbegin()=='/')
604 {
605 const size_t p = fname.find_last_of('/');
606 fout.append(fname.substr(p+1));
607 }
608
609 fCopy.open(fout);
610 if (!fCopy)
611 {
612 clear(rdstate()|ios::badbit);
613#ifdef __EXCEPTIONS
614 throw runtime_error("Could not open output file.");
615#else
616 gLog << ___err___ << "ERROR - Failed to open output file." << endl;
617#endif
618 }
619
620 const streampos p = tellg();
621 seekg(0);
622
623 vector<char> buf(p);
624 read(buf.data(), p);
625
626 fCopy.write(buf.data(), p);
627 if (!fCopy)
628 clear(rdstate()|ios::badbit);
629 }
630
631public:
632 fits(const string &fname, bool force=false) : izstream(fname.c_str())
633 {
634 Constructor(fname, "", force);
635 }
636
637 fits(const string &fname, const string &fout, bool force=false) : izstream(fname.c_str())
638 {
639 Constructor(fname, fout, force);
640 }
641
642 ~fits()
643 {
644 copy(istreambuf_iterator<char>(*this),
645 istreambuf_iterator<char>(),
646 ostreambuf_iterator<char>(fCopy));
647 }
648
649 uint8_t ReadRow(size_t row)
650 {
651 // if (row!=fRow+1) // Fast seeking is ensured by izstream
652 seekg(fTable.offset+row*fTable.bytes_per_row);
653
654 // For the checksum we need everything to be correctly aligned
655 const uint8_t offset = (row*fTable.bytes_per_row)%4;
656
657 auto ib = fBufferRow.begin();
658 auto ie = fBufferRow.end();
659 *ib++ = 0;
660 *ib++ = 0;
661 *ib++ = 0;
662 *ib = 0;
663
664 *--ie = 0;
665 *--ie = 0;
666 *--ie = 0;
667 *--ie = 0;
668 *--ie = 0;
669 *--ie = 0;
670 *--ie = 0;
671 *--ie = 0;
672
673 read(fBufferRow.data()+offset, fTable.bytes_per_row);
674 //fin.clear(fin.rdstate()&~ios::eofbit);
675
676 if (row==fRow+1)
677 {
678 fChkData.add(fBufferRow);
679 if (fCopy.is_open() && fCopy.good())
680 fCopy.write(fBufferRow.data()+offset, fTable.bytes_per_row);
681 if (!fCopy)
682 clear(rdstate()|ios::badbit);
683 }
684 else
685 if (fCopy.is_open())
686 clear(rdstate()|ios::badbit);
687
688 fRow = row;
689
690 return offset;
691 }
692
693 template<size_t N>
694 void revcpy(char *dest, const char *src, int num)
695 {
696 const char *pend = src + num*N;
697 for (const char *ptr = src; ptr<pend; ptr+=N, dest+=N)
698 reverse_copy(ptr, ptr+N, dest);
699 }
700
701#if !defined(__MARS__) && !defined(__CINT__)
702 bool GetRow(size_t row, bool check=true)
703#else
704 bool GetRowNum(size_t row, bool check=true)
705#endif
706 {
707 if (check && row>=fTable.num_rows)
708 return false;
709
710 const uint8_t offset = ReadRow(row);
711 if (!good())
712 return good();
713
714 const char *ptr = fBufferRow.data() + offset;
715
716 for (Addresses::const_iterator it=fAddresses.begin(); it!=fAddresses.end(); it++)
717 {
718 const Table::Column &c = it->second;
719
720 const char *src = ptr + c.offset;
721 char *dest = reinterpret_cast<char*>(it->first);
722
723 // Let the compiler do some optimization by
724 // knowing that we only have 1, 2, 4 and 8
725 switch (c.size)
726 {
727 case 1: memcpy (dest, src, c.num*c.size); break;
728 case 2: revcpy<2>(dest, src, c.num); break;
729 case 4: revcpy<4>(dest, src, c.num); break;
730 case 8: revcpy<8>(dest, src, c.num); break;
731 }
732 }
733
734 return good();
735 }
736
737 bool GetNextRow(bool check=true)
738 {
739#if !defined(__MARS__) && !defined(__CINT__)
740 return GetRow(fRow+1, check);
741#else
742 return GetRowNum(fRow+1, check);
743#endif
744 }
745
746 bool SkipNextRow()
747 {
748 seekg(fTable.offset+(++fRow)*fTable.bytes_per_row);
749 return good();
750 }
751
752 static bool Compare(const Address &p1, const Address &p2)
753 {
754 return p1.first>p2.first;
755 }
756
757 template<class T, class S>
758 const T &GetAs(const string &name)
759 {
760 return *reinterpret_cast<S*>(fPointers[name]);
761 }
762
763 void *SetPtrAddress(const string &name)
764 {
765 if (fTable.cols.count(name)==0)
766 {
767 ostringstream str;
768 str <<"SetPtrAddress('" << name << "') - Column not found." << endl;
769#ifdef __EXCEPTIONS
770 throw runtime_error(str.str());
771#else
772 gLog << ___err___ << "ERROR - " << str.str() << endl;
773 return NULL;
774#endif
775 }
776
777 Pointers::const_iterator it = fPointers.find(name);
778 if (it!=fPointers.end())
779 return it->second;
780
781 fGarbage.push_back(vector<char>(fTable.cols[name].size*fTable.cols[name].num));
782
783 void *ptr = fGarbage.back().data();
784
785 fPointers[name] = ptr;
786 fAddresses.push_back(make_pair(ptr, fTable.cols[name]));
787 sort(fAddresses.begin(), fAddresses.end(), Compare);
788 return ptr;
789 }
790
791 template<typename T>
792 bool SetPtrAddress(const string &name, T *ptr, size_t cnt)
793 {
794 if (fTable.cols.count(name)==0)
795 {
796 ostringstream str;
797 str << "SetPtrAddress('" << name << "') - Column not found." << endl;
798#ifdef __EXCEPTIONS
799 throw runtime_error(str.str());
800#else
801 gLog << ___err___ << "ERROR - " << str.str() << endl;
802 return false;
803#endif
804 }
805
806 if (sizeof(T)!=fTable.cols[name].size)
807 {
808 ostringstream str;
809 str << "SetPtrAddress('" << name << "') - Element size mismatch: expected "
810 << fTable.cols[name].size << " from header, got " << sizeof(T) << endl;
811#ifdef __EXCEPTIONS
812 throw runtime_error(str.str());
813#else
814 gLog << ___err___ << "ERROR - " << str.str() << endl;
815 return false;
816#endif
817 }
818
819 if (cnt!=fTable.cols[name].num)
820 {
821 ostringstream str;
822 str << "SetPtrAddress('" << name << "') - Element count mismatch: expected "
823 << fTable.cols[name].num << " from header, got " << cnt << endl;
824#ifdef __EXCEPTIONS
825 throw runtime_error(str.str());
826#else
827 gLog << ___err___ << "ERROR - " << str.str() << endl;
828 return false;
829#endif
830 }
831
832 // if (fAddresses.count(ptr)>0)
833 // gLog << warn << "SetPtrAddress('" << name << "') - Pointer " << ptr << " already assigned." << endl;
834
835 //fAddresses[ptr] = fTable.cols[name];
836 fPointers[name] = ptr;
837 fAddresses.push_back(make_pair(ptr, fTable.cols[name]));
838 sort(fAddresses.begin(), fAddresses.end(), Compare);
839 return true;
840 }
841
842 template<class T>
843 bool SetRefAddress(const string &name, T &ptr)
844 {
845 return SetPtrAddress(name, &ptr, sizeof(ptr)/sizeof(T));
846 }
847
848 template<typename T>
849 bool SetVecAddress(const string &name, vector<T> &vec)
850 {
851 return SetPtrAddress(name, vec.data(), vec.size());
852 }
853
854 template<typename T>
855 T Get(const string &key) const
856 {
857 return fTable.Get<T>(key);
858 }
859
860 template<typename T>
861 T Get(const string &key, const string &deflt) const
862 {
863 return fTable.Get<T>(key, deflt);
864 }
865
866 bool SetPtrAddress(const string &name, void *ptr)
867 {
868 if (fTable.cols.count(name)==0)
869 {
870 ostringstream str;
871 str <<"SetPtrAddress('" << name << "') - Column not found." << endl;
872#ifdef __EXCEPTIONS
873 throw runtime_error(str.str());
874#else
875 gLog << ___err___ << "ERROR - " << str.str() << endl;
876 return false;
877#endif
878 }
879
880 // if (fAddresses.count(ptr)>0)
881 // gLog << warn << "SetPtrAddress('" << name << "') - Pointer " << ptr << " already assigned." << endl;
882
883 //fAddresses[ptr] = fTable.cols[name];
884 fPointers[name] = ptr;
885 fAddresses.push_back(make_pair(ptr, fTable.cols[name]));
886 sort(fAddresses.begin(), fAddresses.end(), Compare);
887 return true;
888 }
889
890 bool HasKey(const string &key) const { return fTable.HasKey(key); }
891 bool HasColumn(const string& col) const { return fTable.HasColumn(col);}
892 const Table::Columns &GetColumns() const { return fTable.GetColumns();}
893 const Table::Keys &GetKeys() const { return fTable.GetKeys();}
894
895 int64_t GetInt(const string &key) const { return fTable.Get<int64_t>(key); }
896 uint64_t GetUInt(const string &key) const { return fTable.Get<uint64_t>(key); }
897 double GetFloat(const string &key) const { return fTable.Get<double>(key); }
898 string GetStr(const string &key) const { return fTable.Get<string>(key); }
899
900 size_t GetN(const string &key) const
901 {
902 return fTable.GetN(key);
903 }
904
905 size_t GetNumRows() const { return fTable.num_rows; }
906 size_t GetRow() const { return fRow==(size_t)-1 ? 0 : fRow; }
907
908 operator bool() const { return fTable && fTable.offset!=0; }
909
910 void PrintKeys() const { fTable.PrintKeys(); }
911 void PrintColumns() const { fTable.PrintColumns(); }
912
913 bool IsHeaderOk() const { return fTable.datasum<0?false:(fChkHeader+Checksum(fTable.datasum)).valid(); }
914 bool IsFileOk() const { return (fChkHeader+fChkData).valid(); }
915
916};
917
918#ifndef __MARS__
919};
920#endif
921#endif
Note: See TracBrowser for help on using the repository browser.