LSST Applications g04c3c9f7ca+2075667efa,g1e125bf412+5f448d5fcf,g2079a07aa2+3e9fd84d81,g2305ad1205+b635cf1488,g2bbee38e9b+6c6beb4891,g337abbeb29+6c6beb4891,g33d1c0ed96+6c6beb4891,g3a166c0a6a+6c6beb4891,g50ff169b8f+96c6868917,g52b1c1532d+585e252eca,g591dd9f2cf+42f171e1e6,g5c3423f6d4+d536b04327,g607f77f49a+d536b04327,g6f43f06aed+ca1339dc19,g858d7b2824+d536b04327,g8ee334c5b4+d7f9608c2f,g9963eaa53e+b3dc1655d3,g998f4353bf+d536b04327,g99cad8db69+8ef2408349,g9ddcbc5298+9a081db1e4,ga1e77700b3+2cbb763275,gadfd92a7e4+aec2f3b930,gae0086650b+585e252eca,gb0e22166c9+0e73c8378f,gb3b7280ab2+cb5fdb229e,gbb8dafda3b+a327199e22,gc120e1dc64+88074880ea,gc28159a63d+6c6beb4891,gcdd4ae20e8+bd241b2308,gcde1bda545+903e937d91,gcf0d15dbbd+bd241b2308,gdaeeff99f8+f9a426f77a,gddc38dedce+585e252eca,ge79ae78c31+6c6beb4891,gfbcc870c63+b310236976,w.2024.23
LSST Data Management Base Package
Loading...
Searching...
No Matches
Public Types | Public Member Functions | Static Public Attributes | Friends | List of all members
lsst::afw::table::detail::SchemaImpl Class Reference

A private implementation class to hide the messy details of Schema. More...

#include <SchemaImpl.h>

Public Types

using ItemVariant = decltype(makeItemVariantType(FieldTypes{}))
 A Boost.Variant type that can hold any one of the allowed SchemaItem types.
 
using ItemContainer = std::vector<ItemVariant>
 A std::vector whose elements can be any of the allowed SchemaItem types.
 
using NameMap = std::map<std::string, std::size_t>
 A map from field names to position in the vector, so we can do name lookups.
 
using OffsetMap = std::map<std::size_t, std::size_t>
 A map from standard field offsets to position in the vector, so we can do field lookups.
 
using FlagMap = std::map<std::pair<std::size_t, std::size_t>, std::size_t>
 A map from Flag field offset/bit pairs to position in the vector, so we can do Flag field lookups.
 

Public Member Functions

std::size_t getRecordSize () const
 The size of a record in bytes.
 
std::size_t getFieldCount () const
 The total number of fields.
 
std::size_t getFlagFieldCount () const
 The number of Flag fields.
 
std::size_t getNonFlagFieldCount () const
 The number of non-Flag fields.
 
template<typename T >
SchemaItem< T > find (std::string const &name) const
 Find an item by name (used to implement Schema::find).
 
template<typename T >
SchemaItem< T > find (Key< T > const &key) const
 Find an item by key (used to implement Schema::find).
 
SchemaItem< Flag > find (Key< Flag > const &key) const
 Find an item by key (used to implement Schema::find).
 
