artdaq_core  v1_05_07
 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 QUICKVEC_T QuickVec<RawDataType>
21 # define DO_STDVEC 0
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 #if DO_STDVEC == 1
87  typedef std::vector<RawDataType>::reference reference;
88  typedef std::vector<RawDataType>::iterator iterator;
89  typedef std::vector<RawDataType>::const_iterator const_iterator;
90  typedef std::vector<RawDataType>::value_type value_type;
91  typedef std::vector<RawDataType>::difference_type difference_type;
92  typedef std::vector<RawDataType>::size_type size_type;
93 #else
94  typedef QUICKVEC_T::reference reference;
95  typedef QUICKVEC_T::iterator iterator;
96  typedef QUICKVEC_T::const_iterator const_iterator;
97  typedef QUICKVEC_T::value_type value_type;
98  typedef QUICKVEC_T::difference_type difference_type;
99  typedef QUICKVEC_T::size_type size_type;
100 #endif
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 
292  RawDataType * dataAddress();
293  RawDataType * metadataAddress(); // for internal use only
294  RawDataType * headerAddress();
295 
296  static std::unique_ptr<Fragment> eodFrag(size_t nFragsToExpect);
297 
298  // 12-Apr-2013, KAB - this method is deprecated, please do not use
299  template <class InputIterator>
300  static
301  Fragment
302  dataFrag(sequence_id_t sequenceID,
303  fragment_id_t fragID,
304  InputIterator i,
305  InputIterator e);
306 
307  static
308  Fragment
309  dataFrag(sequence_id_t sequenceID,
310  fragment_id_t fragID,
311  RawDataType const * dataPtr,
312  size_t dataSize,
313  timestamp_t timestamp = Fragment::InvalidTimestamp);
314 #endif
315 
316 private:
317  template <typename T> static std::size_t validatedMetadataSize_();
318  void updateFragmentHeaderWC_();
319 #if DO_STDVEC == 1
320  std::vector<RawDataType> vals_;
321 #else
322  QUICKVEC_T vals_;
323 #endif
324 
325 #if HIDE_FROM_ROOT
326  detail::RawFragmentHeader * fragmentHeader();
327  detail::RawFragmentHeader const * fragmentHeader() const;
328 #endif
329 };
330 
331 #if HIDE_FROM_ROOT
332 inline
333 bool
334 constexpr
335 artdaq::Fragment::
336 isUserFragmentType(type_t fragmentType)
337 {
338  return fragmentType >= detail::RawFragmentHeader::FIRST_USER_TYPE &&
339  fragmentType <= detail::RawFragmentHeader::LAST_USER_TYPE;
340 }
341 
342 inline
343 bool
344 constexpr
345 artdaq::Fragment::
346 isSystemFragmentType(type_t fragmentType)
347 {
348  return fragmentType >= detail::RawFragmentHeader::FIRST_SYSTEM_TYPE;
349 }
350 
351 template<typename T>
352 std::size_t
353 artdaq::Fragment::
354 validatedMetadataSize_()
355 {
356  // Make sure a size_t is big enough to hold the maximum metadata
357  // size. This *should* always be true, but it is a compile-time check
358  // and therefore cheap.
359  static_assert(sizeof(size_t) >=
360  sizeof(decltype(std::numeric_limits<detail::RawFragmentHeader::metadata_word_count_t>::max())),
361  "metadata_word_count_t is too big!");
362 
363  static size_t constexpr max_md_wc =
364  std::numeric_limits<detail::RawFragmentHeader::metadata_word_count_t>::max();
365  size_t requested_md_wc =
366  std::ceil(sizeof(T) / static_cast<double>(sizeof(artdaq::RawDataType)));
367  if (requested_md_wc > max_md_wc) {
368  throw cet::exception("InvalidRequest")
369  << "The requested metadata structure is too large: "
370  << "requested word count = " << requested_md_wc
371  << ", maximum word count = " << max_md_wc;
372  }
373  return requested_md_wc;
374 }
375 
376 template <class T>
377 artdaq::Fragment::
378 Fragment(std::size_t payload_size, sequence_id_t sequence_id,
379  fragment_id_t fragment_id,
380  type_t type, const T & metadata, timestamp_t timestamp) :
381  vals_((artdaq::detail::RawFragmentHeader::num_words() + // Header
382  validatedMetadataSize_<T>() + // Metadata
383  payload_size), // User data
384  0)
385 {
386  updateFragmentHeaderWC_();
387  fragmentHeader()->sequence_id = sequence_id;
388  fragmentHeader()->fragment_id = fragment_id;
389  fragmentHeader()->timestamp = timestamp;
390  fragmentHeader()->type = type;
391 
392  fragmentHeader()->metadata_word_count =
393  vals_.size() -
394  (artdaq::detail::RawFragmentHeader::num_words() + payload_size);
395 
396  memcpy(metadataAddress(), &metadata, sizeof(T));
397 }
398 
399 inline
400 std::size_t
401 artdaq::Fragment::size() const
402 {
403  return fragmentHeader()->word_count;
404 }
405 
406 inline
407 artdaq::Fragment::version_t
408 artdaq::Fragment::version() const
409 {
410  return fragmentHeader()->version;
411 }
412 
413 inline
414 artdaq::Fragment::type_t
415 artdaq::Fragment::type() const
416 {
417  return static_cast<type_t>(fragmentHeader()->type);
418 }
419 
420 inline
421 artdaq::Fragment::sequence_id_t
422 artdaq::Fragment::sequenceID() const
423 {
424  return fragmentHeader()->sequence_id;
425 }
426 
427 inline
428 artdaq::Fragment::fragment_id_t
429 artdaq::Fragment::fragmentID() const
430 {
431  return fragmentHeader()->fragment_id;
432 }
433 
434 inline
435 artdaq::Fragment::timestamp_t
436 artdaq::Fragment::timestamp() const
437 {
438  return fragmentHeader()->timestamp;
439 }
440 
441 inline
442 void
443 artdaq::Fragment::setVersion(version_t version)
444 {
445  fragmentHeader()->version = version;
446 }
447 
448 inline
449 void
450 artdaq::Fragment::setUserType(type_t type)
451 {
452  fragmentHeader()->setUserType(static_cast<uint8_t>(type));
453 }
454 
455 inline
456 void
457 artdaq::Fragment::setSystemType(type_t type)
458 {
459  fragmentHeader()->setSystemType(static_cast<uint8_t>(type));
460 }
461 
462 inline
463 void
464 artdaq::Fragment::setSequenceID(sequence_id_t sequence_id)
465 {
466  assert(sequence_id <= detail::RawFragmentHeader::InvalidSequenceID);
467  fragmentHeader()->sequence_id = sequence_id;
468 }
469 
470 inline
471 void
472 artdaq::Fragment::setFragmentID(fragment_id_t fragment_id)
473 {
474  fragmentHeader()->fragment_id = fragment_id;
475 }
476 
477 inline
478 void
479 artdaq::Fragment::setTimestamp(timestamp_t timestamp)
480 {
481  fragmentHeader()->timestamp = timestamp;
482 }
483 
484 inline
485 void
486 artdaq::Fragment::updateFragmentHeaderWC_()
487 {
488  // Make sure vals_.size() fits inside 32 bits. Left-shift here should
489  // match bitfield size of word_count in RawFragmentHeader.
490  assert(vals_.size() < (1ULL << 32));
491  fragmentHeader()->word_count = vals_.size();
492 }
493 
494 inline
495 std::size_t
496 artdaq::Fragment::dataSize() const
497 {
498  return vals_.size() - detail::RawFragmentHeader::num_words() -
499  fragmentHeader()->metadata_word_count;
500 }
501 
502 inline
503 bool
504 artdaq::Fragment::hasMetadata() const
505 {
506  return fragmentHeader()->metadata_word_count != 0;
507 }
508 
509 template <class T>
510 T *
511 artdaq::Fragment::metadata()
512 {
513  if (fragmentHeader()->metadata_word_count == 0) {
514  throw cet::exception("InvalidRequest")
515  << "No metadata has been stored in this Fragment.";
516  }
517 
518  return reinterpret_cast_checked<T *>
519  (&vals_[detail::RawFragmentHeader::num_words()]);
520 }
521 
522 template <class T>
523 T const *
524 artdaq::Fragment::metadata() const
525 {
526  if (fragmentHeader()->metadata_word_count == 0) {
527  throw cet::exception("InvalidRequest")
528  << "No metadata has been stored in this Fragment.";
529  }
530  return reinterpret_cast_checked<T const *>
531  (&vals_[detail::RawFragmentHeader::num_words()]);
532 }
533 
534 template <class T>
535 void
536 artdaq::Fragment::setMetadata(const T & metadata)
537 {
538  if (fragmentHeader()->metadata_word_count != 0) {
539  throw cet::exception("InvalidRequest")
540  << "Metadata has already been stored in this Fragment.";
541  }
542  auto const mdSize = validatedMetadataSize_<T>();
543  vals_.insert(dataBegin(), mdSize, 0);
544  updateFragmentHeaderWC_();
545  fragmentHeader()->metadata_word_count = mdSize;
546 
547  memcpy(metadataAddress(), &metadata, sizeof(T));
548 }
549 
550 template <class T>
551 void
552 artdaq::Fragment::updateMetadata(const T & metadata)
553 {
554  if (fragmentHeader()->metadata_word_count == 0) {
555  throw cet::exception("InvalidRequest")
556  << "No metadata in fragment; please use Fragment::setMetadata instead of Fragment::updateMetadata";
557  }
558 
559  auto const mdSize = validatedMetadataSize_<T>();
560 
561  if (fragmentHeader()->metadata_word_count != mdSize) {
562  throw cet::exception("InvalidRequest")
563  << "Mismatch between type of metadata struct passed to updateMetadata and existing metadata struct";
564  }
565 
566  memcpy(metadataAddress(), &metadata, sizeof(T));
567 }
568 
569 inline void
570 artdaq::Fragment::resize(std::size_t sz)
571 {
572  vals_.resize(sz + fragmentHeader()->metadata_word_count +
573  detail::RawFragmentHeader::num_words());
574  updateFragmentHeaderWC_();
575 }
576 inline
577 void
578 artdaq::Fragment::resize(std::size_t sz, RawDataType v)
579 {
580  vals_.resize(sz + fragmentHeader()->metadata_word_count +
581  detail::RawFragmentHeader::num_words(), v);
582  updateFragmentHeaderWC_();
583 }
584 
585 inline void
586 artdaq::Fragment::resizeBytes(std::size_t szbytes)
587 {
588  RawDataType nwords = ceil(szbytes / static_cast<double>(sizeof(RawDataType)));
589  resize(nwords);
590 }
591 inline
592 void
593 artdaq::Fragment::resizeBytes(std::size_t szbytes, byte_t v)
594 {
595  RawDataType defaultval;
596  byte_t* ptr = reinterpret_cast_checked<byte_t*>(&defaultval);
597 
598  for (uint8_t i = 0; i < sizeof(RawDataType); ++i) {
599  *ptr = v;
600  ptr++;
601  }
602 
603  RawDataType nwords = ceil(szbytes / static_cast<double>(sizeof(RawDataType)));
604 
605  resize(nwords, defaultval);
606 }
607 
608 
609 inline
610 void
611 artdaq::Fragment::autoResize()
612 {
613  vals_.resize(fragmentHeader()->word_count);
614  updateFragmentHeaderWC_();
615 }
616 
617 inline
618 artdaq::Fragment::iterator
619 artdaq::Fragment::dataBegin()
620 {
621  return vals_.begin() + detail::RawFragmentHeader::num_words() +
622  fragmentHeader()->metadata_word_count;
623 }
624 
625 inline
626 artdaq::Fragment::iterator
627 artdaq::Fragment::dataEnd()
628 {
629  return vals_.end();
630 }
631 
632 inline
633 artdaq::Fragment::iterator
634 artdaq::Fragment::headerBegin()
635 {
636  return vals_.begin();
637 }
638 
639 inline
640 artdaq::Fragment::const_iterator
641 artdaq::Fragment::dataBegin() const
642 {
643  return vals_.begin() + detail::RawFragmentHeader::num_words() +
644  fragmentHeader()->metadata_word_count;
645 }
646 
647 inline
648 artdaq::Fragment::const_iterator
649 artdaq::Fragment::dataEnd() const
650 {
651  return vals_.end();
652 }
653 
654 inline
655 artdaq::Fragment::const_iterator
656 artdaq::Fragment::headerBegin() const
657 {
658  return vals_.begin();
659 }
660 
661 
662 inline
663 void
664 artdaq::Fragment::clear()
665 {
666  vals_.erase(dataBegin(), dataEnd());
667  updateFragmentHeaderWC_();
668 }
669 
670 inline
671 bool
672 artdaq::Fragment::empty()
673 {
674  return (vals_.size() - detail::RawFragmentHeader::num_words() -
675  fragmentHeader()->metadata_word_count) == 0;
676 }
677 
678 inline
679 void
680 artdaq::Fragment::reserve(std::size_t cap)
681 {
682  vals_.reserve(cap + detail::RawFragmentHeader::num_words() +
683  fragmentHeader()->metadata_word_count);
684 }
685 
686 inline
687 void
688 artdaq::Fragment::swap(Fragment & other)
689 {
690  vals_.swap(other.vals_);
691 }
692 
693 inline
694 artdaq::RawDataType *
695 artdaq::Fragment::dataAddress()
696 {
697  return &vals_[0] + detail::RawFragmentHeader::num_words() +
698  fragmentHeader()->metadata_word_count;
699 }
700 
701 inline
702 artdaq::RawDataType *
703 artdaq::Fragment::metadataAddress()
704 {
705  if (fragmentHeader()->metadata_word_count == 0) {
706  throw cet::exception("InvalidRequest")
707  << "No metadata has been stored in this Fragment.";
708  }
709  return &vals_[0] + detail::RawFragmentHeader::num_words();
710 }
711 
712 inline
713 artdaq::RawDataType *
714 artdaq::Fragment::headerAddress()
715 {
716  return &vals_[0];
717 }
718 
719 // 12-Apr-2013, KAB - this method is deprecated, please do not use
720 template <class InputIterator>
722 artdaq::Fragment::
723 dataFrag(sequence_id_t sequenceID,
724  fragment_id_t fragID,
725  InputIterator i,
726  InputIterator e)
727 {
728  Fragment result(sequenceID, fragID);
729  result.vals_.reserve(std::distance(i, e) + detail::RawFragmentHeader::num_words());
730  std::copy(i, e, std::back_inserter(result.vals_));
731  return result;
732 }
733 
734 inline
736 artdaq::Fragment::fragmentHeader()
737 {
738  return reinterpret_cast_checked<detail::RawFragmentHeader *>(&vals_[0]);
739 }
740 
741 inline
743 artdaq::Fragment::fragmentHeader() const
744 {
745  return reinterpret_cast_checked<detail::RawFragmentHeader const *>(&vals_[0]);
746 }
747 
748 inline
749 void
750 swap(artdaq::Fragment & x, artdaq::Fragment & y)
751 {
752  x.swap(y);
753 }
754 
755 inline
756 std::ostream &
757 artdaq::operator<<(std::ostream & os, artdaq::Fragment const & f)
758 {
759  f.print(os);
760  return os;
761 }
762 #endif/* HIDE_FROM_ROOT */
763 
764 #endif /* artdaq_core_Data_Fragment_hh */
765