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