template<typename F >
decltype(autofindAndApply (std::string const &name, F &&func) const
 Find an item by name and run the given functor on it.
 
std::set< std::stringgetNames (bool topOnly) const
 Return a set of field names (used to implement Schema::getNames).
 
std::set< std::stringgetNames (bool topOnly, std::string const &prefix) const
 Return a set of field names (used to implement SubSchema::getNames).
 
template<typename T >
int contains (SchemaItem< T > const &item, int flags) const
 
template<typename T >
Key< T > addField (Field< T > const &field, bool doReplace=false)
 Add a field to the schema (used to implement Schema::addField).
 
Key< Flag > addField (Field< Flag > const &field, bool doReplace=false)
 Add a field to the schema (used to implement Schema::addField).
 
template<typename T >
Key< Array< T > > addField (Field< Array< T > > const &field, bool doReplace=false)
 Add a field to the schema (used to implement Schema::addField).
 
Key< std::stringaddField (Field< std::string > const &field, bool doReplace=false)
 Add a field to the schema (used to implement Schema::addField).
 
template<typename T >
void replaceField (Key< T > const &key, Field< T > const &field)
 Replace the Field in an existing SchemaItem without changing the Key.
 
ItemContainer constgetItems () const
 Return the vector of SchemaItem variants.
 
 SchemaImpl ()
 Default constructor.
 

Static Public Attributes

static int const VERSION = 3
 

Friends

class detail::Access
 

Detailed Description

A private implementation class to hide the messy details of Schema.

This can't be a real pimpl class, because some of the most important functionality is in the forEach function, a templated function we can't explicitly instantiate in a source file. But putting all the details here draws a clear line between what users should look at (Schema) and what they shouldn't (this).

Because Schema holds SchemaImpl by shared pointer, one SchemaImpl can be shared between multiple Schemas (and SubSchemas), which implement copy-on-write by creating a new SchemaImpl if the pointer they have isn't unique when they are modified.

Definition at line 45 of file SchemaImpl.h.

Member Typedef Documentation

◆ FlagMap

A map from Flag field offset/bit pairs to position in the vector, so we can do Flag field lookups.

Definition at line 63 of file SchemaImpl.h.

◆ ItemContainer

A std::vector whose elements can be any of the allowed SchemaItem types.

Definition at line 57 of file SchemaImpl.h.

◆ ItemVariant

A Boost.Variant type that can hold any one of the allowed SchemaItem types.

Definition at line 55 of file SchemaImpl.h.

◆ NameMap

A map from field names to position in the vector, so we can do name lookups.

Definition at line 59 of file SchemaImpl.h.

◆ OffsetMap

A map from standard field offsets to position in the vector, so we can do field lookups.

Definition at line 61 of file SchemaImpl.h.

Constructor & Destructor Documentation

◆ SchemaImpl()

lsst::afw::table::detail::SchemaImpl::SchemaImpl ( )
inline

Default constructor.

Definition at line 136 of file SchemaImpl.h.

136: _recordSize(0), _lastFlagField(0), _lastFlagBit(0), _items(), _initFlag(false) {}

Member Function Documentation

◆ addField() [1/4]

template<typename T >
Key< Array< T > > lsst::afw::table::detail::SchemaImpl::addField ( Field< Array< T > > const & field,
bool doReplace = false )

Add a field to the schema (used to implement Schema::addField).

Definition at line 294 of file Schema.cc.

294 {
295 if (field.isVariableLength()) {
296 // Variable-length array: allocate space for one ndarray
297 return addFieldImpl(sizeof(ndarray::Array<T, 1, 1>), 1, field, doReplace);
298 }
299 // Fixed-length array: allocate space for getElementCount() elements of type T
300 return addFieldImpl(sizeof(typename Field<T>::Element), field.getElementCount(), field, doReplace);
301}

◆ addField() [2/4]

Key< Flag > lsst::afw::table::detail::SchemaImpl::addField ( Field< Flag > const & field,
bool doReplace = false )

Add a field to the schema (used to implement Schema::addField).

Definition at line 318 of file Schema.cc.

318 {
319 static std::size_t const ELEMENT_SIZE = sizeof(Field<Flag>::Element);
321 _names.insert(std::pair<std::string, std::size_t>(field.getName(), _items.size()));
322 if (!result.second) {
323 if (doReplace) {
324 SchemaItem<Flag> *item = std::get_if<SchemaItem<Flag>>(&_items[result.first->second]);
325 if (!item) {
326 throw LSST_EXCEPT(
328 (boost::format("Cannot replace field with name '%s' because types differ.") %
329 field.getName())
330 .str());
331 }
332 if (item->field.getElementCount() != field.getElementCount()) {
333 throw LSST_EXCEPT(
335 (boost::format("Cannot replace field with name '%s' because sizes differ.") %
336 field.getName())
337 .str());
338 }
339 item->field = field;
340 return item->key;
341 } else {
342 throw LSST_EXCEPT(
344 (boost::format("Field with name '%s' already present in schema.") % field.getName())
345 .str());
346 }
347 } else {
348 if (!_initFlag || _lastFlagBit >= ELEMENT_SIZE * 8) {
349 std::size_t padding = ELEMENT_SIZE - _recordSize % ELEMENT_SIZE;
350 if (padding != ELEMENT_SIZE) {
351 _recordSize += padding;
352 }
353 _lastFlagField = _recordSize;
354 _lastFlagBit = 0;
355 _initFlag = true;
356 _recordSize += field.getElementCount() * ELEMENT_SIZE;
357 }
358 SchemaItem<Flag> item(detail::Access::makeKey(_lastFlagField, _lastFlagBit), field);
359 ++_lastFlagBit;
361 std::make_pair(item.key.getOffset(), item.key.getBit()), _items.size()));
362 _items.push_back(item);
363 return item.key;
364 }
365}
py::object result
Definition _schema.cc:429
table::Key< int > field
Definition ApCorrMap.cc:77
#define LSST_EXCEPT(type,...)
Create an exception with a given type.
Definition Exception.h:48
static Key< T > makeKey(std::size_t offset)
Definition Access.h:65
Reports invalid arguments.
Definition Runtime.h:66
Reports errors from accepting an object of an unexpected or inappropriate type.
Definition Runtime.h:167
T insert(T... args)
T make_pair(T... args)
T push_back(T... args)
T size(T... args)

