artdaq_core  v1_07_01
 All Classes Namespaces Functions
Fragment.hh
1 #ifndef artdaq_core_Data_Fragment_hh
2 #define artdaq_core_Data_Fragment_hh
3 
4 #include <algorithm>
5 //#include <cassert>
6 #include <cstddef>
7 #include <iosfwd>
8 #include <iterator>
9 #include <vector>
10 #include <memory>
11 #include <map>
12 #include <cmath>
13 #include <stdint.h>
14 #include <string.h>
15 
16 #include "artdaq-core/Data/detail/RawFragmentHeader.hh"
17 #include "artdaq-core/Data/dictionarycontrol.hh"
18 
19 namespace artdaq {
20 # include "QuickVec.hh"
21 # define DATAVEC_T QuickVec<RawDataType>
22 //#define DATAVEC_T std::vector<RawDataType>
23  typedef detail::RawFragmentHeader::RawDataType RawDataType;
24 
25  class Fragment;
26  bool fragmentSequenceIDCompare(Fragment i, Fragment j);
27 
28  std::ostream & operator<<(std::ostream & os, Fragment const & f);
29 }
30 
32 public:
33  // Create a Fragment with all header values zeroed.
34  Fragment();
35 
36  // JCF, 3/25/14
37  // Add interface functions which allow users to work with the
38  // underlying data (a vector of RawDataTypes) in byte representation
39 
40  typedef uint8_t byte_t;
41 
42  // Hide most things from ROOT.
43 #if HIDE_FROM_ROOT
44 
45  // http://stackoverflow.com/questions/33939687
46  // This should generate an exception if artdaq::Fragment is not move-constructible
47  Fragment(const Fragment&) = default;
48  Fragment(Fragment&&) noexcept;
49  Fragment& operator=(const Fragment&) = default;
50  Fragment& operator=(Fragment&&) noexcept;
51 
52  typedef detail::RawFragmentHeader::version_t version_t;
53  typedef detail::RawFragmentHeader::type_t type_t;
54  typedef detail::RawFragmentHeader::sequence_id_t sequence_id_t;
55  typedef detail::RawFragmentHeader::fragment_id_t fragment_id_t;
56  typedef detail::RawFragmentHeader::timestamp_t timestamp_t;
57 
58  static constexpr version_t InvalidVersion =
59  detail::RawFragmentHeader::InvalidVersion;
60  static constexpr sequence_id_t InvalidSequenceID =
61  detail::RawFragmentHeader::InvalidSequenceID;
62  static constexpr fragment_id_t InvalidFragmentID =
63  detail::RawFragmentHeader::InvalidFragmentID;
64  static constexpr timestamp_t InvalidTimestamp =
65  detail::RawFragmentHeader::InvalidTimestamp;
66 
67  static constexpr type_t InvalidFragmentType =
68  detail::RawFragmentHeader::InvalidFragmentType;
69  static constexpr type_t EndOfDataFragmentType =
70  detail::RawFragmentHeader::EndOfDataFragmentType;
71  static constexpr type_t DataFragmentType =
72  detail::RawFragmentHeader::DataFragmentType;
73  static constexpr type_t InitFragmentType =
74  detail::RawFragmentHeader::InitFragmentType;
75  static constexpr type_t EndOfRunFragmentType =
76  detail::RawFragmentHeader::EndOfRunFragmentType;
77  static constexpr type_t EndOfSubrunFragmentType =
78  detail::RawFragmentHeader::EndOfSubrunFragmentType;
79  static constexpr type_t ShutdownFragmentType =
80  detail::RawFragmentHeader::ShutdownFragmentType;
81  static constexpr type_t FirstUserFragmentType =
82  detail::RawFragmentHeader::FIRST_USER_TYPE;
83  static constexpr type_t EmptyFragmentType =
84  detail::RawFragmentHeader::EmptyFragmentType;
85  static constexpr type_t ContainerFragmentType =
86  detail::RawFragmentHeader::ContainerFragmentType;
87 
88  static constexpr bool isUserFragmentType(type_t fragmentType);
89  static constexpr bool isSystemFragmentType(type_t fragmentType);
90  static std::map<type_t, std::string> MakeSystemTypeMap()
91  {
92  return detail::RawFragmentHeader::MakeSystemTypeMap();
93  }
94 
95  typedef DATAVEC_T::reference reference;
96  typedef DATAVEC_T::iterator iterator;
97  typedef DATAVEC_T::const_iterator const_iterator;
98  typedef DATAVEC_T::value_type value_type;
99  typedef DATAVEC_T::difference_type difference_type;
100  typedef DATAVEC_T::size_type size_type;
101 
102  // Create a Fragment ready to hold n words (RawDataTypes) of payload, and with
103  // all values zeroed.
104  explicit Fragment(std::size_t n);
105 
106  // Similar, but provide size of payload in bytes, and use a static
107  // factory function rather than a constructor to allow for the
108  // function name "FragmentBytes"
109 
110  static std::unique_ptr<Fragment> FragmentBytes(std::size_t nbytes) {
111  RawDataType nwords = ceil(nbytes / static_cast<double>(sizeof(RawDataType)));
112  return std::unique_ptr<Fragment>(new Fragment(nwords));
113  }
114 
115  // Create a Fragment ready to hold the specified number of words
116  // of payload, with the specified sequence ID, fragment ID, timestamp,
117  // fragment type, and metadata.
118  template <class T>
119  Fragment(std::size_t payload_size, sequence_id_t sequence_id,
120  fragment_id_t fragment_id, type_t type, const T & metadata,
121  timestamp_t timestamp = Fragment::InvalidTimestamp);
122 
123  // Similar, but provide size of payload in bytes, and use a static
124  // factory function rather than a constructor to allow for the
125  // function name "FragmentBytes"
126 
127  template <class T>
128  static std::unique_ptr<Fragment> FragmentBytes(std::size_t payload_size_in_bytes,
129  sequence_id_t sequence_id,
130  fragment_id_t fragment_id,
131  type_t type, const T & metadata,
132  timestamp_t timestamp = Fragment::InvalidTimestamp) {
133  RawDataType nwords = ceil(payload_size_in_bytes /
134  static_cast<double>(sizeof(RawDataType)));
135  return std::unique_ptr<Fragment>(new Fragment(nwords, sequence_id, fragment_id, type, metadata, timestamp));
136  }
137 
138  // Create a fragment with the given event id and fragment id, and
139  // with no data payload.
140  Fragment(sequence_id_t sequenceID,
141  fragment_id_t fragID,
142  type_t type = Fragment::DataFragmentType,
143  timestamp_t timestamp = Fragment::InvalidTimestamp);
144 
145  // Print out summary information for this Fragment to the given stream.
146  void print(std::ostream & os) const;
147 
148  // Header accessors
149  std::size_t size() const;
150  version_t version() const;
151  type_t type() const;
152  sequence_id_t sequenceID() const;
153  fragment_id_t fragmentID() const;
154  timestamp_t timestamp() const;
155 
156  // Header setters
157  void setVersion(version_t version);
158  void setUserType(type_t type);
159  void setSystemType(type_t type);
160  void setSequenceID(sequence_id_t sequence_id);
161  void setFragmentID(fragment_id_t fragment_id);
162  void setTimestamp(timestamp_t timestamp);
163 
164  // Size of vals_ vector ( header + (optional) metadata + payload) in bytes.
165  std::size_t sizeBytes() const { return sizeof(RawDataType) * size(); }
166 
167  // Return the number of words in the data payload. This does not
168  // include the number of words in the header.
169  std::size_t dataSize() const;
170 
171  // Similar, but use bytes instead
172  std::size_t dataSizeBytes() const {
173  return sizeof(RawDataType) * dataSize();
174  }
175 
176  // Test whether this Fragment has metadata
177  bool hasMetadata() const;
178 
179  // Return a pointer to the metadata. This throws an exception
180  // if the fragment contains no metadata.
181  template <class T> T * metadata();
182  template <class T> T const * metadata() const;
183 
184  // Set the metadata in the Fragment to the contents of
185  // the specified structure. This throws an exception if
186  // the Fragment already contains metadata.
187  template <class T> void setMetadata(const T & md);
188 
189  // If you wish to alter metadata which already exists, use this function:
190  template <class T> void updateMetadata(const T & md);
191 
192  // Resize the data payload to hold sz words.
193  void resize(std::size_t sz);
194  void resize(std::size_t sz, RawDataType v);
195 
196  // Resize the data payload to hold szbytes bytes (padded by the
197  // 8-byte RawDataTypes, so, e.g., requesting 14 bytes will actually
198  // get you 16)
199 
200  void resizeBytes(std::size_t szbytes);
201  void resizeBytes(std::size_t szbytes, byte_t v);
202 
203  // Resize the fragment to hold the number of words in the header.
204  void autoResize();
205 
206  // Return an iterator to the beginning of the data payload (post-header).
207  iterator dataBegin();
208  // ... and the end
209  iterator dataEnd();
210 
211  // JCF, 1/21/15
212 
213  // There's actually not an ironclad guarantee in the C++ standard
214  // that the pointer reinterpret_cast<> returns has the same address
215  // as the pointer that was casted. It IS tested in the artdaq-core
216  // test suite, but since any uncaught, unexpected behavior from
217  // reinterpret_cast could be disastrous, I've wrapped it in this
218  // function and added a check just to be completely safe.
219 
220  // I supply const- and non-const versions; const_cast<> would
221  // require a #pragma override of const-cast-as-error, which is a can
222  // of worms I don't wish to open.
223 
224  // Please note that for this const-version, you'll need the const-
225  // qualifier to the pointer you pass as a parameter (i.e.,
226  // reinterpret_cast_checked<const PtrType*>, not reinterpret_cast_checked<PtrType*>)
227 
228  template <typename T>
229  T reinterpret_cast_checked(const RawDataType* in) const {
230  T newpointer = reinterpret_cast<T>(in);
231 
232  if (static_cast<const void*>(newpointer) != static_cast<const void*>(in)) {
233  throw cet::exception("Error in Fragment.hh: reinterpret_cast failed to return expected address-- please contact John Freeman at jcfree@fnal.gov");
234  }
235 
236  return newpointer;
237  }
238 
239 
240  template <typename T>
241  T reinterpret_cast_checked(RawDataType* in) {
242  T newpointer = reinterpret_cast<T>(in);
243 
244  if (static_cast<void*>(newpointer) != static_cast<void*>(in)) {
245  throw cet::exception("Error in Fragment.hh: reinterpret_cast failed to return expected address-- please contact John Freeman at jcfree@fnal.gov");
246  }
247 
248  return newpointer;
249  }
250 
251  // Return Fragment::byte_t* pointing at the beginning/ends of the payload
252 
253  // JCF, 3/25/14 -- one nice thing about returning a pointer rather
254  // than an iterator is that we don't need to take the address of the
255  // dereferenced iterator (e.g., via &*dataBegin() ) to get ahold of the memory
256 
257  byte_t* dataBeginBytes() { return reinterpret_cast_checked<byte_t*>(&* dataBegin()); }
258  byte_t* dataEndBytes() { return reinterpret_cast_checked<byte_t*>(&* dataEnd()); }
259 
260  // Return an iterator to the beginning of the header (should be used
261  // for serialization only: use setters for preference).
262  iterator headerBegin();
263 
264  // Return a pointer-to-Fragment::byte_t pointing to the beginning of the header
265  byte_t* headerBeginBytes() { return reinterpret_cast_checked<byte_t*>(&* headerBegin()); }
266 
267 
268  const_iterator dataBegin() const;
269  const_iterator dataEnd() const;
270 
271  const byte_t* dataBeginBytes() const {
272  return reinterpret_cast_checked<const byte_t*>(&* dataBegin());
273  }
274 
275  const byte_t* dataEndBytes() const {
276  return reinterpret_cast_checked<const byte_t*>(&* dataEnd());
277  }
278 
279 
280  const_iterator headerBegin() const; // See note for non-const, above.
281 
282  const byte_t* headerBeginBytes() const {
283  return reinterpret_cast_checked<const byte_t*>(&* headerBegin());
284  }
285 
286 
287  void clear();
288  bool empty();
289  void reserve(std::size_t cap);
290  void swap(Fragment & other);
291  void swap(DATAVEC_T & other) { vals_.swap(other); };
292 
293  RawDataType * dataAddress();
294  RawDataType * metadataAddress(); // for internal use only
295  RawDataType * headerAddress();
296 
297  static std::unique_ptr<Fragment> eodFrag(size_t nFragsToExpect);
298 
299  // 12-Apr-2013, KAB - this method is deprecated, please do not use
300  template <class InputIterator>
301  static
302  Fragment
303  dataFrag(sequence_id_t sequenceID,
304  fragment_id_t fragID,
305  InputIterator i,
306  InputIterator e);
307 
308  static
309  Fragment
310  dataFrag(sequence_id_t sequenceID,
311  fragment_id_t fragID,
312  RawDataType const * dataPtr,
313  size_t dataSize,
314  timestamp_t timestamp = Fragment::InvalidTimestamp);
315 #endif
316 
317 private:
318  template <typename T> static std::size_t validatedMetadataSize_();
319  void updateFragmentHeaderWC_();
320 
321  DATAVEC_T vals_;
322 
323 #if HIDE_FROM_ROOT
324  detail::RawFragmentHeader * fragmentHeader();
325  detail::RawFragmentHeader const * fragmentHeader() const;
326 #endif
327 };
328 
329 #if HIDE_FROM_ROOT
330 
331 
332 // http://stackoverflow.com/questions/33939687
333 // This should generate an exception if artdaq::Fragment is not move-constructible
334 inline artdaq::Fragment::Fragment(artdaq::Fragment&&) noexcept = default;
335 inline artdaq::Fragment& artdaq::Fragment::operator=(artdaq::Fragment&&) noexcept = default;
336 
337 inline
338 bool
339 constexpr
340 artdaq::Fragment::
341 isUserFragmentType(type_t fragmentType)
342 {
343  return fragmentType >= detail::RawFragmentHeader::FIRST_USER_TYPE &&
344  fragmentType <= detail::RawFragmentHeader::LAST_USER_TYPE;
345 }
346 
347 inline
348 bool
349 constexpr
350 artdaq::Fragment::
351 isSystemFragmentType(type_t fragmentType)
352 {
353  return fragmentType >= detail::RawFragmentHeader::FIRST_SYSTEM_TYPE;
354 }
355 
356 template<typename T>
357 std::size_t
358 artdaq::Fragment::
359 validatedMetadataSize_()
360 {
361  // Make sure a size_t is big enough to hold the maximum metadata
362  // size. This *should* always be true, but it is a compile-time check
363  // and therefore cheap.
364  static_assert(sizeof(size_t) >=
365  sizeof(decltype(std::numeric_limits<detail::RawFragmentHeader::metadata_word_count_t>::max())),
366  "metadata_word_count_t is too big!");
367 
368  static size_t constexpr max_md_wc =
369  std::numeric_limits<detail::RawFragmentHeader::metadata_word_count_t>::max();
370  size_t requested_md_wc =
371  std::ceil(sizeof(T) / static_cast<double>(sizeof(artdaq::RawDataType)));
372  if (requested_md_wc > max_md_wc) {
373  throw cet::exception("InvalidRequest")
374  << "The requested metadata structure is too large: "
375  << "requested word count = " << requested_md_wc
376  << ", maximum word count = " << max_md_wc;
377  }
378  return requested_md_wc;
379 }
380 
381 template <class T>
382 artdaq::Fragment::
383 Fragment(std::size_t payload_size, sequence_id_t sequence_id,
384  fragment_id_t fragment_id,
385  type_t type, const T & metadata, timestamp_t timestamp) :
386  vals_((artdaq::detail::RawFragmentHeader::num_words() + // Header
387  validatedMetadataSize_<T>() + // Metadata
388  payload_size), // User data
389  0)
390 {
391  updateFragmentHeaderWC_();
392  fragmentHeader()->sequence_id = sequence_id;
393  fragmentHeader()->fragment_id = fragment_id;
394  fragmentHeader()->timestamp = timestamp;
395  fragmentHeader()->type = type;
396 
397  fragmentHeader()->metadata_word_count =
398  vals_.size() -
399  (artdaq::detail::RawFragmentHeader::num_words() + payload_size);
400 
401  memcpy(metadataAddress(), &metadata, sizeof(T));
402 }
403 
404 inline
405 std::size_t
406 artdaq::Fragment::size() const
407 {
408  return fragmentHeader()->word_count;
409 }
410 
411 inline
412 artdaq::Fragment::version_t
413 artdaq::Fragment::version() const
414 {
415  return fragmentHeader()->version;
416 }
417 
418 inline
419 artdaq::Fragment::type_t
420 artdaq::Fragment::type() const
421 {
422  return static_cast<type_t>(fragmentHeader()->type);
423 }
424 
425 inline
426 artdaq::Fragment::sequence_id_t
427 artdaq::Fragment::sequenceID() const
428 {
429  return fragmentHeader()->sequence_id;
430 }
431 
432 inline
433 artdaq::Fragment::fragment_id_t
434 artdaq::Fragment::fragmentID() const
435 {
436  return fragmentHeader()->fragment_id;
437 }
438 
439 inline
440 artdaq::Fragment::timestamp_t
441 artdaq::Fragment::timestamp() const
442 {
443  return fragmentHeader()->timestamp;
444 }
445 
446 inline
447 void
448 artdaq::Fragment::setVersion(version_t version)
449 {
450  fragmentHeader()->version = version;
451 }
452 
453 inline
454 void
455 artdaq::Fragment::setUserType(type_t type)
456 {
457  fragmentHeader()->setUserType(static_cast<uint8_t>(type));
458 }
459 
460 inline
461 void
462 artdaq::Fragment::setSystemType(type_t type)
463 {
464  fragmentHeader()->setSystemType(static_cast<uint8_t>(type));
465 }
466 
467 inline
468 void
469 artdaq::Fragment::setSequenceID(sequence_id_t sequence_id)
470 {
471  assert(sequence_id <= detail::RawFragmentHeader::InvalidSequenceID);
472  fragmentHeader()->sequence_id = sequence_id;
473 }
474 
475 inline
476 void
477 artdaq::Fragment::setFragmentID(fragment_id_t fragment_id)
478 {
479  fragmentHeader()->fragment_id = fragment_id;
480 }
481 
482 inline
483 void
484 artdaq::Fragment::setTimestamp(timestamp_t timestamp)
485 {
486  fragmentHeader()->timestamp = timestamp;
487 }
488 
489 inline
490 void
491 artdaq::Fragment::updateFragmentHeaderWC_()
492 {
493  // Make sure vals_.size() fits inside 32 bits. Left-shift here should
494  // match bitfield size of word_count in RawFragmentHeader.
495  assert(vals_.size() < (1ULL << 32));
496  fragmentHeader()->word_count = vals_.size();
497 }
498 
499 inline
500 std::size_t
501 artdaq::Fragment::dataSize() const
502 {
503  return vals_.size() - detail::RawFragmentHeader::num_words() -
504  fragmentHeader()->metadata_word_count;
505 }
506 
507 inline
508 bool
509 artdaq::Fragment::hasMetadata() const
510 {
511  return fragmentHeader()->metadata_word_count != 0;
512 }
513 
514 template <class T>
515 T *
516 artdaq::Fragment::metadata()
517 {
518  if (fragmentHeader()->metadata_word_count == 0) {
519  throw cet::exception("InvalidRequest")
520  << "No metadata has been stored in this Fragment.";
521  }
522 
523  return reinterpret_cast_checked<T *>
524  (&vals_[detail::RawFragmentHeader::num_words()]);
525 }
526 
527 template <class T>
528 T const *
529 artdaq::Fragment::metadata() const
530 {
531  if (fragmentHeader()->metadata_word_count == 0) {
532  throw cet::exception("InvalidRequest")
533  << "No metadata has been stored in this Fragment.";
534  }
535  return reinterpret_cast_checked<T const *>
536  (&vals_[detail::RawFragmentHeader::num_words()]);
537 }
538 
539 template <class T>
540 void
541 artdaq::Fragment::setMetadata(const T & metadata)
542 {
543  if (fragmentHeader()->metadata_word_count != 0) {
544  throw cet::exception("InvalidRequest")
545  << "Metadata has already been stored in this Fragment.";
546  }
547  auto const mdSize = validatedMetadataSize_<T>();
548  vals_.insert(dataBegin(), mdSize, 0);
549  updateFragmentHeaderWC_();
550  fragmentHeader()->metadata_word_count = mdSize;
551 
552  memcpy(metadataAddress(), &metadata, sizeof(T));
553 }
554 
555 template <class T>
556 void
557 artdaq::Fragment::updateMetadata(const T & metadata)
558 {
559  if (fragmentHeader()->metadata_word_count == 0) {
560  throw cet::exception("InvalidRequest")
561  << "No metadata in fragment; please use Fragment::setMetadata instead of Fragment::updateMetadata";
562  }
563 
564  auto const mdSize = validatedMetadataSize_<T>();
565 
566  if (fragmentHeader()->metadata_word_count != mdSize) {
567  throw cet::exception("InvalidRequest")
568  << "Mismatch between type of metadata struct passed to updateMetadata and existing metadata struct";
569  }
570 
571  memcpy(metadataAddress(), &metadata, sizeof(T));
572 }
573 
574 inline void
575 artdaq::Fragment::resize(std::size_t sz)
576 {
577  vals_.resize(sz + fragmentHeader()->metadata_word_count +
578  detail::RawFragmentHeader::num_words());
579  updateFragmentHeaderWC_();
580 }
581 inline
582 void
583 artdaq::Fragment::resize(std::size_t sz, RawDataType v)
584 {
585  vals_.resize(sz + fragmentHeader()->metadata_word_count +
586  detail::RawFragmentHeader::num_words(), v);
587  updateFragmentHeaderWC_();
588 }
589 
590 inline void
591 artdaq::Fragment::resizeBytes(std::size_t szbytes)
592 {
593  RawDataType nwords = ceil(szbytes / static_cast<double>(sizeof(RawDataType)));
594  resize(nwords);
595 }
596 inline
597 void
598 artdaq::Fragment::resizeBytes(std::size_t szbytes, byte_t v)
599 {
600  RawDataType defaultval;
601  byte_t* ptr = reinterpret_cast_checked<byte_t*>(&defaultval);
602 
603  for (uint8_t i = 0; i < sizeof(RawDataType); ++i) {
604  *ptr = v;
605  ptr++;
606  }
607 
608  RawDataType nwords = ceil(szbytes / static_cast<double>(sizeof(RawDataType)));
609 
610  resize(nwords, defaultval);
611 }
612 
613 
614 inline
615 void
616 artdaq::Fragment::autoResize()
617 {
618  vals_.resize(fragmentHeader()->word_count);
619  updateFragmentHeaderWC_();
620 }
621 
622 inline
623 artdaq::Fragment::iterator
624 artdaq::Fragment::dataBegin()
625 {
626  return vals_.begin() + detail::RawFragmentHeader::num_words() +
627  fragmentHeader()->metadata_word_count;
628 }
629 
630 inline
631 artdaq::Fragment::iterator
632 artdaq::Fragment::dataEnd()
633 {
634  return vals_.end();
635 }
636 
637 inline
638 artdaq::Fragment::iterator
639 artdaq::Fragment::headerBegin()
640 {
641  return vals_.begin();
642 }
643 
644 inline
645 artdaq::Fragment::const_iterator
646 artdaq::Fragment::dataBegin() const
647 {
648  return vals_.begin() + detail::RawFragmentHeader::num_words() +
649  fragmentHeader()->metadata_word_count;
650 }
651 
652 inline
653 artdaq::Fragment::const_iterator
654 artdaq::Fragment::dataEnd() const
655 {
656  return vals_.end();
657 }
658 
659 inline
660 artdaq::Fragment::const_iterator
661 artdaq::Fragment::headerBegin() const
662 {
663  return vals_.begin();
664 }
665 
666 
667 inline
668 void
669 artdaq::Fragment::clear()
670 {
671  vals_.erase(dataBegin(), dataEnd());
672  updateFragmentHeaderWC_();
673 }
674 
675 inline
676 bool
677 artdaq::Fragment::empty()
678 {
679  return (vals_.size() - detail::RawFragmentHeader::num_words() -
680  fragmentHeader()->metadata_word_count) == 0;
681 }
682 
683 inline
684 void
685 artdaq::Fragment::reserve(std::size_t cap)
686 {
687  vals_.reserve(cap + detail::RawFragmentHeader::num_words() +
688  fragmentHeader()->metadata_word_count);
689 }
690 
691 inline
692 void
693 artdaq::Fragment::swap(Fragment & other)
694 {
695  vals_.swap(other.vals_);
696 }
697 
698 inline
699 artdaq::RawDataType *
700 artdaq::Fragment::dataAddress()
701 {
702  return &vals_[0] + detail::RawFragmentHeader::num_words() +
703  fragmentHeader()->metadata_word_count;
704 }
705 
706 inline
707 artdaq::RawDataType *
708 artdaq::Fragment::metadataAddress()
709 {
710  if (fragmentHeader()->metadata_word_count == 0) {
711  throw cet::exception("InvalidRequest")
712  << "No metadata has been stored in this Fragment.";
713  }
714  return &vals_[0] + detail::RawFragmentHeader::num_words();
715 }
716 
717 inline
718 artdaq::RawDataType *
719 artdaq::Fragment::headerAddress()
720 {
721  return &vals_[0];
722 }
723 
724 // 12-Apr-2013, KAB - this method is deprecated, please do not use
725 template <class InputIterator>
727 artdaq::Fragment::
728 dataFrag(sequence_id_t sequenceID,
729  fragment_id_t fragID,
730  InputIterator i,
731  InputIterator e)
732 {
733  Fragment result(sequenceID, fragID);
734  result.vals_.reserve(std::distance(i, e) + detail::RawFragmentHeader::num_words());
735  std::copy(i, e, std::back_inserter(result.vals_));
736  return result;
737 }
738 
739 inline
741 artdaq::Fragment::fragmentHeader()
742 {
743  return reinterpret_cast_checked<detail::RawFragmentHeader *>(&vals_[0]);
744 }
745 
746 inline
748 artdaq::Fragment::fragmentHeader() const
749 {
750  return reinterpret_cast_checked<detail::RawFragmentHeader const *>(&vals_[0]);
751 }
752 
753 inline
754 void
755 swap(artdaq::Fragment & x, artdaq::Fragment & y)
756 {
757  x.swap(y);
758 }
759 
760 inline
761 std::ostream &
762 artdaq::operator<<(std::ostream & os, artdaq::Fragment const & f)
763 {
764  f.print(os);
765  return os;
766 }
767 #endif/* HIDE_FROM_ROOT */
768 
769 #endif /* artdaq_core_Data_Fragment_hh */
770