7 #include "boost/preprocessor/seq/for_each.hpp"
8 #include "boost/preprocessor/tuple/to_seq.hpp"
26 inline char getDelimiter() {
return '_'; }
46 bool operator()(SchemaItem<T>
const &
a, SchemaItem<T>
const &
b)
const {
47 return a.key ==
b.key;
50 template <
typename T,
typename U>
51 bool operator()(SchemaItem<T>
const &
a, SchemaItem<U>
const &
b)
const {
57 static bool compareKeys(ItemVariant
const &
a, ItemVariant
const &
b) {
61 static bool compareNames(ItemVariant
const &
a, ItemVariant
const &
b) {
63 [](
auto const &
a,
auto const &
b) {
return a.field.getName() ==
b.field.getName(); },
68 static bool compareDocs(ItemVariant
const &
a, ItemVariant
const &
b) {
70 [](
auto const &
a,
auto const &
b) {
return a.field.getDoc() ==
b.field.getDoc(); },
75 static bool compareUnits(ItemVariant
const &
a, ItemVariant
const &
b) {
77 [](
auto const &
a,
auto const &
b) {
return a.field.getUnits() ==
b.field.getUnits(); },
94 if (i != _names.
end() && i->first ==
name) {
97 return std::get<SchemaItem<T>>(_items[i->second]);
98 }
catch (std::bad_variant_access &err) {
109 template <
typename T>
112 if (i != _offsets.
end() && i->first == key.
getOffset()) {
114 return std::get<SchemaItem<T>>(_items[i->second]);
115 }
catch (std::bad_variant_access &err) {
120 (
boost::format(
"Field or subfield with offset %d not found with type '%s'.") %
128 if (i != _flags.
end()) {
129 if (i->first.first == key.
getOffset() && i->first.second == key.
getBit()) {
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.") %
155 template <
typename T>
157 bool throwIfMissing =
true) {
158 SchemaImpl::OffsetMap::const_iterator i = offsets.
find(key.
getOffset());
159 if (i == offsets.
end()) {
160 if (throwIfMissing) {
162 (
boost::format(
"Key of type %s with offset %d not found in Schema") %
174 Key<Flag>
const &key,
bool throwIfMissing =
true) {
175 SchemaImpl::FlagMap::const_iterator i = flags.find(
std::make_pair(key.getOffset(), key.getBit()));
176 if (i == flags.end()) {
177 if (throwIfMissing) {
179 pex::exceptions::NotFoundError,
180 (
boost::format(
"Key of type Flag with offset %d and bit %d not found in Schema") %
181 key.getOffset() % key.getBit())
192 template <
typename T>
194 NameMap::iterator j = _names.
find(
field.getName());
196 if (j != _names.
end()) {
199 item = std::get_if<SchemaItem<T>>(&_items[j->second]);
200 if (!item || key != item->
key) {
203 (
boost::format(
"Field with name '%s' already present in schema with a different key.") %
209 std::size_t index = findKey(_offsets, _flags, key);
210 item = std::get_if<SchemaItem<T>>(&_items[index]);
224 template <
typename T>
228 "Can only check whether item is in schema if flags & EQUAL_KEYS");
233 cmpItem = std::get_if<SchemaItem<T> >(&_items[index]);
236 flags &= ~
Schema::EQUAL_NAMES;
239 flags &= ~
Schema::EQUAL_DOCS;
242 flags &= ~
Schema::EQUAL_UNITS;
254 for (
auto const &_name : _names) {
256 if (sep == std::string::npos) {
263 for (
auto const &_name : _names) {
276 if (sep == std::string::npos) {
293 template <
typename T>
295 if (
field.isVariableLength()) {
297 return addFieldImpl(
sizeof(ndarray::Array<T, 1, 1>), 1,
field, doReplace);
304 if (
field.isVariableLength()) {
313 template <
typename T>
328 (
boost::format(
"Cannot replace field with name '%s' because types differ.") %
335 (
boost::format(
"Cannot replace field with name '%s' because sizes differ.") %
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;
353 _lastFlagField = _recordSize;
356 _recordSize +=
field.getElementCount() * ELEMENT_SIZE;
367 template <
typename T>
377 (
boost::format(
"Cannot replace field with name '%s' because types differ.") %
384 if (item->
field.getElementCount() !=
field.getElementCount()) {
387 (
boost::format(
"Cannot replace field with name '%s' because sizes differ.") %
400 std::size_t padding = elementSize - _recordSize % elementSize;
401 if (padding != elementSize) {
402 _recordSize += padding;
405 _recordSize += elementCount * elementSize;
454 return afw::table::join(
a,
b, getDelimiter());
457 void Schema::_edit() {
466 template <
typename T>
469 _aliases->_apply(tmp);
470 return _impl->
find<
T>(tmp);
473 template <
typename T>
475 return _impl->
find(key);
478 template <
typename T>
484 template <
typename T>
491 if (_impl == other._impl)
return flags;
495 for (Impl::ItemContainer::const_iterator i1 = _impl->
getItems().
begin(),
528 template <
typename T>
530 return _impl->
contains(item, flags);
535 aliases = std::make_shared<AliasMap>();
548 using result_type = void;
550 template <
typename T>
552 *
os <<
" (" << item.
field <<
", " << item.
key <<
"),\n";
565 for (
auto const &
iter : *
schema.getAliasMap()) {
566 os <<
" '" <<
iter.first <<
"'->'" <<
iter.second <<
"'\n";
577 return afw::table::join(
a,
b, getDelimiter());
581 : _impl(impl), _aliases(aliases), _name(
name) {}
583 template <
typename T>
602 #define INSTANTIATE_LAYOUT(r, data, elem) \
603 template Key<elem> Schema::addField(Field<elem> const &, bool); \
604 template SchemaItem<elem> Schema::find(std::string const &) const; \
605 template SchemaItem<elem> Schema::find(Key<elem> const &) const; \
606 template SchemaItem<elem> detail::SchemaImpl::find(std::string const &name) const; \
607 template int Schema::contains(SchemaItem<elem> const &, int) const; \
608 template void Schema::replaceField(Key<elem> const &, Field<elem> const &); \
609 template SchemaItem<elem> SubSchema::find(std::string const &) const;
table::Key< std::string > name
#define LSST_EXCEPT(type,...)
Create an exception with a given type.
#define INSTANTIATE_LAYOUT(r, data, elem)
A simple struct that combines the two arguments that must be passed to most cfitsio routines and cont...
void readMetadata(daf::base::PropertySet &metadata, bool strip=false)
Read a FITS header into a PropertySet or PropertyList.
Lifetime-management for memory that goes into FITS memory files.
Mapping class that holds aliases for a Schema.
Tag types used to declare specialized field types.
Key specialization for Flag.
std::size_t getBit() const
The index of this field's bit within the integer it shares with other Flag fields.
std::size_t getOffset() const
Return the offset in bytes of the integer element that holds this field's bit.
A class used as a handle to a particular field in a table.
std::size_t getOffset() const noexcept
Return the offset (in bytes) of this field within a record.
Defines the fields and offsets for a table.
void forEach(F &func) const
Apply a functor to each SchemaItem in the Schema.
Schema()
Construct an empty Schema.
void disconnectAliases()
Sever the connection between this schema and any others with which it shares aliases.
Schema & operator=(Schema const &other)
std::string join(std::string const &a, std::string const &b) const
Join strings using the field delimiter appropriate for this Schema.
void setAliasMap(std::shared_ptr< AliasMap > aliases)
Set the alias map.
std::set< std::string > getNames(bool topOnly=false) const
Return a set of field names in the schema.
static Schema fromFitsMetadata(daf::base::PropertyList &header, bool stripMetadata=true)
Construct from reading a FITS header.
Key< T > addField(Field< T > const &field, bool doReplace=false)
Add a new field to the Schema, and return the associated Key.
static Schema readFits(std::string const &filename, int hdu=fits::DEFAULT_HDU)
Construct from reading a FITS file.
std::size_t hash_value() const noexcept
Return a hash of this object.
int contains(Schema const &other, int flags=EQUAL_KEYS) const
Test whether the given schema is a subset of this.
int compare(Schema const &other, int flags=EQUAL_KEYS) const
Do a detailed equality comparison of two schemas.
void replaceField(Key< T > const &key, Field< T > const &field)
Replace the Field (name/description) for an existing Key.
SchemaItem< T > find(std::string const &name) const
Find a SchemaItem in the Schema by name.
@ EQUAL_DOCS
Fields have the same documentation (ordered).
@ EQUAL_NAMES
Fields have the same names (ordered).
@ EQUAL_UNITS
Fields have the same units (ordered).
@ EQUAL_KEYS
Keys have the same types offsets, and sizes.
@ EQUAL_FIELDS
Fields are identical (but aliases may not be).
@ EQUAL_ALIASES
Schemas have identical AliasMaps.
std::shared_ptr< AliasMap > getAliasMap() const
Return the map of aliases.
A proxy type for name lookups in a Schema.
std::string join(std::string const &a, std::string const &b) const
Join strings using the field delimiter appropriate for this Schema.
SubSchema operator[](std::string const &name) const
Return a nested proxy.
std::set< std::string > getNames(bool topOnly=false) const
Return a set of nested names that start with the SubSchema's prefix.
SchemaItem< T > find(std::string const &name) const
Find a nested SchemaItem by name.
static Key< T > makeKey(std::size_t offset)
A private implementation class to hide the messy details of Schema.
ItemContainer const & getItems() const
Return the vector of SchemaItem variants.
std::set< std::string > getNames(bool topOnly) const
Return a set of field names (used to implement Schema::getNames).
Key< T > addField(Field< T > const &field, bool doReplace=false)
Add a field to the schema (used to implement Schema::addField).
int contains(SchemaItem< T > const &item, int flags) const
void replaceField(Key< T > const &key, Field< T > const &field)
Replace the Field in an existing SchemaItem without changing the Key.
SchemaItem< T > find(std::string const &name) const
Find an item by name (used to implement Schema::find).
std::map< std::pair< std::size_t, std::size_t >, std::size_t > FlagMap
A map from Flag field offset/bit pairs to position in the vector, so we can do Flag field lookups.
decltype(makeItemVariantType(FieldTypes{})) ItemVariant
A Boost.Variant type that can hold any one of the allowed SchemaItem types.
std::map< std::size_t, std::size_t > OffsetMap
A map from standard field offsets to position in the vector, so we can do field lookups.
Class for storing ordered metadata with comments.
Reports invalid arguments.
Reports errors in the logical structure of the program.
Reports attempts to access elements using an invalid key.
Reports errors from accepting an object of an unexpected or inappropriate type.
std::ostream & operator<<(std::ostream &os, BaseRecord const &record)
BOOST_PP_SEQ_FOR_EACH(INSTANTIATE_COLUMNVIEW_SCALAR, _, BOOST_PP_TUPLE_TO_SEQ(AFW_TABLE_SCALAR_FIELD_TYPE_N, AFW_TABLE_SCALAR_FIELD_TYPE_TUPLE)) BOOST_PP_SEQ_FOR_EACH(INSTANTIATE_COLUMNVIEW_ARRAY
std::size_t hashCombine(std::size_t seed) noexcept
Combine hashes.
def format(config, name=None, writeSourceLine=True, prefix="", verbose=False)
A base class for image defects.
std::size_t getElementCount() const
Return the number of subfield elements (always one for scalars).
A description of a field in a table.
typename FieldBase< T >::Element Element
Type used to store field data in the table (a field may have multiple elements).
A simple pair-like struct for mapping a Field (name and description) with a Key (used for actual data...
#define AFW_TABLE_FIELD_TYPE_N
#define AFW_TABLE_FIELD_TYPE_TUPLE