LSSTApplications  18.0.0+106,18.0.0+50,19.0.0,19.0.0+1,19.0.0+10,19.0.0+11,19.0.0+13,19.0.0+17,19.0.0+2,19.0.0-1-g20d9b18+6,19.0.0-1-g425ff20,19.0.0-1-g5549ca4,19.0.0-1-g580fafe+6,19.0.0-1-g6fe20d0+1,19.0.0-1-g7011481+9,19.0.0-1-g8c57eb9+6,19.0.0-1-gb5175dc+11,19.0.0-1-gdc0e4a7+9,19.0.0-1-ge272bc4+6,19.0.0-1-ge3aa853,19.0.0-10-g448f008b,19.0.0-12-g6990b2c,19.0.0-2-g0d9f9cd+11,19.0.0-2-g3d9e4fb2+11,19.0.0-2-g5037de4,19.0.0-2-gb96a1c4+3,19.0.0-2-gd955cfd+15,19.0.0-3-g2d13df8,19.0.0-3-g6f3c7dc,19.0.0-4-g725f80e+11,19.0.0-4-ga671dab3b+1,19.0.0-4-gad373c5+3,19.0.0-5-ga2acb9c+2,19.0.0-5-gfe96e6c+2,w.2020.01
LSSTDataManagementBasePackage
Classes | 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>

Classes

struct  VisitorWrapper
 A functor-wrapper used in the implementation of Schema::forEach. More...
 

Public Types

typedef boost::mpl::transform< FieldTypes, MakeItem >::type ItemTypes
 An MPL sequence of all the allowed SchemaItem templates. More...
 
typedef boost::make_variant_over< ItemTypes >::type ItemVariant
 A Boost.Variant type that can hold any one of the allowed SchemaItem types. More...
 
typedef std::vector< ItemVariantItemContainer
 A std::vector whose elements can be any of the allowed SchemaItem types. More...
 
typedef std::map< std::string, int > NameMap
 A map from field names to position in the vector, so we can do name lookups. More...
 
typedef std::map< int, int > OffsetMap
 A map from standard field offsets to position in the vector, so we can do field lookups. More...
 
typedef std::map< std::pair< int, int >, int > FlagMap
 A map from Flag field offset/bit pairs to position in the vector, so we can do Flag field lookups. More...
 

Public Member Functions

int getRecordSize () const
 The size of a record in bytes. More...
 
int getFieldCount () const
 The total number of fields. More...
 
int getFlagFieldCount () const
 The number of Flag fields. More...
 
int 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 >
void 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 48 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 72 of file SchemaImpl.h.

◆ ItemContainer

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

Definition at line 66 of file SchemaImpl.h.

◆ ItemTypes

An MPL sequence of all the allowed SchemaItem templates.

Definition at line 62 of file SchemaImpl.h.

◆ ItemVariant

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

Definition at line 64 of file SchemaImpl.h.

◆ NameMap

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

Definition at line 68 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 70 of file SchemaImpl.h.

Constructor & Destructor Documentation

◆ SchemaImpl()

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

Default constructor.

Definition at line 146 of file SchemaImpl.h.

146 : _recordSize(0), _lastFlagField(-1), _lastFlagBit(-1), _items() {}

Member Function Documentation