◆ addField() [3/4]

Key< std::string > lsst::afw::table::detail::SchemaImpl::addField ( Field< std::string > const & field,
bool doReplace = false )

Add a field to the schema (used to implement Schema::addField).

Definition at line 303 of file Schema.cc.

303 {
304 if (field.isVariableLength()) {
305 // Variable-length string: allocate space for one std::string
306 return addFieldImpl(sizeof(std::string), 1, field, doReplace);
307 }
308 // Fixed-length string: allocate space for getElementCount() chars
309 return addFieldImpl(sizeof(typename Field<std::string>::Element), field.getElementCount(), field,
310 doReplace);
311}

◆ addField() [4/4]

template<typename T >
Key< T > lsst::afw::table::detail::SchemaImpl::addField ( Field< T > const & field,
bool doReplace = false )

Add a field to the schema (used to implement Schema::addField).

Definition at line 314 of file Schema.cc.

314 {
315 return addFieldImpl(sizeof(typename Field<T>::Element), field.getElementCount(), field, doReplace);
316}

◆ contains()

template<typename T >
int lsst::afw::table::detail::SchemaImpl::contains ( SchemaItem< T > const & item,
int flags ) const

Definition at line 225 of file Schema.cc.

225 {
226 if (!(flags & Schema::EQUAL_KEYS)) {
227 throw LSST_EXCEPT(pex::exceptions::LogicError,
228 "Can only check whether item is in schema if flags & EQUAL_KEYS");
229 }
230 SchemaItem<T> const *cmpItem = nullptr;
231 std::size_t index = findKey(_offsets, _flags, item.key, false);
232 if (index != std::numeric_limits<size_t>::max()) {
233 cmpItem = std::get_if<SchemaItem<T> >(&_items[index]);
234 if (!cmpItem) {
235 if ((flags & Schema::EQUAL_NAMES) && cmpItem->field.getName() != item.field.getName()) {
236 flags &= ~Schema::EQUAL_NAMES;
237 }
238 if ((flags & Schema::EQUAL_DOCS) && cmpItem->field.getDoc() != item.field.getDoc()) {
239 flags &= ~Schema::EQUAL_DOCS;
240 }
241 if ((flags & Schema::EQUAL_UNITS) && cmpItem->field.getUnits() != item.field.getUnits()) {
242 flags &= ~Schema::EQUAL_UNITS;
243 }
244 }
245 } else {
246 flags = 0;
247 }
248 return flags;
249}
@ EQUAL_DOCS
Fields have the same documentation (ordered).
Definition Schema.h:68
@ EQUAL_NAMES
Fields have the same names (ordered).
Definition Schema.h:67
@ EQUAL_UNITS
Fields have the same units (ordered).
Definition Schema.h:69
@ EQUAL_KEYS
Keys have the same types offsets, and sizes.
Definition Schema.h:66

◆ find() [1/3]

