LSST Applications g04e9c324dd+8c5ae1fdc5,g134cb467dc+1b3060144d,g18429d2f64+f642bf4753,g199a45376c+0ba108daf9,g1fd858c14a+2dcf163641,g262e1987ae+7b8c96d2ca,g29ae962dfc+3bd6ecb08a,g2cef7863aa+aef1011c0b,g35bb328faa+8c5ae1fdc5,g3fd5ace14f+53e1a9e7c5,g4595892280+fef73a337f,g47891489e3+2efcf17695,g4d44eb3520+642b70b07e,g53246c7159+8c5ae1fdc5,g67b6fd64d1+2efcf17695,g67fd3c3899+b70e05ef52,g74acd417e5+317eb4c7d4,g786e29fd12+668abc6043,g87389fa792+8856018cbb,g89139ef638+2efcf17695,g8d7436a09f+3be3c13596,g8ea07a8fe4+9f5ccc88ac,g90f42f885a+a4e7b16d9b,g97be763408+ad77d7208f,g9dd6db0277+b70e05ef52,ga681d05dcb+a3f46e7fff,gabf8522325+735880ea63,gac2eed3f23+2efcf17695,gb89ab40317+2efcf17695,gbf99507273+8c5ae1fdc5,gd8ff7fe66e+b70e05ef52,gdab6d2f7ff+317eb4c7d4,gdc713202bf+b70e05ef52,gdfd2d52018+b10e285e0f,ge365c994fd+310e8507c4,ge410e46f29+2efcf17695,geaed405ab2+562b3308c0,gffca2db377+8c5ae1fdc5,w.2025.35
LSST Data Management Base Package
Loading...
Searching...
No Matches
BaseRecord.cc
Go to the documentation of this file.
1// -*- lsst-c++ -*-
2
3#include <iostream>
4
8
9namespace lsst {
10namespace afw {
11namespace table {
12
13namespace {
14
15// A Schema Functor used to set floating point-fields to NaN and initialize variable-length arrays
16// using placement new. All other fields are left alone, as they should already be zero.
17struct RecordInitializer {
18 template <typename T>
19 static void fill(T *element, std::size_t size) {} // this matches all non-floating-point-element fields.
20
21 static void fill(float *element, std::size_t size) {
22 std::fill(element, element + size, std::numeric_limits<float>::quiet_NaN());
23 }
24
25 static void fill(double *element, std::size_t size) {
26 std::fill(element, element + size, std::numeric_limits<double>::quiet_NaN());
27 }
28
29 static void fill(lsst::geom::Angle *element, std::size_t size) {
30 fill(reinterpret_cast<double *>(element), size);
31 }
32
33 template <typename T>
34 void operator()(SchemaItem<T> const &item) const {
35 fill(reinterpret_cast<typename Field<T>::Element *>(data + item.key.getOffset()),
36 item.key.getElementCount());
37 }
38
39 template <typename T>
40 void operator()(SchemaItem<Array<T> > const &item) const {
41 if (item.key.isVariableLength()) {
42 // Use placement new because the memory (for one ndarray) is already allocated
43 new (data + item.key.getOffset()) ndarray::Array<T, 1, 1>();
44 } else {
45 fill(reinterpret_cast<typename Field<T>::Element *>(data + item.key.getOffset()),
46 item.key.getElementCount());
47 }
48 }
49
50 void operator()(SchemaItem<std::string> const &item) const {
51 if (item.key.isVariableLength()) {
52 // Use placement new because the memory (for one std::string) is already allocated
53 new (reinterpret_cast<std::string *>(data + item.key.getOffset())) std::string();
54 } else {
55 fill(reinterpret_cast<char *>(data + item.key.getOffset()), item.key.getElementCount());
56 }
57 }
58
59 void operator()(SchemaItem<Flag> const &item) const {} // do nothing for Flag fields; already 0
60
61 char *data;
62};
63
64// A Schema::forEach and SchemaMapper::forEach functor that copies data from one record to another.
65struct CopyValue {
66 template <typename U>
67 void operator()(Key<U> const& inputKey, Key<U> const& outputKey) const {
68 typename Field<U>::Element const* inputElem = _inputRecord->getElement(inputKey);
69 std::copy(inputElem, inputElem + inputKey.getElementCount(), _outputRecord->getElement(outputKey));
70 }
71
72 template <typename U>
73 void operator()(Key<Array<U> > const& inputKey, Key<Array<U> > const& outputKey) const {
74 if (inputKey.isVariableLength() != outputKey.isVariableLength()) {
75 throw LSST_EXCEPT(lsst::pex::exceptions::InvalidParameterError,
76 "At least one input array field is variable-length"
77 " and the correponding output is not, or vice-versa");
78 }
79 if (inputKey.isVariableLength()) {
80 ndarray::Array<U, 1, 1> value = ndarray::copy(_inputRecord->get(inputKey));
81 _outputRecord->set(outputKey, value);
82 return;
83 }
84 typename Field<U>::Element const* inputElem = _inputRecord->getElement(inputKey);
85 std::copy(inputElem, inputElem + inputKey.getElementCount(), _outputRecord->getElement(outputKey));
86 }
87
88 void operator()(Key<std::string> const& inputKey, Key<std::string> const& outputKey) const {
89 if (inputKey.isVariableLength() != outputKey.isVariableLength()) {
90 throw LSST_EXCEPT(lsst::pex::exceptions::InvalidParameterError,
91 "At least one input string field is variable-length "
92 "and the correponding output is not, or vice-versa");
93 }
94 if (inputKey.isVariableLength()) {
95 std::string value = _inputRecord->get(inputKey);
96 _outputRecord->set(outputKey, value);
97 return;
98 }
99 char const* inputElem = _inputRecord->getElement(inputKey);
100 std::copy(inputElem, inputElem + inputKey.getElementCount(), _outputRecord->getElement(outputKey));
101 }
102
103 void operator()(Key<Flag> const& inputKey, Key<Flag> const& outputKey) const {
104 _outputRecord->set(outputKey, _inputRecord->get(inputKey));
105 }
106
107 template <typename U>
108 void operator()(SchemaItem<U> const& item) const {
109 (*this)(item.key, item.key);
110 }
111
112 CopyValue(BaseRecord const* inputRecord, BaseRecord* outputRecord)
113 : _inputRecord(inputRecord), _outputRecord(outputRecord) {}
114
115private:
116 BaseRecord const* _inputRecord;
117 BaseRecord* _outputRecord;
118};
119
120} // namespace
121
122void BaseRecord::assign(BaseRecord const& other) {
123 if (this->getSchema() != other.getSchema()) {
124 throw LSST_EXCEPT(lsst::pex::exceptions::LogicError, "Unequal schemas in record assignment.");
125 }
126 this->getSchema().forEach(CopyValue(&other, this));
127 this->_assign(other); // let derived classes assign their own stuff
128}
129
130void BaseRecord::assign(BaseRecord const& other, SchemaMapper const& mapper) {
131 if (!other.getSchema().contains(mapper.getInputSchema())) {
133 "Unequal schemas between input record and mapper.");
134 }
135 if (!this->getSchema().contains(mapper.getOutputSchema())) {
137 "Unequal schemas between output record and mapper.");
138 }
139 mapper.forEach(CopyValue(&other, this)); // use the functor we defined above
140 this->_assign(other); // let derived classes assign their own stuff
141}
142
144 _data(std::move(data.data)),
145 _table(std::move(data.table)),
146 _manager(std::move(data.manager))
147{
148 RecordInitializer f = {reinterpret_cast<char *>(_data)};
149 _table->getSchema().forEach(f);
150}
151
153 getSchema().forEach([&os, this](auto const& item) {
154 os << item.field.getName() << ": " << this->get(item.key) << std::endl;
155 });
156}
157
159 record._stream(os);
160 return os;
161}
162
163} // namespace table
164} // namespace afw
165} // namespace lsst
#define LSST_EXCEPT(type,...)
Create an exception with a given type.
Definition Exception.h:48
Field< T >::Value get(Key< T > const &key) const
Return the value of a field for the given key.
Definition BaseRecord.h:151
void assign(BaseRecord const &other)
Copy all field values from other to this, requiring that they have equal schemas.
Schema getSchema() const
Return the Schema that holds this record's fields and keys.
Definition BaseRecord.h:80
BaseRecord(ConstructionToken const &, detail::RecordData &&data)
Construct a record with uninitialized data.
virtual void _assign(BaseRecord const &other)
Called by assign() after transferring fields to allow subclass data members to be copied.
Definition BaseRecord.h:209
virtual void _stream(std::ostream &os) const
Called by operator<<.
void forEach(F &func) const
Apply a functor to each SchemaItem in the Schema.
Definition Schema.h:214
int contains(Schema const &other, int flags=EQUAL_KEYS) const
Test whether the given schema is a subset of this.
Definition Schema.cc:490
A mapping between the keys of two Schemas, used to copy data between them.
Schema const getOutputSchema() const
Return the output schema (copy-on-write).
void forEach(F &func) const
Call the given functor for each key pair in the mapper.
Schema const getInputSchema() const
Return the input schema (copy-on-write).
Reports errors in the logical structure of the program.
Definition Runtime.h:46
T copy(T... args)
T endl(T... args)
T fill(T... args)
std::ostream & operator<<(std::ostream &os, BaseRecord const &record)
STL namespace.
decltype(sizeof(void *)) size_t
Definition doctest.h:524
T quiet_NaN(T... args)
typename FieldBase< T >::Element Element
Type used to store field data in the table (a field may have multiple elements).
Definition Field.h:26
Helper struct that contains the information passed from BaseTable to BaseRecord at construction.
Definition BaseTable.h:32