LSSTApplications  19.0.0-14-gb0260a2+72efe9b372,20.0.0+7927753e06,20.0.0+8829bf0056,20.0.0+995114c5d2,20.0.0+b6f4b2abd1,20.0.0+bddc4f4cbe,20.0.0-1-g253301a+8829bf0056,20.0.0-1-g2b7511a+0d71a2d77f,20.0.0-1-g5b95a8c+7461dd0434,20.0.0-12-g321c96ea+23efe4bbff,20.0.0-16-gfab17e72e+fdf35455f6,20.0.0-2-g0070d88+ba3ffc8f0b,20.0.0-2-g4dae9ad+ee58a624b3,20.0.0-2-g61b8584+5d3db074ba,20.0.0-2-gb780d76+d529cf1a41,20.0.0-2-ged6426c+226a441f5f,20.0.0-2-gf072044+8829bf0056,20.0.0-2-gf1f7952+ee58a624b3,20.0.0-20-geae50cf+e37fec0aee,20.0.0-25-g3dcad98+544a109665,20.0.0-25-g5eafb0f+ee58a624b3,20.0.0-27-g64178ef+f1f297b00a,20.0.0-3-g4cc78c6+e0676b0dc8,20.0.0-3-g8f21e14+4fd2c12c9a,20.0.0-3-gbd60e8c+187b78b4b8,20.0.0-3-gbecbe05+48431fa087,20.0.0-38-ge4adf513+a12e1f8e37,20.0.0-4-g97dc21a+544a109665,20.0.0-4-gb4befbc+087873070b,20.0.0-4-gf910f65+5d3db074ba,20.0.0-5-gdfe0fee+199202a608,20.0.0-5-gfbfe500+d529cf1a41,20.0.0-6-g64f541c+d529cf1a41,20.0.0-6-g9a5b7a1+a1cd37312e,20.0.0-68-ga3f3dda+5fca18c6a4,20.0.0-9-g4aef684+e18322736b,w.2020.45
LSSTDataManagementBasePackage
BaseRecord.cc
Go to the documentation of this file.
1 // -*- lsst-c++ -*-
2 
3 #include <cstring>
4 #include <iostream>
5 
6 #include "lsst/pex/exceptions.h"
9 
10 namespace lsst {
11 namespace afw {
12 namespace table {
13 
14 namespace {
15 
16 // A Schema Functor used to set floating point-fields to NaN and initialize variable-length arrays
17 // using placement new. All other fields are left alone, as they should already be zero.
18 struct RecordInitializer {
19  template <typename T>
20  static void fill(T *element, int size) {} // this matches all non-floating-point-element fields.
21 
22  static void fill(float *element, int size) {
24  }
25 
26  static void fill(double *element, int size) {
28  }
29 
30  static void fill(lsst::geom::Angle *element, int size) {
31  fill(reinterpret_cast<double *>(element), size);
32  }
33 
34  template <typename T>
35  void operator()(SchemaItem<T> const &item) const {
36  fill(reinterpret_cast<typename Field<T>::Element *>(data + item.key.getOffset()),
37  item.key.getElementCount());
38  }
39 
40  template <typename T>
41  void operator()(SchemaItem<Array<T> > const &item) const {
42  if (item.key.isVariableLength()) {
43  // Use placement new because the memory (for one ndarray) is already allocated
44  new (data + item.key.getOffset()) ndarray::Array<T, 1, 1>();
45  } else {
46  fill(reinterpret_cast<typename Field<T>::Element *>(data + item.key.getOffset()),
47  item.key.getElementCount());
48  }
49  }
50 
51  void operator()(SchemaItem<std::string> const &item) const {
52  if (item.key.isVariableLength()) {
53  // Use placement new because the memory (for one std::string) is already allocated
54  new (reinterpret_cast<std::string *>(data + item.key.getOffset())) std::string();
55  } else {
56  fill(reinterpret_cast<char *>(data + item.key.getOffset()), item.key.getElementCount());
57  }
58  }
59 
60  void operator()(SchemaItem<Flag> const &item) const {} // do nothing for Flag fields; already 0
61 
62  char *data;
63 };
64 
65 // A Schema::forEach and SchemaMapper::forEach functor that copies data from one record to another.
66 struct CopyValue {
67  template <typename U>
68  void operator()(Key<U> const& inputKey, Key<U> const& outputKey) const {
69  typename Field<U>::Element const* inputElem = _inputRecord->getElement(inputKey);
70  std::copy(inputElem, inputElem + inputKey.getElementCount(), _outputRecord->getElement(outputKey));
71  }
72 
73  template <typename U>
74  void operator()(Key<Array<U> > const& inputKey, Key<Array<U> > const& outputKey) const {
75  if (inputKey.isVariableLength() != outputKey.isVariableLength()) {
77  "At least one input array field is variable-length"
78  " and the correponding output is not, or vice-versa");
79  }
80  if (inputKey.isVariableLength()) {
81  ndarray::Array<U, 1, 1> value = ndarray::copy(_inputRecord->get(inputKey));
82  _outputRecord->set(outputKey, value);
83  return;
84  }
85  typename Field<U>::Element const* inputElem = _inputRecord->getElement(inputKey);
86  std::copy(inputElem, inputElem + inputKey.getElementCount(), _outputRecord->getElement(outputKey));
87  }
88 
89  void operator()(Key<std::string> const& inputKey, Key<std::string> const& outputKey) const {
90  if (inputKey.isVariableLength() != outputKey.isVariableLength()) {
92  "At least one input string field is variable-length "
93  "and the correponding output is not, or vice-versa");
94  }
95  if (inputKey.isVariableLength()) {
96  std::string value = _inputRecord->get(inputKey);
97  _outputRecord->set(outputKey, value);
98  return;
99  }
100  char const* inputElem = _inputRecord->getElement(inputKey);
101  std::copy(inputElem, inputElem + inputKey.getElementCount(), _outputRecord->getElement(outputKey));
102  }
103 
104  void operator()(Key<Flag> const& inputKey, Key<Flag> const& outputKey) const {
105  _outputRecord->set(outputKey, _inputRecord->get(inputKey));
106  }
107 
108  template <typename U>
109  void operator()(SchemaItem<U> const& item) const {
110  (*this)(item.key, item.key);
111  }
112 
113  CopyValue(BaseRecord const* inputRecord, BaseRecord* outputRecord)
114  : _inputRecord(inputRecord), _outputRecord(outputRecord) {}
115 
116 private:
117  BaseRecord const* _inputRecord;
118  BaseRecord* _outputRecord;
119 };
120 
121 } // namespace
122 
124  if (this->getSchema() != other.getSchema()) {
125  throw LSST_EXCEPT(lsst::pex::exceptions::LogicError, "Unequal schemas in record assignment.");
126  }
127  this->getSchema().forEach(CopyValue(&other, this));
128  this->_assign(other); // let derived classes assign their own stuff
129 }
130 
132  if (!other.getSchema().contains(mapper.getInputSchema())) {
134  "Unequal schemas between input record and mapper.");
135  }
136  if (!this->getSchema().contains(mapper.getOutputSchema())) {
138  "Unequal schemas between output record and mapper.");
139  }
140  mapper.forEach(CopyValue(&other, this)); // use the functor we defined above
141  this->_assign(other); // let derived classes assign their own stuff
142 }
143 
145  _data(std::move(data.data)),
146  _table(std::move(data.table)),
147  _manager(std::move(data.manager))
148 {
149  RecordInitializer f = {reinterpret_cast<char *>(_data)};
150  _table->getSchema().forEach(f);
151 }
152 
154  getSchema().forEach([&os, this](auto const& item) {
155  os << item.field.getName() << ": " << this->get(item.key) << std::endl;
156  });
157 }
158 
160  record._stream(os);
161  return os;
162 }
163 
164 } // namespace table
165 } // namespace afw
166 } // namespace lsst
SchemaMapper.h
std::string
STL class.
lsst::afw::table::BaseRecord::get
Field< T >::Value get(Key< T > const &key) const
Return the value of a field for the given key.
Definition: BaseRecord.h:151
lsst::afw
Definition: imageAlgorithm.dox:1
lsst::afw::table::BaseRecord::_stream
virtual void _stream(std::ostream &os) const
Called by operator<<.
Definition: BaseRecord.cc:153
lsst::afw::table::detail::RecordData
Helper struct that contains the information passed from BaseTable to BaseRecord at construction.
Definition: BaseTable.h:32
lsst::afw::table::Schema::forEach
void forEach(F &&func) const
Apply a functor to each SchemaItem in the Schema.
Definition: Schema.h:212
std::fill
T fill(T... args)
BaseRecord.h
data
char * data
Definition: BaseRecord.cc:62
lsst::afw::table::BaseRecord::_assign
virtual void _assign(BaseRecord const &other)
Called by assign() after transferring fields to allow subclass data members to be copied.
Definition: BaseRecord.h:209
lsst::afw::table::BaseRecord::BaseRecord
BaseRecord(ConstructionToken const &, detail::RecordData &&data)
Construct a record with uninitialized data.
Definition: BaseRecord.cc:144
std::ostream
STL class.
astshim.fitsChanContinued.contains
def contains(self, name)
Definition: fitsChanContinued.py:127
other
ItemVariant const * other
Definition: Schema.cc:56
lsst::afw::table::BaseRecord
Base class for all records.
Definition: BaseRecord.h:31
lsst.pex::exceptions::LogicError
Reports errors in the logical structure of the program.
Definition: Runtime.h:46
lsst::afw::table::SchemaMapper
A mapping between the keys of two Schemas, used to copy data between them.
Definition: SchemaMapper.h:21
std::copy
T copy(T... args)
lsst
A base class for image defects.
Definition: imageAlgorithm.dox:1
LSST_EXCEPT
#define LSST_EXCEPT(type,...)
Create an exception with a given type.
Definition: Exception.h:48
lsst::afw::table::BaseRecord::ConstructionToken
Definition: BaseRecord.h:38
os
std::ostream * os
Definition: Schema.cc:746
std::endl
T endl(T... args)
lsst.pex::exceptions::InvalidParameterError
Reports invalid arguments.
Definition: Runtime.h:66
std
STL namespace.
lsst::afw::table::BaseRecord::assign
void assign(BaseRecord const &other)
Copy all field values from other to this, requiring that they have equal schemas.
Definition: BaseRecord.cc:123
lsst::afw::table::operator<<
std::ostream & operator<<(std::ostream &os, BaseRecord const &record)
Definition: BaseRecord.cc:159
lsst::geom::Angle
A class representing an angle.
Definition: Angle.h:127
lsst::afw::table::SchemaMapper::getOutputSchema
Schema const getOutputSchema() const
Return the output schema (copy-on-write).
Definition: SchemaMapper.h:27
mapper
SchemaMapper * mapper
Definition: SchemaMapper.cc:78
lsst::afw::table::BaseRecord::getSchema
Schema getSchema() const
Return the Schema that holds this record's fields and keys.
Definition: BaseRecord.h:80
lsst::afw::table::Field::Element
FieldBase< T >::Element Element
Type used to store field data in the table (a field may have multiple elements).
Definition: Field.h:26
element
double element[2]
Definition: BaseTable.cc:91
std::numeric_limits
exceptions.h