SchemaItem< Flag > lsst::afw::table::detail::SchemaImpl::find ( Key< Flag > const & key) const

Find an item by key (used to implement Schema::find).

Definition at line 126 of file Schema.cc.

126 {
127 FlagMap::const_iterator i = _flags.lower_bound(std::make_pair(key.getOffset(), key.getBit()));
128 if (i != _flags.end()) {
129 if (i->first.first == key.getOffset() && i->first.second == key.getBit()) {
130 try {
131 return std::get<SchemaItem<Flag>>(_items[i->second]);
132 } catch (std::bad_variant_access &err) {
134 (boost::format("Flag field with offset %d and bit %d not found.") %
135 key.getOffset() % key.getBit())
136 .str());
137 }
138 }
139 }
141 (boost::format("Flag field with offset %d and bit %d not found.") % key.getOffset() %
142 key.getBit())
143 .str());
144}
Reports attempts to access elements using an invalid key.
Definition Runtime.h:151
T end(T... args)
T lower_bound(T... args)

◆ find() [2/3]

template<typename T >
SchemaItem< T > lsst::afw::table::detail::SchemaImpl::find ( Key< T > const & key) const

Find an item by key (used to implement Schema::find).

Definition at line 110 of file Schema.cc.

110 {
111 OffsetMap::const_iterator i = _offsets.lower_bound(key.getOffset());
112 if (i != _offsets.end() && i->first == key.getOffset()) {
113 try {
114 return std::get<SchemaItem<T>>(_items[i->second]);
115 } catch (std::bad_variant_access &err) {
116 // just swallow the exception; this might be a subfield key that points to the beginning.
117 }
118 }
120 (boost::format("Field or subfield with offset %d not found with type '%s'.") %
121 key.getOffset() % Field<T>::getTypeString())
122 .str());
123}

◆ find() [3/3]

template<typename T >
SchemaItem< T > lsst::afw::table::detail::SchemaImpl::find ( std::string const & name) const

Find an item by name (used to implement Schema::find).

Definition at line 92 of file Schema.cc.

92 {
93 NameMap::const_iterator i = _names.lower_bound(name);
94 if (i != _names.end() && i->first == name) {
95 // got an exact match; we're done if it has the right type, and dead if it doesn't.
96 try {
97 return std::get<SchemaItem<T>>(_items[i->second]);
98 } catch (std::bad_variant_access &err) {
100 (boost::format("Field '%s' does not have the given type.") % name).str());
101 }
102 }
104 (boost::format("Field with name '%s' not found with type '%s'.") % name %
105 Field<T>::getTypeString())
106 .str());
107}

◆ findAndApply()

template<typename F >
decltype(auto) lsst::afw::table::detail::SchemaImpl::findAndApply ( std::string const & name,
F && func ) const
inline

Find an item by name and run the given functor on it.

Definition at line 90 of file SchemaImpl.h.

90 {
91 auto iter = _names.find(name);
92 if (iter == _names.end()) {
93 throw LSST_EXCEPT(pex::exceptions::NotFoundError,
94 (boost::format("Field with name '%s' not found") % name).str());
95 }
96 return std::visit(std::forward<F>(func), _items[iter->second]);
97 }
T find(T... args)

◆ getFieldCount()

std::size_t lsst::afw::table::detail::SchemaImpl::getFieldCount ( ) const
inline

The total number of fields.

Definition at line 69 of file SchemaImpl.h.

69{ return _names.size(); }

◆ getFlagFieldCount()

std::size_t lsst::afw::table::detail::SchemaImpl::getFlagFieldCount ( ) const
inline

The number of Flag fields.

Definition at line 72 of file SchemaImpl.h.

72{ return _flags.size(); }

◆ getItems()

ItemContainer const & lsst::afw::table::detail::SchemaImpl::getItems ( ) const
inline

Return the vector of SchemaItem variants.

Fields are in the order they are added. That means they're also ordered with increasing Key offsets, except for Flag fields, which are in increasing order of (offset, bit) relative to each other, but not relative to all the other fields.

Definition at line 133 of file SchemaImpl.h.

133{ return _items; }

◆ getNames() [1/2]