◆ addField() [1/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 504 of file Schema.cc.

504  {
505  return addFieldImpl(sizeof(typename Field<T>::Element), field.getElementCount(), field, doReplace);
506 }
table::Key< int > field
Definition: ApCorrMap.cc:77
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 508 of file Schema.cc.

508  {
509  static int const ELEMENT_SIZE = sizeof(Field<Flag>::Element);
511  _names.insert(std::pair<std::string, int>(field.getName(), _items.size()));
512  if (!result.second) {
513  if (doReplace) {
514  SchemaItem<Flag> *item = boost::get<SchemaItem<Flag> >(&_items[result.first->second]);
515  if (!item) {
516  throw LSST_EXCEPT(
518  (boost::format("Cannot replace field with name '%s' because types differ.") %
519  field.getName())
520  .str());
521  }
522  if (item->field.getElementCount() != field.getElementCount()) {
523  throw LSST_EXCEPT(
525  (boost::format("Cannot replace field with name '%s' because sizes differ.") %
526  field.getName())
527  .str());
528  }
529  item->field = field;
530  return item->key;
531  } else {
532  throw LSST_EXCEPT(
534  (boost::format("Field with name '%s' already present in schema.") % field.getName())
535  .str());
536  }
537  } else {
538  if (_lastFlagField < 0 || _lastFlagBit >= ELEMENT_SIZE * 8) {
539  int padding = ELEMENT_SIZE - _recordSize % ELEMENT_SIZE;
540  if (padding != ELEMENT_SIZE) {
541  _recordSize += padding;
542  }
543  _lastFlagField = _recordSize;
544  _lastFlagBit = 0;
545  _recordSize += field.getElementCount() * ELEMENT_SIZE;
546  }
547  SchemaItem<Flag> item(detail::Access::makeKey(_lastFlagField, _lastFlagBit), field);
548  ++_lastFlagBit;
549  _flags.insert(std::pair<std::pair<int, int>, int>(
550  std::make_pair(item.key.getOffset(), item.key.getBit()), _items.size()));
551  _items.push_back(item);
552  return item.key;
553  }
554 }
def format(config, name=None, writeSourceLine=True, prefix="", verbose=False)
Definition: history.py:174
table::Key< int > field
Definition: ApCorrMap.cc:77
static Key< T > makeKey(int offset)
Definition: Access.h:65
T push_back(T... args)
T make_pair(T... args)
std::unique_ptr< SchemaItem< U > > result
Definition: Schema.cc:195
T insert(T... args)
T size(T... args)
#define LSST_EXCEPT(type,...)
Create an exception with a given type.
Definition: Exception.h:48
FieldBase< Flag >::Element Element
Type used to store field data in the table (a field may have multiple elements).
Definition: Field.h:26
Reports invalid arguments.
Definition: Runtime.h:66
Reports errors from accepting an object of an unexpected or inappropriate type.
Definition: Runtime.h:167

◆ addField() [3/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 484 of file Schema.cc.

484  {
485  if (field.isVariableLength()) {
486  // Variable-length array: allocate space for one ndarray
487  return addFieldImpl(sizeof(ndarray::Array<T, 1, 1>), 1, field, doReplace);
488  }
489  // Fixed-length array: allocate space for getElementCount() elements of type T
490  return addFieldImpl(sizeof(typename Field<T>::Element), field.getElementCount(), field, doReplace);
491 }
table::Key< int > field
Definition: ApCorrMap.cc:77
FieldBase< T >::Element Element
Type used to store field data in the table (a field may have multiple elements).
Definition: Field.h:26

◆ addField() [4/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 493 of file Schema.cc.

493  {
494  if (field.isVariableLength()) {
495  // Variable-length string: allocate space for one std::string
496  return addFieldImpl(sizeof(std::string), 1, field, doReplace);
497  }
498  // Fixed-length string: allocate space for getElementCount() chars
499  return addFieldImpl(sizeof(typename Field<std::string>::Element), field.getElementCount(), field,
500  doReplace);
501 }
table::Key< int > field
Definition: ApCorrMap.cc:77
STL class.
FieldBase< T >::Element Element
Type used to store field data in the table (a field may have multiple elements).
Definition: Field.h:26

◆ contains()

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

Definition at line 415 of file Schema.cc.

415  {
416  if (!(flags & Schema::EQUAL_KEYS)) {
417  throw LSST_EXCEPT(pex::exceptions::LogicError,
418  "Can only check whether item is in schema if flags & EQUAL_KEYS");
419  }
420  SchemaItem<T> const *cmpItem = 0;
421  int index = findKey(_offsets, _flags, item.key, false);
422  if (index >= 0) {
423  cmpItem = boost::get<SchemaItem<T> >(&_items[index]);
424  if (!cmpItem) {
425  if ((flags & Schema::EQUAL_NAMES) && cmpItem->field.getName() != item.field.getName()) {
426  flags &= ~Schema::EQUAL_NAMES;
427  }
428  if ((flags & Schema::EQUAL_DOCS) && cmpItem->field.getDoc() != item.field.getDoc()) {
429  flags &= ~Schema::EQUAL_DOCS;
430  }
431  if ((flags & Schema::EQUAL_UNITS) && cmpItem->field.getUnits() != item.field.getUnits()) {
432  flags &= ~Schema::EQUAL_UNITS;
433  }
434  }
435  } else {
436  flags = 0;
437  }
438  return flags;
439 }
Keys have the same types offsets, and sizes.
Definition: Schema.h:65
Fields have the same units (ordered).
Definition: Schema.h:68
Fields have the same names (ordered).
Definition: Schema.h:66
#define LSST_EXCEPT(type,...)
Create an exception with a given type.
Definition: Exception.h:48
Fields have the same documentation (ordered).
Definition: Schema.h:67

◆ find() [1/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 202 of file Schema.cc.

202  {
203  NameMap::const_iterator i = _names.lower_bound(name);
204  if (i != _names.end()) {
205  if (i->first == name) {
206  // got an exact match; we're done if it has the right type, and dead if it doesn't.
207  try {
208  return boost::get<SchemaItem<T> const>(_items[i->second]);
209  } catch (boost::bad_get &err) {
211  (boost::format("Field '%s' does not have the given type.") % name).str());
212  }
213  }
214  }
215  // We didn't get an exact match, but we might be searching for "a.x/a_x" and "a" might be a point field.
216  // Because the names are sorted, we know we overshot it, so we work backwards.
217  ExtractItemByName<T> extractor(name, getDelimiter());
218  while (i != _names.begin()) {
219  --i;
220  boost::apply_visitor(extractor, _items[i->second]); // see if the current item is a match
221  if (extractor.result) return *extractor.result;
222  }
224  (boost::format("Field or subfield with name '%s' not found with type '%s'.") % name %
226  .str());
227 }
def format(config, name=None, writeSourceLine=True, prefix="", verbose=False)
Definition: history.py:174
T end(T... args)
T lower_bound(T... args)
Reports attempts to access elements using an invalid key.
Definition: Runtime.h:151
#define LSST_EXCEPT(type,...)
Create an exception with a given type.
Definition: Exception.h:48
T begin(T... args)
std::string name
Definition: Schema.cc:194
Reports errors from accepting an object of an unexpected or inappropriate type.
Definition: Runtime.h:167
static std::string getTypeString()
Return a string description of the field type.
Definition: FieldBase.cc:56

◆ 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 289 of file Schema.cc.

289  {
290  OffsetMap::const_iterator i = _offsets.lower_bound(key.getOffset());
291  if (i != _offsets.end()) {
292  if (i->first == key.getOffset()) {
293  try {
294  return boost::get<SchemaItem<T> const>(_items[i->second]);
295  } catch (boost::bad_get &err) {
296  // just swallow the exception; this might be a subfield key that points to the beginning.
297  }
298  }
299  // We didn't get an exact match, but we might be searching for a subfield.
300  // Because the offsets are sorted, we know we overshot it, so we work backwards.
301  ExtractItemByKey<T> extractor(key, getDelimiter());
302  while (i != _offsets.begin()) {
303  --i;
304  boost::apply_visitor(extractor, _items[i->second]);
305  if (extractor.result) return *extractor.result;
306  }
307  }
309  (boost::format("Field or subfield with offset %d not found with type '%s'.") %
310  key.getOffset() % Field<T>::getTypeString())
311  .str());
312 }
def format(config, name=None, writeSourceLine=True, prefix="", verbose=False)
Definition: history.py:174
T end(T... args)
T lower_bound(T... args)
Reports attempts to access elements using an invalid key.
Definition: Runtime.h:151
Key< U > key
Definition: Schema.cc:281
#define LSST_EXCEPT(type,...)
Create an exception with a given type.
Definition: Exception.h:48
T begin(T... args)
static std::string getTypeString()
Return a string description of the field type.
Definition: FieldBase.cc:56

◆ find() [3/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 315 of file Schema.cc.

315  {
316  FlagMap::const_iterator i = _flags.lower_bound(std::make_pair(key.getOffset(), key.getBit()));
317  if (i != _flags.end()) {
318  if (i->first.first == key.getOffset() && i->first.second == key.getBit()) {
319  try {
320  return boost::get<SchemaItem<Flag> const>(_items[i->second]);
321  } catch (boost::bad_get &err) {
323  (boost::format("Flag field with offset %d and bit %d not found.") %
324  key.getOffset() % key.getBit())
325  .str());
326  }
327  }
328  }
329  // Flag keys are never subfields, so we require an exact match.
331  (boost::format("Flag field with offset %d and bit %d not found.") % key.getOffset() %
332  key.getBit())
333  .str());
334 }
def format(config, name=None, writeSourceLine=True, prefix="", verbose=False)
Definition: history.py:174
T end(T... args)
T lower_bound(T... args)
Reports attempts to access elements using an invalid key.
Definition: Runtime.h:151
Key< U > key
Definition: Schema.cc:281
T make_pair(T... args)
#define LSST_EXCEPT(type,...)
Create an exception with a given type.
Definition: Exception.h:48

◆ findAndApply()

template<typename F >
void 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 99 of file SchemaImpl.h.

99  {
100  auto iter = _names.find(name);
101  if (iter == _names.end()) {
102  throw LSST_EXCEPT(pex::exceptions::NotFoundError,
103  (boost::format("Field with name '%s' not found") % name).str());
104  }
105  VisitorWrapper<F> visitor(std::forward<F>(func));
106  visitor(_items[iter->second]);
107  }
def format(config, name=None, writeSourceLine=True, prefix="", verbose=False)
Definition: history.py:174
T end(T... args)
T find(T... args)
#define LSST_EXCEPT(type,...)
Create an exception with a given type.
Definition: Exception.h:48

◆ getFieldCount()

int lsst::afw::table::detail::SchemaImpl::getFieldCount ( ) const
inline

The total number of fields.

Definition at line 78 of file SchemaImpl.h.

78 { return _names.size(); }
T size(T... args)

◆ getFlagFieldCount()

int lsst::afw::table::detail::SchemaImpl::getFlagFieldCount ( ) const
inline

The number of Flag fields.

Definition at line 81 of file SchemaImpl.h.

81 { return _flags.size(); }
T size(T... args)

◆ 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 143 of file SchemaImpl.h.

143 { 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 441 of file Schema.cc.

441  {
443  if (topOnly) {
444  for (NameMap::const_iterator i = _names.begin(); i != _names.end(); ++i) {
445  std::size_t sep = i->first.find(getDelimiter());
446  if (sep == std::string::npos) {
447  result.insert(result.end(), i->first);
448  } else {
449  result.insert(result.end(), i->first.substr(0, sep));
450  }
451  }
452  } else {
453  for (NameMap::const_iterator i = _names.begin(); i != _names.end(); ++i) {
454  result.insert(result.end(), i->first);
455  }
456  }
457  return result;
458 }
T end(T... args)
std::unique_ptr< SchemaItem< U > > result
Definition: Schema.cc:195
T insert(T... args)
STL class.
T begin(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 460 of file Schema.cc.

460  {
462  if (topOnly) {
463  for (NameMap::const_iterator i = _names.lower_bound(prefix); i != _names.end(); ++i) {
464  if (i->first.compare(0, prefix.size(), prefix) != 0) break;
465  std::size_t sep = i->first.find(getDelimiter(), prefix.size() + 1);
466  if (sep == std::string::npos) {
467  result.insert(result.end(),
468  i->first.substr(prefix.size() + 1, i->first.size() - prefix.size()));
469  } else {
470  result.insert(result.end(), i->first.substr(prefix.size() + 1, sep - prefix.size() - 1));
471  }
472  }
473  } else {
474  for (NameMap::const_iterator i = _names.lower_bound(prefix); i != _names.end(); ++i) {
475  if (i->first.compare(0, prefix.size(), prefix) != 0) break;
476  result.insert(result.end(),
477  i->first.substr(prefix.size() + 1, i->first.size() - prefix.size() - 1));
478  }
479  }
480  return result;
481 }
T end(T... args)
T lower_bound(T... args)
std::unique_ptr< SchemaItem< U > > result
Definition: Schema.cc:195
T insert(T... args)
T size(T... args)
STL class.
std::string prefix
Definition: SchemaMapper.cc:79

◆ getNonFlagFieldCount()

int lsst::afw::table::detail::SchemaImpl::getNonFlagFieldCount ( ) const
inline

The number of non-Flag fields.

Definition at line 84 of file SchemaImpl.h.

84 { return _offsets.size(); }
T size(T... args)

◆ getRecordSize()

int lsst::afw::table::detail::SchemaImpl::getRecordSize ( ) const
inline

The size of a record in bytes.

Definition at line 75 of file SchemaImpl.h.

75 { 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 383 of file Schema.cc.

383  {
384  NameMap::iterator j = _names.find(field.getName());
385  SchemaItem<T> *item = 0;
386  if (j != _names.end()) {
387  // The field name is already present in the Schema; see if it's the one we're replacing.
388  // If we can get the old item with this, we don't need to update the name map at all.
389  item = boost::get<SchemaItem<T> >(&_items[j->second]);
390  if (!item || key != item->key) {
391  throw LSST_EXCEPT(
393  (boost::format("Field with name '%s' already present in schema with a different key.") %
394  field.getName())
395  .str());
396  }
397  }
398  if (!item) { // Need to find the original item by key, since it's a new name.
399  int index = findKey(_offsets, _flags, key);
400  item = boost::get<SchemaItem<T> >(&_items[index]);
401  if (!item) {
403  (boost::format("Incorrect key type '%s'.") % key).str());
404  }
405  j = _names.find(item->field.getName());
406  _names.insert(j, std::pair<std::string, int>(field.getName(), j->second));
407  _names.erase(j);
408  }
409  item->field = field;
410 }
def format(config, name=None, writeSourceLine=True, prefix="", verbose=False)
Definition: history.py:174
table::Key< int > field
Definition: ApCorrMap.cc:77
T end(T... args)
T erase(T... args)
Key< U > key
Definition: Schema.cc:281
T insert(T... args)
T find(T... args)
#define LSST_EXCEPT(type,...)
Create an exception with a given type.
Definition: Exception.h:48
Reports invalid arguments.
Definition: Runtime.h:66
Reports errors from accepting an object of an unexpected or inappropriate type.
Definition: Runtime.h:167

Friends And Related Function Documentation

◆ detail::Access

friend class detail::Access
friend

Definition at line 185 of file SchemaImpl.h.

Member Data Documentation

◆ VERSION

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

Definition at line 59 of file SchemaImpl.h.


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