LSST Applications  21.0.0-172-gfb10e10a+18fedfabac,22.0.0+297cba6710,22.0.0+80564b0ff1,22.0.0+8d77f4f51a,22.0.0+a28f4c53b1,22.0.0+dcf3732eb2,22.0.1-1-g7d6de66+2a20fdde0d,22.0.1-1-g8e32f31+297cba6710,22.0.1-1-geca5380+7fa3b7d9b6,22.0.1-12-g44dc1dc+2a20fdde0d,22.0.1-15-g6a90155+515f58c32b,22.0.1-16-g9282f48+790f5f2caa,22.0.1-2-g92698f7+dcf3732eb2,22.0.1-2-ga9b0f51+7fa3b7d9b6,22.0.1-2-gd1925c9+bf4f0e694f,22.0.1-24-g1ad7a390+a9625a72a8,22.0.1-25-g5bf6245+3ad8ecd50b,22.0.1-25-gb120d7b+8b5510f75f,22.0.1-27-g97737f7+2a20fdde0d,22.0.1-32-gf62ce7b1+aa4237961e,22.0.1-4-g0b3f228+2a20fdde0d,22.0.1-4-g243d05b+871c1b8305,22.0.1-4-g3a563be+32dcf1063f,22.0.1-4-g44f2e3d+9e4ab0f4fa,22.0.1-42-gca6935d93+ba5e5ca3eb,22.0.1-5-g15c806e+85460ae5f3,22.0.1-5-g58711c4+611d128589,22.0.1-5-g75bb458+99c117b92f,22.0.1-6-g1c63a23+7fa3b7d9b6,22.0.1-6-g50866e6+84ff5a128b,22.0.1-6-g8d3140d+720564cf76,22.0.1-6-gd805d02+cc5644f571,22.0.1-8-ge5750ce+85460ae5f3,master-g6e05de7fdc+babf819c66,master-g99da0e417a+8d77f4f51a,w.2021.48
LSST Data Management Base Package
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. More...
 
using ItemContainer = std::vector< ItemVariant >
 A std::vector whose elements can be any of the allowed SchemaItem types. More...
 
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. More...
 
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. More...
 
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. More...
 

Public Member Functions

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

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

using lsst::afw::table::detail::SchemaImpl::ItemVariant = decltype(makeItemVariantType(FieldTypes{}))

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 }
table::Key< int > field
Definition: ApCorrMap.cc:77
typename FieldBase< T >::Element Element
Type used to store field data in the table (a field may have multiple elements).
Definition: Field.h:26

◆ 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
#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)
def format(config, name=None, writeSourceLine=True, prefix="", verbose=False)
Definition: history.py:174
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 }
static std::string getTypeString()
Return a string description of the field type.
Definition: FieldBase.cc:56

◆ 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 %
106  .str());
107 }
table::Key< std::string > name
Definition: Amplifier.cc:116

◆ 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
Definition: SchemaMapper.cc:72

◆ 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 Function Documentation

◆ detail::Access

friend class detail::Access
friend

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: