source: trunk/FACT++/src/Converter.cc@ 10449

Last change on this file since 10449 was 10449, checked in by tbretz, 10 years ago
Added Print member function; fixed interpretation of hex and oct values
File size: 26.1 KB
Line 
1// **************************************************************************
2/** @class Converter
3
4@brief A compiler for the DIM data format string
5
6The Converter class interprets arguments in a string accoring to the
7given format definition and produces a corresponding memory block from it
8which can be attached to an event later.
9
10The format is given according to the Dim format description:
11
12 The format parameter specifies the contents of the structure in the
13 form T:N[;T:N]*[;T] where T is the item type: (I)nteger, (C)haracter,
14 (L)ong, (S)hort, (F)loat, (D)ouble, X(tra long) and N is the
15 number of such items. The type alone at the end means all following items
16 are of the same type. Example: "I:3;F:2;C" means 3 Integers, 2 Floats and
17 characters until the end. The format parameter is used for
18 communicating between different platforms.
19
20Note, that the strange notation T:N[;T:N]*[;T] is meant to be a regular
21expression. An Xtra-long is a 'long long'.
22
23Since Dim itself never really interpretes the format string, the programmer
24is responsible to make sure that the delivered data and the interpretation
25is consistent. Therefore the provided class can be of some help.
26
27For example:
28
29\code
30 Converter c(cout, "I:1;F:2;I:2", );
31 vector<char> v = c.GetVector("COMMAND 1 2.5 4.2 3 4");
32\endcode
33
34would produce a 20 byte data block with the integers 1, the floats
352.5 and 4.2, and the intergers 3 and 4, in this order.
36
37The opposite direction is also possible
38
39\code
40 Converter c(cout, "I:1;F:2;I:2");
41 cout << c.GetString(pointer, size) << endl;
42 \endcode
43
44Other conversion functions also exist.
45
46To check if the compilation of the format string was successfull
47the valid() member functio is provided.
48
49The format parameter \b W(ord) is dedicated to this kind of conversion and
50not understood by Dim. In addition there are \b O(ptions) which are like
51Words but can be omitted. They should only be used at the end of the string.
52Both can be encapsulated in quotationmarks '"'. Nested quotationmarks
53are not supported. \b B(ool) is also special. It evaluates true/false,
54yes/no, on/off, 1/0.
55
56The non-DIM like format options can be switched on and off by using the
57strict argument in the constructor. In general DimCommands can use these
58options, but DimServices not.
59
60@remark Note that all values are interpreted as signed, except the single
61char (e.g. C:5)
62
63*/
64// **************************************************************************
65#include "Converter.h"
66
67#include <iostream>
68#include <iomanip>
69#include <sstream>
70
71#include <cctype> // std::tolower
72#include <algorithm> // std::transform
73
74#include <boost/regex.hpp>
75
76#include "Readline.h"
77#include "WindowLog.h"
78
79using namespace std;
80
81// --------------------------------------------------------------------------
82//
83//! This function is supposed to remove all whitespaces from the format
84//! string to allow easier regular expressions later.
85//!
86//! @param s
87//! string to be cleaned
88//!
89//! @returns
90//! string cleaned from whitespaces
91//
92std::string Converter::Clean(std::string s)
93{
94 while (1)
95 {
96 const size_t pos = s.find_last_of(' ');
97 if (pos==string::npos)
98 break;
99 s.erase(pos, pos+1);
100 }
101
102 return s;
103}
104
105// --------------------------------------------------------------------------
106//
107//! This is just a simplification. For the time being it is used to output
108//! the interpreted contents to the logging stream. Its main purpose
109//! is to add the contents of val in a binary representation to the
110//! vector v
111//!
112//! @tparam
113//! data type of the variable which should be added
114//!
115//! @param val
116//! reference to the data
117//!
118//! @param v
119//! vector<char> to which the binary copy should be added
120//!
121template <class T>
122void Converter::GetBinImp(std::vector<char> &v, const T &val) const
123{
124 wout << " (" << val << ")";
125
126 v.insert(v.end(),
127 reinterpret_cast<const char*>(&val),
128 reinterpret_cast<const char*>(&val+1));
129}
130
131// --------------------------------------------------------------------------
132//
133//! This is just a simplification. For the time being it is used to output
134//! the interpreted contents to the logging stream. Its main purpose
135//! is to add the contents of val as a boost::any object to the
136//! vector v
137//!
138//! @tparam
139//! data type of the variable which should be added
140//!
141//! @param val
142//! reference to the data
143//!
144//! @param v
145//! vector<boost::any> to which the value should be added
146//!
147template <class T>
148void Converter::GetBinImp(std::vector<boost::any> &v, const T &val) const
149{
150 wout << " (" << val << ")";
151
152 v.push_back(val);
153}
154
155// --------------------------------------------------------------------------
156//
157//! This is just a simplification. For the time being it is used to output
158//! the interpreted contents to the logging stream. Its main purpose
159//! is to add the contents of the provided string at the end of the vector v.
160//! vector v
161//!
162//! @param val
163//! reference to the string
164//!
165//! @param v
166//! vector<char> to which the value should be added
167//!
168void Converter::GetBinString(std::vector<char> &v, const string &val) const
169{
170 wout << " (" << val << ")";
171
172 v.insert(v.end(), val.begin(), val.end()+1);
173}
174
175// --------------------------------------------------------------------------
176//
177//! This is just a simplification. For the time being it is used to output
178//! the interpreted contents to the logging stream. Its main purpose
179//! is to add the contents of the provided string at the end of the vector v.
180//! vector v
181//!
182//! @param val
183//! reference to the string
184//!
185//! @param v
186//! vector<boost::any> to which the value should be added
187//!
188void Converter::GetBinString(std::vector<boost::any> &v, const string &val) const
189{
190 wout << " (" << val << ")";
191
192 v.push_back(val);
193 v.push_back('\n');
194}
195
196// --------------------------------------------------------------------------
197//
198//! Converts from the stringstream into the provided type.
199//!
200//! @param line
201//! reference to the stringstream from which the data should be
202//! interpreted
203//!
204//! @tparam
205//! Type of the data to be returned
206//!
207//! @returns
208//! The interpreted data
209//!
210template <class T>
211T Converter::Get(std::stringstream &line) const
212{
213 char c;
214 line >> c;
215
216 if (c=='0')
217 {
218 if (line.peek()==-1)
219 return 0;
220
221 if (line.peek()=='x')
222 {
223 line >> c;
224 line >> hex;
225 }
226 else
227 line >> oct;
228
229 }
230 else
231 {
232 line.unget();
233 line >> dec;
234 }
235
236
237 T val;
238 line >> val;
239 return val;
240}
241
242// --------------------------------------------------------------------------
243//
244//! Converts from the stringstream into bool. It allows to use lexical
245//! boolean representations like yes/no, on/off, true/false and of
246//! course 0/1. If the conversion fails the failbit is set.
247//!
248//! @param line
249//! reference to the stringstream from which the data should be
250//! interpreted
251//!
252//! @returns
253//! The boolean. 0 in case of failure
254//!
255bool Converter::GetBool(std::stringstream &line) const
256{
257 string buf;
258 line >> buf;
259 transform(buf.begin(), buf.end(), buf.begin(), (int(*)(int)) std::tolower);
260
261 if (buf=="yes" || buf=="true" || buf=="on" || buf=="1")
262 return true;
263
264 if (buf=="no" || buf=="false" || buf=="off" || buf=="0")
265 return false;
266
267 line.clear(ios::failbit);
268
269 return false;
270}
271
272// --------------------------------------------------------------------------
273//
274//! Converts from the stringstream into a string. Leading whitespaces are
275//! skipped. Everything up to the next whitespace is returned.
276//! strings can be encapsulated into escape characters ("). Note, that
277//! they cannot be nested.
278//!
279//! @param line
280//! reference to the stringstream from which the data should be
281//! interpreted
282//!
283//! @returns
284//! The string
285//!
286string Converter::GetString(std::stringstream &line) const
287{
288 while (line.peek()==' ')
289 line.get();
290
291 string buf;
292 if (line.peek()=='\"')
293 {
294 line.get();
295 getline(line, buf, '\"');
296 if (line.peek()==-1)
297 line.clear(ios::eofbit);
298 }
299 else
300 line >> buf;
301
302 return buf;
303}
304
305// --------------------------------------------------------------------------
306//
307//! Converts from the stringstream into a string. Leading whitespaces are
308//! skipped. Everything until the end-of-line is returned. A trailing
309//! \0 is added.
310//!
311//! @param line
312//! reference to the stringstream from which the data should be
313//! interpreted
314//!
315//! @returns
316//! The string
317//!
318string Converter::GetStringEol(stringstream &line) const
319{
320 // Remove leading whitespaces
321 while (line.peek()==' ')
322 line.get();
323
324 line >> noskipws;
325
326 const istream_iterator<char> eol; // end-of-line iterator
327 const string s(istream_iterator<char>(line), eol);
328 return s + '\0';
329}
330
331// --------------------------------------------------------------------------
332//
333//! Converts from a binary block into a string. The type of the expected
334//! value is defined by the template parameter.
335//!
336//! @param ptr
337//! A refrenece to the pointer of the binary representation to be
338//! interpreted. The pointer is incremented by the sizeof the type.
339//!
340//! @tparam T
341//! Expected type
342//!
343//! @returns
344//! The string
345//!
346template<class T>
347string Converter::GetString(const char* &ptr) const
348{
349 const T &t = *reinterpret_cast<const T*>(ptr);
350
351 ostringstream stream;
352 stream << t;
353 ptr += sizeof(T);
354
355 return stream.str();
356}
357
358// --------------------------------------------------------------------------
359//
360//! Convert the pointer using GetString into a string and add it (prefixed
361//! by a whaitespace) to the given string.
362//!
363//! @param str
364//! Reference to the string to which the ptr should be added
365//!
366//! @param ptr
367//! Pointer to the binary representation. It will be incremented
368//! according to the sze of the template argument
369//!
370//! @tparam T
371//! Type as which the binary data should be interpreted
372//!
373template<class T>
374void Converter::Add(string &str, const char* &ptr) const
375{
376 str += ' ' + GetString<T>(ptr);
377}
378
379// --------------------------------------------------------------------------
380//
381//! Convert the pointer into a boost::any object and add it to the
382//! provided vector
383//!
384//! @param vec
385//! Vector to which the boost::any object should be added
386//!
387//! @param ptr
388//! Pointer to the binary representation. It will be incremented
389//! according to the size of the template argument
390//!
391//! @tparam T
392//! Type as which the binary data should be interpreted
393//!
394template<class T>
395void Converter::Add(vector<boost::any> &vec, const char* &ptr) const
396{
397 vec.push_back(*reinterpret_cast<const T*>(ptr));
398 ptr += sizeof(T);
399}
400
401// --------------------------------------------------------------------------
402//
403//! Add the string pointed to by ptr to the given string.
404//!
405//! @param str
406//! Reference to the string to which the ptr should be added
407//!
408//! @param ptr
409//! Pointer to the binary representation. It will be incremented
410//! according to the size of the template argument
411//!
412void Converter::AddString(string &str, const char* &ptr) const
413{
414 const string txt(ptr);
415 str += ' '+txt;
416 ptr += txt.length()+1;
417}
418
419// --------------------------------------------------------------------------
420//
421//! Add the string pointed to by ptr as boost::any to the provided vector
422//!
423//! @param vec
424//! Vector to which the boost::any object should be added
425//!
426//! @param ptr
427//! Pointer to the binary representation. It will be incremented
428//! according to the size of the template argument
429//!
430void Converter::AddString(vector<boost::any> &vec, const char* &ptr) const
431{
432 const string txt(ptr);
433 vec.push_back(txt);
434 ptr += txt.length()+1;
435}
436
437// --------------------------------------------------------------------------
438//
439//! Compiles the format string into fList. See Compile() for more details.
440//!
441//! @param out
442//! Output stream to which possible logging is redirected
443//!
444//! @param fmt
445//! Format to be compiled. For details see class reference
446//!
447//! @param strict
448//! Setting this to true allows non DIM options, whiel false
449//! will restrict the possible format strings to the ones also
450//! understood by DIM.
451//!
452Converter::Converter(std::ostream &out, const std::string &fmt, bool strict)
453: wout(out), fFormat(Clean(fmt)), fList(Compile(out, fmt, strict))
454{
455}
456
457// --------------------------------------------------------------------------
458//
459//! Compiles the format string into fList.
460//!
461//! Output by default is redirected to cout.
462//!
463//! @param fmt
464//! Format to be compiled. For details see class reference
465//!
466//! @param strict
467//! Setting this to true allows non DIM options, whiel false
468//! will restrict the possible format strings to the ones also
469//! understood by DIM.
470//!
471Converter::Converter(const std::string &fmt, bool strict)
472: wout(cout), fFormat(Clean(fmt)), fList(Compile(fmt, strict))
473{
474}
475
476// --------------------------------------------------------------------------
477//
478//! Converts the provided format string into a vector.
479//!
480//! @tparam T
481//! Kind of data to be returned. This can either be boost::any objects
482//! or a bnary data-block (char).
483//!
484//! @param str
485//! Data to be converted. For details see class reference
486//!
487//! @returns
488//! A vector of the given template type containing the arguments. In
489//! case of failure an empty vector is returned.
490//!
491//! @throws
492//! std::runtime_error if the conversion was not successfull
493//!
494template <class T>
495vector<T> Converter::Get(const std::string &str) const
496{
497 if (!valid())
498 throw runtime_error("Compiled format invalid!");
499
500 // If the format is empty we are already done
501 if (empty() && str.empty())
502 {
503 wout << endl;
504 return vector<T>();
505 }
506
507 int arg = 0;
508 stringstream line(str);
509
510 vector<T> data;
511
512 for (Converter::FormatList::const_iterator i=fList.begin(); i<fList.end()-1; i++)
513 {
514 if (*i->first.first == typeid(string))
515 {
516 GetBinString(data, GetStringEol(line));
517 line.clear(ios::eofbit);
518 continue;
519 }
520
521 // Get as many items from the input line as requested
522 for (int j=0; j<i->second.first; j++)
523 {
524 switch (i->first.first->name()[0])
525 {
526 case 'b': GetBinImp(data, GetBool(line)); break;
527 case 's': GetBinImp(data, Get<short> (line)); break;
528 case 'i': GetBinImp(data, Get<int> (line)); break;
529 case 'l': GetBinImp(data, Get<long> (line)); break;
530 case 'f': GetBinImp(data, Get<float> (line)); break;
531 case 'd': GetBinImp(data, Get<double> (line)); break;
532 case 'x': GetBinImp(data, Get<long long>(line)); break;
533 case 'c':
534 if (line.peek()==-1)
535 {
536 line.clear(ios::failbit|ios::eofbit);
537 break;
538 }
539 GetBinImp(data, Get<unsigned char>(line));
540 if (line.peek()==-1)
541 line.clear(ios::eofbit);
542 break;
543 case 'N':
544 GetBinString(data, GetString(line));
545 if (*i->first.first == typeid(O))
546 line.clear(ios::goodbit|(line.rdstate()&ios::eofbit));
547 break;
548 default:
549 // This should never happen!
550 throw runtime_error("Format '"+string(i->first.first->name())+" not supported!");
551 }
552
553 arg++;
554 }
555
556 if (!line)
557 break;
558 }
559 wout << endl;
560
561 // Something wrong with the conversion (e.g. 5.5 for an int)
562 if (line.fail() && !line.eof())
563 {
564 line.clear(); // This is necesasary to get a proper response from tellg()
565
566 ostringstream err;
567 err << "Error converting argument at " << arg << " [fmt=" << fFormat << "]!\n";
568 err << line.str() << "\n";
569 err << setw(int(line.tellg())) << " " << "^\n";
570 throw runtime_error(err.str());
571 }
572
573 // Not enough arguments, we have not reached the end
574 if (line.fail() && line.eof())
575 {
576 line.clear();
577
578 ostringstream err;
579 err << "Not enough arguments [fmt=" << fFormat << "]!\n";
580 err << line.str() << "\n";
581 err << setw(int(line.tellg())+1) << " " << "^\n";
582 throw runtime_error(err.str());
583 }
584
585 // Too many arguments, we have not reached the end
586 // Unfortunately, this can also mean that there is something
587 // wrong with the last argument
588 if (line.good() && !line.eof())
589 {
590 ostringstream err;
591 err << "More arguments available than expected [fmt=" << fFormat << "]!\n";
592 err << line.str() << "\n";
593 err << setw(int(line.tellg())+1) << " " << "^\n";
594 throw runtime_error(err.str());
595 }
596
597 return data;
598
599}
600
601std::vector<boost::any> Converter::GetAny(const std::string &str) const
602{
603 return Get<boost::any>(str);
604}
605
606std::vector<char> Converter::GetVector(const std::string &str) const
607{
608 return Get<char>(str);
609}
610
611// --------------------------------------------------------------------------
612//
613//! Converts the provided data block into a vector of boost::any or
614//! a string.
615//!
616//! @tparam T
617//! Kind of data to be returned. This can either be boost::any objects
618//! or a string
619//!
620//! @returns
621//! A vector of the given template type containing the arguments. In
622//! case of failure an empty vector is returned.
623//!
624//! @throws
625//! std::runtime_error if the conversion was not successfull
626//!
627template<class T>
628T Converter::Get(const void *dat, size_t size) const
629{
630 if (!valid())
631 throw runtime_error("Compiled format invalid!");
632
633 const char *ptr = reinterpret_cast<const char *>(dat);
634
635 T text;
636 for (Converter::FormatList::const_iterator i=fList.begin(); i<fList.end()-1; i++)
637 {
638 if (ptr-size>dat)
639 {
640 ostringstream err;
641 err << "Format description [fmt=" << fFormat << "] exceeds available data size (" << size << ")";
642 throw runtime_error(err.str());
643 }
644
645 if (*i->first.first == typeid(string))
646 {
647 if (size>0)
648 AddString(text, ptr);
649 if (ptr-size<=dat)
650 return text;
651 break;
652 }
653
654 // Get as many items from the input line as requested
655 for (int j=0; j<i->second.first; j++)
656 {
657 switch (i->first.first->name()[0])
658 {
659 case 'b': Add<bool> (text, ptr); break;
660 case 'c': Add<char> (text, ptr); break;
661 case 's': Add<short> (text, ptr); break;
662 case 'i': Add<int> (text, ptr); break;
663 case 'l': Add<long> (text, ptr); break;
664 case 'f': Add<float> (text, ptr); break;
665 case 'd': Add<double> (text, ptr); break;
666 case 'x': Add<long long>(text, ptr); break;
667 case 'N': AddString(text, ptr); break;
668
669 case 'v':
670 // This should never happen!
671 throw runtime_error("Type 'void' not supported!");
672 default:
673 throw runtime_error("TypeId '"+string(i->first.first->name())+"' not known!");
674 }
675 }
676 }
677
678 if (ptr-size!=dat)
679 {
680 ostringstream err;
681 err << "Data block size (" << size << ") doesn't fit format description [fmt=" << fFormat << "]";
682 throw runtime_error(err.str());
683 }
684
685 return text;
686}
687
688std::vector<boost::any> Converter::GetAny(const void *dat, size_t size) const
689{
690 return Get<vector<boost::any>>(dat, size);
691}
692
693std::vector<char> Converter::GetVector(const void *dat, size_t size) const
694{
695 const string ref = GetString(dat, size);
696
697 vector<char> data;
698 data.insert(data.begin(), ref.begin()+1, ref.end());
699 data.push_back(0);
700
701 return data;
702}
703
704string Converter::GetString(const void *dat, size_t size) const
705{
706 const string s = Get<string>(dat, size);
707 return s.empty() ? s : s.substr(1);
708}
709
710template<class T>
711Converter::Type Converter::GetType()
712{
713 Type t;
714 t.first = &typeid(T);
715 t.second = sizeof(T);
716 return t;
717}
718
719template<class T>
720Converter::Type Converter::GetVoid()
721{
722 Type t;
723 t.first = &typeid(T);
724 t.second = 0;
725 return t;
726}
727
728// --------------------------------------------------------------------------
729//
730//! static function to compile a format string.
731//!
732//! @param out
733//! Output stream to which possible logging is redirected
734//!
735//! @param fmt
736//! Format to be compiled. For details see class reference
737//!
738//! @param strict
739//! Setting this to true allows non DIM options, whiel false
740//! will restrict the possible format strings to the ones also
741//! understood by DIM.
742//!
743Converter::FormatList Converter::Compile(std::ostream &out, const std::string &fmt, bool strict)
744{
745 ostringstream text;
746
747 // Access both, the data and the format through a stringstream
748 stringstream stream(fmt);
749
750 // For better performance we could use sregex
751 static const boost::regex expr1("^([CSILFDXBOW])(:([1-9]+[0-9]*))?$");
752 static const boost::regex expr2("^([CSILFDX])(:([1-9]+[0-9]*))?$");
753
754 FormatList list;
755 Format format;
756
757 // Tokenize the format
758 string buffer;
759 while (getline(stream, buffer, ';'))
760 {
761 boost::smatch what;
762 if (!boost::regex_match(buffer, what, strict?expr2:expr1))
763 {
764 out << kRed << "Wrong format string '" << buffer << "'!" << endl;
765 return FormatList();
766 }
767
768 const string t = what[1]; // type id
769 const string n = what[3]; // counter
770
771 const int cnt = atoi(n.c_str());
772
773 // if the :N part was not given assume 1
774 format.second.first = cnt == 0 ? 1: cnt;
775
776 // Check if the format is just C (without a number)
777 // That would mean that it is a \0 terminated string
778 if (t[0]=='C' && cnt==0)
779 {
780 format.first = GetType<string>();
781 list.push_back(format);
782 format.second.second = 0; // end position not known
783 break;
784 }
785
786 // Get as many items from the input line as requested
787 switch (t[0])
788 {
789 case 'B': format.first = GetType<bool>(); break;
790 case 'C': format.first = GetType<char>(); break;
791 case 'S': format.first = GetType<short>(); break;
792 case 'I': format.first = GetType<int>(); break;
793 case 'L': format.first = GetType<long>(); break;
794 case 'F': format.first = GetType<float>(); break;
795 case 'D': format.first = GetType<double>(); break;
796 case 'X': format.first = GetType<long long>(); break;
797 case 'O': format.first = GetVoid<O>(); break;
798 case 'W': format.first = GetVoid<W>(); break;
799 default:
800 // This should never happen!
801 out << kRed << "Format '" << t[0] << " not known!" << endl;
802 return list;
803 }
804
805 list.push_back(format);
806 format.second.second += format.first.second * format.second.first;
807 }
808
809 format.first = GetVoid<void>();
810 format.second.first = 0;
811
812 list.push_back(format);
813
814 return list;
815}
816
817// --------------------------------------------------------------------------
818//
819//! Same as Compile(ostream&,string&,bool) but cout is used as the default
820//! output stream.
821//!
822//!
823Converter::FormatList Converter::Compile(const std::string &fmt, bool strict)
824{
825 return Compile(cout, fmt, strict);
826}
827
828vector<string> Converter::Regex(const string &expr, const string &line)
829{
830 const boost::regex reg(expr);
831
832 boost::smatch what;
833 if (!boost::regex_match(line, what, reg, boost::match_extra))
834 return vector<string>();
835
836 vector<string> ret;
837 for (unsigned int i=0; i<what.size(); i++)
838 ret.push_back(what[i]);
839
840 return ret;
841}
842
843
844void Converter::ToFits(void *dest, const void *src, size_t size) const
845{
846 // crawl through the src buffer and copy the data appropriately to the
847 // destination buffer
848 // Assumption: the string is always last. This way we
849 // use the provided size to determine the number
850 // of character to copy
851
852 char *charDest = static_cast<char*>(dest);
853 const char *charSrc = static_cast<const char*>(src);
854
855 for (Converter::FormatList::const_iterator i=fList.begin(); i!=fList.end(); i++)
856 {
857//ETIENNE this check fails for very fine cases. Disabled it
858 // FIXME: This is still not really safe
859// if (charDest-size>=dest)
860// {
861// ostringstream err;
862// err << "Format description [fmt=" << fFormat << "] exceeds available data size (" << size << ")";
863// throw runtime_error(err.str());
864// }
865
866 const char type = i->first.first->name()[0];
867
868 // string types
869 if (type=='S' || type=='O' || type=='W')
870 {
871 // copy string until termination
872 while (*charSrc)
873 *charDest++ = *charSrc++;
874
875 // Copy \0-termination
876//ETIENNE: Do not copy the \0 as it must not be written to fits files. just increment charSrc instead
877 // *charDest++ = *charSrc++;
878 charSrc++;
879 continue;
880 }
881
882 const int s = i->first.second; // size of element
883 const int n = i->second.first; // number of elements
884
885 // for all elements of this column
886 for (int j=0; j<n; j++)
887 {
888 //ETIENNE moved the +s-1 to the second argument and removed the -1
889 reverse_copy(charSrc, charSrc+s, charDest);
890
891 charSrc += s;
892 charDest += s;
893 }
894 }
895
896 if (charDest-size!=dest)
897 {
898 ostringstream err;
899 err << "Data block size (" << size << ") doesn't fit format description [fmt=" << fFormat << "]";
900 throw runtime_error(err.str());
901 }
902}
903
904vector<char> Converter::ToFits(const void *src, size_t size) const
905{
906 vector<char> dest(size);
907 ToFits(&dest[0], src, size);
908 return dest;
909}
910
911
912void Converter::Print(std::ostream &out) const
913{
914 for (FormatList::const_iterator i=fList.begin(); i!=fList.end(); i++)
915 {
916 out << "Type=" << i->first.first->name() << "[" << i->first.second << "] ";
917 out << "N=" << i->second.first << " ";
918 out << "offset=" << i->second.second << endl;
919 }
920}
921
922void Converter::Print() const
923{
924 return Print(cout);
925}
926
927
928
929
930
931
932
Note: See TracBrowser for help on using the repository browser.