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