00001
00002
00015 #ifndef EFORMAT_HEADER_H
00016 #define EFORMAT_HEADER_H
00017
00018 #include "eformat/Version.h"
00019 #include "eformat/SourceIdentifier.h"
00020 #include "eformat/util.h"
00021 #include "eformat/SizeCheckIssue.h"
00022 #include "eformat/BadVersionIssue.h"
00023 #include "eformat/WrongMarkerIssue.h"
00024 #include "eformat/WrongSizeIssue.h"
00025 #include "eformat/NoSuchChildIssue.h"
00026 #include "ers/ers.h"
00027
00028 namespace eformat {
00029
00040 template <class TPointer> class Header {
00041
00042 public:
00043
00051 Header (const TPointer& it, uint32_t match);
00052
00056 Header () : m_start() {}
00057
00063 Header (const Header& other) : m_start(other.m_start) {}
00064
00068 virtual ~Header() {}
00069
00075 Header& operator= (const Header& other)
00076 { m_start = other.m_start; return *this; }
00077
00084 Header& assign (const TPointer& it, uint32_t match);
00085
00090 virtual bool check () const;
00091
00095 inline uint32_t marker() const { return m_start[0]; }
00096
00100 inline uint32_t fragment_size_word() const { return m_start[1]; }
00101
00106 inline uint32_t header_size_word() const { return m_start[2]; }
00107
00111 inline uint32_t version() const { return m_start[3]; }
00112
00116 inline uint32_t source_id() const { return m_start[4]; }
00117
00121 inline uint32_t nstatus () const { return m_start[5]; }
00122
00128 inline void start (TPointer& it) const { it = m_start; }
00129
00135 inline void payload (TPointer& it) const
00136 { it = m_start; it+= header_size_word(); }
00137
00143 inline void end (TPointer& it) const
00144 { it = m_start; it += fragment_size_word(); }
00145
00149 inline uint32_t payload_size_word (void) const
00150 { return fragment_size_word() - header_size_word(); }
00151
00157 inline void status (TPointer& it) const { it = m_start; it += 6; }
00158
00159
00164 inline uint32_t nspecific () const { return m_start[6 + nstatus()]; }
00165
00172 inline void specific_header (TPointer& it) const
00173 { it = m_start; it += 7 + nstatus(); }
00174
00178 virtual uint32_t nchildren () const;
00179
00188 virtual void child (TPointer& p, size_t n) const;
00189
00201 virtual void child_check (TPointer& p, size_t n) const;
00202
00213 virtual uint32_t children (TPointer* p, size_t max) const;
00214
00215 private:
00216
00217 TPointer m_start;
00218
00219 };
00220
00221 }
00222
00223 template <class TPointer>
00224 eformat::Header<TPointer>::Header (const TPointer& it, uint32_t match)
00225 : m_start(it)
00226 {
00227 ERS_DEBUG_3("Building header 0x%x from iterator", match);
00228 if (marker() != match) {
00229 throw EFORMAT_WRONG_MARKER(marker(), match);
00230 }
00231 ERS_DEBUG_1("Initialized header with source identifier = %s",
00232 eformat::helper::SourceIdentifier(match).human().c_str());
00233 }
00234
00235 template <class TPointer> eformat::Header<TPointer>&
00236 eformat::Header<TPointer>::assign (const TPointer& it, uint32_t match)
00237 {
00238 ERS_DEBUG_3("Rebuilding header 0x%x from iterator", match);
00239 m_start = it;
00240 if (marker() != match) {
00241 throw EFORMAT_WRONG_MARKER(marker(), match);
00242 }
00243 ERS_DEBUG_1("Re-initialized header with source identifier = %s",
00244 eformat::helper::SourceIdentifier(match).human().c_str());
00245 return *this;
00246 }
00247
00248 template <class TPointer>
00249 bool eformat::Header<TPointer>::check () const
00250 {
00251 ERS_DEBUG_2("Checking for consistency of fragment of type %s [%s]",
00252 eformat::marker2string(marker()).c_str(),
00253 eformat::helper::SourceIdentifier(source_id()).human().c_str());
00254 if ( version() >> 16 != eformat::MAJOR_DEFAULT_VERSION )
00255 throw EFORMAT_BAD_VERSION(version() >> 16, eformat::MAJOR_DEFAULT_VERSION);
00256 if ( header_size_word() != (7 + nstatus() + nspecific()) )
00257 throw EFORMAT_SIZE_CHECK(header_size_word(),
00258 (7 + nstatus() + nspecific()));
00259 return true;
00260 }
00261
00262 template <class TPointer>
00263 uint32_t eformat::Header<TPointer>::nchildren () const
00264 {
00265 ERS_DEBUG_2("User asked for number of children of fragment type %s [%s]",
00266 eformat::marker2string(marker()).c_str(),
00267 eformat::helper::SourceIdentifier(source_id()).human().c_str());
00268 return children(0,0);
00269 }
00270
00271 template <class TPointer>
00272 void eformat::Header<TPointer>::child (TPointer& p, size_t n) const
00273 {
00274 ERS_DEBUG_2("User asked for child %ud of fragment type %s [%s]", n,
00275 eformat::marker2string(marker()).c_str(),
00276 eformat::helper::SourceIdentifier(source_id()).human().c_str());
00277 TPointer next;
00278 payload(next);
00279 for (size_t i=0; i<n; ++i) next += next[1];
00280 ERS_DEBUG_3("Set user object");
00281 p = next;
00282 }
00283
00284 template <class TPointer>
00285 void eformat::Header<TPointer>::child_check (TPointer& p, size_t n) const
00286 {
00287 uint32_t total = nchildren();
00288 if (n >= total) throw EFORMAT_NO_SUCH_CHILD(n, total);
00289 child(p, n);
00290 }
00291
00292 template <class TPointer>
00293 uint32_t eformat::Header<TPointer>::children (TPointer* p, size_t max) const
00294 {
00295 ERS_DEBUG_2("Retrieving all children...");
00296 TPointer payload_start;
00297 payload(payload_start);
00298 try {
00299 return find_fragments(child_marker(static_cast<HeaderMarker>(marker())),
00300 payload_start, payload_size_word(), p, max);
00301 }
00302 catch (WrongMarkerIssue& ex) {
00303
00304 throw EFORMAT_WRONG_SIZE(fragment_size_word());
00305 }
00306 return 0;
00307 }
00308
00309 #endif //EFORMAT_HEADER_H