std::set< std::string > lsst::afw::table::detail::SchemaImpl::getNames ( bool topOnly) const

Return a set of field names (used to implement Schema::getNames).

Definition at line 251 of file Schema.cc.

251 {
253 if (topOnly) {
254 for (auto const &_name : _names) {
255 std::size_t sep = _name.first.find(getDelimiter());
256 if (sep == std::string::npos) {
257 result.insert(result.end(), _name.first);
258 } else {
259 result.insert(result.end(), _name.first.substr(0, sep));
260 }
261 }
262 } else {
263 for (auto const &_name : _names) {
264 result.insert(result.end(), _name.first);
265 }
266 }
267 return result;
268}
T substr(T... args)

◆ getNames() [2/2]

std::set< std::string > lsst::afw::table::detail::SchemaImpl::getNames ( bool topOnly,
std::string const & prefix ) const

Return a set of field names (used to implement SubSchema::getNames).

Definition at line 270 of file Schema.cc.

270 {
272 if (topOnly) {
273 for (NameMap::const_iterator i = _names.lower_bound(prefix); i != _names.end(); ++i) {
274 if (i->first.compare(0, prefix.size(), prefix) != 0) break;
275 std::size_t sep = i->first.find(getDelimiter(), prefix.size() + 1);
276 if (sep == std::string::npos) {
277 result.insert(result.end(),
278 i->first.substr(prefix.size() + 1, i->first.size() - prefix.size()));
279 } else {
280 result.insert(result.end(), i->first.substr(prefix.size() + 1, sep - prefix.size() - 1));
281 }
282 }
283 } else {
284 for (NameMap::const_iterator i = _names.lower_bound(prefix); i != _names.end(); ++i) {
285 if (i->first.compare(0, prefix.size(), prefix) != 0) break;
286 result.insert(result.end(),
287 i->first.substr(prefix.size() + 1, i->first.size() - prefix.size() - 1));
288 }
289 }
290 return result;
291}
std::string prefix

◆ getNonFlagFieldCount()

std::size_t lsst::afw::table::detail::SchemaImpl::getNonFlagFieldCount ( ) const
inline

The number of non-Flag fields.

Definition at line 75 of file SchemaImpl.h.

75{ return _offsets.size(); }

◆ getRecordSize()

std::size_t lsst::afw::table::detail::SchemaImpl::getRecordSize ( ) const
inline

The size of a record in bytes.

Definition at line 66 of file SchemaImpl.h.

66{ return _recordSize; }

◆ replaceField()

template<typename T >
void lsst::afw::table::detail::SchemaImpl::replaceField ( Key< T > const & key,
Field< T > const & field )

Replace the Field in an existing SchemaItem without changing the Key.

Definition at line 193 of file Schema.cc.

193 {
194 NameMap::iterator j = _names.find(field.getName());
195 SchemaItem<T> *item = nullptr;
196 if (j != _names.end()) {
197 // The field name is already present in the Schema; see if it's the one we're replacing.
198 // If we can get the old item with this, we don't need to update the name map at all.
199 item = std::get_if<SchemaItem<T>>(&_items[j->second]);
200 if (!item || key != item->key) {
201 throw LSST_EXCEPT(
203 (boost::format("Field with name '%s' already present in schema with a different key.") %
204 field.getName())
205 .str());
206 }
207 }
208 if (!item) { // Need to find the original item by key, since it's a new name.
209 std::size_t index = findKey(_offsets, _flags, key);
210 item = std::get_if<SchemaItem<T>>(&_items[index]);
211 if (!item) {
213 (boost::format("Incorrect key type '%s'.") % key).str());
214 }
215 j = _names.find(item->field.getName());
216 _names.insert(j, std::pair<std::string, std::size_t>(field.getName(), j->second));
217 _names.erase(j);
218 }
219 item->field = field;
220}
T erase(T... args)

Friends And Related Symbol Documentation

◆ detail::Access

Definition at line 139 of file SchemaImpl.h.

Member Data Documentation

◆ VERSION

int const lsst::afw::table::detail::SchemaImpl::VERSION = 3
static

Definition at line 52 of file SchemaImpl.h.


The documentation for this class was generated from the following files: