diff --git a/.gitignore b/.gitignore index 0ddcb8676..14c88b1da 100644 --- a/.gitignore +++ b/.gitignore @@ -77,7 +77,7 @@ xdr-datatypes.h dmr_memory_cache doxy.conf doxygen_warnings.txt -main_page.doxygen +doxygen.log ## conf/ generated files conf/compile diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 000000000..43c546363 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,109 @@ +# AGENTS.md + +## Scope + +These instructions apply to the entire `libdap4` repository. + +## Project Context + +- `libdap4` is a legacy C++ implementation of DAP2/DAP4 with long-lived downstream consumers. +- Prioritize compatibility, behavioral stability, and small, reviewable diffs. +- Prefer minimal, targeted changes over broad refactors. + +## Primary Build Systems + +- Prefer autotools for day-to-day work unless the task is explicitly CMake-focused. +- Keep both autotools and CMake build paths healthy when changing shared build logic. + +## Autotools Workflow (preferred) + +For a fresh git checkout: + +```sh +autoreconf --force --install --verbose +./configure --prefix=$prefix --enable-developer +make -j +make -j check +``` + +For release-tarball style builds: + +```sh +./configure +make -j +make -j check +``` + +Notes: + +- Check that the environment variable 'prefix' is defined before running any command that uses it. +- Use `--prefix=` when installation path matters. +- Use `TESTSUITEFLAGS=-j` with `make check` when parallelizing tests. +- If `make check` fails due to missing `config.guess`, link `conf/config.guess` into `tests/` per `tests/README`. + +## CMake Workflow (supported) + +- Presets are defined in `CMakePresets.json`. +- Common presets: `default`, `debug`, `developer`, `asan`. + +Typical flow: + +```sh +cmake --preset developer +cmake --build --preset developer -j +ctest --preset developer --output-on-failure +``` + +## Testing Expectations + +- For code changes, run focused tests in affected areas first, then broader suites when risk is higher. +- Autotools default: `make -j check` +- CMake default: `ctest --preset default` (or `developer` for debug/developer builds) +- Unit/integration labels are available through CMake test presets (`unit`, `int`). +- If tests are flaky or expected-fail in legacy areas, call that out explicitly in your summary. + +## Documentation And Doxygen + +- Doxygen docs are built with: + +```sh +make docs +``` + +- Inputs are `doxy.conf` and `main_page.doxygen` (generated from `.in` templates by configure). +- When updating doc config/templates, keep generated and template files consistent with the chosen build workflow. + +## Legacy C++ Constraints + +- Match local style in touched files; do not perform unrelated formatting sweeps. +- Avoid API/ABI-impacting changes unless explicitly requested. +- Be conservative with ownership/lifetime changes in pointer-heavy code. +- Parser/scanner sources are generated (`*.tab.cc`, `*.tab.hh`, `lex.*.cc`); edit `*.yy`/`*.lex` sources, not generated outputs, unless the task explicitly requires generated-file updates. + +## Tooling And Quality + +- `clang-format` and pre-commit are configured (`README.pre-commit.md`, `.pre-commit-config.yaml`). +- Prefer running formatting/hooks only on changed files relevant to the task. +- Address sanitizer is supported (`--enable-asan` in autotools, `asan` preset in CMake) for memory-safety debugging. + +## Change Discipline + +- Do not revert unrelated local changes in a dirty worktree. +- Keep edits tightly scoped to the request. +- If you encounter unexpected repository changes during work, stop and ask how to proceed. +- Do not run destructive git commands unless explicitly requested. + +## Review Priorities + +When asked to review: + +1. Behavioral regressions in protocol/data-model behavior +2. Memory/resource safety and ownership lifetime issues +3. Parser/serialization correctness and edge cases +4. Build-system regressions (autotools and CMake) +5. Missing or weak regression coverage + +## Communication + +- State assumptions and environment details explicitly (build system, preset/configure flags, test scope). +- If full validation is not run, say exactly what was run and what was not. diff --git a/AISExceptions.h b/AISExceptions.h index e64f591d1..fea614b6f 100644 --- a/AISExceptions.h +++ b/AISExceptions.h @@ -43,6 +43,10 @@ class NoSuchPrimaryResource : public Error { class AISDatabaseReadFailed : public Error { public: AISDatabaseReadFailed() : Error("The AIS database read failed.") {} + + /** @brief Build an AIS read-failure error with additional context. + * @param msg Additional details about the read failure. + */ explicit AISDatabaseReadFailed(const string &msg) : Error(string("The AIS database read failed: ") + msg) {} }; @@ -50,6 +54,10 @@ class AISDatabaseReadFailed : public Error { class AISDatabaseWriteFailed : public Error { public: AISDatabaseWriteFailed() : Error("The AIS database write failed.") {} + + /** @brief Build an AIS write-failure error with additional context. + * @param msg Additional details about the write failure. + */ explicit AISDatabaseWriteFailed(const string &msg) : Error(string("The AIS database write failed: ") + msg) {} }; diff --git a/AISResources.h b/AISResources.h index 411ac65cf..baa9ff79a 100644 --- a/AISResources.h +++ b/AISResources.h @@ -45,8 +45,11 @@ using namespace std; namespace libdap { +/** @brief Sequence of ancillary resources associated with a primary entry. */ typedef vector ResourceVector; +/** @brief Mutable iterator over a `ResourceVector`. */ typedef ResourceVector::iterator ResourceVectorIter; +/** @brief Constant iterator over a `ResourceVector`. */ typedef ResourceVector::const_iterator ResourceVectorCIter; /** Maintain a database of AIS resources. Groups of AIS resources are diff --git a/AlarmHandler.h b/AlarmHandler.h index fe420fa1f..0d5ccb86e 100644 --- a/AlarmHandler.h +++ b/AlarmHandler.h @@ -50,6 +50,9 @@ class AlarmHandler : public EventHandler { // Ensure that d_stream gets initialized... AlarmHandler() : d_file(0) {} + /** @brief Build an alarm handler that writes timeout errors to a FILE sink. + * @param s Destination stream used by the handler. + */ explicit AlarmHandler(FILE *s) : d_file(s) //, d_stream( cout ) {} diff --git a/Ancillary.h b/Ancillary.h index 0b14a05ca..575a92a1b 100644 --- a/Ancillary.h +++ b/Ancillary.h @@ -42,14 +42,27 @@ namespace libdap { +/** @brief Locate and read ancillary DAS/DDS sidecar documents. */ class Ancillary { public: static string find_ancillary_file(const string &pathname, const string &ext, const string &dir, const string &file); static string find_group_ancillary_file(const string &pathname, const string &ext); + /** @brief Read ancillary DAS content and merge it into a `DAS`. + * @param das Destination DAS to populate. + * @param pathname Source dataset path or URL. + * @param dir Optional directory override for sidecar lookup. + * @param file Optional explicit ancillary filename. + */ static void read_ancillary_das(DAS &das, const string &pathname, const string &dir = "", const string &file = ""); + /** @brief Read ancillary DDS content and merge it into a `DDS`. + * @param dds Destination DDS to populate. + * @param pathname Source dataset path or URL. + * @param dir Optional directory override for sidecar lookup. + * @param file Optional explicit ancillary filename. + */ static void read_ancillary_dds(DDS &dds, const string &pathname, const string &dir = "", const string &file = ""); }; diff --git a/Array.h b/Array.h index 4e8a476b9..472089621 100644 --- a/Array.h +++ b/Array.h @@ -57,6 +57,7 @@ class XMLWriter; class D4Dimension; class D4Dimensions; +/** @brief Legacy maximum array size for 32-bit DAP2 interfaces. */ const int DODS_MAX_ARRAY = DODS_INT_MAX; /** This class is used to hold arrays of data. The elements of the array can @@ -159,8 +160,17 @@ class Array : public Vector { dimension() = default; + /** + * @brief Builds a dimension descriptor from size and optional name. + * @param s Unconstrained dimension size. + * @param n Dimension name. + */ dimension(int64_t s, string n) : size(s), name(std::move(n)), stop(s - 1), c_size(s) {} + /** + * @brief Builds a dimension descriptor from a shared DAP4 dimension. + * @param d Shared dimension definition. + */ explicit dimension(D4Dimension *d); }; @@ -171,18 +181,20 @@ class Array : public Vector { // by another module. However, there are issues in the current BES // that prevent us from implementing in this way. // So we need to use libdap to do the job. + /** @brief Per-chunk direct-I/O metadata for a variable. */ struct var_chunk_info_t { - unsigned int filter_mask; - unsigned long long chunk_direct_io_offset; - unsigned long long chunk_buffer_size; - vector chunk_coords; + unsigned int filter_mask; ///< Enabled filter bit-mask for this chunk. + unsigned long long chunk_direct_io_offset; ///< On-disk byte offset for direct I/O. + unsigned long long chunk_buffer_size; ///< Compressed chunk size in bytes. + vector chunk_coords; ///< Multidimensional chunk coordinates. }; + /** @brief Storage layout and filter metadata for direct-I/O reads. */ struct var_storage_info { - string filter; - vector deflate_levels; - vector chunk_dims; - vector var_chunk_info; + string filter; ///< Filter pipeline description. + vector deflate_levels; ///< Deflate levels per filter stage. + vector chunk_dims; ///< Chunk dimensions in row-major order. + vector var_chunk_info; ///< Per-chunk metadata records. }; private: @@ -200,12 +212,35 @@ class Array : public Vector { friend class D4Group; protected: + /** + * @brief Copies Array-specific members from another array. + * @param a Source array. + */ void _duplicate(const Array &a); + /** + * @brief Prints array values recursively to a C stdio stream. + * @param out Output file stream. + * @param index Current flat element index. + * @param dims Number of dimensions remaining in recursion. + * @param shape Constrained dimension sizes. + * @param is_root_grp True when printing in root-group context. + * @return Next flat index after printing. + */ uint64_t print_array(FILE *out, uint64_t index, unsigned int dims, uint64_t shape[], bool is_root_grp); + /** + * @brief Prints array values recursively to a C++ stream. + * @param out Output stream. + * @param index Current flat element index. + * @param dims Number of dimensions remaining in recursion. + * @param shape Constrained dimension sizes. + * @param is_root_grp True when printing in root-group context. + * @return Next flat index after printing. + */ uint64_t print_array(ostream &out, uint64_t index, unsigned int dims, uint64_t shape[], bool is_root_grp); + /** @brief Returns mutable access to the internal dimension list. */ std::vector &shape() { return _shape; } public: @@ -224,37 +259,96 @@ class Array : public Vector { @see dim_end() */ typedef std::vector::iterator Dim_iter; + /** + * @brief Constructs an array with element prototype. + * @param n Variable name. + * @param v Element prototype. + * @param is_dap4 True when this variable is part of a DAP4 model. + */ Array(const string &n, BaseType *v, bool is_dap4 = false); + /** + * @brief Constructs an array with declaration metadata and prototype. + * @param n Variable name. + * @param d Declaration context. + * @param v Element prototype. + * @param is_dap4 True when this variable is part of a DAP4 model. + */ Array(const string &n, const string &d, BaseType *v, bool is_dap4 = false); Array(const Array &rhs); ~Array() override; + /** + * @brief Assigns from another array. + * @param rhs Source array. + * @return This instance after assignment. + */ Array &operator=(const Array &rhs); BaseType *ptr_duplicate() override; + /** @brief Returns true when this array is being used as a DAP2 Grid map/array component. */ bool is_dap2_grid(); void transform_to_dap4(D4Group *root, Constructor *container) override; + /** + * @brief Converts this DAP4 array into equivalent DAP2 values. + * @param parent_attr_table Destination attribute table for converted metadata. + * @param show_shared_dims True to include shared-dimension annotations. + * @return Heap-allocated list of DAP2 values derived from this array. + */ std::vector *transform_to_dap2(AttrTable *parent_attr_table, bool show_shared_dims = false) override; void add_var(BaseType *v, Part p = nil) override; + /** + * @brief Adds a child variable without copying. + * @param v Variable to append. + * @param p Constructor part selector. + */ void add_var_nocopy(BaseType *v, Part p = nil) override; void append_dim(int size, const string &name = ""); + /** + * @brief Appends a new dimension using 64-bit size. + * @param size Unconstrained dimension size. + * @param name Optional dimension name. + */ void append_dim_ll(int64_t size, const string &name = ""); + /** + * @brief Appends a shared DAP4 dimension. + * @param dim Shared dimension definition. + */ void append_dim(D4Dimension *dim); void prepend_dim(int size, const string &name = ""); + /** + * @brief Prepends a shared DAP4 dimension. + * @param dim Shared dimension definition. + */ void prepend_dim(D4Dimension *dim); void clear_all_dims(); void rename_dim(const string &oldName = "", const string &newName = ""); virtual void add_constraint(Dim_iter i, int start, int stride, int stop); + /** + * @brief Applies a 64-bit slice constraint to one dimension. + * @param i Iterator to the target dimension. + * @param start Slice start index. + * @param stride Slice stride. + * @param stop Slice stop index. + */ virtual void add_constraint_ll(Dim_iter i, int64_t start, int64_t stride, int64_t stop); + /** + * @brief Applies a shared-dimension-based constraint to one dimension. + * @param i Iterator to the target dimension. + * @param dim Shared dimension carrying the active slice. + */ virtual void add_constraint(Dim_iter i, D4Dimension *dim); virtual void reset_constraint(); virtual void clear_constraint(); // deprecated - virtual void update_length(int size = 0); // should be used internally only + virtual void update_length(int size = 0); // should be used internally only + /** + * @brief Recomputes total element count using 64-bit arithmetic. + * @param size Optional explicit size override; zero recomputes from dimensions. + */ virtual void update_length_ll(unsigned long long size = 0); // should be used internally only Dim_iter dim_begin(); @@ -265,29 +359,88 @@ class Array : public Vector { virtual int dimension_stop(Dim_iter i, bool constrained = false); virtual int dimension_stride(Dim_iter i, bool constrained = false); + /** + * @brief Returns unconstrained or constrained dimension size. + * @param i Dimension iterator. + * @param constrained True to use constrained size. + * @return Dimension size as a 64-bit value. + */ virtual int64_t dimension_size_ll(Dim_iter i, bool constrained = false); + /** + * @brief Returns unconstrained or constrained dimension start index. + * @param i Dimension iterator. + * @param constrained True to use constrained start. + * @return Dimension start index as a 64-bit value. + */ virtual int64_t dimension_start_ll(Dim_iter i, bool constrained = false); + /** + * @brief Returns unconstrained or constrained dimension stop index. + * @param i Dimension iterator. + * @param constrained True to use constrained stop. + * @return Dimension stop index as a 64-bit value. + */ virtual int64_t dimension_stop_ll(Dim_iter i, bool constrained = false); + /** + * @brief Returns unconstrained or constrained dimension stride. + * @param i Dimension iterator. + * @param constrained True to use constrained stride. + * @return Dimension stride as a 64-bit value. + */ virtual int64_t dimension_stride_ll(Dim_iter i, bool constrained = false); virtual string dimension_name(Dim_iter i); + /** + * @brief Returns the DAP4 shared-dimension object used by a dimension. + * @param i Dimension iterator. + * @return Shared dimension pointer, or null for local dimensions. + */ virtual D4Dimension *dimension_D4dim(Dim_iter i); virtual unsigned int dimensions(bool constrained = false); + /** + * @brief Returns this array's DAP4 map collection. + * @return Map collection pointer, or null when none is attached. + */ virtual D4Maps *maps(); void print_dap4(XMLWriter &xml, bool constrained = false) override; // These are all DAP2 output methods + /** + * @brief Prints the declaration using C++ streams. + * @param out Output stream. + * @param space Indentation prefix. + * @param print_semi True to print a trailing semicolon. + * @param constraint_info True to include projection details. + * @param constrained True to print constrained declarations. + * @param is_root_grp True when printing in root-group context. + * @param array_member True when printing as an array member declaration. + */ void print_decl(ostream &out, string space = " ", bool print_semi = true, bool constraint_info = false, bool constrained = false, bool is_root_grp = true, bool array_member = false) override; void print_xml(ostream &out, string space = " ", bool constrained = false) override; + /** + * @brief Prints XML representation using an XML writer. + * @param xml Output XML writer. + * @param constrained True to emit constrained form. + */ void print_xml_writer(XMLWriter &xml, bool constrained = false) override; + /** + * @brief Prints XML writer output for a configurable XML tag. + * @param out Output XML writer. + * @param constrained True to emit constrained form. + * @param tag XML tag name. + */ virtual void print_xml_writer_core(XMLWriter &out, bool constrained, string tag); + /** + * @brief Prints this array as a Grid map element using XML writer output. + * @param xml Output XML writer. + * @param constrained True to emit constrained form. + */ virtual void print_as_map_xml_writer(XMLWriter &xml, bool constrained); virtual void print_xml_core(FILE *out, string space, bool constrained, string tag); @@ -296,13 +449,37 @@ class Array : public Vector { // not used (?) virtual void print_as_map_xml(ostream &out, string space = " ", bool constrained = false); + /** + * @brief Prints values using C++ streams. + * @param out Output stream. + * @param space Indentation prefix. + * @param print_decl_p True to include declaration text. + * @param is_root_grp True when printing in root-group context. + */ void print_val(ostream &out, string space = "", bool print_decl_p = true, bool is_root_grp = true) override; void print_xml(FILE *out, string space = " ", bool constrained = false) override; virtual void print_as_map_xml(FILE *out, string space = " ", bool constrained = false); + /** + * @brief Prints values using C stdio. + * @param out Output file stream. + * @param space Indentation prefix. + * @param print_decl_p True to include declaration text. + * @param is_root_grp True when printing in root-group context. + */ void print_val(FILE *out, string space = "", bool print_decl_p = true, bool is_root_grp = true) override; + /** + * @brief Prints the declaration using C stdio. + * @param out Output file stream. + * @param space Indentation prefix. + * @param print_semi True to print a trailing semicolon. + * @param constraint_info True to include projection details. + * @param constrained True to print constrained declarations. + * @param child_grp True when printing a nested-group context. + * @param array_member True when printing as an array member declaration. + */ void print_decl(FILE *out, string space = " ", bool print_semi = true, bool constraint_info = false, - bool constrained = false, bool is_root_grp = true, bool array_member = false) override; + bool constrained = false, bool child_grp = true, bool array_member = false) override; bool check_semantics(string &msg, bool all = false) override; @@ -311,9 +488,19 @@ class Array : public Vector { void dump(ostream &strm) const override; // The following methods are for direct IO optimization. + /** @brief Returns whether direct-I/O metadata is enabled for this array. */ bool get_dio_flag() const { return direct_io_flag; } + /** + * @brief Enables or disables direct-I/O metadata behavior. + * @param dio_flag_value True to enable direct-I/O metadata. + */ void set_dio_flag(bool dio_flag_value = true) { direct_io_flag = dio_flag_value; } + /** @brief Returns mutable access to direct-I/O storage metadata. */ var_storage_info &get_var_storage_info() { return vs_info; } + /** + * @brief Replaces direct-I/O storage metadata. + * @param my_vs_info New storage metadata. + */ void set_var_storage_info(const var_storage_info &my_vs_info); }; diff --git a/AttrTable.h b/AttrTable.h index cf15aed45..9d8fafc0c 100644 --- a/AttrTable.h +++ b/AttrTable.h @@ -156,30 +156,35 @@ class AttrTable : public DapObj { This struct is public because its type is used in public typedefs. */ struct entry { - string name; - AttrType type; + string name; ///< Attribute name within the containing table. + AttrType type; ///< Attribute type tag. - bool is_alias; - string aliased_to; + bool is_alias; ///< True when this entry aliases another entry's value/container. + string aliased_to; ///< Alias target path or name. - bool is_global; // use this to mark non-container attributes. see below. + bool is_global; ///< Marks non-container attributes that are global to their constructor context. - bool is_utf8_str = false; + bool is_utf8_str = false; ///< True when string values should be emitted as UTF-8 text. // If type == Attr_container, use attributes to read the contained // table, otherwise use attr to read the vector of values. - AttrTable *attributes; - std::vector *attr; // a vector of values. jhrg 12/5/94 + AttrTable *attributes; ///< Nested container table when `type == Attr_container`. + std::vector *attr; ///< Scalar/vector values for non-container attributes. entry() : name(""), type(Attr_unknown), is_alias(false), aliased_to(""), is_global(true), attributes(0), attr(0) {} + /** + * @brief Copy-constructs an entry. + * @param rhs Entry to copy. + */ entry(const entry &rhs) : name(rhs.name), type(rhs.type), is_alias(rhs.is_alias), aliased_to(rhs.aliased_to), is_global(rhs.is_global), attributes(0), attr(0) { clone(rhs); } + /** @brief Deletes owned value or container storage for this entry. */ void delete_entry() { if (is_alias) // alias copies the pointers. return; @@ -194,6 +199,10 @@ class AttrTable : public DapObj { virtual ~entry() { delete_entry(); } + /** + * @brief Clones entry payload from another entry. + * @param rhs Entry that provides value/container payload. + */ void clone(const entry &rhs) { #if 0 name = rhs.name; @@ -222,6 +231,11 @@ class AttrTable : public DapObj { } } + /** + * @brief Assigns this entry from another entry. + * @param rhs Entry to copy. + * @return This entry after assignment. + */ entry &operator=(const entry &rhs) { if (this != &rhs) { delete_entry(); @@ -254,7 +268,9 @@ class AttrTable : public DapObj { } }; + /** @brief Read-only iterator over attribute entries. */ typedef std::vector::const_iterator Attr_citer; + /** @brief Mutable iterator over attribute entries. */ typedef std::vector::iterator Attr_iter; private: @@ -297,7 +313,16 @@ class AttrTable : public DapObj { @return A pointer to the parent AttrTable. */ virtual AttrTable *get_parent() const { return d_parent; } + /** + * @brief Reports whether this table models global attributes. + * @return True when this container is marked as global. + */ virtual bool is_global_attribute() const { return d_is_global_attribute; } + + /** + * @brief Marks whether this table models global attributes. + * @param ga True to mark the table as global. + */ virtual void set_is_global_attribute(bool ga) { d_is_global_attribute = ga; } virtual unsigned int append_attr(const string &name, const string &type, const string &value); @@ -313,6 +338,11 @@ class AttrTable : public DapObj { virtual AttrTable *recurrsive_find(const string &target, Attr_iter *location); Attr_iter simple_find(const string &target); + /** + * @brief Finds a direct child container by name. + * @param target Child container name. + * @return Matching child container or null. + */ AttrTable *simple_find_container(const string &target); virtual AttrTable *get_attr_table(const string &name); @@ -344,6 +374,12 @@ class AttrTable : public DapObj { virtual bool attr_alias(const string &alias, const string &name); bool has_dap4_types(const std::string &path, std::vector &inventory) const; + /** + * @brief Reports whether this table contains DAP4-only attribute types. + * @param path Path prefix used when recording discovered attributes. + * @param inventory Output list populated with names of DAP4-typed attributes. + * @return True if at least one DAP4-only attribute type is present. + */ bool is_dap4_type(const std::string &path, std::vector &inventory) const; virtual void print(FILE *out, string pad = " ", bool dereference = false); @@ -352,6 +388,10 @@ class AttrTable : public DapObj { virtual void print_xml(FILE *out, string pad = " ", bool constrained = false); virtual void print_xml(ostream &out, string pad = " ", bool constrained = false); + /** + * @brief Prints this table using the XML writer API. + * @param xml Destination XML writer. + */ void print_xml_writer(XMLWriter &xml); void print_dap4(XMLWriter &xml); diff --git a/BaseType.h b/BaseType.h index 9ba7e5713..3b696d69f 100644 --- a/BaseType.h +++ b/BaseType.h @@ -146,6 +146,7 @@ class BaseType : public DapObj { void m_duplicate(const BaseType &bt); public: + /** @brief Stack type used to record traversal paths through constructor variables. */ typedef stack btp_stack; // These ctors assume is_dap4 is false @@ -158,10 +159,22 @@ class BaseType : public DapObj { virtual string toString(); virtual void transform_to_dap4(D4Group *root, Constructor *container); + + /** + * @brief Convert this variable to its DAP2 form. + * @param parent_attr_table Destination attribute table that receives translated DAP4 metadata. + * @param show_shared_dims True to emit shared-dimension information where supported. + * @return Newly allocated DAP2 variables that represent this object. + */ virtual std::vector *transform_to_dap2(AttrTable *parent_attr_table, bool show_shared_dims = false); void dump(ostream &strm) const override; + /** + * @brief Assigns this variable from another variable. + * @param rhs Source variable. + * @return This instance after assignment. + */ BaseType &operator=(const BaseType &rhs); /** @@ -178,7 +191,16 @@ class BaseType : public DapObj { */ virtual void clear_local_data() { set_read_p(false); } + /** + * @brief Reports whether this variable uses DAP4 semantics. + * @return True when this instance belongs to a DAP4 model. + */ virtual bool is_dap4() const { return d_is_dap4; } + + /** + * @brief Sets whether this variable uses DAP4 semantics. + * @param v True when this instance belongs to a DAP4 model. + */ virtual void set_is_dap4(const bool v) { d_is_dap4 = v; } /** Clone this instance. Allocate a new instance and copy \c *this into @@ -261,6 +283,10 @@ class BaseType : public DapObj { virtual void set_parent(BaseType *parent); virtual BaseType *get_parent() const; + /** + * @brief Returns the root-most ancestor in this variable's containment chain. + * @return The outermost containing variable, or this variable when it has no parent. + */ virtual BaseType *get_ancestor(); virtual void transfer_attributes(AttrTable *at); @@ -303,6 +329,12 @@ class BaseType : public DapObj { virtual BaseType *var(const string &name, btp_stack &s); virtual void add_var(BaseType *bt, Part part = nil); + + /** + * @brief Adds a child variable without transferring ownership through duplication. + * @param bt Child variable to add. + * @param part Constructor section where the variable belongs. + */ virtual void add_var_nocopy(BaseType *bt, Part part = nil); virtual bool read(); @@ -314,18 +346,49 @@ class BaseType : public DapObj { virtual unsigned int width(bool constrained = false) const; + /** + * @brief Returns the serialized width in bytes as a 64-bit value. + * @param constrained True to compute size for the constrained projection. + * @return Width in bytes. + */ virtual int64_t width_ll(bool constrained = false) const; + /** + * @brief Prints this variable declaration to a C stdio stream. + * @param out Output file stream. + * @param space Indentation prefix. + * @param print_semi True to print a trailing semicolon. + * @param constraint_info True to include projection details. + * @param constrained True to emit constrained form. + * @param is_root_grp True when printing in root-group context. + * @param array_member True when printing as an array member declaration. + * @param is_array_member Alias for `array_member` used by some implementations. + */ virtual void print_decl(FILE *out, string space = " ", bool print_semi = true, bool constraint_info = false, bool constrained = false, bool is_root_grp = true, bool array_member = false); virtual void print_xml(FILE *out, string space = " ", bool constrained = false); + /** + * @brief Prints this variable declaration to a C++ stream. + * @param out Output stream. + * @param space Indentation prefix. + * @param print_semi True to print a trailing semicolon. + * @param constraint_info True to include projection details. + * @param constrained True to emit constrained form. + * @param is_root_grp True when printing in root-group context. + * @param array_member True when printing as an array member declaration. + */ virtual void print_decl(ostream &out, string space = " ", bool print_semi = true, bool constraint_info = false, bool constrained = false, bool is_root_grp = true, bool array_member = false); virtual void print_xml(ostream &out, string space = " ", bool constrained = false); + /** + * @brief Prints this variable in XML form using an XML writer. + * @param xml Destination XML writer. + * @param constrained True to emit constrained form. + */ virtual void print_xml_writer(XMLWriter &xml, bool constrained = false); virtual void print_dap4(XMLWriter &xml, bool constrained = false); @@ -522,7 +585,8 @@ class BaseType : public DapObj { @param space This value is passed to the print_decl() function, and controls the leading spaces of the output. @param print_decl_p A boolean value controlling whether the - variable declaration is printed as well as the value. */ + variable declaration is printed as well as the value. + @param is_root_grp True when printing in root-group context. */ virtual void print_val(FILE *out, string space = "", bool print_decl_p = true, bool is_root_grp = true); @@ -539,7 +603,8 @@ class BaseType : public DapObj { @param space This value is passed to the print_decl() function, and controls the leading spaces of the output. @param print_decl_p A boolean value controlling whether the - variable declaration is printed as well as the value. */ + variable declaration is printed as well as the value. + @param is_root_grp True when printing in root-group context. */ virtual void print_val(ostream &out, string space = "", bool print_decl_p = true, bool is_root_grp = true) = 0; //@} diff --git a/BaseTypeFactory.h b/BaseTypeFactory.h index 2f2ba6401..87e1ac8bd 100644 --- a/BaseTypeFactory.h +++ b/BaseTypeFactory.h @@ -82,13 +82,15 @@ class BaseTypeFactory { virtual ~BaseTypeFactory() {} /** + * @brief Build a new variable for the requested type. * Build a new variable and return it using a BaseType pointer. The - * type of the variable is given using Type enumeration. + * type of the variable is given using Type enumeration. * * @note Added for DAP4 * - * @param t The type of the variable to create - * @parma name The (optional) name of the variable. + * @param t The type of the variable to create. + * @param name Optional variable name. + * @return Newly allocated variable instance. */ virtual BaseType *NewVariable(Type t, const string &name = "") const; @@ -99,20 +101,46 @@ class BaseTypeFactory { */ virtual BaseTypeFactory *ptr_duplicate() const { throw InternalErr(__FILE__, __LINE__, "Not Implemented."); } + /** @brief Builds a `Byte` variable. @param n Optional variable name. @return Newly allocated variable instance. */ virtual Byte *NewByte(const string &n = "") const; + /** @brief Builds an `Int16` variable. @param n Optional variable name. @return Newly allocated variable instance. + */ virtual Int16 *NewInt16(const string &n = "") const; + /** @brief Builds a `UInt16` variable. @param n Optional variable name. @return Newly allocated variable instance. + */ virtual UInt16 *NewUInt16(const string &n = "") const; + /** @brief Builds an `Int32` variable. @param n Optional variable name. @return Newly allocated variable instance. + */ virtual Int32 *NewInt32(const string &n = "") const; + /** @brief Builds a `UInt32` variable. @param n Optional variable name. @return Newly allocated variable instance. + */ virtual UInt32 *NewUInt32(const string &n = "") const; + /** @brief Builds a `Float32` variable. @param n Optional variable name. @return Newly allocated variable instance. + */ virtual Float32 *NewFloat32(const string &n = "") const; + /** @brief Builds a `Float64` variable. @param n Optional variable name. @return Newly allocated variable instance. + */ virtual Float64 *NewFloat64(const string &n = "") const; + /** @brief Builds a `Str` variable. @param n Optional variable name. @return Newly allocated variable instance. */ virtual Str *NewStr(const string &n = "") const; + /** @brief Builds a `Url` variable. @param n Optional variable name. @return Newly allocated variable instance. */ virtual Url *NewUrl(const string &n = "") const; + /** + * @brief Builds an `Array` variable. + * @param n Optional variable name. + * @param v Optional element prototype. + * @return Newly allocated variable instance. + */ virtual Array *NewArray(const string &n = "", BaseType *v = 0) const; + /** @brief Builds a `Structure` variable. @param n Optional variable name. @return Newly allocated variable + * instance. */ virtual Structure *NewStructure(const string &n = "") const; + /** @brief Builds a `Sequence` variable. @param n Optional variable name. @return Newly allocated variable instance. + */ virtual Sequence *NewSequence(const string &n = "") const; + /** @brief Builds a `Grid` variable. @param n Optional variable name. @return Newly allocated variable instance. */ virtual Grid *NewGrid(const string &n = "") const; }; diff --git a/Byte.h b/Byte.h index fed2f7e0e..88f2bd067 100644 --- a/Byte.h +++ b/Byte.h @@ -58,6 +58,7 @@ namespace libdap { */ class Byte : public BaseType { protected: + /// Stored scalar byte value. dods_byte d_buf; public: @@ -66,13 +67,34 @@ class Byte : public BaseType { ~Byte() override {} + /** + * @brief Copy-constructs a byte variable from another instance. + * + * The new instance copies the source value and metadata. + * + * @param copy_from Source instance to copy. + */ Byte(const Byte ©_from); + /** + * @brief Assigns from another byte variable. + * + * Replaces this instance's value and metadata with those of `rhs`. + * + * @param rhs Source instance. + * @return This instance after assignment. + */ Byte &operator=(const Byte &rhs); unsigned int width(bool = false) const override { return sizeof(dods_byte); } - int64_t width_ll(bool = false) const override { return sizeof(dods_byte); } + /** + * @brief Returns the storage width in bytes. + * + * @param constrained Ignored for scalar byte values. + * @return Number of bytes used by the byte value. + */ + int64_t width_ll(bool constrained = false) const override { return sizeof(dods_byte); } BaseType *ptr_duplicate() override; @@ -91,11 +113,34 @@ class Byte : public BaseType { virtual bool set_value(const dods_byte value); virtual dods_byte value() const; + /** + * @brief Writes this value using C stdio output. + * + * @param out Output file stream. + * @param space Indentation prefix. + * @param print_decl_p True to include declaration text. + * @param is_root_grp True when printing in the root group context. + */ void print_val(FILE *out, string space = "", bool print_decl_p = true, bool is_root_grp = true) override; + /** + * @brief Writes this value using C++ stream output. + * + * @param out Output stream. + * @param space Indentation prefix. + * @param print_decl_p True to include declaration text. + * @param is_root_grp True when printing in the root group context. + */ void print_val(ostream &out, string space = "", bool print_decl_p = true, bool is_root_grp = true) override; bool ops(BaseType *b, int op) override; bool d4_ops(BaseType *b, int op) override; + /** + * @brief Converts this DAP4 value into equivalent DAP2 value objects. + * + * @param parent_attr_table Destination attribute table for converted metadata. + * @param show_shared_dims True to include shared-dimension annotations. + * @return A heap-allocated list of DAP2 values corresponding to this object. + */ std::vector *transform_to_dap2(AttrTable *parent_attr_table, bool show_shared_dims = false) override; void dump(ostream &strm) const override; diff --git a/Clause.h b/Clause.h index 485a94e35..69386b32d 100644 --- a/Clause.h +++ b/Clause.h @@ -105,8 +105,24 @@ struct Clause { Clause &operator=(const Clause &); public: + /** + * @brief Builds a relational clause. + * @param oper Relational operator token. + * @param a1 Left-hand operand. + * @param rv Right-hand operand list. + */ Clause(const int oper, rvalue *a1, rvalue_list *rv); + /** + * @brief Builds a boolean-function clause. + * @param func Boolean function to evaluate. + * @param rv Function argument list. + */ Clause(bool_func func, rvalue_list *rv); + /** + * @brief Builds a value-returning function clause. + * @param func Function returning a `BaseType*`. + * @param rv Function argument list. + */ Clause(btp_func func, rvalue_list *rv); Clause(); diff --git a/Connect.h b/Connect.h index 9dec0507f..56bf901a5 100644 --- a/Connect.h +++ b/Connect.h @@ -155,6 +155,7 @@ class Connect { virtual ~Connect(); + /** @brief Returns true when this connection targets a local dataset/file. */ bool is_local(); // *** Add get_* versions of accessors. 02/27/03 jhrg @@ -166,8 +167,14 @@ class Connect { void set_xdap_protocol(int major, int minor); void set_cache_enabled(bool enabled); + /** @brief Returns whether HTTP caching is enabled for this connection. */ bool is_cache_enabled(); + /** + * @brief Sets the `XDAP-Accept` header version sent to the server. + * @param major Accepted protocol major version. + * @param minor Accepted protocol minor version. + */ void set_xdap_accept(int major, int minor); /** Return the protocol/implementation version of the most recent @@ -201,12 +208,31 @@ class Connect { virtual void request_data(DataDDS &data, string expr = ""); virtual void request_data_url(DataDDS &data); + /** + * @brief Requests a DataDDX response for this dataset. + * @param data Destination DataDDS object. + * @param expr Optional constraint expression. + */ virtual void request_data_ddx(DataDDS &data, string expr = ""); + /** + * @brief Requests a DataDDX response using the CE embedded in the current URL. + * @param data Destination DataDDS object. + */ virtual void request_data_ddx_url(DataDDS &data); virtual void read_data(DataDDS &data, Response *rs); virtual void read_data_no_mime(DataDDS &data, Response *rs); + /** + * @brief Parses a DAP2 data response (with MIME headers) into a DDS. + * @param data Destination DDS. + * @param rs Response object containing the payload. + */ virtual void read_data(DDS &data, Response *rs); + /** + * @brief Parses a DAP2 data response body (without MIME headers) into a DDS. + * @param data Destination DDS. + * @param rs Response object containing the payload. + */ virtual void read_data_no_mime(DDS &data, Response *rs); }; diff --git a/ConstraintEvaluator.h b/ConstraintEvaluator.h index e2fce604d..5ec29d0ad 100644 --- a/ConstraintEvaluator.h +++ b/ConstraintEvaluator.h @@ -56,10 +56,14 @@ class ConstraintEvaluator { friend class func_name_is; public: + /** @brief Read-only iterator over parsed CE clauses. */ typedef std::vector::const_iterator Clause_citer; + /** @brief Mutable iterator over parsed CE clauses. */ typedef std::vector::iterator Clause_iter; + /** @brief Read-only iterator over temporary constant values. */ typedef std::vector::const_iterator Constants_citer; + /** @brief Mutable iterator over temporary constant values. */ typedef std::vector::iterator Constants_iter; ConstraintEvaluator(); diff --git a/Constructor.h b/Constructor.h index 4945bf2c5..583e86c08 100644 --- a/Constructor.h +++ b/Constructor.h @@ -44,20 +44,53 @@ class Constructor : public BaseType { void m_duplicate(const Constructor &s); protected: + /** @brief Child variables owned by this constructor instance. */ std::vector d_vars; + /** + * @brief Finds a descendant variable by leaf-name match. + * @param name Name fragment to match. + * @param s Optional stack used to record the match path. + * @return Matching variable, or null when none is found. + */ BaseType *m_leaf_match(const string &name, btp_stack *s = nullptr); + /** + * @brief Finds a descendant variable by exact fully-qualified match. + * @param name Fully-qualified name to match. + * @param s Optional stack used to record the match path. + * @return Matching variable, or null when none is found. + */ BaseType *m_exact_match(const string &name, btp_stack *s = nullptr); + /** + * @brief Constructs a constructor type with name and explicit type. + * @param name Variable name. + * @param type Concrete constructor type. + * @param is_dap4 True when this variable is part of a DAP4 model. + */ Constructor(const string &name, const Type &type, bool is_dap4 = false) : BaseType(name, type, is_dap4) {} + /** + * @brief Constructs a constructor type with dataset declaration metadata. + * @param name Variable name. + * @param dataset Declaration context. + * @param type Concrete constructor type. + * @param is_dap4 True when this variable is part of a DAP4 model. + */ Constructor(const string &name, const string &dataset, const Type &type, bool is_dap4 = false) : BaseType(name, dataset, type, is_dap4) {} + /** + * @brief Copy-constructs a constructor and duplicates child variables. + * @param copy_from Source constructor. + */ Constructor(const Constructor ©_from) : BaseType(copy_from) { m_duplicate(copy_from); } public: + /** @brief Iterator type for read-only traversal of child variables. */ typedef std::vector::const_iterator Vars_citer; + /** @brief Iterator type for mutable traversal of child variables. */ typedef std::vector::iterator Vars_iter; + /** @brief Reverse iterator type for mutable traversal of child variables. */ typedef std::vector::reverse_iterator Vars_riter; Constructor() = delete; // Why? jhrg 4/25/22 @@ -67,6 +100,11 @@ class Constructor : public BaseType { delete var; } + /** + * @brief Assigns this constructor from another. + * @param rhs Source constructor. + * @return This instance after assignment. + */ Constructor &operator=(const Constructor &rhs) { if (this == &rhs) return *this; @@ -126,6 +164,7 @@ class Constructor : public BaseType { // DAP4 void compute_checksum(Crc32 &checksum) override; + /** @brief Reads any required DAP4-side data into this constructor. */ void intern_data() override; void serialize(D4StreamMarshaller &m, DMR &dmr, bool filter = false) override; void deserialize(D4StreamUnMarshaller &um, DMR &dmr) override; @@ -142,6 +181,16 @@ class Constructor : public BaseType { void set_in_selection(bool state) override; + /** + * @brief Prints the declaration using C++ streams. + * @param out Output stream. + * @param space Indentation prefix. + * @param print_semi True to print a trailing semicolon. + * @param constraint_info True to include projection details. + * @param constrained True to print constrained declarations. + * @param is_root_grp True when printing in root-group context. + * @param array_member True when printing as an array member declaration. + */ void print_decl(ostream &out, string space = " ", bool print_semi = true, bool constraint_info = false, bool constrained = false, bool is_root_grp = true, bool array_member = false) override; @@ -149,19 +198,53 @@ class Constructor : public BaseType { void print_dap4(XMLWriter &xml, bool constrained = false) override; + /** + * @brief Prints XML representation using an XML writer. + * @param xml Output XML writer. + * @param constrained True to emit constrained form. + */ void print_xml_writer(XMLWriter &xml, bool constrained = false) override; + /** + * @brief Prints the declaration using C stdio. + * @param out Output file stream. + * @param space Indentation prefix. + * @param print_semi True to print a trailing semicolon. + * @param constraint_info True to include projection details. + * @param constrained True to print constrained declarations. + * @param is_root_grp True when printing in root-group context. + * @param array_member True when printing as an array member declaration. + */ void print_decl(FILE *out, string space = " ", bool print_semi = true, bool constraint_info = false, bool constrained = false, bool is_root_grp = true, bool array_member = false) override; void print_xml(FILE *out, string space = " ", bool constrained = false) override; + /** + * @brief Prints values using C stdio. + * @param out Output file stream. + * @param space Indentation prefix. + * @param print_decl_p True to include declaration text. + * @param is_root_grp True when printing in root-group context. + */ void print_val(FILE *out, string space = "", bool print_decl_p = true, bool is_root_grp = true) override; + /** + * @brief Prints values using C++ streams. + * @param out Output stream. + * @param space Indentation prefix. + * @param print_decl_p True to include declaration text. + * @param is_root_grp True when printing in root-group context. + */ void print_val(ostream &out, string space = "", bool print_decl_p = true, bool is_root_grp = true) override; bool check_semantics(string &msg, bool all = false) override; void transfer_attributes(AttrTable *at) override; + /** + * @brief Builds an attribute table that stores dropped-variable metadata. + * @param dropped_vars Variables omitted from a transformed response. + * @return Newly allocated attribute table describing dropped variables. + */ static AttrTable *make_dropped_vars_attr_table(vector *dropped_vars); void dump(ostream &strm) const override; diff --git a/D4AsyncUtil.h b/D4AsyncUtil.h index 38896e15d..7b5333897 100644 --- a/D4AsyncUtil.h +++ b/D4AsyncUtil.h @@ -12,8 +12,10 @@ namespace libdap { +/** @brief Enumerates standardized async rejection reasons. */ enum RejectReasonCode { TIME, UNAVAILABLE, PRIVILEGES, OTHER }; +/** @brief Utility for writing DAP2/DAP4 asynchronous status responses. */ class D4AsyncUtil { private: #if 0 @@ -25,12 +27,16 @@ class D4AsyncUtil { D4AsyncUtil(); virtual ~D4AsyncUtil(); + /// XML attribute name used to inject a stylesheet reference. const static string STYLESHEET_REFERENCE_KEY; /** * @brief Write the DAP4 AsyncRequired response. * Print the AsyncRequired in XML form. * @param xml Print to this XMLWriter instance + * @param expectedDelay Estimated delay before an accepted response can be polled. + * @param responseLifetime Maximum lifetime of the eventual asynchronous response. + * @param stylesheet_ref Optional stylesheet URL to include in the XML. */ void writeD4AsyncRequired(XMLWriter &xml, long expectedDelay, long responseLifetime, string *stylesheet_ref = 0); @@ -38,6 +44,10 @@ class D4AsyncUtil { * @brief Write the DAP4 AsyncAccepted response. * Write the AsyncAccepted in XML form. * @param xml Print to this XMLWriter instance + * @param expectedDelay Estimated delay before the result is expected. + * @param responseLifetime Lifetime of the asynchronous response resource. + * @param asyncResourceUrl URL clients use to poll for the response. + * @param stylesheet_ref Optional stylesheet URL to include in the XML. */ void writeD4AsyncAccepted(XMLWriter &xml, long expectedDelay, long responseLifetime, string asyncResourceUrl, string *stylesheet_ref = 0); @@ -46,6 +56,7 @@ class D4AsyncUtil { * @brief Write the DAP4 AsyncPending response. * Write the DAP4 AsyncPending in XML form. * @param xml Print to this XMLWriter instance + * @param stylesheet_ref Optional stylesheet URL to include in the XML. */ void writeD4AsyncPending(XMLWriter &xml, string *stylesheet_ref = 0); @@ -53,6 +64,7 @@ class D4AsyncUtil { * @brief Write the DAP4 AsyncResponseGone response. * Write the DAP4 AsyncRequired in XML form. * @param xml Print to this XMLWriter instance + * @param stylesheet_ref Optional stylesheet URL to include in the XML. */ void writeD4AsyncResponseGone(XMLWriter &xml, string *stylesheet_ref = 0); @@ -60,20 +72,51 @@ class D4AsyncUtil { * @brief Write the DAP4 ResponseRejected response. * Write the DAP4 AsyncRequired in XML form. * @param xml Print to this XMLWriter instance + * @param code Machine-readable reason for rejection. + * @param description Human-readable rejection description. + * @param stylesheet_ref Optional stylesheet URL to include in the XML. */ void writeD4AsyncResponseRejected(XMLWriter &xml, RejectReasonCode code, string description, string *stylesheet_ref = 0); + + /** @brief Convert a rejection code to its protocol string value. + * @param code Rejection reason code. + * @return Protocol token for `code`. + */ string getRejectReasonCodeString(RejectReasonCode code); /** * @brief Write the DAP2 AsyncRequired response . * Write the DAP2 AsyncRequired in XML form. * @param xml Print to this XMLWriter instance + * @param expectedDelay Estimated delay before an accepted response can be polled. + * @param responseLifetime Maximum lifetime of the eventual asynchronous response. */ void writeD2AsyncRequired(XMLWriter &xml, long expectedDelay, long responseLifetime); + + /** @brief Write a DAP2 AsyncAccepted XML response. + * @param xml Destination XML writer. + * @param expectedDelay Estimated delay before the result is expected. + * @param responseLifetime Lifetime of the asynchronous response resource. + * @param asyncResourceUrl URL clients use to poll for the response. + */ void writeD2AsyncAccepted(XMLWriter &xml, long expectedDelay, long responseLifetime, string asyncResourceUrl); + + /** @brief Write a DAP2 AsyncPending XML response. + * @param xml Destination XML writer. + */ void writeD2AsyncPending(XMLWriter &xml); + + /** @brief Write a DAP2 AsyncResponseGone XML response. + * @param xml Destination XML writer. + */ void writeD2AsyncResponseGone(XMLWriter &xml); + + /** @brief Write a DAP2 AsyncResponseRejected XML response. + * @param xml Destination XML writer. + * @param code Machine-readable reason for rejection. + * @param description Human-readable rejection description. + */ void writeD2AsyncResponseRejected(XMLWriter &xml, RejectReasonCode code, string description); }; diff --git a/D4Attributes.h b/D4Attributes.h index 660e6bfed..959a21618 100644 --- a/D4Attributes.h +++ b/D4Attributes.h @@ -40,6 +40,7 @@ namespace libdap { class AttrTable; class D4Attributes; +/** @brief Represents one DAP4 attribute value or container node. */ class D4Attribute : public DapObj { string d_name; D4AttributeType d_type; // Attributes are limited to the simple types @@ -58,46 +59,111 @@ class D4Attribute : public DapObj { void m_duplicate(const D4Attribute &src); public: + /** @brief Mutable iterator over scalar attribute values. */ typedef vector::iterator D4AttributeIter; + /** @brief Read-only iterator over scalar attribute values. */ typedef vector::const_iterator D4AttributeCIter; D4Attribute() : d_name(""), d_type(attr_null_c), d_attributes(0) {} + + /** + * @brief Builds an attribute with a name and declared type. + * @param name Attribute name. + * @param type Attribute type. + */ D4Attribute(const string &name, D4AttributeType type) : d_name(name), d_type(type), d_attributes(0) {} + /** + * @brief Copy-constructs an attribute. + * @param src Source attribute. + */ D4Attribute(const D4Attribute &src); ~D4Attribute() override; + + /** + * @brief Assigns this attribute from another attribute. + * @param rhs Source attribute. + * @return This attribute after assignment. + */ D4Attribute &operator=(const D4Attribute &rhs); + /** @brief Returns the attribute name. */ string name() const { return d_name; } + + /** + * @brief Sets the attribute name. + * @param name Attribute name. + */ void set_name(const string &name) { d_name = name; } + /** @brief Returns the attribute type. */ D4AttributeType type() const { return d_type; } + + /** + * @brief Sets the attribute type. + * @param type Attribute type. + */ void set_type(D4AttributeType type) { d_type = type; } + /** @brief Returns whether string values should be interpreted as UTF-8. */ bool get_utf8_str_flag() const { return is_utf8_str; } + + /** + * @brief Sets whether string values should be interpreted as UTF-8. + * @param utf8_str_flag True when string values are UTF-8 encoded text. + */ void set_utf8_str_flag(bool utf8_str_flag) { is_utf8_str = utf8_str_flag; } + /** + * @brief Appends one scalar value. + * @param value Value to append. + */ void add_value(const string &value) { d_values.push_back(value); } + + /** + * @brief Replaces scalar values with a vector of values. + * @param values New scalar values. + */ void add_value_vector(const vector &values) { d_values = values; } + /** @brief Returns an iterator to the first scalar value. */ D4AttributeIter value_begin() { return d_values.begin(); } + /** @brief Returns an iterator one past the last scalar value. */ D4AttributeIter value_end() { return d_values.end(); } + /** @brief Returns the number of scalar values. */ unsigned int num_values() const { return d_values.size(); } + + /** + * @brief Returns one scalar value by index. + * @param i Zero-based value index. + * @return The requested value. + */ string value(unsigned int i) const { return d_values[i]; } + /** + * @brief Returns the nested attribute container for `attr_container_c` attributes. + * @return Nested attribute container. + */ D4Attributes *attributes(); bool is_dap4_type(const std::string &path, std::vector &inventory); + /** + * @brief Prints this attribute in DAP4 DMR form. + * @param xml Destination XML writer. + */ void print_dap4(XMLWriter &xml) const; void dump(ostream &strm) const override; }; +/** @brief Container for a variable's DAP4 attributes. */ class D4Attributes : public DapObj { public: + /** @brief Mutable iterator over `D4Attribute` pointers. */ typedef vector::iterator D4AttributesIter; + /** @brief Read-only iterator over `D4Attribute` pointers. */ typedef vector::const_iterator D4AttributesCIter; private: @@ -114,6 +180,11 @@ class D4Attributes : public DapObj { public: D4Attributes() {} + + /** + * @brief Copy-constructs an attribute collection. + * @param rhs Source collection. + */ D4Attributes(const D4Attributes &rhs) { m_duplicate(rhs); } ~D4Attributes() override { @@ -123,6 +194,11 @@ class D4Attributes : public DapObj { } } + /** + * @brief Assigns this collection from another collection. + * @param rhs Source collection. + * @return This collection after assignment. + */ D4Attributes &operator=(const D4Attributes &rhs) { if (this == &rhs) return *this; @@ -133,10 +209,19 @@ class D4Attributes : public DapObj { void transform_to_dap4(AttrTable &at); void transform_attrs_to_dap2(AttrTable *d2_attr_table); + /** @brief Returns true when this collection has no attributes. */ bool empty() const { return d_attrs.empty(); } + /** + * @brief Appends a deep copy of an attribute. + * @param attr Source attribute. + */ void add_attribute(D4Attribute *attr) { d_attrs.push_back(new D4Attribute(*attr)); } + /** + * @brief Appends an attribute pointer without copying. + * @param attr Attribute pointer to store. + */ void add_attribute_nocopy(D4Attribute *attr) { d_attrs.push_back(attr); } /// Get an iterator to the start of the enumerations @@ -145,6 +230,11 @@ class D4Attributes : public DapObj { /// Get an iterator to the end of the enumerations D4AttributesIter attribute_end() { return d_attrs.end(); } + /** + * @brief Finds an attribute by name. + * @param name Attribute name. + * @return Matching attribute or null. + */ D4Attribute *find(const string &name); D4Attribute *get(const string &fqn); void erase(const string &fqn); @@ -159,6 +249,10 @@ class D4Attributes : public DapObj { bool has_dap4_types(const std::string &path, std::vector &inventory) const; + /** + * @brief Prints all attributes in DAP4 DMR form. + * @param xml Destination XML writer. + */ void print_dap4(XMLWriter &xml) const; void dump(ostream &strm) const override; diff --git a/D4BaseTypeFactory.h b/D4BaseTypeFactory.h index 9365c0214..623e168eb 100644 --- a/D4BaseTypeFactory.h +++ b/D4BaseTypeFactory.h @@ -80,8 +80,12 @@ class D4BaseTypeFactory : public BaseTypeFactory { Byte *NewByte(const string &n = "") const override; // The Int8 types are new for DAP4 + /** @brief Builds an `Int8` variable. @param n Optional variable name. @return Newly allocated variable instance. */ virtual Int8 *NewInt8(const string &n = "") const; + /** @brief Builds a DAP4 `Char` alias (`UInt8`) variable. @param n Optional variable name. @return Newly allocated + * variable instance. */ virtual Byte *NewChar(const string &n = "") const; + /** @brief Builds a `UInt8` variable. @param n Optional variable name. @return Newly allocated variable instance. */ virtual Byte *NewUInt8(const string &n = "") const; Int16 *NewInt16(const string &n = "") const override; @@ -90,25 +94,40 @@ class D4BaseTypeFactory : public BaseTypeFactory { UInt32 *NewUInt32(const string &n = "") const override; // New for DAP4 + /** @brief Builds an `Int64` variable. @param n Optional variable name. @return Newly allocated variable instance. + */ virtual Int64 *NewInt64(const string &n = "") const; + /** @brief Builds a `UInt64` variable. @param n Optional variable name. @return Newly allocated variable instance. + */ virtual UInt64 *NewUInt64(const string &n = "") const; Float32 *NewFloat32(const string &n = "") const override; Float64 *NewFloat64(const string &n = "") const override; + /** + * @brief Builds a DAP4 enum variable. + * @param n Optional variable name. + * @param type Backing integer type for the enum. + * @return Newly allocated enum variable. + */ virtual D4Enum *NewEnum(const string &n = "", Type type = dods_null_c) const; Str *NewStr(const string &n = "") const override; Url *NewUrl(const string &n = "") const override; virtual Url *NewURL(const string &n = "") const; + /** @brief Builds a `D4Opaque` variable. @param n Optional variable name. @return Newly allocated variable instance. + */ virtual D4Opaque *NewOpaque(const string &n = "") const; Array *NewArray(const string &n = "", BaseType *v = 0) const override; Structure *NewStructure(const string &n = "") const override; + /** @brief Builds a `D4Sequence` variable. @param n Optional variable name. @return Newly allocated variable + * instance. */ virtual D4Sequence *NewD4Sequence(const string &n = "") const; + /** @brief Builds a `D4Group` variable. @param n Optional group name. @return Newly allocated group instance. */ virtual D4Group *NewGroup(const string &n = "") const; }; diff --git a/D4Connect.h b/D4Connect.h index 642c638cc..ab887c1c3 100644 --- a/D4Connect.h +++ b/D4Connect.h @@ -34,6 +34,7 @@ class HTTPConnect; class DMR; class Response; +/** @brief Client-side helper for requesting/parsing DAP4 DMR and data responses. */ class D4Connect { private: HTTPConnect *d_http; @@ -61,6 +62,12 @@ class D4Connect { D4Connect &operator=(const D4Connect &); public: + /** + * @brief Builds a DAP4 connection to a URL. + * @param url Dataset URL. + * @param uname Optional username for authenticated requests. + * @param password Optional password for authenticated requests. + */ D4Connect(const std::string &url, std::string uname = "", std::string password = ""); virtual ~D4Connect(); diff --git a/D4Dimensions.h b/D4Dimensions.h index dadb65176..e916712c1 100644 --- a/D4Dimensions.h +++ b/D4Dimensions.h @@ -36,6 +36,7 @@ class D4Group; class D4Dimensions; class XMLWriter; +/** @brief Describes one named DAP4 shared dimension. */ class D4Dimension { string d_name; unsigned long long d_size; @@ -51,32 +52,52 @@ class D4Dimension { D4Dimension() : d_name(""), d_size(0), d_parent(0), d_constrained(false), d_c_start(0), d_c_stride(0), d_c_stop(0), d_used_by_projected_var(false) {} + + /** + * @brief Builds a named shared dimension. + * @param name Dimension name. + * @param size Unconstrained size. + * @param d Parent dimensions collection. + */ D4Dimension(const string &name, unsigned long long size, D4Dimensions *d = 0) : d_name(name), d_size(size), d_parent(d), d_constrained(false), d_c_start(0), d_c_stride(0), d_c_stop(0), d_used_by_projected_var(false) {} + /** @brief Returns the dimension name. */ string name() const { return d_name; } + /** @brief Sets the dimension name. @param name Dimension name. */ void set_name(const string &name) { d_name = name; } string fully_qualified_name() const; + /** @brief Returns the unconstrained dimension size. */ unsigned long long size() const { return d_size; } + /** @brief Sets the unconstrained dimension size. @param size Dimension size. */ void set_size(unsigned long long size) { d_size = size; } // Because we build these in the XML parser and it's all text... + /** @brief Sets the unconstrained dimension size from text. @param size Dimension size text. */ void set_size(const string &size); + /** @brief Returns the parent dimensions collection. */ D4Dimensions *parent() const { return d_parent; } + /** @brief Sets the parent dimensions collection. @param d Parent dimensions collection. */ void set_parent(D4Dimensions *d) { d_parent = d; } + /** @brief Returns true when this dimension is constrained by a slice. */ bool constrained() const { return d_constrained; } + /** @brief Returns the constrained start index. */ int64_t c_start() const { return d_c_start; } + /** @brief Returns the constrained stride. */ int64_t c_stride() const { return d_c_stride; } + /** @brief Returns the constrained stop index. */ int64_t c_stop() const { return d_c_stop; } + /** @brief Returns whether any projected variable uses this shared dimension. */ bool used_by_projected_var() const { return d_used_by_projected_var; } + /** @brief Sets whether any projected variable uses this shared dimension. @param state Usage flag. */ void set_used_by_projected_var(bool state) { d_used_by_projected_var = state; } /** - * Set this Shared Diemension's constraint. While an Array Dimension object uses a + * Set this Shared Dimension's constraint. While an Array Dimension object uses a * stop value of -1 to indicate the end of the dimension, this method does not support * that; the caller will have to sort out the correct end value for 'stop'. * @param start Starting index (zero-based) @@ -90,6 +111,10 @@ class D4Dimension { d_constrained = true; } + /** + * @brief Prints this dimension in DAP4 DMR form. + * @param xml Destination XML writer. + */ void print_dap4(XMLWriter &xml) const; }; @@ -107,6 +132,10 @@ class D4Dimensions { // Note Code in Array depends on the order of these 'new' dimensions // matching the 'old' dimensions they are derived from. See // Array::update_dimension_pointers. jhrg 8/25/14 + /** + * @brief Deep-copies dimensions and parent linkage from another collection. + * @param rhs Source dimensions collection. + */ void m_duplicate(const D4Dimensions &rhs) { D4DimensionsCIter i = rhs.d_dims.begin(); while (i != rhs.d_dims.end()) { @@ -120,10 +149,21 @@ class D4Dimensions { public: /// Iterator used for D4Dimensions typedef vector::iterator D4DimensionsIter; + /// Read-only iterator used for D4Dimensions typedef vector::const_iterator D4DimensionsCIter; D4Dimensions() : d_parent(0) {} + + /** + * @brief Builds a dimensions collection owned by a group. + * @param g Owning group. + */ D4Dimensions(D4Group *g) : d_parent(g) {} + + /** + * @brief Copy-constructs a dimensions collection. + * @param rhs Source collection. + */ D4Dimensions(const D4Dimensions &rhs) : d_parent(0) { m_duplicate(rhs); } virtual ~D4Dimensions() { @@ -132,6 +172,11 @@ class D4Dimensions { delete *i++; } + /** + * @brief Assigns this dimensions collection from another collection. + * @param rhs Source collection. + * @return This collection after assignment. + */ D4Dimensions &operator=(const D4Dimensions &rhs) { if (this == &rhs) return *this; @@ -142,7 +187,9 @@ class D4Dimensions { /// Does this D4Dimensions object actually have dimensions? bool empty() const { return d_dims.empty(); } + /** @brief Returns the owning group. */ D4Group *parent() const { return d_parent; } + /** @brief Sets the owning group. @param g Owning group. */ void set_parent(D4Group *g) { d_parent = g; } /** Append a new dimension. @@ -169,6 +216,11 @@ class D4Dimensions { /// Get an iterator to the end of the dimensions D4DimensionsIter dim_end() { return d_dims.end(); } + /** + * @brief Finds a dimension by name. + * @param name Dimension name. + * @return Matching dimension or null. + */ D4Dimension *find_dim(const string &name); /** Insert a dimension. @@ -189,6 +241,11 @@ class D4Dimensions { d_dims.insert(i, dim); } + /** + * @brief Prints all dimensions in DAP4 DMR form. + * @param xml Destination XML writer. + * @param constrained True to print constrained dimensions when available. + */ void print_dap4(XMLWriter &xml, bool constrained = false) const; }; diff --git a/D4Enum.h b/D4Enum.h index 2cc768c92..36aa354c0 100644 --- a/D4Enum.h +++ b/D4Enum.h @@ -56,7 +56,7 @@ class D4Enum : public BaseType { protected: // Use an unsigned 64-bit int. the value() and set_value() // accessors cast to other types as needed, including signed ones. - uint64_t d_buf; + uint64_t d_buf; ///< Stored enumeration value. private: Type d_element_type; @@ -91,14 +91,36 @@ class D4Enum : public BaseType { D4Enum(); // No empty constructor public: + /** + * @brief Builds an enum from the enumeration-definition name. + * @param name Variable name. + * @param enum_type Enumeration-definition name. + */ D4Enum(const string &name, const string &enum_type); + /** + * @brief Builds an enum with an explicit backing integer type. + * @param name Variable name. + * @param type Backing integer type. + */ D4Enum(const string &name, Type type); + /** + * @brief Builds an enum with dataset context and explicit backing type. + * @param name Variable name. + * @param dataset Dataset declaration context. + * @param type Backing integer type. + */ D4Enum(const string &name, const string &dataset, Type type); + /** @brief Copy-constructs an enum variable. @param src Source enum variable. */ D4Enum(const D4Enum &src) : BaseType(src) { m_duplicate(src); } + /** + * @brief Assigns this enum from another enum. + * @param rhs Source enum. + * @return This enum after assignment. + */ D4Enum &operator=(const D4Enum &rhs) { if (this == &rhs) return *this; @@ -109,15 +131,33 @@ class D4Enum : public BaseType { ~D4Enum() override {} + /** @brief Returns the linked enumeration definition. */ virtual D4EnumDef *enumeration() const { return d_enum_def; } + + /** + * @brief Links this variable to an enumeration definition. + * @param enum_def Enumeration definition to use. + */ virtual void set_enumeration(D4EnumDef *enum_def); BaseType *ptr_duplicate() override { return new D4Enum(*this); } + /** @brief Returns the enum backing integer type. */ Type element_type() { return d_element_type; } + + /** + * @brief Sets the enum backing integer type. + * @param type Backing integer type. + */ void set_element_type(Type type) { d_element_type = type; } + /** @brief Returns whether this enum should be interpreted as signed. */ bool is_signed() const { return d_is_signed; } + + /** + * @brief Sets signedness based on a DAP type. + * @param t DAP type used to infer signedness. + */ void set_is_signed(Type t); /** @@ -172,6 +212,11 @@ class D4Enum : public BaseType { void print_val(ostream &out, string space = "", bool print_decl_p = true, bool is_root_grp = true) override; + /** + * @brief Prints this enum in DAP4 XML form. + * @param xml Destination XML writer. + * @param constrained True to emit constrained form. + */ void print_xml_writer(XMLWriter &xml, bool constrained) override; bool ops(BaseType *b, int op) override; @@ -181,6 +226,12 @@ class D4Enum : public BaseType { unsigned int val2buf(void *, bool) override; unsigned int buf2val(void **) override; + /** + * @brief Converts this enum to its DAP2 representation. + * @param parent_attr_table Destination attribute table for converted metadata. + * @param show_shared_dims True to include shared-dimension metadata where relevant. + * @return Newly allocated DAP2 variable list. + */ std::vector *transform_to_dap2(AttrTable *parent_attr_table, bool show_shared_dims) override; }; diff --git a/D4EnumDefs.h b/D4EnumDefs.h index 60317c5a1..c0b7f7f28 100644 --- a/D4EnumDefs.h +++ b/D4EnumDefs.h @@ -39,6 +39,7 @@ namespace libdap { class D4EnumDefs; class D4Group; +/** @brief Defines one DAP4 Enumeration type and its label/value pairs. */ class D4EnumDef { string d_name; Type d_type; @@ -56,35 +57,66 @@ class D4EnumDef { void print_value(XMLWriter &xml, const D4EnumDef::tuple &tuple) const; public: + /** @brief Iterator over enumeration label/value tuples. */ typedef vector::iterator D4EnumValueIter; D4EnumDef() : d_name(""), d_type(dods_null_c), d_parent(0) {} + + /** + * @brief Builds an enumeration definition. + * @param n Enumeration name. + * @param t Backing integer type. + * @param e Parent enumeration-definition collection. + */ D4EnumDef(const string &n, const Type &t, D4EnumDefs *e = 0) : d_name(n), d_type(t), d_parent(e) {} + /** @brief Copy-constructs an enumeration definition. @param rhs Source definition. */ D4EnumDef(const D4EnumDef &rhs) = default; virtual ~D4EnumDef() {} + /** @brief Assigns this definition from another definition. @param rhs Source definition. @return This definition. + */ D4EnumDef &operator=(const D4EnumDef &rhs) = default; + /** @brief Returns the enumeration name. */ string name() const { return d_name; } + /** @brief Sets the enumeration name. @param n Enumeration name. */ void set_name(const string &n) { d_name = n; } + /** @brief Returns the backing integer type. */ Type type() const { return d_type; } + /** @brief Sets the backing integer type. @param t Backing integer type. */ void set_type(Type t) { d_type = t; } + /** @brief Returns the parent definition collection. */ D4EnumDefs *parent() const { return d_parent; } + /** @brief Sets the parent definition collection. @param e Parent definition collection. */ void set_parent(D4EnumDefs *e) { d_parent = e; } + /** @brief Returns true when this definition has no label/value pairs. */ bool empty() const { return d_tuples.empty(); } + /** + * @brief Adds one label/value pair to the enumeration definition. + * @param label Label text. + * @param value Integer value for the label. + */ void add_value(const string &label, long long value) { d_tuples.push_back(tuple(label, value)); } + /** @brief Returns an iterator to the first label/value tuple. */ D4EnumValueIter value_begin() { return d_tuples.begin(); } + /** @brief Returns an iterator one past the last label/value tuple. */ D4EnumValueIter value_end() { return d_tuples.end(); } + /** @brief Returns a mutable reference to tuple label text. @param i Tuple iterator. */ string &label(D4EnumValueIter i) { return (*i).label; } + /** @brief Returns tuple numeric value. @param i Tuple iterator. */ long long value(D4EnumValueIter i) { return (*i).value; } bool is_valid_enum_value(long long value); + /** + * @brief Prints this enumeration definition in DAP4 DMR form. + * @param xml Destination XML writer. + */ void print_dap4(XMLWriter &xml) const; }; @@ -107,10 +139,13 @@ class D4EnumDefs { } public: + /** @brief Mutable iterator over enumeration definitions. */ typedef vector::iterator D4EnumDefIter; + /** @brief Read-only iterator over enumeration definitions. */ typedef vector::const_iterator D4EnumDefCIter; D4EnumDefs() : d_parent(0) {} + /** @brief Copy-constructs an enumeration-definition collection. @param rhs Source collection. */ D4EnumDefs(const D4EnumDefs &rhs) { m_duplicate(rhs); } virtual ~D4EnumDefs() { @@ -120,6 +155,11 @@ class D4EnumDefs { } } + /** + * @brief Assigns this collection from another collection. + * @param rhs Source collection. + * @return This collection after assignment. + */ D4EnumDefs &operator=(const D4EnumDefs &rhs) { if (this == &rhs) return *this; @@ -127,9 +167,12 @@ class D4EnumDefs { return *this; } + /** @brief Returns true when there are no enumeration definitions. */ bool empty() const { return d_enums.empty(); } + /** @brief Returns the owning group. */ D4Group *parent() const { return d_parent; } + /** @brief Sets the owning group. @param g Owning group. */ void set_parent(D4Group *g) { d_parent = g; } /** Append a new D4EnumDef. @@ -137,6 +180,10 @@ class D4EnumDefs { * @param enum_def The enumeration. */ void add_enum(D4EnumDef *enum_def) { add_enum_nocopy(new D4EnumDef(*enum_def)); } + /** + * @brief Appends an enumeration definition pointer without deep-copying. + * @param enum_def Enumeration definition to store. + */ void add_enum_nocopy(D4EnumDef *enum_def) { enum_def->set_parent(this); d_enums.push_back(enum_def); @@ -148,6 +195,11 @@ class D4EnumDefs { /// Get an iterator to the end of the enumerations D4EnumDefIter enum_end() { return d_enums.end(); } + /** + * @brief Finds an enumeration definition by name. + * @param name Enumeration definition name. + * @return Matching definition or null. + */ D4EnumDef *find_enum_def(const string &name); /** @@ -164,6 +216,11 @@ class D4EnumDefs { d_enums.insert(i, enum_def_copy); } + /** + * @brief Prints all enumeration definitions in DAP4 DMR form. + * @param xml Destination XML writer. + * @param constrained Present for interface parity; ignored here. + */ void print_dap4(XMLWriter &xml, bool constrained = false) const; }; diff --git a/D4FilterClause.h b/D4FilterClause.h index c86617215..5fdd0b0ad 100644 --- a/D4FilterClause.h +++ b/D4FilterClause.h @@ -48,16 +48,25 @@ class D4FilterClauseList { void m_duplicate(const D4FilterClauseList &src); public: + /** @brief Mutable iterator over filter-clause pointers. */ typedef std::vector::iterator iter; + /** @brief Read-only iterator over filter-clause pointers. */ typedef std::vector::const_iterator citer; D4FilterClauseList() {} + /** @brief Copy-constructs a filter-clause list. @param src Source clause list. */ D4FilterClauseList(const D4FilterClauseList &src) { m_duplicate(src); } + /** @brief Builds a one-element filter-clause list. @param c Initial clause pointer. */ D4FilterClauseList(D4FilterClause *c) { add_clause(c); } virtual ~D4FilterClauseList(); + /** + * @brief Assigns this list from another list. + * @param rhs Source list. + * @return This list after assignment. + */ D4FilterClauseList &operator=(const D4FilterClauseList &rhs) { if (this == &rhs) return *this; @@ -67,13 +76,25 @@ class D4FilterClauseList { return *this; } + /** + * @brief Appends a filter clause pointer. + * @param c Clause pointer to append. + */ void add_clause(D4FilterClause *c) { d_clauses.push_back(c); } + /** + * @brief Returns a clause by index. + * @param i Zero-based clause index. + * @return Clause pointer at index `i`. + */ D4FilterClause *get_clause(unsigned int i) { return d_clauses.at(i); } + /** @brief Returns a const iterator to the first clause. */ citer cbegin() const { return d_clauses.begin(); } + /** @brief Returns a const iterator one past the last clause. */ citer cend() const { return d_clauses.end(); } + /** @brief Returns the number of clauses in this list. */ unsigned int size() const { return d_clauses.size(); } // get the clause value; this version supports functional clauses @@ -108,6 +129,7 @@ class D4FilterClauseList { */ class D4FilterClause { public: + /** @brief Comparison and special operators for DAP4 filter clauses. */ enum ops { // Stock relops null = 0, @@ -166,8 +188,14 @@ class D4FilterClause { assert(arg2 && "null arg2"); } + /** @brief Copy-constructs a filter clause. @param src Source clause. */ D4FilterClause(const D4FilterClause &src) { m_duplicate(src); } + /** + * @brief Assigns this clause from another clause. + * @param rhs Source clause. + * @return This clause after assignment. + */ D4FilterClause &operator=(const D4FilterClause &rhs) { if (this == &rhs) return *this; diff --git a/D4Function.h b/D4Function.h index b1e29cf28..760c4969a 100644 --- a/D4Function.h +++ b/D4Function.h @@ -38,6 +38,7 @@ class DMR; // to a function that takes...' but I used this to make the code fit more closely to // the pattern established by the DAP2 CE functions. jhrg 3/10/14 +/** @brief Signature type for DAP4 server-side function handlers. */ typedef BaseType *(*D4Function)(D4RValueList *, DMR &); } // namespace libdap diff --git a/D4Group.h b/D4Group.h index c5463c91c..77f9abc9b 100644 --- a/D4Group.h +++ b/D4Group.h @@ -63,23 +63,37 @@ class D4Group : public Constructor { D4Group *find_grp_internal(const string &grp_path); protected: + /** + * @brief Deep-copies group-local members from another group. + * @param g Source group. + */ void m_duplicate(const D4Group &g); public: + /** @brief Mutable iterator over child groups. */ typedef vector::iterator groupsIter; + /** @brief Read-only iterator over child groups. */ typedef vector::const_iterator groupsCIter; + /** @brief Builds a group with a name. @param name Group name. */ D4Group(const string &name); + /** @brief Builds a group with name and dataset context. @param name Group name. @param dataset Dataset context. */ D4Group(const string &name, const string &dataset); D4Group(const D4Group &rhs); ~D4Group() override; + /** + * @brief Assigns this group from another group. + * @param rhs Source group. + * @return This group after assignment. + */ D4Group &operator=(const D4Group &rhs); // This method returned a D4Group * previously. jhrg 11/17/16 BaseType *ptr_duplicate() override; + /** @brief Updates array dimension pointers after copy/parse operations. */ void update_variables_d4dimension_pointers(); // TODO Wire up the new D4Dimensions object to have this group as its parent. jhrg 8/22/22 /// Get the dimensions defined for this Group @@ -96,6 +110,11 @@ class D4Group : public Constructor { Array *find_map_source(const string &path); + /** + * @brief Finds an enumeration definition by path. + * @param path Enumeration definition path. + * @return Matching definition or null. + */ D4EnumDef *find_enum_def(const string &path); /// Get the enumerations defined for this Group @@ -110,11 +129,23 @@ class D4Group : public Constructor { /// Check if this group contains enumerations. bool has_enum_defs() const { return (d_enum_defs != nullptr); } + /** + * @brief Finds the first variable in this group hierarchy that uses a dimension. + * @param dim Dimension to search for. + * @return First matching variable or null. + */ BaseType *find_first_var_that_uses_dimension(D4Dimension *dim); + + /** + * @brief Finds the first variable in this group hierarchy that uses an enumeration. + * @param enum_def Enumeration definition to search for. + * @return First matching variable or null. + */ BaseType *find_first_var_that_uses_enumeration(D4EnumDef *enum_def); BaseType *find_var(const string &name); + /** @brief Returns all immediate child groups. */ const vector &groups() const { return d_groups; } /// Get an iterator to the start of the values @@ -123,17 +154,36 @@ class D4Group : public Constructor { /// Get an iterator to the end of the values groupsIter grp_end() { return d_groups.end(); } + /** + * @brief Appends a deep copy of a child group. + * @param g Child group to copy and append. + */ void add_group(const D4Group *g) { add_group_nocopy(new D4Group(*g)); } + /** + * @brief Appends a child group pointer without copying. + * @param g Child group to append. + */ void add_group_nocopy(D4Group *g) { g->set_parent(this); d_groups.push_back(g); } + + /** + * @brief Inserts a child group pointer before the given iterator. + * @param g Child group to insert. + * @param i Insertion point. + */ void insert_group_nocopy(D4Group *g, groupsIter i) { g->set_parent(this); d_groups.insert(i, g); } + /** + * @brief Finds an immediate child group by name. + * @param grp_name Child group name. + * @return Matching child group or null. + */ D4Group *find_child_grp(const string &grp_name); long request_size(bool constrained); diff --git a/D4Maps.h b/D4Maps.h index 403990226..68decb766 100644 --- a/D4Maps.h +++ b/D4Maps.h @@ -86,9 +86,12 @@ class D4Map { ///@} virtual ~D4Map() = default; + /** @brief Returns this map name. */ const string &name() const { return d_name; } + /** @brief Sets this map name. @param name Map name. */ void set_name(const string &name) { d_name = name; } + /** @brief Returns the fully-qualified path to the source array. */ const std::string &get_array_path() const { return d_array_path; } ///@note We can set the path even if the referenced Array does not yet exist! void set_array_path(const std::string &array) { d_array_path = array; } @@ -102,11 +105,19 @@ class D4Map { Array *array() const { return d_array; } ///@} + /** + * @brief Sets the cached source-array pointer and path. + * @param array Source array. + */ void set_array(Array *array) { d_array = array; d_array_path = array->FQN(); } + /** + * @brief Prints this map in DAP4 DMR form. + * @param xml Destination XML writer. + */ virtual void print_dap4(XMLWriter &xml); }; @@ -116,7 +127,9 @@ class D4Map { */ class D4Maps { public: + /** @brief Mutable iterator over map objects. */ typedef vector::iterator D4MapsIter; + /** @brief Read-only iterator over map objects. */ typedef vector::const_iterator D4MapsCIter; private: @@ -137,7 +150,17 @@ class D4Maps { // See comment below at operator=(). jhrg 9/12/23 D4Maps(const D4Maps &maps) = delete; + /** + * @brief Builds an empty map collection for a parent array. + * @param parent Parent array that owns this map collection. + */ explicit D4Maps(const Array *parent) : d_parent(parent) {} + + /** + * @brief Copy-constructs a map collection for a new parent array. + * @param maps Source map collection. + * @param parent Parent array for the copy. + */ D4Maps(const D4Maps &maps, const Array *parent) { m_duplicate(maps, parent); } virtual ~D4Maps() { @@ -156,6 +179,10 @@ class D4Maps { */ void add_map(D4Map *map) { d_maps.push_back(map); } + /** + * @brief Removes a map by name. + * @param map Map identifying the name to remove. + */ void remove_map(D4Map *map) { d_maps.erase( std::remove_if(d_maps.begin(), d_maps.end(), [&map](const D4Map *m) { return m->name() == map->name(); }), @@ -175,14 +202,27 @@ class D4Maps { #endif } + /** + * @brief Returns one map by index. + * @param i Zero-based map index. + * @return Map at index `i`. + */ D4Map *get_map(int i) const { return d_maps.at(i); } + /** @brief Returns an iterator to the first map. */ D4MapsIter map_begin() { return d_maps.begin(); } + /** @brief Returns an iterator one past the last map. */ D4MapsIter map_end() { return d_maps.end(); } + /** @brief Returns the number of maps in this collection. */ int size() const { return d_maps.size(); } + /** @brief Returns true when this collection has no maps. */ bool empty() const { return d_maps.empty(); } + /** + * @brief Prints all maps in DAP4 DMR form. + * @param xml Destination XML writer. + */ virtual void print_dap4(XMLWriter &xml) { for (const auto &d_map : d_maps) d_map->print_dap4(xml); diff --git a/D4Opaque.h b/D4Opaque.h index 81235bf6e..10b5f5e2e 100644 --- a/D4Opaque.h +++ b/D4Opaque.h @@ -34,21 +34,32 @@ class Crc32; namespace libdap { +/** @brief DAP4 opaque binary blob type. */ class D4Opaque : public BaseType { public: + /** @brief In-memory container type for opaque bytes. */ typedef std::vector dods_opaque; protected: - dods_opaque d_buf; + dods_opaque d_buf; ///< Stored opaque bytes. public: + /** @brief Builds an opaque variable with a name. @param n Variable name. */ D4Opaque(const std::string &n) : BaseType(n, dods_opaque_c, true /*is_dap4*/), d_buf(0) {} + /** @brief Builds an opaque variable with name and dataset context. @param n Variable name. @param d Dataset + * context. */ D4Opaque(const std::string &n, const std::string &d) : BaseType(n, d, dods_opaque_c, true /*is_dap4*/), d_buf(0) {} ~D4Opaque() override {} + /** @brief Copy-constructs an opaque variable. @param copy_from Source variable. */ D4Opaque(const D4Opaque ©_from) : BaseType(copy_from) { d_buf = copy_from.d_buf; } + /** + * @brief Assigns this opaque variable from another one. + * @param rhs Source variable. + * @return This variable after assignment. + */ D4Opaque &operator=(const D4Opaque &rhs); BaseType *ptr_duplicate() override { return new D4Opaque(*this); } diff --git a/D4ParseError.h b/D4ParseError.h index 1d487106c..46aeb7a02 100644 --- a/D4ParseError.h +++ b/D4ParseError.h @@ -34,6 +34,10 @@ namespace libdap { class D4ParseError : public Error { public: D4ParseError() : Error("The DMR response document parse failed.") {} + + /** @brief Build a DMR parse-failure error with additional details. + * @param msg Additional parse context. + */ explicit D4ParseError(const string &msg) : Error(string("The DMR response document parse failed: ") + msg) {} }; diff --git a/D4ParserSax2.h b/D4ParserSax2.h index e51602a82..d8a0ba951 100644 --- a/D4ParserSax2.h +++ b/D4ParserSax2.h @@ -36,6 +36,8 @@ #include +#include "BaseType.h" + #define CRLF "\r\n" #define D4_PARSE_BUFF_SIZE 1048576 @@ -124,25 +126,25 @@ class D4ParserSax2 { DMR *dmr() const { return d_dmr; } // These stacks hold the state of the parse as it progresses. - stack s; // Current parse state + std::stack s; // Current parse state void push_state(D4ParserSax2::ParseState state) { s.push(state); } D4ParserSax2::ParseState get_state() const { return s.top(); } void pop_state() { s.pop(); } bool empty_state() const { return s.empty(); } - stack btp_stack; // current variable(s) + std::stack btp_stack; // current variable(s) void push_basetype(BaseType *btp) { btp_stack.push(btp); } BaseType *top_basetype() const { return btp_stack.top(); } void pop_basetype() { btp_stack.pop(); } bool empty_basetype() const { return btp_stack.empty(); } - stack grp_stack; // current groups(s) + std::stack grp_stack; // current groups(s) void push_group(D4Group *grp) { grp_stack.push(grp); } D4Group *top_group() const { return grp_stack.top(); } void pop_group() { grp_stack.pop(); } bool empty_group() const { return grp_stack.empty(); } - stack d_attrs_stack; // DAP4 Attributes + std::stack d_attrs_stack; // DAP4 Attributes void push_attributes(D4Attributes *attr) { d_attrs_stack.push(attr); } D4Attributes *top_attributes() const { return d_attrs_stack.top(); } void pop_attributes() { d_attrs_stack.pop(); } @@ -157,7 +159,7 @@ class D4ParserSax2 { void clear_dim_def() { d_dim_def = 0; } // Accumulate stuff inside an 'OtherXML' DAP attribute here - string other_xml; + std::string other_xml; // When we're parsing unknown XML, how deeply is it nested? This is used // for the OtherXML DAP attributes. @@ -165,14 +167,14 @@ class D4ParserSax2 { unsigned int unknown_depth; // These are used for processing errors. - string d_error_msg; // Error message(s), if any. + std::string d_error_msg; // Error message(s), if any. xmlParserCtxtPtr d_context; // used for error message line numbers // These hold temporary values read during the parse. - string dods_attr_name; // DAP4 attributes, not XML attributes - string dods_attr_type; // ... not XML ... - string char_data; // char data in value elements; null after use - string root_ns; // What is the namespace of the root node (Group) + std::string dods_attr_name; // DAP4 attributes, not XML attributes + std::string dods_attr_type; // ... not XML ... + std::string char_data; // char data in value elements; null after use + std::string root_ns; // What is the namespace of the root node (Group) bool d_debug; bool debug() const { return d_debug; } @@ -181,9 +183,9 @@ class D4ParserSax2 { class XMLAttribute { public: - string prefix; - string nsURI; - string value; + std::string prefix; + std::string nsURI; + std::string value; void clone(const XMLAttribute &src) { prefix = src.prefix; @@ -192,13 +194,14 @@ class D4ParserSax2 { } XMLAttribute() : prefix(""), nsURI(""), value("") {} - XMLAttribute(const string &p, const string &ns, const string &v) : prefix(p), nsURI(ns), value(v) {} + XMLAttribute(const std::string &p, const std::string &ns, const std::string &v) + : prefix(p), nsURI(ns), value(v) {} // 'attributes' as passed from libxml2 is a five element array but this // ctor gets the back four elements. explicit XMLAttribute(const xmlChar **attributes /*[4]*/) { prefix = attributes[0] != 0 ? (const char *)attributes[0] : ""; nsURI = attributes[1] != 0 ? (const char *)attributes[1] : ""; - value = string((const char *)attributes[2], (const char *)attributes[3]); + value = std::string((const char *)attributes[2], (const char *)attributes[3]); } XMLAttribute(const XMLAttribute &rhs) { clone(rhs); } ~XMLAttribute() = default; @@ -210,14 +213,14 @@ class D4ParserSax2 { } }; - typedef map XMLAttrMap; + typedef std::map XMLAttrMap; XMLAttrMap xml_attrs; // dump XML attributes here XMLAttrMap::iterator xml_attr_begin() { return xml_attrs.begin(); } XMLAttrMap::iterator xml_attr_end() { return xml_attrs.end(); } - map namespace_table; + std::map namespace_table; void cleanup_parse(); @@ -229,8 +232,8 @@ class D4ParserSax2 { //@{ void transfer_xml_attrs(const xmlChar **attrs, int nb_attributes); void transfer_xml_ns(const xmlChar **namespaces, int nb_namespaces); - bool check_required_attribute(const string &attr); - bool check_attribute(const string &attr); + bool check_required_attribute(const std::string &attr); + bool check_attribute(const std::string &attr); void process_variable_helper(Type t, ParseState s, const xmlChar **attrs, int nb_attributes); bool process_dimension(const char *name, const xmlChar **attrs, int nb_attrs); bool process_dimension_def(const char *name, const xmlChar **attrs, int nb_attrs); @@ -266,13 +269,32 @@ class D4ParserSax2 { d_dmr_sax_parser.endElementNs = &D4ParserSax2::dmr_end_element; } - void intern(istream &f, DMR *dest_dmr, bool debug = false); + /** @brief Parse a DMR document from an input stream. + * @param f Stream containing XML DMR text. + * @param dest_dmr Destination DMR populated by parsing. + * @param debug Enable parser debug tracing when true. + */ + void intern(std::istream &f, DMR *dest_dmr, bool debug = false); + // Deprecated - this does not read from a file, it parses text in the string 'document' - void intern(const string &document, DMR *dest_dmr, bool debug = false); + /** @brief Parse a DMR document from in-memory XML text. + * @param document XML DMR document text. + * @param dest_dmr Destination DMR populated by parsing. + * @param debug Enable parser debug tracing when true. + */ + void intern(const std::string &document, DMR *dest_dmr, bool debug = false); + + /** @brief Parse a DMR document from a raw memory buffer. + * @param buffer Pointer to XML DMR bytes. + * @param size Number of bytes available in `buffer`. + * @param dest_dmr Destination DMR populated by parsing. + * @param debug Enable parser debug tracing when true. + */ void intern(const char *buffer, int size, DMR *dest_dmr, bool debug = false); /** - * @defgroup strict The 'strict' mode + * @name strict + * The 'strict' mode * @{ * The strict mode of the parser is the default. In this mode any error * will result in an exception and parsing will stop. When strict mode diff --git a/D4RValue.h b/D4RValue.h index d31560a11..ab72dd6d0 100644 --- a/D4RValue.h +++ b/D4RValue.h @@ -40,6 +40,7 @@ class D4RValue; // Factory class to build RValue objects. User by the parser/ce-evaluator D4RValue *D4RValueFactory(std::string cpps); +/** @brief Container for parsed DAP4 function/filter rvalues. */ class D4RValueList { private: std::vector d_rvalues; @@ -47,14 +48,22 @@ class D4RValueList { void m_duplicate(const D4RValueList &src); public: + /** @brief Mutable iterator over `D4RValue*` entries. */ typedef std::vector::iterator iter; D4RValueList() {} + /** @brief Copy-constructs an rvalue list. @param src Source list. */ D4RValueList(const D4RValueList &src) { m_duplicate(src); } + /** @brief Builds a one-element rvalue list. @param rv Initial rvalue pointer. */ D4RValueList(D4RValue *rv) { add_rvalue(rv); } virtual ~D4RValueList(); + /** + * @brief Assigns this list from another list. + * @param rhs Source list. + * @return This list after assignment. + */ D4RValueList &operator=(const D4RValueList &rhs) { if (this == &rhs) return *this; @@ -62,13 +71,25 @@ class D4RValueList { return *this; } + /** + * @brief Appends an rvalue pointer. + * @param rv Rvalue pointer to append. + */ void add_rvalue(D4RValue *rv) { d_rvalues.push_back(rv); } + /** + * @brief Returns an rvalue by index. + * @param i Zero-based index. + * @return Rvalue pointer at index `i`. + */ D4RValue *get_rvalue(unsigned int i) { return d_rvalues.at(i); } + /** @brief Returns an iterator to the first rvalue. */ iter begin() { return d_rvalues.begin(); } + /** @brief Returns an iterator one past the last rvalue. */ iter end() { return d_rvalues.end(); } + /** @brief Returns the number of rvalues in this list. */ unsigned int size() const { return d_rvalues.size(); } }; @@ -78,6 +99,7 @@ class D4RValueList { */ class D4RValue { public: + /** @brief Identifies what source currently provides this rvalue's value. */ enum value_kind { unknown, basetype, function, constant }; private: @@ -97,28 +119,53 @@ class D4RValue { public: D4RValue() : d_variable(0), d_func(0), d_args(0), d_constant(0), d_value_kind(unknown) {} + /** @brief Copy-constructs an rvalue. @param src Source rvalue. */ D4RValue(const D4RValue &src) { m_duplicate(src); } + /** @brief Builds an rvalue that references a dataset variable. @param btp Variable pointer. */ D4RValue(BaseType *btp) : d_variable(btp), d_func(0), d_args(0), d_constant(0), d_value_kind(basetype) {} + /** @brief Builds an rvalue that evaluates a function call. + * @param f Function pointer. + * @param args Function argument list. + */ D4RValue(D4Function f, D4RValueList *args) : d_variable(0), d_func(f), d_args(args), d_constant(0), d_value_kind(function) {} + /** @brief Builds an unsigned-integer constant rvalue. @param ui Constant value. */ D4RValue(unsigned long long ui); + /** @brief Builds a signed-integer constant rvalue. @param i Constant value. */ D4RValue(long long i); + /** @brief Builds a floating-point constant rvalue. @param r Constant value. */ D4RValue(double r); + /** @brief Builds a string constant rvalue. @param s Constant value. */ D4RValue(std::string s); + /** @brief Builds a byte-vector constant rvalue. @param byte_args Constant values. */ D4RValue(std::vector &byte_args); + /** @brief Builds an int8-vector constant rvalue. @param byte_int8 Constant values. */ D4RValue(std::vector &byte_int8); + /** @brief Builds a uint16-vector constant rvalue. @param byte_uint16 Constant values. */ D4RValue(std::vector &byte_uint16); + /** @brief Builds an int16-vector constant rvalue. @param byte_int16 Constant values. */ D4RValue(std::vector &byte_int16); + /** @brief Builds a uint32-vector constant rvalue. @param byte_uint32 Constant values. */ D4RValue(std::vector &byte_uint32); + /** @brief Builds an int32-vector constant rvalue. @param byte_int32 Constant values. */ D4RValue(std::vector &byte_int32); + /** @brief Builds a uint64-vector constant rvalue. @param byte_uint64 Constant values. */ D4RValue(std::vector &byte_uint64); + /** @brief Builds an int64-vector constant rvalue. @param byte_int64 Constant values. */ D4RValue(std::vector &byte_int64); + /** @brief Builds a float32-vector constant rvalue. @param byte_float32 Constant values. */ D4RValue(std::vector &byte_float32); + /** @brief Builds a float64-vector constant rvalue. @param byte_float64 Constant values. */ D4RValue(std::vector &byte_float64); virtual ~D4RValue(); + /** + * @brief Assigns this rvalue from another rvalue. + * @param rhs Source rvalue. + * @return This rvalue after assignment. + */ D4RValue &operator=(D4RValue &rhs) { if (this == &rhs) return *this; diff --git a/D4Sequence.h b/D4Sequence.h index 97812e68d..e25d348f8 100644 --- a/D4Sequence.h +++ b/D4Sequence.h @@ -146,9 +146,9 @@ class D4Sequence : public Constructor { // instances of BaseTypeRow objects which hold instances of BaseType. // // Allow these values to be accessed by subclasses - D4SeqValues d_values; + D4SeqValues d_values; ///< Sequence rows, where each row is a vector of `BaseType*` values. - int64_t d_length; // How many elements are in the sequence; -1 if not currently known + int64_t d_length; ///< Number of sequence rows; `-1` if unknown. #if INDEX_SUBSETTING int d_starting_row_number; @@ -156,6 +156,10 @@ class D4Sequence : public Constructor { int d_ending_row_number; #endif + /** + * @brief Deep-copies sequence-local members from another sequence. + * @param s Source sequence. + */ void m_duplicate(const D4Sequence &s); // Specialize this if you have a data source that requires read() @@ -172,6 +176,11 @@ class D4Sequence : public Constructor { ~D4Sequence() override; + /** + * @brief Assigns this sequence from another sequence. + * @param rhs Source sequence. + * @return This sequence after assignment. + */ D4Sequence &operator=(const D4Sequence &rhs); BaseType *ptr_duplicate() override; @@ -291,10 +300,38 @@ class D4Sequence : public Constructor { virtual D4SeqValues &value_ref() { return d_values; } virtual D4SeqRow *row_value(size_t row); + /** + * @brief Returns a variable value by row number and member name. + * @param row Row index. + * @param row_num Alias used by some implementations for the row index. + * @param name Member variable name. + * @return Value object for the requested cell. + */ virtual BaseType *var_value(size_t row, const string &name); + /** + * @brief Returns a variable value by row number and member index. + * @param row Row index. + * @param row_num Alias used by some implementations for the row index. + * @param i Member index within the row. + * @return Value object for the requested cell. + */ virtual BaseType *var_value(size_t row, size_t i); + /** + * @brief Prints one sequence row. + * @param out Output stream. + * @param row Row index. + * @param space Indentation prefix. + * @param print_row_num True to include row number prefixes. + */ virtual void print_one_row(ostream &out, int row, string space, bool print_row_num = false); + /** + * @brief Prints all sequence rows. + * @param out Output stream. + * @param space Indentation prefix. + * @param print_decl_p True to print declaration text. + * @param print_row_numbers True to print row-number prefixes. + */ virtual void print_val_by_rows(ostream &out, string space = "", bool print_decl_p = true, bool print_row_numbers = true); void print_val(ostream &out, string space = "", bool print_decl_p = true, bool is_root_grp = true) override; diff --git a/D4StreamMarshaller.h b/D4StreamMarshaller.h index a57737ade..c53577a97 100644 --- a/D4StreamMarshaller.h +++ b/D4StreamMarshaller.h @@ -85,6 +85,12 @@ class D4StreamMarshaller : public Marshaller { #endif public: + /** + * @brief Builds a DAP4 stream marshaller. + * @param out Destination stream. + * @param write_data True to emit serialized bytes to `out`. + * @param compute_checksums True to update/emit checksums while writing. + */ explicit D4StreamMarshaller(std::ostream &out, bool write_data = true, bool compute_checksums = false); D4StreamMarshaller() = delete; @@ -102,23 +108,41 @@ class D4StreamMarshaller : public Marshaller { virtual void put_checksum(); virtual void put_count(int64_t count); + /** @copydoc Marshaller::put_byte */ void put_byte(dods_byte val) override; + /** @brief Serialize one DAP4 `Int8` value. + * @param val Value to serialize. + */ virtual void put_int8(dods_int8 val); + /** @copydoc Marshaller::put_int16 */ void put_int16(dods_int16 val) override; + /** @copydoc Marshaller::put_int32 */ void put_int32(dods_int32 val) override; // Added + /** @brief Serialize one DAP4 `Int64` value. + * @param val Value to serialize. + */ virtual void put_int64(dods_int64 val); + /** @copydoc Marshaller::put_float32 */ void put_float32(dods_float32 val) override; + /** @copydoc Marshaller::put_float64 */ void put_float64(dods_float64 val) override; + /** @copydoc Marshaller::put_uint16 */ void put_uint16(dods_uint16 val) override; + /** @copydoc Marshaller::put_uint32 */ void put_uint32(dods_uint32 val) override; // Added + /** @brief Serialize one DAP4 `UInt64` value. + * @param val Value to serialize. + */ virtual void put_uint64(dods_uint64 val); + /** @copydoc Marshaller::put_str */ void put_str(const string &val) override; + /** @copydoc Marshaller::put_url */ void put_url(const string &val) override; /// @brief Not supported by DAP4 @@ -126,12 +150,28 @@ class D4StreamMarshaller : public Marshaller { throw InternalErr(__FILE__, __LINE__, "Not implemented for DAP4; use put_opaque_dap4() instead."); } + /** + * @brief Serialize DAP4 opaque bytes. + * @param val Buffer containing bytes. + * @param num_bytes Number of bytes to serialize. + */ virtual void put_opaque_dap4(const char *val, int64_t num_bytes); /// @brief Not supported by DAP4 void put_int(int) override { throw InternalErr(__FILE__, __LINE__, "Not Implemented; use put_length_prefix."); } + /** + * @brief Serialize a contiguous byte block. + * @param val Buffer containing serialized element bytes. + * @param num_bytes Number of bytes to write. + */ virtual void put_vector(char *val, int64_t num_bytes); + /** + * @brief Serialize a vector with explicit element count and element width. + * @param val Buffer containing vector bytes. + * @param num_elem Number of elements. + * @param elem_size Number of bytes per element. + */ virtual void put_vector(char *val, int64_t num_elem, int elem_size); virtual void put_vector_float32(char *val, int64_t num_elem); virtual void put_vector_float64(char *val, int64_t num_elem); diff --git a/D4StreamUnMarshaller.h b/D4StreamUnMarshaller.h index ee38bb240..3aa431544 100644 --- a/D4StreamUnMarshaller.h +++ b/D4StreamUnMarshaller.h @@ -64,6 +64,7 @@ class Vector; */ class D4StreamUnMarshaller : public UnMarshaller { public: + /** @brief Number of bytes used by a serialized checksum trailer. */ const static unsigned int c_checksum_length = 4; private: @@ -85,10 +86,19 @@ class D4StreamUnMarshaller : public UnMarshaller { void m_twidle_vector_elements(char *vals, int64_t num, int width); public: + /** + * @brief Builds a DAP4 stream unmarshaller. + * @param in Source stream. + * @param twiddle_bytes True when multi-byte values must be byte-swapped. + */ D4StreamUnMarshaller(istream &in, bool twiddle_bytes); D4StreamUnMarshaller(istream &in); ~D4StreamUnMarshaller() override; + /** + * @brief Enables or disables byte swapping for multi-byte values. + * @param twiddle True to swap bytes. + */ void set_twiddle_bytes(bool twiddle) { d_twiddle_bytes = twiddle; } /** @@ -105,34 +115,69 @@ class D4StreamUnMarshaller : public UnMarshaller { return (is_host_big_endian() && !d_twiddle_bytes) || (!is_host_big_endian() && d_twiddle_bytes); } + /** + * @brief Reads and returns the checksum value from the stream. + * @return Decoded checksum. + */ Crc32::checksum get_checksum(); + /** + * @brief Reads and returns the checksum as hex text. + * @return Checksum string. + */ string get_checksum_str(); int64_t get_count(); + /** @copydoc UnMarshaller::get_byte */ void get_byte(dods_byte &val) override; + /** @brief Deserialize one DAP4 `Int8` value. + * @param val Destination for the decoded value. + */ virtual void get_int8(dods_int8 &val); + /** @copydoc UnMarshaller::get_int16 */ void get_int16(dods_int16 &val) override; + /** @copydoc UnMarshaller::get_int32 */ void get_int32(dods_int32 &val) override; + /** @brief Deserialize one DAP4 `Int64` value. + * @param val Destination for the decoded value. + */ virtual void get_int64(dods_int64 &val); + /** @copydoc UnMarshaller::get_float32 */ void get_float32(dods_float32 &val) override; + /** @copydoc UnMarshaller::get_float64 */ void get_float64(dods_float64 &val) override; + /** @copydoc UnMarshaller::get_uint16 */ void get_uint16(dods_uint16 &val) override; + /** @copydoc UnMarshaller::get_uint32 */ void get_uint32(dods_uint32 &val) override; + /** @brief Deserialize one DAP4 `UInt64` value. + * @param val Destination for the decoded value. + */ virtual void get_uint64(dods_uint64 &val); + /** @copydoc UnMarshaller::get_str */ void get_str(string &val) override; + /** @copydoc UnMarshaller::get_url */ void get_url(string &val) override; void get_opaque(char *, unsigned int) override { throw InternalErr(__FILE__, __LINE__, "Not implemented for DAP4, use get_opaque_dap4() instead."); } + /** + * @brief Deserialize DAP4 opaque bytes into a caller-owned buffer. + * @param val Output pointer to allocated byte buffer. + * @param len Number of decoded bytes. + */ virtual void get_opaque_dap4(char **val, int64_t &len); + /** + * @brief Deserialize DAP4 opaque bytes into a vector. + * @param val Destination byte vector. + */ virtual void get_opaque_dap4(vector &val); void get_int(int &) override { throw InternalErr(__FILE__, __LINE__, "Not implemented for DAP4"); } @@ -149,9 +194,30 @@ class D4StreamUnMarshaller : public UnMarshaller { throw InternalErr(__FILE__, __LINE__, "Not implemented for DAP4"); } + /** + * @brief Deserialize a fixed-size byte block. + * @param val Destination buffer. + * @param num_bytes Number of bytes to read. + */ virtual void get_vector(char *val, int64_t num_bytes); + /** + * @brief Deserialize fixed-size elements into a caller buffer. + * @param val Destination buffer. + * @param num_elem Number of elements to read. + * @param elem_size Bytes per element. + */ virtual void get_vector(char *val, int64_t num_elem, int elem_size); + /** + * @brief Deserialize `Float32` elements. + * @param val Destination buffer. + * @param num_elem Number of elements to read. + */ virtual void get_vector_float32(char *val, int64_t num_elem); + /** + * @brief Deserialize `Float64` elements. + * @param val Destination buffer. + * @param num_elem Number of elements to read. + */ virtual void get_vector_float64(char *val, int64_t num_elem); void dump(ostream &strm) const override; diff --git a/DAPCache3.h b/DAPCache3.h index 4d78b7fbf..19d34061d 100644 --- a/DAPCache3.h +++ b/DAPCache3.h @@ -39,12 +39,14 @@ namespace libdap { // These typedefs are used to record information about the files in the cache. // See DAPCache3.cc and look at the purge() method. +/** @brief Metadata for one file found in the DAP cache directory. */ typedef struct { - std::string name; - unsigned long long size; - time_t time; + std::string name; ///< Cache file name. + unsigned long long size; ///< Cache file size in bytes. + time_t time; ///< Last-modified time. } cache_entry; +/** @brief List of cache-file metadata entries. */ typedef std::list CacheFiles; /** @brief Implementation of a caching mechanism for compressed data. @@ -111,14 +113,31 @@ class DAPCache3 : public libdap::DapObj { static void delete_instance(); public: + /** + * @brief Returns/creates the singleton cache instance. + * @param cache_dir Cache root directory. + * @param prefix Filename prefix used for cache entries. + * @param size Maximum cache size in bytes. + * @return Singleton cache instance. + */ static DAPCache3 *get_instance(const std::string &cache_dir, const std::string &prefix, unsigned long long size); static DAPCache3 *get_instance(); std::string get_cache_file_name(const std::string &src, bool mangle = true); virtual bool create_and_lock(const std::string &target, int &fd); + /** + * @brief Opens an existing cache file and acquires a shared read lock. + * @param target Cache file path. + * @param fd Output file descriptor associated with the lock. + * @return True when the file exists and lock acquisition succeeds. + */ virtual bool get_read_lock(const std::string &target, int &fd); virtual void exclusive_to_shared_lock(int fd); + /** + * @brief Releases lock and closes the descriptor tracked for a target file. + * @param target Cache file path whose tracked descriptor should be closed. + */ virtual void unlock_and_close(const std::string &target); virtual void unlock_and_close(int fd); diff --git a/DAS.h b/DAS.h index a2426a0dd..14acd323a 100644 --- a/DAS.h +++ b/DAS.h @@ -134,10 +134,20 @@ class DAS : public DapObj { public: DAS() : DapObj(), d_container(0) {} + + /** + * @brief Copy-constructs a DAS. + * @param das Source DAS. + */ DAS(const DAS &das) { duplicate(das); } ~DAS() override {} + /** + * @brief Assigns this DAS from another DAS. + * @param rhs Source DAS. + * @return This DAS after assignment. + */ DAS &operator=(const DAS &rhs); /** @brief Returns the name of the current attribute container when multiple diff --git a/DDS.h b/DDS.h index 4217af9a3..35de784d2 100644 --- a/DDS.h +++ b/DDS.h @@ -202,13 +202,34 @@ class DDS : public DapObj { friend class DDSTest; protected: + /** + * @brief Copies state from another DDS. + * @param dds Source DDS. + */ void duplicate(const DDS &dds); + + /** + * @brief Finds a variable by leaf-name match. + * @param name Leaf name to match. + * @param s Optional stack used to record match path. + * @return Matching variable, or null when none is found. + */ BaseType *leaf_match(const string &name, BaseType::btp_stack *s = 0); + + /** + * @brief Finds a variable by exact fully-qualified name. + * @param name Fully-qualified variable name. + * @param s Optional stack used to record match path. + * @return Matching variable, or null when none is found. + */ BaseType *exact_match(const string &name, BaseType::btp_stack *s = 0); public: + /** @brief Iterator type for read-only traversal of top-level variables. */ typedef std::vector::const_iterator Vars_citer; + /** @brief Iterator type for mutable traversal of top-level variables. */ typedef std::vector::iterator Vars_iter; + /** @brief Reverse iterator type for mutable traversal of top-level variables. */ typedef std::vector::reverse_iterator Vars_riter; DDS(BaseTypeFactory *factory, const string &name = ""); @@ -217,6 +238,11 @@ class DDS : public DapObj { ~DDS() override; + /** + * @brief Assigns this DDS from another DDS. + * @param rhs Source DDS. + * @return This DDS after assignment. + */ DDS &operator=(const DDS &rhs); virtual void transfer_attributes(DAS *das); @@ -253,7 +279,11 @@ class DDS : public DapObj { int get_dap_minor() const { return d_dap_minor; } void set_dap_version(const string &version_string = "2.0"); + + /** @brief Returns the DAP protocol version string. */ string get_dap_version() const { return d_dap_version; } + + /** @brief Returns the DAP4 DMR version corresponding to DDS exports. */ string get_dmr_version() const { return "1.0"; } /// @deprecated @@ -389,6 +419,11 @@ class DDS : public DapObj { void print_das(ostream &out); DAS *get_das(); + + /** + * @brief Populates a DAS object from this DDS's global and variable attributes. + * @param das Destination DAS to populate. + */ void get_das(DAS *das); void mark_all(bool state); diff --git a/DDXExceptions.h b/DDXExceptions.h index 5d6aaec85..4efe5abe0 100644 --- a/DDXExceptions.h +++ b/DDXExceptions.h @@ -36,6 +36,10 @@ namespace libdap { class DDXParseFailed : public Error { public: DDXParseFailed() : Error("The DDX response document parse failed.") {} + + /** @brief Build a DDX parse-failure error with additional details. + * @param msg Additional parse context. + */ DDXParseFailed(const string &msg) : Error(string("The DDX response document parse failed: ") + msg) {} }; diff --git a/DDXParserSAX2.h b/DDXParserSAX2.h index 593e40749..4a4f66b23 100644 --- a/DDXParserSAX2.h +++ b/DDXParserSAX2.h @@ -226,6 +226,9 @@ class DDXParser { friend class DDXParserTest; public: + /** @brief Build a parser bound to a BaseType factory. + * @param factory Factory used to allocate parsed variables. + */ DDXParser(BaseTypeFactory *factory) : d_factory(factory), other_xml(""), other_xml_depth(0), unknown_depth(0), error_msg(""), ctxt(0), dds(0), blob_href(0), dods_attr_name(""), dods_attr_type(""), char_data(""), root_ns("") { @@ -246,7 +249,14 @@ class DDXParser { } void intern(const string &document, DDS *dest_dds, string &cid); void intern_stream(FILE *in, DDS *dds, string &cid, const string &boundary = ""); - void intern_stream(istream &in, DDS *dds, string &cid, const string &boundary = ""); + + /** @brief Parse a DDX document from an input stream. + * @param in Stream containing a DDX document. + * @param dest_dds Destination DDS populated by parsing. + * @param cid Output MIME content-id for blob data, if present. + * @param boundary MIME multipart boundary when parsing multipart input. + */ + void intern_stream(istream &in, DDS *dest_dds, string &cid, const string &boundary = ""); static void ddx_start_document(void *parser); static void ddx_end_document(void *parser); diff --git a/DMR.h b/DMR.h index d400181a7..6464b0daf 100644 --- a/DMR.h +++ b/DMR.h @@ -37,6 +37,7 @@ namespace libdap { +/** @brief Default XML namespace URI for DAP4 DMR documents. */ const string c_dap40_namespace = "http://xml.opendap.org/ns/DAP/4.0#"; class D4Group; @@ -112,6 +113,11 @@ class DMR : public DapObj { ~DMR() override; + /** + * @brief Assigns this DMR from another DMR. + * @param rhs Source DMR. + * @return This DMR after assignment. + */ DMR &operator=(const DMR &rhs); virtual void build_using_dds(DDS &dds); @@ -149,12 +155,28 @@ class DMR : public DapObj { void set_filename(const std::string &fn) { d_filename = fn; } //@} + /** @brief Returns the DAP protocol version string. */ std::string dap_version() const { return d_dap_version; } + + /** + * @brief Sets the DAP protocol version string and parsed major/minor values. + * @param version_string DAP protocol version (for example, `4.0`). + */ void set_dap_version(const std::string &version_string); + + /** @brief Returns the DAP protocol major version number. */ int dap_major() const { return d_dap_major; } + + /** @brief Returns the DAP protocol minor version number. */ int dap_minor() const { return d_dap_minor; } + /** @brief Returns the DMR document version string. */ std::string dmr_version() const { return d_dmr_version; } + + /** + * @brief Sets the DMR document version string. + * @param v DMR version value. + */ void set_dmr_version(const std::string &v) { d_dmr_version = v; } /// Get the URL that will return this DMR @@ -238,14 +260,32 @@ class DMR : public DapObj { void dump(std::ostream &strm) const override; // The following methods are for direct IO optimization. + /** @brief Returns the global direct-I/O optimization flag. */ bool get_global_dio_flag() const { return global_dio_flag; } + + /** + * @brief Sets the global direct-I/O optimization flag. + * @param dio_flag_value True to enable direct-I/O optimizations. + */ void set_global_dio_flag(bool dio_flag_value = true) { global_dio_flag = dio_flag_value; } // The following methods are for utf8_encoding. + /** @brief Returns whether XML output should declare UTF-8 encoding. */ bool get_utf8_xml_encoding() const { return utf8_xml_encoding; } + + /** + * @brief Sets whether XML output should declare UTF-8 encoding. + * @param encoding_value True to emit UTF-8 encoding metadata. + */ void set_utf8_xml_encoding(bool encoding_value = true) { utf8_xml_encoding = encoding_value; } + /** @brief Returns whether DAP4 checksums are enabled for data responses. */ bool use_checksums() const { return d_use_dap4_checksums; } + + /** + * @brief Enables or disables DAP4 checksums for data responses. + * @param value True to include checksums. + */ void use_checksums(bool value) { d_use_dap4_checksums = value; } }; diff --git a/DODSFilter.h b/DODSFilter.h index 6a29a8143..4f8ec7afc 100644 --- a/DODSFilter.h +++ b/DODSFilter.h @@ -89,27 +89,27 @@ class DODSFilter { }; protected: - bool d_comp; // True if the output should be compressed. - bool d_bad_options; // True if the options (argc,argv) are bad. - bool d_conditional_request; + bool d_comp; ///< True if the output should be compressed. + bool d_bad_options; ///< True if command-line options were invalid. + bool d_conditional_request; ///< True when request includes conditional headers. - string d_program_name; // Name of the filter program - string d_dataset; // Name of the dataset/database - string d_dap2ce; // DAP2 Constraint expression - string d_cgi_ver; // Version of CGI script (caller) - string d_anc_dir; // Look here for ancillary files - string d_anc_file; // Use this for ancillary file name - string d_cache_dir; // Use this for cache files - string d_url; // URL minus CE. + string d_program_name; ///< Name of the filter program. + string d_dataset; ///< Dataset/database identifier. + string d_dap2ce; ///< DAP2 constraint expression. + string d_cgi_ver; ///< CGI caller version string. + string d_anc_dir; ///< Ancillary-file directory path. + string d_anc_file; ///< Ancillary-file base name. + string d_cache_dir; ///< Cache directory path. + string d_url; ///< Request URL without CE. - Response d_response; // enum name of the response to generate - string d_action; // string name of the response to generate + Response d_response; ///< Enumerated response type to generate. + string d_action; ///< String action/response token. - int d_timeout; // Server timeout after N seconds + int d_timeout; ///< Server timeout in seconds. - time_t d_anc_das_lmt; // Last modified time of the anc. DAS. - time_t d_anc_dds_lmt; // Last modified time of the anc. DDS. - time_t d_if_modified_since; // Time from a conditional request. + time_t d_anc_das_lmt; ///< Last-modified time of ancillary DAS. + time_t d_anc_dds_lmt; ///< Last-modified time of ancillary DDS. + time_t d_if_modified_since; ///< `If-Modified-Since` request timestamp. void initialize(); void initialize(int argc, char *argv[]); @@ -135,9 +135,17 @@ class DODSFilter { virtual void set_cgi_version(string version); virtual string get_ce() const; + /** + * @brief Sets the DAP2 constraint expression text. + * @param _ce Constraint expression. + */ virtual void set_ce(string _ce); virtual string get_dataset_name() const; + /** + * @brief Sets the dataset name/path token. + * @param _dataset Dataset identifier. + */ virtual void set_dataset_name(const string _dataset); virtual string get_URL() const; @@ -165,23 +173,64 @@ class DODSFilter { int get_timeout() const; + /** + * @brief Arms timeout handling for stream writes. + * @param stream Output stream associated with response generation. + */ virtual void establish_timeout(ostream &stream) const; virtual void print_usage() const; virtual void send_version_info() const; + /** + * @brief Writes DAS response (with optional MIME headers) to standard output. + * @param das DAS object to serialize. + * @param anc_location Optional ancillary resource location. + * @param with_mime_headers True to emit MIME headers. + */ virtual void send_das(DAS &das, const string &anc_location = "", bool with_mime_headers = true) const; virtual void send_das(ostream &out, DAS &das, const string &anc_location = "", bool with_mime_headers = true) const; + /** + * @brief Writes DDS response (with optional MIME headers) to standard output. + * @param dds DDS object to serialize. + * @param eval Constraint evaluator context. + * @param constrained True to emit constrained form. + * @param anc_location Optional ancillary resource location. + * @param with_mime_headers True to emit MIME headers. + */ virtual void send_dds(DDS &dds, ConstraintEvaluator &eval, bool constrained = false, const string &anc_location = "", bool with_mime_headers = true) const; virtual void send_dds(ostream &out, DDS &dds, ConstraintEvaluator &eval, bool constrained = false, const string &anc_location = "", bool with_mime_headers = true) const; // deprecated + /** + * @brief Writes a function-result response body to a C++ stream. + * @param var Function-result variable. + * @param dds Dataset descriptor. + * @param eval Constraint evaluator context. + * @param out Output stream. + */ virtual void functional_constraint(BaseType &var, DDS &dds, ConstraintEvaluator &eval, ostream &out) const; + /** + * @brief Writes a constrained dataset response to a C++ stream. + * @param dds Dataset descriptor. + * @param eval Constraint evaluator context. + * @param out Output stream. + * @param ce_eval True to evaluate CE selections before serialization. + */ virtual void dataset_constraint(DDS &dds, ConstraintEvaluator &eval, ostream &out, bool ce_eval = true) const; + /** + * @brief Writes a constrained dataset DDX multipart response. + * @param dds Dataset descriptor. + * @param eval Constraint evaluator context. + * @param out Output stream. + * @param boundary MIME multipart boundary. + * @param start MIME content-id for the root part. + * @param ce_eval True to evaluate CE selections before serialization. + */ virtual void dataset_constraint_ddx(DDS &dds, ConstraintEvaluator &eval, ostream &out, const string &boundary, const string &start, bool ce_eval = true) const; @@ -192,13 +241,31 @@ class DODSFilter { const string &boundary, const string &anc_location = "", bool with_mime_headers = true) const; + /** + * @brief Arms timeout handling for C stdio writes. + * @param stream Output C stream associated with response generation. + */ virtual void establish_timeout(FILE *stream) const; virtual void send_das(FILE *out, DAS &das, const string &anc_location = "", bool with_mime_headers = true) const; virtual void send_dds(FILE *out, DDS &dds, ConstraintEvaluator &eval, bool constrained = false, const string &anc_location = "", bool with_mime_headers = true) const; // deprecated + /** + * @brief Writes function-result response body to a C stdio stream. + * @param var Function-result variable. + * @param dds Dataset descriptor. + * @param eval Constraint evaluator context. + * @param out Output file stream. + */ virtual void functional_constraint(BaseType &var, DDS &dds, ConstraintEvaluator &eval, FILE *out) const; + /** + * @brief Writes a constrained dataset response to a C stdio stream. + * @param dds Dataset descriptor. + * @param eval Constraint evaluator context. + * @param out Output file stream. + * @param ce_eval True to evaluate CE selections before serialization. + */ virtual void dataset_constraint(DDS &dds, ConstraintEvaluator &eval, FILE *out, bool ce_eval = true) const; virtual void send_data(DDS &dds, ConstraintEvaluator &eval, FILE *data_stream, const string &anc_location = "", bool with_mime_headers = true) const; diff --git a/DapIndent.h b/DapIndent.h index de006a570..32002c0b3 100644 --- a/DapIndent.h +++ b/DapIndent.h @@ -52,11 +52,29 @@ class DapIndent { static string _indent; public: + /** @brief Increase current indentation by one level. */ static void Indent(); + + /** @brief Decrease current indentation by one level. */ static void UnIndent(); + + /** @brief Reset indentation to an empty string. */ static void Reset(); + + /** @brief Get the current indentation string. + * @return Current indentation text. + */ static const string &GetIndent(); + + /** @brief Set the indentation string explicitly. + * @param indent New indentation text. + */ static void SetIndent(const string &indent); + + /** @brief Write the current indentation to a stream. + * @param strm Stream that receives indentation text. + * @return `strm`, for chaining. + */ static ostream &LMarg(ostream &strm); }; diff --git a/DapXmlNamespaces.h b/DapXmlNamespaces.h index d8caa46c0..b364c0287 100644 --- a/DapXmlNamespaces.h +++ b/DapXmlNamespaces.h @@ -29,8 +29,10 @@ namespace libdap { +/** @brief Supported DAP XML namespace/schema versions. */ enum DAPVersion { DAP_2_0, DAP_3_2, DAP_4_0 }; +/** @brief Helper for namespace and schema URIs used in DAP XML documents. */ class DapXmlNamspaces { public: diff --git a/DataDDS.h b/DataDDS.h index 1bff1fdd9..9077cd472 100644 --- a/DataDDS.h +++ b/DataDDS.h @@ -107,12 +107,22 @@ class DataDDS : public DDS { /** @brief Returns the minor version number. */ int get_version_minor() const { return d_server_version_minor; } + /** + * @brief Sets the protocol version string and updates parsed major/minor fields. + * @param p Protocol version string from a response header. + */ void set_protocol(const string &p) { d_protocol_version = p; m_protocol_string_to_numbers(); } + + /** @brief Returns the raw protocol version string. */ string get_protocol() const { return d_protocol_version; } + + /** @brief Returns the parsed protocol major version number. */ int get_protocol_major() const { return d_server_protocol_major; } + + /** @brief Returns the parsed protocol minor version number. */ int get_protocol_minor() const { return d_server_protocol_minor; } void dump(ostream &strm) const override; diff --git a/Doxygen-plan.md b/Doxygen-plan.md index 806f32d5f..fd6223b8b 100644 --- a/Doxygen-plan.md +++ b/Doxygen-plan.md @@ -1,7 +1,7 @@ **Documentation Plan Prompt** -You are working in `libdap4`. Document public methods in stages, with review after each stage. -Target baseline is **1,918 undocumented public methods** (from prior scan). +You are working in `libdap4`. Document public methods in stages, with review after each stage. +Target baseline is **1,918 undocumented public methods** (from prior scan). Use existing Doxygen settings from `doxy.conf` exactly as-is. **Doxygen Constraints To Respect** @@ -20,15 +20,16 @@ Use existing Doxygen settings from `doxy.conf` exactly as-is. **Documentation Style Rules** 1. Add Doxygen comments in headers (`.h`, `.hh`) directly above public method declarations. Document in header by default; use implementation comments only for complex algorithm/side-effect details. -2. Prefer this form: +2. Insert a blank line between a new documentation comment and the preceding method declaration if there is no blank line already. +3. Prefer this form: - `@brief` one-sentence behavior summary. - Follow with a paragraph-level detailed description (behavior, constraints, side effects, preconditions/postconditions as needed). - `@param` for each parameter. - `@return` when non-void. - `@throw` when exceptions are part of method contract. -3. Keep wording behavior-focused, not implementation-focused. -4. For overloads, document each overload’s distinct contract. -5. For inherited overrides with identical behavior, use concise comments and rely on inherited docs only where it is semantically correct. +4. Keep wording behavior-focused, not implementation-focused. +5. For overloads, document each overload’s distinct contract. +6. For inherited overrides with identical behavior, use concise comments and rely on inherited docs only where it is semantically correct. **Per-Stage Workflow (repeat for every stage)** diff --git a/Error.h b/Error.h index e8969be7e..576d139cf 100644 --- a/Error.h +++ b/Error.h @@ -91,9 +91,13 @@ typedef int ErrorCode; // using standard errno+netCDF error codes from server class Error : public std::exception { protected: + /// Numeric code used by clients/servers to classify this error. ErrorCode _error_code; + /// Human-readable description suitable for logs and user messages. std::string _error_message; + /// Source filename recorded when the error was created. std::string d_file; + /// Source line number recorded when the error was created. int d_line = 0; public: @@ -127,26 +131,51 @@ class Error : public std::exception { : exception(), _error_code(unknown_error), _error_message(std::move(msg)), d_file(std::move(file)), d_line(line) {} + /** @brief Copy-construct an Error instance. + * @param copy_from Source error to copy. + */ Error(const Error ©_from) noexcept : exception(), _error_code(copy_from._error_code), _error_message(copy_from._error_message), d_file(copy_from.d_file), d_line(copy_from.d_line) {} ~Error() override = default; + /** @brief Assign all error fields from another Error. + * @param rhs Source error to copy. + * @return This instance. + */ Error &operator=(const Error &rhs); bool OK() const; bool parse(FILE *fp); void print(FILE *out) const; + /** @brief Serialize this error in DAP text form. + * @param out Destination stream. + */ void print(std::ostream &out) const; ErrorCode get_error_code() const; std::string get_error_message() const; void set_error_code(ErrorCode ec = undefined_error); void set_error_message(const std::string &msg = ""); + /** @brief Get the recorded source filename. + * @return Source filename, or empty if not set. + */ std::string get_file() const { return d_file; } + + /** @brief Set the source filename metadata. + * @param f Source filename. + */ void set_file(std::string f) { d_file = std::move(f); } + + /** @brief Get the recorded source line number. + * @return Source line number, or 0 if not set. + */ int get_line() const { return d_line; } + + /** @brief Set the source line metadata. + * @param l Source line number. + */ void set_line(int l) { d_line = l; } /// The pointer is valid only for the lifetime of the Error instance. jhrg 9/22/20 diff --git a/Float32.h b/Float32.h index cf7f3875a..6b00602df 100644 --- a/Float32.h +++ b/Float32.h @@ -58,14 +58,26 @@ class DMR; */ class Float32 : public BaseType { protected: + /// Stored scalar 32-bit floating-point value. dods_float32 d_buf; public: Float32(const string &n); Float32(const string &n, const string &d); + /** + * @brief Copy-constructs from another 32-bit floating point variable. + * + * @param copy_from Source instance. + */ Float32(const Float32 ©_from); + /** + * @brief Assigns from another 32-bit floating point variable. + * + * @param rhs Source instance. + * @return This instance after assignment. + */ Float32 &operator=(const Float32 &rhs); ~Float32() override {} @@ -74,7 +86,13 @@ class Float32 : public BaseType { unsigned int width(bool = false) const override { return sizeof(dods_float32); } - int64_t width_ll(bool = false) const override { return sizeof(dods_float32); } + /** + * @brief Returns the storage width in bytes. + * + * @param constrained Ignored for scalar values. + * @return Number of bytes used by this value. + */ + int64_t width_ll(bool constrained = false) const override { return sizeof(dods_float32); } // DAP2 bool serialize(ConstraintEvaluator &eval, DDS &dds, Marshaller &m, bool ce_eval = true) override; @@ -89,9 +107,31 @@ class Float32 : public BaseType { unsigned int buf2val(void **val) override; virtual dods_float32 value() const; + /** + * @brief Sets the current value. + * + * @param f New 32-bit floating point value. + * @return True when the value is accepted. + */ virtual bool set_value(dods_float32 f); + /** + * @brief Writes this value using C stdio output. + * + * @param out Output file stream. + * @param space Indentation prefix. + * @param print_decl_p True to include declaration text. + * @param is_root_grp True when printing in the root group context. + */ void print_val(FILE *out, string space = "", bool print_decl_p = true, bool is_root_grp = true) override; + /** + * @brief Writes this value using C++ stream output. + * + * @param out Output stream. + * @param space Indentation prefix. + * @param print_decl_p True to include declaration text. + * @param is_root_grp True when printing in the root group context. + */ void print_val(ostream &out, string space = "", bool print_decl_p = true, bool is_root_grp = true) override; bool ops(BaseType *b, int op) override; diff --git a/Float64.h b/Float64.h index 71bdc05df..9f9c85f55 100644 --- a/Float64.h +++ b/Float64.h @@ -57,6 +57,7 @@ namespace libdap { class Float64 : public BaseType { protected: + /// Stored scalar 64-bit floating-point value. dods_float64 d_buf; public: @@ -64,15 +65,32 @@ class Float64 : public BaseType { Float64(const string &n, const string &d); ~Float64() override {} + /** + * @brief Copy-constructs from another 64-bit floating point variable. + * + * @param copy_from Source instance. + */ Float64(const Float64 ©_from); + /** + * @brief Assigns from another 64-bit floating point variable. + * + * @param rhs Source instance. + * @return This instance after assignment. + */ Float64 &operator=(const Float64 &rhs); BaseType *ptr_duplicate() override; unsigned int width(bool = false) const override { return sizeof(dods_float64); } - int64_t width_ll(bool = false) const override { return sizeof(dods_float64); } + /** + * @brief Returns the storage width in bytes. + * + * @param constrained Ignored for scalar values. + * @return Number of bytes used by this value. + */ + int64_t width_ll(bool constrained = false) const override { return sizeof(dods_float64); } // DAP2 bool serialize(ConstraintEvaluator &eval, DDS &dds, Marshaller &m, bool ce_eval = true) override; @@ -87,9 +105,31 @@ class Float64 : public BaseType { unsigned int buf2val(void **val) override; virtual dods_float64 value() const; + /** + * @brief Sets the current value. + * + * @param val New 64-bit floating point value. + * @return True when the value is accepted. + */ virtual bool set_value(dods_float64 val); + /** + * @brief Writes this value using C stdio output. + * + * @param out Output file stream. + * @param space Indentation prefix. + * @param print_decl_p True to include declaration text. + * @param is_root_grp True when printing in the root group context. + */ void print_val(FILE *out, string space = "", bool print_decl_p = true, bool is_root_grp = true) override; + /** + * @brief Writes this value using C++ stream output. + * + * @param out Output stream. + * @param space Indentation prefix. + * @param print_decl_p True to include declaration text. + * @param is_root_grp True when printing in the root group context. + */ void print_val(ostream &out, string space = "", bool print_decl_p = true, bool is_root_grp = true) override; bool ops(BaseType *b, int op) override; diff --git a/GNU/GNURegex.h b/GNU/GNURegex.h index 4392266e3..e1d46cb98 100644 --- a/GNU/GNURegex.h +++ b/GNU/GNURegex.h @@ -82,12 +82,16 @@ class Regex { explicit Regex(const std::string &s) { init(s); } #if USE_CPP_11_REGEX + /// @brief Compile a C-string regular expression. void init(const char *s) { d_exp = std::regex(s); } + /// @brief Compile a C++-string regular expression. void init(const std::string &s) { d_exp = std::regex(s); } // , std::regex::basic ~Regex() = default; #else + /// @brief Compile a C-string regular expression. void init(const char *t); + /// @brief Compile a C++-string regular expression. void init(const std::string &s) { init(s.c_str()); } // std::regex::ECMAScript ~Regex(); diff --git a/GNU/GetOpt.h b/GNU/GetOpt.h index 3fb77a60e..c4a696c03 100644 --- a/GNU/GetOpt.h +++ b/GNU/GetOpt.h @@ -34,6 +34,7 @@ Foundation 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA. // #include +/** @brief GNU-style command-line option parser helper. */ class GetOpt { private: /* The next char to be scanned in the option-element @@ -92,6 +93,7 @@ class GetOpt { Also, when `ordering' is RETURN_IN_ORDER, each non-option ARGV-element is returned here. */ + /// Argument value for the current option. char *optarg; /* Index in ARGV of the next element to be scanned. @@ -105,18 +107,32 @@ class GetOpt { Otherwise, `optind' communicates from one call to the next how much of ARGV has been scanned so far. */ + /// Index in `argv` of the next element to process. int optind; /* Callers store zero here to inhibit the error message for unrecognized options. */ + /// When zero, suppresses unknown-option diagnostics. int opterr; + /// Cached `argc` value for parser state. int nargc; + /// Cached `argv` value for parser state. char **nargv; + /// Option-specification string used by the parser. const char *noptstring; + /** @brief Build an option parser for one argv vector. + * @param argc Argument count. + * @param argv Argument vector. + * @param optstring Option definition string. + */ GetOpt(int argc, char **argv, const char *optstring); + + /** @brief Parse and return the next option token. + * @return Option character, `EOF` when parsing is complete, or `'?'` on error. + */ int operator()(void); }; diff --git a/Grid.h b/Grid.h index db8c06a35..021327775 100644 --- a/Grid.h +++ b/Grid.h @@ -124,6 +124,10 @@ class Grid : public Constructor { bool d_is_array_set; protected: // subclasses need access [mjohnson 11 nov 2009] + /** + * @brief Copies Grid-specific state from another grid. + * @param s Source grid. + */ void m_duplicate(const Grid &s); public: @@ -132,10 +136,18 @@ class Grid : public Constructor { Grid(const Grid &rhs); ~Grid() override; + /** @brief Iterator type for read-only traversal of map variables. */ typedef std::vector::const_iterator Map_citer; + /** @brief Iterator type for mutable traversal of map variables. */ typedef std::vector::iterator Map_iter; + /** @brief Reverse iterator type for mutable traversal of map variables. */ typedef std::vector::reverse_iterator Map_riter; + /** + * @brief Assigns from another grid. + * @param rhs Source grid. + * @return This instance after assignment. + */ Grid &operator=(const Grid &rhs); BaseType *ptr_duplicate() override; @@ -161,17 +173,56 @@ class Grid : public Constructor { virtual void clear_constraint(); + /** + * @brief Prints the declaration using C++ streams. + * @param out Output stream. + * @param space Indentation prefix. + * @param print_semi True to print a trailing semicolon. + * @param constraint_info True to include projection details. + * @param constrained True to print constrained declarations. + * @param is_root_grp True when printing in root-group context. + * @param array_member True when printing as an array member declaration. + */ void print_decl(ostream &out, string space = " ", bool print_semi = true, bool constraint_info = false, bool constrained = false, bool is_root_grp = true, bool array_member = false) override; void print_xml(ostream &out, string space = " ", bool constrained = false) override; + /** + * @brief Prints XML representation using an XML writer. + * @param xml Output XML writer. + * @param constrained True to emit constrained form. + */ void print_xml_writer(XMLWriter &xml, bool constrained = false) override; + /** + * @brief Prints values using C++ streams. + * @param out Output stream. + * @param space Indentation prefix. + * @param print_decl_p True to include declaration text. + * @param is_root_grp True when printing in root-group context. + */ void print_val(ostream &out, string space = "", bool print_decl_p = true, bool is_root_grp = true) override; + /** + * @brief Prints the declaration using C stdio. + * @param out Output file stream. + * @param space Indentation prefix. + * @param print_semi True to print a trailing semicolon. + * @param constraint_info True to include projection details. + * @param constrained True to print constrained declarations. + * @param is_root_grp True when printing in root-group context. + * @param array_member True when printing as an array member declaration. + */ void print_decl(FILE *out, string space = " ", bool print_semi = true, bool constraint_info = false, bool constrained = false, bool is_root_grp = true, bool array_member = false) override; void print_xml(FILE *out, string space = " ", bool constrained = false) override; + /** + * @brief Prints values using C stdio. + * @param out Output file stream. + * @param space Indentation prefix. + * @param print_decl_p True to include declaration text. + * @param is_root_grp True when printing in root-group context. + */ void print_val(FILE *out, string space = "", bool print_decl_p = true, bool is_root_grp = true) override; void transfer_attributes(AttrTable *at_container) override; diff --git a/Int16.h b/Int16.h index 501fd764f..3caf4aca8 100644 --- a/Int16.h +++ b/Int16.h @@ -56,6 +56,7 @@ class DMR; class Int16 : public BaseType { protected: + /// Stored scalar 16-bit signed integer value. dods_int16 d_buf; public: @@ -63,15 +64,32 @@ class Int16 : public BaseType { Int16(const string &n, const string &d); ~Int16() override {} + /** + * @brief Copy-constructs from another 16-bit signed integer variable. + * + * @param copy_from Source instance. + */ Int16(const Int16 ©_from); + /** + * @brief Assigns from another 16-bit signed integer variable. + * + * @param rhs Source instance. + * @return This instance after assignment. + */ Int16 &operator=(const Int16 &rhs); BaseType *ptr_duplicate() override; unsigned int width(bool = false) const override { return sizeof(dods_int16); } - int64_t width_ll(bool = false) const override { return sizeof(dods_int16); } + /** + * @brief Returns the storage width in bytes. + * + * @param constrained Ignored for scalar values. + * @return Number of bytes used by this value. + */ + int64_t width_ll(bool constrained = false) const override { return sizeof(dods_int16); } // DAP2 bool serialize(ConstraintEvaluator &eval, DDS &dds, Marshaller &m, bool ce_eval = true) override; @@ -85,10 +103,37 @@ class Int16 : public BaseType { unsigned int val2buf(void *val, bool reuse = false) override; unsigned int buf2val(void **val) override; + /** + * @brief Returns the current value. + * + * @return Stored signed 16-bit value. + */ virtual dods_int16 value() const; + /** + * @brief Sets the current value. + * + * @param val New signed 16-bit value. + * @return True when the value is accepted. + */ virtual bool set_value(dods_int16 val); + /** + * @brief Writes this value using C stdio output. + * + * @param out Output file stream. + * @param space Indentation prefix. + * @param print_decl_p True to include declaration text. + * @param is_root_grp True when printing in the root group context. + */ void print_val(FILE *out, string space = "", bool print_decl_p = true, bool is_root_grp = true) override; + /** + * @brief Writes this value using C++ stream output. + * + * @param out Output stream. + * @param space Indentation prefix. + * @param print_decl_p True to include declaration text. + * @param is_root_grp True when printing in the root group context. + */ void print_val(ostream &out, string space = "", bool print_decl_p = true, bool is_root_grp = true) override; bool ops(BaseType *b, int op) override; diff --git a/Int32.h b/Int32.h index 859467f59..518de708e 100644 --- a/Int32.h +++ b/Int32.h @@ -62,14 +62,26 @@ class ConstraintEvaluator; class Int32 : public BaseType { protected: + /// Stored scalar 32-bit signed integer value. dods_int32 d_buf; public: Int32(const string &n); Int32(const string &n, const string &d); + /** + * @brief Copy-constructs from another 32-bit signed integer variable. + * + * @param copy_from Source instance. + */ Int32(const Int32 ©_from); + /** + * @brief Assigns from another 32-bit signed integer variable. + * + * @param rhs Source instance. + * @return This instance after assignment. + */ Int32 &operator=(const Int32 &rhs); ~Int32() override; @@ -78,7 +90,13 @@ class Int32 : public BaseType { unsigned int width(bool = false) const override { return sizeof(dods_int32); } - int64_t width_ll(bool = false) const override { return sizeof(dods_int32); } + /** + * @brief Returns the storage width in bytes. + * + * @param constrained Ignored for scalar values. + * @return Number of bytes used by this value. + */ + int64_t width_ll(bool constrained = false) const override { return sizeof(dods_int32); } // DAP2 bool serialize(ConstraintEvaluator &eval, DDS &dds, Marshaller &m, bool ce_eval = true) override; @@ -92,10 +110,37 @@ class Int32 : public BaseType { unsigned int val2buf(void *val, bool reuse = false) override; unsigned int buf2val(void **val) override; + /** + * @brief Sets the current value. + * + * @param i New signed 32-bit value. + * @return True when the value is accepted. + */ virtual bool set_value(dods_int32 i); + /** + * @brief Returns the current value. + * + * @return Stored signed 32-bit value. + */ virtual dods_int32 value() const; + /** + * @brief Writes this value using C stdio output. + * + * @param out Output file stream. + * @param space Indentation prefix. + * @param print_decl_p True to include declaration text. + * @param is_root_grp True when printing in the root group context. + */ void print_val(FILE *out, string space = "", bool print_decl_p = true, bool is_root_grp = true) override; + /** + * @brief Writes this value using C++ stream output. + * + * @param out Output stream. + * @param space Indentation prefix. + * @param print_decl_p True to include declaration text. + * @param is_root_grp True when printing in the root group context. + */ void print_val(ostream &out, string space = "", bool print_decl_p = true, bool is_root_grp = true) override; bool ops(BaseType *b, int op) override; diff --git a/Int64.h b/Int64.h index 535ade789..bbb8d7567 100644 --- a/Int64.h +++ b/Int64.h @@ -57,14 +57,26 @@ class Int64 : public BaseType { } protected: + /// Stored scalar 64-bit signed integer value. dods_int64 d_buf; public: Int64(const string &n); Int64(const string &n, const string &d); + /** + * @brief Copy-constructs from another 64-bit signed integer variable. + * + * @param copy_from Source instance. + */ Int64(const Int64 ©_from); + /** + * @brief Assigns from another 64-bit signed integer variable. + * + * @param rhs Source instance. + * @return This instance after assignment. + */ Int64 &operator=(const Int64 &rhs); ~Int64() override; @@ -73,16 +85,41 @@ class Int64 : public BaseType { unsigned int width(bool = false) const override { return sizeof(dods_int64); } - int64_t width_ll(bool = false) const override { return sizeof(dods_int64); } + /** + * @brief Returns the storage width in bytes. + * + * @param constrained Ignored for scalar values. + * @return Number of bytes used by this value. + */ + int64_t width_ll(bool constrained = false) const override { return sizeof(dods_int64); } // DAP4 void compute_checksum(Crc32 &checksum) override; void serialize(D4StreamMarshaller &m, DMR &dmr, /*ConstraintEvaluator &eval,*/ bool filter = false) override; void deserialize(D4StreamUnMarshaller &um, DMR &dmr) override; + /** + * @brief Sets the current value. + * + * @param i New signed 64-bit value. + * @return True when the value is accepted. + */ virtual bool set_value(dods_int64 i); + /** + * @brief Returns the current value. + * + * @return Stored signed 64-bit value. + */ virtual dods_int64 value() const; + /** + * @brief Writes this value using C++ stream output. + * + * @param out Output stream. + * @param space Indentation prefix. + * @param print_decl_p True to include declaration text. + * @param is_root_grp True when printing in the root group context. + */ void print_val(ostream &out, string space = "", bool print_decl_p = true, bool is_root_grp = true) override; bool ops(BaseType *b, int op) override; diff --git a/Int8.h b/Int8.h index 624466f5b..d92b5a680 100644 --- a/Int8.h +++ b/Int8.h @@ -52,6 +52,7 @@ class Int8 : public BaseType { } protected: + /// Stored scalar 8-bit signed integer value. dods_int8 d_buf; public: @@ -59,28 +60,71 @@ class Int8 : public BaseType { Int8(const string &n, const string &d); ~Int8() override {} + /** + * @brief Copy-constructs from another 8-bit signed integer variable. + * + * @param copy_from Source instance. + */ Int8(const Int8 ©_from); + /** + * @brief Assigns from another 8-bit signed integer variable. + * + * @param rhs Source instance. + * @return This instance after assignment. + */ Int8 &operator=(const Int8 &rhs); BaseType *ptr_duplicate() override; unsigned int width(bool = false) const override { return sizeof(dods_int8); } - int64_t width_ll(bool = false) const override { return sizeof(dods_int8); } + /** + * @brief Returns the storage width in bytes. + * + * @param constrained Ignored for scalar values. + * @return Number of bytes used by this value. + */ + int64_t width_ll(bool constrained = false) const override { return sizeof(dods_int8); } // DAP4 void compute_checksum(Crc32 &checksum) override; void serialize(D4StreamMarshaller &m, DMR &dmr, /*ConstraintEvaluator &eval,*/ bool filter = false) override; void deserialize(D4StreamUnMarshaller &um, DMR &dmr) override; + /** + * @brief Returns the current value. + * + * @return Stored signed 8-bit value. + */ virtual dods_int8 value() const; + /** + * @brief Sets the current value. + * + * @param val New signed 8-bit value. + * @return True when the value is accepted. + */ virtual bool set_value(dods_int8 val); + /** + * @brief Writes this value using C++ stream output. + * + * @param out Output stream. + * @param space Indentation prefix. + * @param print_decl_p True to include declaration text. + * @param is_root_grp True when printing in the root group context. + */ void print_val(ostream &out, string space = "", bool print_decl_p = true, bool is_root_grp = true) override; bool ops(BaseType *b, int op) override; bool d4_ops(BaseType *b, int op) override; + /** + * @brief Converts this DAP4 value into equivalent DAP2 value objects. + * + * @param parent_attr_table Destination attribute table for converted metadata. + * @param show_shared_dims True to include shared-dimension annotations. + * @return A heap-allocated list of DAP2 values corresponding to this object. + */ std::vector *transform_to_dap2(AttrTable *parent_attr_table, bool show_shared_dims = false) override; bool is_dap4_projected(std::vector &inventory) override; diff --git a/InternalErr.h b/InternalErr.h index 5cddc00b5..d80c707cb 100644 --- a/InternalErr.h +++ b/InternalErr.h @@ -81,6 +81,10 @@ class InternalErr : public Error { ~InternalErr() noexcept override; + /** @brief Assign this instance from another InternalErr. + * @param rhs Source error to copy. + * @return This instance. + */ InternalErr &operator=(const InternalErr &rhs); bool OK(); diff --git a/Keywords2.h b/Keywords2.h index 4b445e6f9..6107f311a 100644 --- a/Keywords2.h +++ b/Keywords2.h @@ -51,9 +51,11 @@ namespace libdap { */ class Keywords { public: - // convenience types + /// Convenience alias for a keyword token. typedef string keyword; + /// Convenience alias for a single keyword value. typedef string keyword_value; + /// Allowed values for one keyword. typedef set value_set_t; private: @@ -73,7 +75,11 @@ class Keywords { virtual string parse_keywords(const string &ce); // Is this keyword in the dictionary? - virtual bool is_known_keyword(const string &s) const; + /** @brief Determine whether a keyword is recognized. + * @param word Keyword token to test. + * @return True if `word` is in the known keyword dictionary. + */ + virtual bool is_known_keyword(const string &word) const; // Get a list of all of the keywords parsed virtual list get_keywords() const; @@ -81,6 +87,10 @@ class Keywords { virtual bool has_keyword(const keyword &kw) const; // Get the parsed keyword (and it's dictionary value) of a particular kind + /** @brief Get the parsed value for one keyword. + * @param kw Keyword whose parsed value should be returned. + * @return Parsed keyword value. + */ virtual keyword_value get_keyword_value(const keyword &kw) const; }; diff --git a/Makefile.am b/Makefile.am index f60b42249..e1ba71936 100644 --- a/Makefile.am +++ b/Makefile.am @@ -104,8 +104,8 @@ EXTRA_DIST = ChangeLog COPYING README.md README.dodsrc COPYRIGHT_URI \ dist_aclocal_DATA = conf/libdap.m4 pkgconfig_DATA = libdap.pc libdapclient.pc libdapserver.pc -CLEANFILES = *.output *.gcda *.gcno *.gcov $(BISON_SRC) $(FLEX_SRC) \ - dods-datatypes.h xdr-datatypes.h getdap.1 dap-config.1 getdap4.1 dmr_memory_cache.1\ +CLEANFILES = *.output *.gcda *.gcno *.gcov $(BISON_SRC) $(FLEX_SRC) doxy.conf doxygen.log \ + dods-datatypes.h xdr-datatypes.h getdap.1 dap-config.1 getdap4.1 dmr_memory_cache.1 \ GNU/*.gcda GNU/*.gcno DISTCLEAN = libdap.spec @@ -115,13 +115,15 @@ clean-local: -rm -rf gcovr-output HTML_DOCS=html -DOXYGEN_CONF=doxy.conf + +doxy.conf: doxy.conf.in + config.status --no-create --file=$@ $< # This target only builds the documents, it does not move them to # github. See README.gh-pages.md for that .PHONY: docs -docs: ${DOXYGEN_CONF} main_page.doxygen - doxygen ${DOXYGEN_CONF} +docs: doxy.conf + doxygen doxy.conf > doxygen.log # cccc computes metrics like Lines of code and McCabe. It's available # on the web... diff --git a/Marshaller.h b/Marshaller.h index 6661412a3..3cc79df99 100644 --- a/Marshaller.h +++ b/Marshaller.h @@ -48,24 +48,69 @@ class Vector; */ class Marshaller : public DapObj { public: + /** @brief Serialize one `Byte` value. + * @param val Value to serialize. + */ virtual void put_byte(dods_byte val) = 0; + /** @brief Serialize one `Int16` value. + * @param val Value to serialize. + */ virtual void put_int16(dods_int16 val) = 0; + /** @brief Serialize one `Int32` value. + * @param val Value to serialize. + */ virtual void put_int32(dods_int32 val) = 0; + /** @brief Serialize one `Float32` value. + * @param val Value to serialize. + */ virtual void put_float32(dods_float32 val) = 0; + /** @brief Serialize one `Float64` value. + * @param val Value to serialize. + */ virtual void put_float64(dods_float64 val) = 0; + /** @brief Serialize one `UInt16` value. + * @param val Value to serialize. + */ virtual void put_uint16(dods_uint16 val) = 0; + /** @brief Serialize one `UInt32` value. + * @param val Value to serialize. + */ virtual void put_uint32(dods_uint32 val) = 0; + /** @brief Serialize one DAP string value. + * @param val Value to serialize. + */ virtual void put_str(const std::string &val) = 0; + /** @brief Serialize one DAP URL value. + * @param val Value to serialize. + */ virtual void put_url(const std::string &val) = 0; + /** @brief Serialize opaque bytes. + * @param val Buffer containing bytes. + * @param len Number of bytes to serialize. + */ virtual void put_opaque(char *val, unsigned int len) = 0; + /** @brief Serialize one legacy DAP integer. + * @param val Value to serialize. + */ virtual void put_int(int val) = 0; + /** @brief Serialize a vector where element width is inferred from `vec`. + * @param val Pointer to vector data bytes. + * @param num Number of elements. + * @param vec Vector metadata used for typing. + */ virtual void put_vector(char *val, int num, Vector &vec) = 0; + /** @brief Serialize a vector with explicit element width. + * @param val Pointer to vector data bytes. + * @param num Number of elements. + * @param width Bytes per element. + * @param vec Vector metadata used for typing. + */ virtual void put_vector(char *val, int num, int width, Vector &vec) = 0; /** diff --git a/MarshallerFuture.h b/MarshallerFuture.h index 016ca1b87..c4e988b9d 100644 --- a/MarshallerFuture.h +++ b/MarshallerFuture.h @@ -122,6 +122,12 @@ class MarshallerThread { }); } + /** + * @brief Start a thread to write a partial chunk payload from a raw buffer. + * @param out Destination stream. + * @param byte_buf Shared bytes whose first four bytes are skipped. + * @param num_bytes Total bytes in `byte_buf`. + */ void start_thread_part(std::ostream &out, const char *byte_buf, std::streamsize num_bytes) { if (d_ostream_future.valid()) { d_ostream_future.get(); @@ -142,6 +148,12 @@ class MarshallerThread { }); } + /** + * @brief Start a thread to write a partial chunk payload from shared bytes. + * @param out Destination stream. + * @param byte_buf Shared bytes whose first four bytes are skipped. + * @param num_bytes Total bytes in `byte_buf`. + */ void start_thread_part(std::ostream &out, std::shared_ptr byte_buf, std::streamsize num_bytes) { if (d_ostream_future.valid()) { d_ostream_future.get(); @@ -159,6 +171,12 @@ class MarshallerThread { }); } + /** + * @brief Start a thread to write bytes to a file descriptor from a raw buffer. + * @param fd Destination file descriptor. + * @param byte_buf Source bytes. + * @param num_bytes Number of bytes to write. + */ void start_thread(int fd, const char *byte_buf, std::streamsize num_bytes) { if (d_fp_future.valid()) { d_fp_future.get(); @@ -176,6 +194,12 @@ class MarshallerThread { }); } + /** + * @brief Start a thread to write bytes to a file descriptor from shared bytes. + * @param fd Destination file descriptor. + * @param byte_buf Source bytes. + * @param num_bytes Number of bytes to write. + */ void start_thread(int fd, std::shared_ptr byte_buf, std::streamsize num_bytes) { if (d_fp_future.valid()) { d_fp_future.get(); diff --git a/MarshallerThread.h b/MarshallerThread.h index 02515ede7..ad96dbeda 100644 --- a/MarshallerThread.h +++ b/MarshallerThread.h @@ -139,10 +139,14 @@ class MarshallerThread { MarshallerThread(); virtual ~MarshallerThread(); + /** @brief Returns the mutex guarding shared output state. */ pthread_mutex_t &get_mutex() { return d_out_mutex; } + /** @brief Returns the condition variable used to signal child-thread completion. */ pthread_cond_t &get_cond() { return d_out_cond; } + /** @brief Returns the current number of active child threads. */ int &get_child_thread_count() { return d_child_thread_count; } + /** @brief Increments the active child-thread count. */ void increment_child_thread_count() { ++d_child_thread_count; } void start_thread(void *(*thread)(void *arg), std::ostream &out, char *byte_buf, std::streamsize bytes_written); diff --git a/RCReader.h b/RCReader.h index 028a670ab..9965d4be6 100644 --- a/RCReader.h +++ b/RCReader.h @@ -126,21 +126,31 @@ class RCReader { friend class HTTPConnectTest; public: + /** @brief Returns the singleton RCReader instance. */ static RCReader *instance(); RCReader(const RCReader &) = delete; RCReader &operator=(const RCReader &) = delete; // GET METHODS + /** @brief Returns configured cache root directory. */ string get_dods_cache_root() const throw() { return d_cache_root; } + /** @brief Returns whether HTTP caching is enabled. */ bool get_use_cache() const throw() { return _dods_use_cache; } + /** @brief Returns maximum cache size (MB). */ int get_max_cache_size() const throw() { return _dods_cache_max; } + /** @brief Returns max per-object cache size (MB). */ unsigned int get_max_cached_obj() const throw() { return _dods_cached_obj; } + /** @brief Returns ignore-expires flag. */ int get_ignore_expires() const throw() { return _dods_ign_expires; } + /** @brief Returns default expiration interval (seconds). */ int get_default_expires() const throw() { return _dods_default_expires; } + /** @brief Returns always-validate flag. */ int get_always_validate() const throw() { return _dods_always_validate; } + /** @brief Returns SSL certificate/host validation setting. */ int get_validate_ssl() const throw() { return d_validate_ssl; } + /** @brief Returns whether compressed responses are requested. */ bool get_deflate() const throw() { return _dods_deflate; } /// Get the proxy server protocol @@ -178,31 +188,48 @@ class RCReader { // real need for suppressing proxy access for the local domain. The // ..._port() method is bogus, however, so it is deprecated. There's no // code that uses it. 06/17/04 jhrg + /** @brief Returns whether NO_PROXY_FOR settings are active. */ bool is_no_proxy_for_used() throw() { return d_dods_no_proxy_for; } + /** @brief Returns NO_PROXY_FOR protocol selector. */ string get_no_proxy_for_protocol() const throw() { return d_dods_no_proxy_for_protocol; } + /** @brief Returns NO_PROXY_FOR host selector. */ string get_no_proxy_for_host() const throw() { return d_dods_no_proxy_for_host; } /// @deprecated int get_no_proxy_for_port() const throw() { return _dods_no_proxy_for_port; } + /** @brief Returns configured AIS database path/name. */ string get_ais_database() const throw() { return d_ais_database; } + /** @brief Returns configured cookie-jar file path. */ string get_cookie_jar() const throw() { return d_cookie_jar; } // SET METHODS + /** @brief Sets whether HTTP caching is enabled. @param b New setting. */ void set_use_cache(bool b) throw() { _dods_use_cache = b; } + /** @brief Sets maximum cache size (MB). @param i New setting. */ void set_max_cache_size(int i) throw() { _dods_cache_max = i; } + /** @brief Sets max per-object cache size (MB). @param i New setting. */ void set_max_cached_obj(int i) throw() { _dods_cached_obj = i; } + /** @brief Sets ignore-expires flag. @param i New setting. */ void set_ignore_expires(int i) throw() { _dods_ign_expires = i; } + /** @brief Sets default expiration interval (seconds). @param i New setting. */ void set_default_expires(int i) throw() { _dods_default_expires = i; } + /** @brief Sets always-validate flag. @param i New setting. */ void set_always_validate(int i) throw() { _dods_always_validate = i; } + /** @brief Sets SSL validation behavior. @param i New setting. */ void set_validate_ssl(int i) throw() { d_validate_ssl = i; } + /** @brief Sets whether to request compressed responses. @param b New setting. */ void set_deflate(bool b) throw() { _dods_deflate = b; } + /** @brief Sets proxy protocol. @param s Proxy protocol token. */ void set_proxy_server_protocol(const string &s) throw() { d_dods_proxy_server_protocol = s; } + /** @brief Sets proxy host. @param s Proxy host. */ void set_proxy_server_host(const string &s) throw() { d_dods_proxy_server_host = s; } + /** @brief Sets proxy port. @param l Proxy port. */ void set_proxy_server_port(int l) throw() { d_dods_proxy_server_port = l; } + /** @brief Sets proxy user/password token. @param s Proxy credentials token. */ void set_proxy_server_userpw(const string &s) throw() { d_dods_proxy_server_userpw = s; } /// @deprecated @@ -215,12 +242,15 @@ class RCReader { /// @deprecated void set_proxy_for_regexp_flags(int i) throw() { _dods_proxy_for_regexp_flags = i; } + /** @brief Sets NO_PROXY_FOR protocol selector. @param s Protocol selector. */ void set_no_proxy_for_protocol(const string &s) throw() { d_dods_no_proxy_for_protocol = s; } + /** @brief Sets NO_PROXY_FOR host selector. @param s Host selector. */ void set_no_proxy_for_host(const string &s) throw() { d_dods_no_proxy_for_host = s; } /// @deprecated void set_no_proxy_for_port(int i) throw() { _dods_no_proxy_for_port = i; } + /** @brief Sets AIS database path/name. @param db AIS database path/name. */ void set_ais_database(const string &db) throw() { d_ais_database = db; } }; diff --git a/RValue.h b/RValue.h index 47416ed1b..7a4780956 100644 --- a/RValue.h +++ b/RValue.h @@ -51,14 +51,29 @@ class rvalue { std::vector *d_args; // arguments to the function public: + /** @brief Mutable iterator over function-call argument rvalues. */ typedef std::vector::iterator Args_iter; + /** @brief Read-only iterator over function-call argument rvalues. */ typedef std::vector::const_iterator Args_citer; + /** + * @brief Builds an rvalue from a dataset variable/value node. + * @param bt BaseType node used as this rvalue's source. + */ rvalue(BaseType *bt); + /** + * @brief Builds an rvalue from a function and argument list. + * @param f Function pointer. + * @param a Function arguments. + */ rvalue(btp_func f, std::vector *a); rvalue(); virtual ~rvalue(); + /** + * @brief Returns a display name for this rvalue. + * @return Human-readable value or function identifier. + */ std::string value_name(); BaseType *bvalue(DDS &dds); @@ -66,16 +81,26 @@ class rvalue { // This type def must come after the class definition above. It is used in // the Clause and DDS classes. +/** @brief Container type for parser/evaluator rvalues. */ typedef std::vector rvalue_list; +/** @brief Read-only iterator for `rvalue_list`. */ typedef std::vector::const_iterator rvalue_list_citer; +/** @brief Mutable iterator for `rvalue_list`. */ typedef std::vector::iterator rvalue_list_iter; +/** @brief Pointer to a vector of `Byte` function arguments. */ typedef std::vector *byte_arg_list; +/** @brief Pointer to a vector of `Int16` function arguments. */ typedef std::vector *int16_arg_list; +/** @brief Pointer to a vector of `UInt16` function arguments. */ typedef std::vector *uint16_arg_list; +/** @brief Pointer to a vector of `Int32` function arguments. */ typedef std::vector *int32_arg_list; +/** @brief Pointer to a vector of `UInt32` function arguments. */ typedef std::vector *uint32_arg_list; +/** @brief Pointer to a vector of `Float32` function arguments. */ typedef std::vector *float32_arg_list; +/** @brief Pointer to a vector of `Float64` function arguments. */ typedef std::vector *float64_arg_list; rvalue_list *make_rvalue_list(rvalue *rv); diff --git a/Response.h b/Response.h index 9a2fe1e4c..67ef0f395 100644 --- a/Response.h +++ b/Response.h @@ -63,6 +63,7 @@ class Response { int d_status = 0; protected: + /// True when this object owns and should delete `d_cpp_stream`. // Hack for HTTPResponse which may allocate a fstream pointer in a setter. jhrg 2/5/25 bool d_delete_cpp_stream_ptr = false; @@ -84,6 +85,10 @@ class Response { @param status The HTTP response status code.*/ explicit Response(FILE *s, int status = 0) : d_stream(s), d_status(status) {} + /** @brief Initialize with a C++ stream. + * @param s Read data from this C++ stream. + * @param status The HTTP response status code. + */ explicit Response(std::fstream *s, int status = 0) : d_cpp_stream(s), d_status(status) {} /** Close the stream. */ diff --git a/Sequence.h b/Sequence.h index ed491e505..d7311c502 100644 --- a/Sequence.h +++ b/Sequence.h @@ -199,21 +199,71 @@ class Sequence : public Constructor { friend class SequenceTest; protected: + /** + * @brief Copies Sequence-specific state from another sequence. + * @param s Source sequence. + */ void m_duplicate(const Sequence &s); + /** @brief Stack used while recursively collecting nested sequence values. */ typedef stack sequence_values_stack_t; + /** + * @brief Serializes the parent portion of a nested sequence (part one). + * @param dds DDS context. + * @param eval Active constraint evaluator. + * @param m Output marshaller. + * @return True when data was emitted. + */ virtual bool serialize_parent_part_one(DDS &dds, ConstraintEvaluator &eval, Marshaller &m); + /** + * @brief Serializes the parent portion of a nested sequence (part two). + * @param dds DDS context. + * @param eval Active constraint evaluator. + * @param m Output marshaller. + */ virtual void serialize_parent_part_two(DDS &dds, ConstraintEvaluator &eval, Marshaller &m); + /** + * @brief Serializes a leaf sequence. + * @param dds DDS context. + * @param eval Active constraint evaluator. + * @param m Output marshaller. + * @param ce_eval True to apply constraint evaluation. + * @return True when data was emitted. + */ virtual bool serialize_leaf(DDS &dds, ConstraintEvaluator &eval, Marshaller &m, bool ce_eval); + /** + * @brief Interns sequence data for parent and leaf cases. + * @param eval Active constraint evaluator. + * @param dds DDS context. + * @param sequence_values_stack Stack of active sequence value buffers. + */ virtual void intern_data_private(ConstraintEvaluator &eval, DDS &dds, sequence_values_stack_t &sequence_values_stack); + /** + * @brief Interns data for a leaf sequence instance. + * @param dds DDS context. + * @param eval Active constraint evaluator. + * @param sequence_values_stack Stack of active sequence value buffers. + */ virtual void intern_data_for_leaf(DDS &dds, ConstraintEvaluator &eval, sequence_values_stack_t &sequence_values_stack); + /** + * @brief Interns parent-sequence data before child traversal. + * @param dds DDS context. + * @param eval Active constraint evaluator. + * @param sequence_values_stack Stack of active sequence value buffers. + */ virtual void intern_data_parent_part_one(DDS &dds, ConstraintEvaluator &eval, sequence_values_stack_t &sequence_values_stack); + /** + * @brief Interns parent-sequence data after child traversal. + * @param dds DDS context. + * @param eval Active constraint evaluator. + * @param sequence_values_stack Stack of active sequence value buffers. + */ virtual void intern_data_parent_part_two(DDS &dds, ConstraintEvaluator &eval, sequence_values_stack_t &sequence_values_stack); @@ -225,6 +275,11 @@ class Sequence : public Constructor { ~Sequence() override; + /** + * @brief Assigns from another sequence. + * @param rhs Source sequence. + * @return This instance after assignment. + */ Sequence &operator=(const Sequence &rhs); BaseType *ptr_duplicate() override; @@ -241,6 +296,10 @@ class Sequence : public Constructor { int length() const override; + /** + * @brief Returns the number of rows currently stored. + * @return Row count. + */ virtual int number_of_rows() const; virtual bool read_row(int row, DDS &dds, ConstraintEvaluator &eval, bool ce_eval = true); @@ -254,7 +313,15 @@ class Sequence : public Constructor { // I added a second method instead of a param with a default value because I think // this will result only in an addition to the ABI/API, not a change. 5/16/15 jhrg void reset_row_number(bool recur); + /** + * @brief Advances the current row index. + * @param i Number of rows to advance. + */ void increment_row_number(unsigned int i) { d_row_number += i; } + /** + * @brief Returns the current row index. + * @return Current row number. + */ int get_row_number() const { return d_row_number; } int get_starting_row_number(); @@ -275,23 +342,85 @@ class Sequence : public Constructor { virtual SequenceValues value(); virtual SequenceValues &value_ref(); + /** + * @brief Returns the value of one column in one row by name. + * @param row Row index. + * @param name Column name. + * @return Pointer to the stored value. + */ virtual BaseType *var_value(size_t row, const string &name); + /** + * @brief Returns the value of one column in one row by column index. + * @param row Row index. + * @param i Column index. + * @return Pointer to the stored value. + */ virtual BaseType *var_value(size_t row, size_t i); virtual BaseTypeRow *row_value(size_t row); + /** + * @brief Prints one row using C++ streams. + * @param out Output stream. + * @param row Row index. + * @param space Indentation prefix. + * @param print_row_num True to include the row number in output. + */ virtual void print_one_row(ostream &out, int row, string space, bool print_row_num = false); + /** + * @brief Prints all rows using C++ streams. + * @param out Output stream. + * @param space Indentation prefix. + * @param print_decl_p True to include declaration text. + * @param print_row_numbers True to include row numbers in output. + */ virtual void print_val_by_rows(ostream &out, string space = "", bool print_decl_p = true, bool print_row_numbers = true); + /** + * @brief Prints sequence values using C++ streams. + * @param out Output stream. + * @param space Indentation prefix. + * @param print_decl_p True to include declaration text. + * @param is_root_grp True when printing in root-group context. + */ void print_val(ostream &out, string space = "", bool print_decl_p = true, bool is_root_grp = true) override; + /** + * @brief Prints one row using C stdio. + * @param out Output file stream. + * @param row Row index. + * @param space Indentation prefix. + * @param print_row_num True to include the row number in output. + */ virtual void print_one_row(FILE *out, int row, string space, bool print_row_num = false); + /** + * @brief Prints all rows using C stdio. + * @param out Output file stream. + * @param space Indentation prefix. + * @param print_decl_p True to include declaration text. + * @param print_row_numbers True to include row numbers in output. + */ virtual void print_val_by_rows(FILE *out, string space = "", bool print_decl_p = true, bool print_row_numbers = true); + /** + * @brief Prints sequence values using C stdio. + * @param out Output file stream. + * @param space Indentation prefix. + * @param print_decl_p True to include declaration text. + * @param is_root_grp True when printing in root-group context. + */ void print_val(FILE *out, string space = "", bool print_decl_p = true, bool is_root_grp = true) override; + /** + * @brief Marks whether this sequence should behave as a leaf. + * @param state True to treat as leaf sequence. + */ virtual void set_leaf_p(bool state); + /** + * @brief Reports whether this sequence is marked as a leaf. + * @return True when this sequence is a leaf. + */ virtual bool is_leaf_sequence(); virtual void set_leaf_sequence(int lvl = 1); diff --git a/ServerFunction.h b/ServerFunction.h index da4d823ef..7e718d075 100644 --- a/ServerFunction.h +++ b/ServerFunction.h @@ -39,6 +39,7 @@ namespace libdap { +/** @brief Metadata and function-pointer wrapper for a callable server function. */ class ServerFunction { private: @@ -59,33 +60,85 @@ class ServerFunction { public: ServerFunction(); + /** + * @brief Builds a boolean server function descriptor. + * @param name Function name. + * @param version Function version string. + * @param description Human-readable description. + * @param usage Usage string. + * @param doc_url Documentation URL. + * @param role Function role/category. + * @param f Boolean CE function pointer. + */ ServerFunction(std::string name, std::string version, std::string description, std::string usage, std::string doc_url, std::string role, bool_func f); + /** + * @brief Builds a BaseType-returning server function descriptor. + * @param name Function name. + * @param version Function version string. + * @param description Human-readable description. + * @param usage Usage string. + * @param doc_url Documentation URL. + * @param role Function role/category. + * @param f Value-returning CE function pointer. + */ ServerFunction(std::string name, std::string version, std::string description, std::string usage, std::string doc_url, std::string role, btp_func f); + /** + * @brief Builds a projection-function descriptor. + * @param name Function name. + * @param version Function version string. + * @param description Human-readable description. + * @param usage Usage string. + * @param doc_url Documentation URL. + * @param role Function role/category. + * @param f Projection CE function pointer. + */ ServerFunction(std::string name, std::string version, std::string description, std::string usage, std::string doc_url, std::string role, proj_func f); + /** + * @brief Builds a DAP4-function descriptor. + * @param name Function name. + * @param version Function version string. + * @param description Human-readable description. + * @param usage Usage string. + * @param doc_url Documentation URL. + * @param role Function role/category. + * @param f DAP4 function pointer. + */ ServerFunction(std::string name, std::string version, std::string description, std::string usage, std::string doc_url, std::string role, D4Function f); virtual ~ServerFunction() {} + /** @brief Returns the registered function name. */ std::string getName() { return name; } + /** @brief Sets the registered function name. @param n Function name. */ void setName(const std::string &n) { name = n; } + /** @brief Returns the usage/help string. */ std::string getUsageString() { return usage; } + /** @brief Sets the usage/help string. @param u Usage/help string. */ void setUsageString(const std::string &u) { usage = u; } + /** @brief Returns the documentation URL. */ std::string getDocUrl() { return doc_url; } + /** @brief Sets the documentation URL. @param url Documentation URL. */ void setDocUrl(const std::string &url) { doc_url = url; } + /** @brief Returns the role/category string. */ std::string getRole() { return role; } + /** @brief Sets the role/category string. @param r Role/category string. */ void setRole(const std::string &r) { role = r; } + /** @brief Returns the description string. */ std::string getDescriptionString() { return description; } + /** @brief Sets the description string. @param desc Description text. */ void setDescriptionString(const std::string &desc) { description = desc; } + /** @brief Returns the function version string. */ std::string getVersion() { return version; } + /** @brief Sets the function version string. @param ver Version string. */ void setVersion(const std::string &ver) { version = ver; } /** @@ -117,14 +170,19 @@ class ServerFunction { * * @param bf */ + /** @brief Installs a boolean CE function pointer. @param bf Boolean function pointer. */ void setFunction(bool_func bf) { d_bool_func = bf; } + /** @brief Installs a value-returning CE function pointer. @param btp Value-returning function pointer. */ void setFunction(btp_func btp) { d_btp_func = btp; } + /** @brief Installs a projection CE function pointer. @param pf Projection function pointer. */ void setFunction(proj_func pf) { d_proj_func = pf; } + /** @brief Installs a DAP4 function pointer. @param pf DAP4 function pointer. */ void setFunction(D4Function pf) { d_d4_function = pf; } + /** @brief Returns a string label for the currently installed function type. */ std::string getTypeString() { if (d_bool_func) return "boolean"; @@ -137,9 +195,13 @@ class ServerFunction { return "null"; } + /** @brief Returns the installed boolean CE function pointer. */ bool_func get_bool_func() { return d_bool_func; } + /** @brief Returns the installed value-returning CE function pointer. */ btp_func get_btp_func() { return d_btp_func; } + /** @brief Returns the installed projection CE function pointer. */ proj_func get_proj_func() { return d_proj_func; } + /** @brief Returns the installed DAP4 function pointer. */ D4Function get_d4_function() { return d_d4_function; } }; diff --git a/ServerFunctionsList.h b/ServerFunctionsList.h index bc390c7a4..b5695636d 100644 --- a/ServerFunctionsList.h +++ b/ServerFunctionsList.h @@ -43,6 +43,7 @@ namespace libdap { class ServerFunctionsListUnitTest; class ConstraintEvaluator; +/** @brief Singleton registry of server-callable functions. */ class ServerFunctionsList { private: std::multimap d_func_list; @@ -56,12 +57,18 @@ class ServerFunctionsList { public: // Added typedefs to reduce clutter jhrg 3/12/14 + /** @brief Mutable iterator over `(name, function)` entries. */ typedef std::multimap::iterator SFLIter; + /** @brief Read-only iterator over `(name, function)` entries. */ typedef std::multimap::const_iterator SFLCIter; ServerFunctionsList(const ServerFunctionsList &) = delete; ServerFunctionsList &operator=(const ServerFunctionsList &) = delete; + /** + * @brief Returns the singleton function registry instance. + * @return Global function registry. + */ static ServerFunctionsList *TheList(); virtual void add_function(ServerFunction *func); @@ -75,6 +82,10 @@ class ServerFunctionsList { SFLIter end(); ServerFunction *getFunction(SFLIter it); + /** + * @brief Populates a vector with registered function names. + * @param names Destination vector for function names. + */ virtual void getFunctionNames(std::vector *names); }; diff --git a/SignalHandler.h b/SignalHandler.h index 5a9b5294e..3eb34924a 100644 --- a/SignalHandler.h +++ b/SignalHandler.h @@ -34,6 +34,7 @@ namespace libdap { +/** @brief C-compatible signal handler function signature. */ typedef void Sigfunc(int); // Plauger, 1992 /** Singleton to handle signals. This class adapts the C-style function call diff --git a/SignalHandlerRegisteredErr.h b/SignalHandlerRegisteredErr.h index 82eefc436..a17baa385 100644 --- a/SignalHandlerRegisteredErr.h +++ b/SignalHandlerRegisteredErr.h @@ -42,6 +42,9 @@ namespace libdap { class SignalHandlerRegisteredErr : public Error { public: + /** @brief Build a cache signal-handler registration error with details. + * @param msg Additional context for the registration failure. + */ SignalHandlerRegisteredErr(const string &msg) : Error() { _error_code = unknown_error; _error_message = ""; diff --git a/StdinResponse.h b/StdinResponse.h index bb5c2b596..da35315cf 100644 --- a/StdinResponse.h +++ b/StdinResponse.h @@ -67,10 +67,24 @@ class StdinResponse : public Response { /** Destructor. Does not close standard input. */ ~StdinResponse() override {} + /** @brief Return the `FILE*` input stream. + * @return Stored C stdio input stream. + */ FILE *get_stream() const override { return d_stdin; } + + /** @brief Set the `FILE*` input stream. + * @param s C stdio input stream. + */ void set_stream(FILE *s) override { d_stdin = s; } + /** @brief Return the C++ input stream. + * @return Stored C++ input stream pointer. + */ std::istream *get_cpp_stream() const override { return d_cin; } + + /** @brief Set the C++ input stream. + * @param in C++ input stream pointer. + */ void set_cpp_stream(std::istream *in) override { d_cin = in; } }; diff --git a/Str.h b/Str.h index c123e28cf..4b97fda44 100644 --- a/Str.h +++ b/Str.h @@ -50,6 +50,7 @@ namespace libdap { // term solution is to fix libdap, but strings should not routinely be > 32k // for the time being... jhrg 4/30/97 +/** @brief Maximum string length accepted by XDR string deserialization paths. */ const unsigned int max_str_len = DODS_USHRT_MAX - 1; /** @brief Holds character string data. @@ -60,6 +61,7 @@ const unsigned int max_str_len = DODS_USHRT_MAX - 1; class Str : public BaseType { protected: + /// Stored scalar string value. string d_buf; public: @@ -68,15 +70,32 @@ class Str : public BaseType { ~Str() override {} + /** + * @brief Copy-constructs from another string variable. + * + * @param copy_from Source instance. + */ Str(const Str ©_from); + /** + * @brief Assigns from another string variable. + * + * @param rhs Source instance. + * @return This instance after assignment. + */ Str &operator=(const Str &rhs); BaseType *ptr_duplicate() override; unsigned int width(bool = false) const override { return sizeof(string); } - int64_t width_ll(bool = false) const override { return sizeof(string); } + /** + * @brief Returns the storage width in bytes. + * + * @param constrained Ignored for scalar values. + * @return Number of bytes used by the in-memory string object. + */ + int64_t width_ll(bool constrained = false) const override { return sizeof(string); } // Return the length of the stored string or zero if no string has been // stored in the instance's internal buffer. @@ -100,7 +119,23 @@ class Str : public BaseType { virtual string esc_string_variable_value(const string &s); + /** + * @brief Writes this value using C stdio output. + * + * @param out Output file stream. + * @param space Indentation prefix. + * @param print_decl_p True to include declaration text. + * @param is_root_grp True when printing in the root group context. + */ void print_val(FILE *out, string space = "", bool print_decl_p = true, bool is_root_grp = true) override; + /** + * @brief Writes this value using C++ stream output. + * + * @param out Output stream. + * @param space Indentation prefix. + * @param print_decl_p True to include declaration text. + * @param is_root_grp True when printing in the root group context. + */ void print_val(ostream &out, string space = "", bool print_decl_p = true, bool is_root_grp = true) override; bool ops(BaseType *b, int op) override; diff --git a/Structure.h b/Structure.h index b6cc2d2f4..e421f764d 100644 --- a/Structure.h +++ b/Structure.h @@ -89,6 +89,11 @@ class Structure : public Constructor { Structure(const Structure &rhs); ~Structure() override; + /** + * @brief Assigns from another structure. + * @param rhs Source structure. + * @return This instance after assignment. + */ Structure &operator=(const Structure &rhs); BaseType *ptr_duplicate() override; diff --git a/TempFile.h b/TempFile.h index 927f92ba5..5ec20a1c0 100644 --- a/TempFile.h +++ b/TempFile.h @@ -14,9 +14,17 @@ namespace libdap { +/** @brief RAII wrapper for a temporary file path and output stream. + * + * Creates a unique file, opens it as an `std::ofstream`, and unlinks it on + * destruction unless ownership is released. + */ class TempFile { public: - // pattern must contain at least 6 trailing 'X' characters, e.g. "/tmp/myapp-XXXXXX" + /** @brief Create and open a new temporary file. + * @param pattern Template path ending with at least six `X` characters. + * @param mode Open mode used for the output stream. + */ explicit TempFile(std::string pattern, std::ios::openmode mode = std::ios::out | std::ios::binary | std::ios::trunc) { create_and_open(std::move(pattern), mode); @@ -27,12 +35,19 @@ class TempFile { TempFile(const TempFile &) = delete; TempFile &operator=(const TempFile &) = delete; + /** @brief Move-construct from another TempFile. + * @param other Source object whose file ownership is transferred. + */ TempFile(TempFile &&other) noexcept : path_(std::move(other.path_)), stream_(std::move(other.stream_)), unlink_on_destroy_(std::exchange(other.unlink_on_destroy_, false)) { other.path_.clear(); } + /** @brief Move-assign from another TempFile. + * @param other Source object whose file ownership is transferred. + * @return This instance. + */ TempFile &operator=(TempFile &&other) noexcept { if (this != &other) { cleanup(); @@ -44,22 +59,44 @@ class TempFile { return *this; } + /** @brief Get the path of the created temporary file. + * @return Absolute or relative path used for the temporary file. + */ const std::string &path() const noexcept { return path_; } + /** @brief Access the writable stream. + * @return Writable `std::ofstream` bound to the temp file. + */ std::ofstream &stream() noexcept { return stream_; } + + /** @brief Access the writable stream as const. + * @return Const `std::ofstream` bound to the temp file. + */ const std::ofstream &stream() const noexcept { return stream_; } + /** @brief Check whether the stream is currently open. + * @return True if the stream is open. + */ bool is_open() const noexcept { return stream_.is_open(); } + + /** @brief Flush buffered output to disk. + */ void flush() noexcept { stream_.flush(); } - // Optional: close early (file will still be unlinked in destructor unless you call release()). + /** @brief Close the stream before destruction. + * + * The file is still unlinked by the destructor unless `release()` is called. + */ void close_stream() { if (stream_.is_open()) stream_.close(); } - // Optional: keep the file on disk after this object dies. - // Closes the stream and disables unlink-on-destroy, returning the path. + /** @brief Keep the temporary file on disk after object destruction. + * + * Closes the stream and disables automatic unlink behavior. + * @return The path to the retained file. + */ std::string release() noexcept { close_stream(); unlink_on_destroy_ = false; diff --git a/UInt16.h b/UInt16.h index c69e73f58..bcc30e06d 100644 --- a/UInt16.h +++ b/UInt16.h @@ -54,6 +54,7 @@ namespace libdap { class UInt16 : public BaseType { protected: + /// Stored scalar 16-bit unsigned integer value. dods_uint16 d_buf; public: @@ -61,15 +62,32 @@ class UInt16 : public BaseType { UInt16(const string &n, const string &d); ~UInt16() override {} + /** + * @brief Copy-constructs from another 16-bit unsigned integer variable. + * + * @param copy_from Source instance. + */ UInt16(const UInt16 ©_from); + /** + * @brief Assigns from another 16-bit unsigned integer variable. + * + * @param rhs Source instance. + * @return This instance after assignment. + */ UInt16 &operator=(const UInt16 &rhs); BaseType *ptr_duplicate() override; unsigned int width(bool = false) const override { return sizeof(dods_uint16); } - int64_t width_ll(bool = false) const override { return sizeof(dods_uint16); } + /** + * @brief Returns the storage width in bytes. + * + * @param constrained Ignored for scalar values. + * @return Number of bytes used by this value. + */ + int64_t width_ll(bool constrained = false) const override { return sizeof(dods_uint16); } // DAP2 bool serialize(ConstraintEvaluator &eval, DDS &dds, Marshaller &m, bool ce_eval = true) override; @@ -83,10 +101,37 @@ class UInt16 : public BaseType { unsigned int val2buf(void *val, bool reuse = false) override; unsigned int buf2val(void **val) override; + /** + * @brief Returns the current value. + * + * @return Stored unsigned 16-bit value. + */ virtual dods_uint16 value() const; + /** + * @brief Sets the current value. + * + * @param val New unsigned 16-bit value. + * @return True when the value is accepted. + */ virtual bool set_value(dods_uint16 val); + /** + * @brief Writes this value using C stdio output. + * + * @param out Output file stream. + * @param space Indentation prefix. + * @param print_decl_p True to include declaration text. + * @param is_root_grp True when printing in the root group context. + */ void print_val(FILE *out, string space = "", bool print_decl_p = true, bool is_root_grp = true) override; + /** + * @brief Writes this value using C++ stream output. + * + * @param out Output stream. + * @param space Indentation prefix. + * @param print_decl_p True to include declaration text. + * @param is_root_grp True when printing in the root group context. + */ void print_val(ostream &out, string space = "", bool print_decl_p = true, bool is_root_grp = true) override; bool ops(BaseType *b, int op) override; diff --git a/UInt32.h b/UInt32.h index 5ebc363f7..0ac28379f 100644 --- a/UInt32.h +++ b/UInt32.h @@ -56,6 +56,7 @@ namespace libdap { class UInt32 : public BaseType { protected: + /// Stored scalar 32-bit unsigned integer value. dods_uint32 d_buf; public: @@ -63,15 +64,32 @@ class UInt32 : public BaseType { UInt32(const string &n, const string &d); ~UInt32() override {} + /** + * @brief Copy-constructs from another 32-bit unsigned integer variable. + * + * @param copy_from Source instance. + */ UInt32(const UInt32 ©_from); + /** + * @brief Assigns from another 32-bit unsigned integer variable. + * + * @param rhs Source instance. + * @return This instance after assignment. + */ UInt32 &operator=(const UInt32 &rhs); BaseType *ptr_duplicate() override; unsigned int width(bool = false) const override { return sizeof(dods_uint32); } - int64_t width_ll(bool = false) const override { return sizeof(dods_uint32); } + /** + * @brief Returns the storage width in bytes. + * + * @param constrained Ignored for scalar values. + * @return Number of bytes used by this value. + */ + int64_t width_ll(bool constrained = false) const override { return sizeof(dods_uint32); } // DAP2 bool serialize(ConstraintEvaluator &eval, DDS &dds, Marshaller &m, bool ce_eval = true) override; @@ -85,10 +103,37 @@ class UInt32 : public BaseType { unsigned int val2buf(void *val, bool reuse = false) override; unsigned int buf2val(void **val) override; + /** + * @brief Returns the current value. + * + * @return Stored unsigned 32-bit value. + */ virtual dods_uint32 value() const; + /** + * @brief Sets the current value. + * + * @param val New unsigned 32-bit value. + * @return True when the value is accepted. + */ virtual bool set_value(dods_uint32 val); + /** + * @brief Writes this value using C stdio output. + * + * @param out Output file stream. + * @param space Indentation prefix. + * @param print_decl_p True to include declaration text. + * @param is_root_grp True when printing in the root group context. + */ void print_val(FILE *out, string space = "", bool print_decl_p = true, bool is_root_grp = true) override; + /** + * @brief Writes this value using C++ stream output. + * + * @param out Output stream. + * @param space Indentation prefix. + * @param print_decl_p True to include declaration text. + * @param is_root_grp True when printing in the root group context. + */ void print_val(ostream &out, string space = "", bool print_decl_p = true, bool is_root_grp = true) override; bool ops(BaseType *b, int op) override; diff --git a/UInt64.h b/UInt64.h index f26fb409c..58f15bd55 100644 --- a/UInt64.h +++ b/UInt64.h @@ -56,6 +56,7 @@ class UInt64 : public BaseType { } protected: + /// Stored scalar 64-bit unsigned integer value. dods_uint64 d_buf; public: @@ -63,29 +64,72 @@ class UInt64 : public BaseType { UInt64(const string &n, const string &d); ~UInt64() override {} + /** + * @brief Copy-constructs from another 64-bit unsigned integer variable. + * + * @param copy_from Source instance. + */ UInt64(const UInt64 ©_from); + /** + * @brief Assigns from another 64-bit unsigned integer variable. + * + * @param rhs Source instance. + * @return This instance after assignment. + */ UInt64 &operator=(const UInt64 &rhs); BaseType *ptr_duplicate() override; unsigned int width(bool = false) const override { return sizeof(dods_uint64); } - int64_t width_ll(bool = false) const override { return sizeof(dods_uint64); } + /** + * @brief Returns the storage width in bytes. + * + * @param constrained Ignored for scalar values. + * @return Number of bytes used by this value. + */ + int64_t width_ll(bool constrained = false) const override { return sizeof(dods_uint64); } // DAP4 void compute_checksum(Crc32 &checksum) override; void serialize(D4StreamMarshaller &m, DMR &dmr, /*ConstraintEvaluator &eval,*/ bool filter = false) override; void deserialize(D4StreamUnMarshaller &um, DMR &dmr) override; + /** + * @brief Returns the current value. + * + * @return Stored unsigned 64-bit value. + */ virtual dods_uint64 value() const; + /** + * @brief Sets the current value. + * + * @param val New unsigned 64-bit value. + * @return True when the value is accepted. + */ virtual bool set_value(dods_uint64 val); + /** + * @brief Writes this value using C++ stream output. + * + * @param out Output stream. + * @param space Indentation prefix. + * @param print_decl_p True to include declaration text. + * @param is_root_grp True when printing in the root group context. + */ void print_val(ostream &out, string space = "", bool print_decl_p = true, bool is_root_grp = true) override; bool ops(BaseType *b, int op) override; bool d4_ops(BaseType *b, int op) override; + /** + * @brief Converts this DAP4 value into equivalent DAP2 value objects. + * + * @param parent_attr_table Destination attribute table for converted metadata. + * @param show_shared_dims True to include shared-dimension annotations. + * @return A heap-allocated list of DAP2 values corresponding to this object. + */ std::vector *transform_to_dap2(AttrTable *parent_attr_table, bool show_shared_dims = false) override; bool is_dap4_projected(std::vector &inventory) override; diff --git a/UnMarshaller.h b/UnMarshaller.h index 9540e355c..1915886ea 100644 --- a/UnMarshaller.h +++ b/UnMarshaller.h @@ -52,24 +52,69 @@ class Vector; */ class UnMarshaller : public DapObj { public: + /** @brief Deserialize one `Byte` value. + * @param val Destination for the decoded value. + */ virtual void get_byte(dods_byte &val) = 0; + /** @brief Deserialize one `Int16` value. + * @param val Destination for the decoded value. + */ virtual void get_int16(dods_int16 &val) = 0; + /** @brief Deserialize one `Int32` value. + * @param val Destination for the decoded value. + */ virtual void get_int32(dods_int32 &val) = 0; + /** @brief Deserialize one `Float32` value. + * @param val Destination for the decoded value. + */ virtual void get_float32(dods_float32 &val) = 0; + /** @brief Deserialize one `Float64` value. + * @param val Destination for the decoded value. + */ virtual void get_float64(dods_float64 &val) = 0; + /** @brief Deserialize one `UInt16` value. + * @param val Destination for the decoded value. + */ virtual void get_uint16(dods_uint16 &val) = 0; + /** @brief Deserialize one `UInt32` value. + * @param val Destination for the decoded value. + */ virtual void get_uint32(dods_uint32 &val) = 0; + /** @brief Deserialize one DAP string value. + * @param val Destination for the decoded value. + */ virtual void get_str(string &val) = 0; + /** @brief Deserialize one DAP URL value. + * @param val Destination for the decoded value. + */ virtual void get_url(string &val) = 0; + /** @brief Deserialize opaque bytes. + * @param val Destination buffer. + * @param len Number of bytes to decode. + */ virtual void get_opaque(char *val, unsigned int len) = 0; + /** @brief Deserialize one legacy DAP integer. + * @param val Destination for the decoded value. + */ virtual void get_int(int &val) = 0; + /** @brief Deserialize a vector where element width is inferred from `vec`. + * @param val Destination pointer for allocated or reused vector data. + * @param num Number of decoded elements. + * @param vec Vector metadata used for typing. + */ virtual void get_vector(char **val, unsigned int &num, Vector &vec) = 0; + /** @brief Deserialize a vector with explicit element width. + * @param val Destination pointer for allocated or reused vector data. + * @param num Number of decoded elements. + * @param width Bytes per element. + * @param vec Vector metadata used for typing. + */ virtual void get_vector(char **val, unsigned int &num, int width, Vector &vec) = 0; virtual void dump(std::ostream &strm) const = 0; diff --git a/Url.h b/Url.h index b21c2b363..d7bc705ce 100644 --- a/Url.h +++ b/Url.h @@ -46,6 +46,7 @@ namespace libdap { class BaseType; +/** @brief Legacy maximum URL length used by older protocol constraints. */ const unsigned int max_url_len = 255; /** @brief Holds an Internet address (URL). @@ -57,7 +58,22 @@ class Url : public Str { public: Url(const std::string &n); Url(const std::string &n, const std::string &d); + /** + * @brief Constructs a URL variable with an explicit type tag. + * + * Use this when callers need to preserve a specific runtime type marker. + * + * @param n Variable name. + * @param t Explicit libdap type tag. + */ Url(const std::string &n, Type t); + /** + * @brief Constructs a URL variable with declaration and explicit type. + * + * @param n Variable name. + * @param d Declaration string. + * @param t Explicit libdap type tag. + */ Url(const std::string &n, const std::string &d, Type t); ~Url() override {} diff --git a/Vector.h b/Vector.h index 32118a90b..16240661b 100644 --- a/Vector.h +++ b/Vector.h @@ -124,12 +124,32 @@ class Vector : public BaseType { void m_duplicate(const Vector &v); public: + /** + * @brief Constructs a vector with an element prototype. + * @param n Variable name. + * @param v Element prototype. + * @param t Concrete vector type tag. + * @param is_dap4 True when this variable is part of a DAP4 model. + */ Vector(const string &n, BaseType *v, const Type &t, bool is_dap4 = false); + /** + * @brief Constructs a vector with declaration metadata and prototype. + * @param n Variable name. + * @param d Declaration context. + * @param v Element prototype. + * @param t Concrete vector type tag. + * @param is_dap4 True when this variable is part of a DAP4 model. + */ Vector(const string &n, const string &d, BaseType *v, const Type &t, bool is_dap4 = false); Vector(const Vector &rhs); ~Vector() override; + /** + * @brief Assigns from another vector. + * @param rhs Source vector. + * @return This instance after assignment. + */ Vector &operator=(const Vector &rhs); // FIXME BaseType *ptr_duplicate() = 0 override; @@ -160,6 +180,10 @@ class Vector : public BaseType { */ vector &get_compound_buf() { return d_compound_buf; } + /** + * @brief Returns the element prototype used by this vector. + * @return Prototype object describing each element. + */ virtual BaseType *prototype() const { return d_proto; } /** @@ -228,30 +252,70 @@ class Vector : public BaseType { // DAP4 void compute_checksum(Crc32 &checksum) override; + /** @brief Reads any required DAP4-side data into this vector. */ void intern_data(/*Crc32 &checksum*/) override; + /** + * @brief Serializes this vector using DAP4 binary encoding. + * @param m Target stream marshaller. + * @param dmr DMR context for encoding decisions. + * @param filter True to apply active projection/filtering. + */ void serialize(D4StreamMarshaller &m, DMR &dmr, bool filter = false) override; void deserialize(D4StreamUnMarshaller &um, DMR &dmr) override; unsigned int val2buf(void *val, bool reuse = false) override; unsigned int buf2val(void **val) override; + /** + * @brief Writes vector values from a 64-bit indexed source buffer. + * @param val Pointer to source values. + * @param reuse True to reuse existing storage when possible. + * @return Number of elements copied. + */ int64_t val2buf_ll(void *val, bool reuse = false); + /** + * @brief Copies vector values into a caller-provided buffer. + * @param val Output pointer to receive copied values. + * @return Number of elements copied. + */ int64_t buf2val_ll(void **val); void set_vec(unsigned int i, BaseType *val); void set_vec_nocopy(unsigned int i, BaseType *val); + /** + * @brief Sets an element at a 64-bit index by copying from `val`. + * @param i Zero-based element index. + * @param val Source element value. + */ void set_vec_ll(uint64_t i, BaseType *val); + /** + * @brief Sets an element at a 64-bit index without copying `val`. + * @param i Zero-based element index. + * @param val Element object to store directly. + */ void set_vec_nocopy_ll(uint64_t i, BaseType *val); void vec_resize(int l); + /** + * @brief Resizes vector storage using 64-bit element counts. + * @param l New number of elements. + */ void vec_resize_ll(int64_t l); void clear_local_data() override; virtual unsigned int get_value_capacity() const; + /** + * @brief Returns reserved capacity in elements using 64-bit precision. + * @return Current capacity available for values. + */ virtual uint64_t get_value_capacity_ll() const; + /** + * @brief Sets value-storage capacity. + * @param l New capacity in elements. + */ void set_value_capacity(uint64_t l); virtual void reserve_value_capacity(unsigned int numElements); virtual void reserve_value_capacity(); @@ -352,9 +416,19 @@ class Vector : public BaseType { BaseType *var(const string &name, btp_stack &s) override; virtual BaseType *var(unsigned int i); + /** + * @brief Returns element `i` from vectors indexed with 64-bit sizes. + * @param i Zero-based element index. + * @return Element at index `i`. + */ virtual BaseType *var_ll(uint64_t i); void add_var(BaseType *v, Part p = nil) override; + /** + * @brief Adds a child variable without copying. + * @param v Variable to append. + * @param p Constructor part selector. + */ void add_var_nocopy(BaseType *v, Part p = nil) override; bool check_semantics(string &msg, bool all = false) override; diff --git a/XDRFileMarshaller.h b/XDRFileMarshaller.h index 755c6a72c..3320cbcc8 100644 --- a/XDRFileMarshaller.h +++ b/XDRFileMarshaller.h @@ -49,27 +49,44 @@ class XDRFileMarshaller : public Marshaller { XDRFileMarshaller &operator=(const XDRFileMarshaller &); public: + /** + * @brief Builds an XDR marshaller that writes to a `FILE*`. + * @param out Destination file stream. + */ XDRFileMarshaller(FILE *out); ~XDRFileMarshaller() override; + /** @copydoc Marshaller::put_byte */ void put_byte(dods_byte val) override; + /** @copydoc Marshaller::put_int16 */ void put_int16(dods_int16 val) override; + /** @copydoc Marshaller::put_int32 */ void put_int32(dods_int32 val) override; + /** @copydoc Marshaller::put_float32 */ void put_float32(dods_float32 val) override; + /** @copydoc Marshaller::put_float64 */ void put_float64(dods_float64 val) override; + /** @copydoc Marshaller::put_uint16 */ void put_uint16(dods_uint16 val) override; + /** @copydoc Marshaller::put_uint32 */ void put_uint32(dods_uint32 val) override; + /** @copydoc Marshaller::put_str */ void put_str(const string &val) override; + /** @copydoc Marshaller::put_url */ void put_url(const string &val) override; + /** @copydoc Marshaller::put_opaque */ void put_opaque(char *val, unsigned int len) override; + /** @copydoc Marshaller::put_int */ void put_int(int val) override; + /** @copydoc Marshaller::put_vector(char *, int, Vector &) */ void put_vector(char *val, int num, Vector &vec) override; + /** @copydoc Marshaller::put_vector(char *, int, int, Vector &) */ void put_vector(char *val, int num, int width, Vector &vec) override; void dump(ostream &strm) const override; diff --git a/XDRFileUnMarshaller.h b/XDRFileUnMarshaller.h index edec398b0..f65500473 100644 --- a/XDRFileUnMarshaller.h +++ b/XDRFileUnMarshaller.h @@ -50,27 +50,44 @@ class XDRFileUnMarshaller : public UnMarshaller { XDRFileUnMarshaller &operator=(const XDRFileUnMarshaller &); public: + /** + * @brief Builds an XDR unmarshaller that reads from a `FILE*`. + * @param out Source file stream. + */ XDRFileUnMarshaller(FILE *out); ~XDRFileUnMarshaller() override; + /** @copydoc UnMarshaller::get_byte */ void get_byte(dods_byte &val) override; + /** @copydoc UnMarshaller::get_int16 */ void get_int16(dods_int16 &val) override; + /** @copydoc UnMarshaller::get_int32 */ void get_int32(dods_int32 &val) override; + /** @copydoc UnMarshaller::get_float32 */ void get_float32(dods_float32 &val) override; + /** @copydoc UnMarshaller::get_float64 */ void get_float64(dods_float64 &val) override; + /** @copydoc UnMarshaller::get_uint16 */ void get_uint16(dods_uint16 &val) override; + /** @copydoc UnMarshaller::get_uint32 */ void get_uint32(dods_uint32 &val) override; + /** @copydoc UnMarshaller::get_str */ void get_str(string &val) override; + /** @copydoc UnMarshaller::get_url */ void get_url(string &val) override; + /** @copydoc UnMarshaller::get_opaque */ void get_opaque(char *val, unsigned int len) override; + /** @copydoc UnMarshaller::get_int */ void get_int(int &val) override; + /** @copydoc UnMarshaller::get_vector(char **, unsigned int &, Vector &) */ void get_vector(char **val, unsigned int &num, Vector &vec) override; + /** @copydoc UnMarshaller::get_vector(char **, unsigned int &, int, Vector &) */ void get_vector(char **val, unsigned int &num, int width, Vector &vec) override; void dump(ostream &strm) const override; diff --git a/XDRStreamMarshaller.h b/XDRStreamMarshaller.h index 8e182dfa3..5c2a2b1a0 100644 --- a/XDRStreamMarshaller.h +++ b/XDRStreamMarshaller.h @@ -72,24 +72,37 @@ class XDRStreamMarshaller : public Marshaller { XDRStreamMarshaller(ostream &out); //, bool checksum = false, bool write_data = true) ; ~XDRStreamMarshaller() override; + /** @copydoc Marshaller::put_byte */ void put_byte(dods_byte val) override; + /** @copydoc Marshaller::put_int16 */ void put_int16(dods_int16 val) override; + /** @copydoc Marshaller::put_int32 */ void put_int32(dods_int32 val) override; + /** @copydoc Marshaller::put_float32 */ void put_float32(dods_float32 val) override; + /** @copydoc Marshaller::put_float64 */ void put_float64(dods_float64 val) override; + /** @copydoc Marshaller::put_uint16 */ void put_uint16(dods_uint16 val) override; + /** @copydoc Marshaller::put_uint32 */ void put_uint32(dods_uint32 val) override; + /** @copydoc Marshaller::put_str */ void put_str(const string &val) override; + /** @copydoc Marshaller::put_url */ void put_url(const string &val) override; + /** @copydoc Marshaller::put_opaque */ void put_opaque(char *val, unsigned int len) override; + /** @copydoc Marshaller::put_int */ void put_int(int val) override; + /** @copydoc Marshaller::put_vector(char *, int, Vector &) */ void put_vector(char *val, int num, Vector &vec) override; + /** @copydoc Marshaller::put_vector(char *, int, int, Vector &) */ void put_vector(char *val, int num, int width, Vector &vec) override; void put_vector_start(int num) override; diff --git a/XDRStreamUnMarshaller.h b/XDRStreamUnMarshaller.h index 1ca99b308..96edabc99 100644 --- a/XDRStreamUnMarshaller.h +++ b/XDRStreamUnMarshaller.h @@ -61,29 +61,53 @@ class XDRStreamUnMarshaller : public UnMarshaller { XDRStreamUnMarshaller &operator=(const XDRStreamUnMarshaller &); public: + /** + * @brief Builds an XDR unmarshaller that reads from a C++ stream. + * @param in Source stream. + */ XDRStreamUnMarshaller(istream &in); ~XDRStreamUnMarshaller() override; + /** @copydoc UnMarshaller::get_byte */ void get_byte(dods_byte &val) override; + /** @copydoc UnMarshaller::get_int16 */ void get_int16(dods_int16 &val) override; + /** @copydoc UnMarshaller::get_int32 */ void get_int32(dods_int32 &val) override; + /** @copydoc UnMarshaller::get_float32 */ void get_float32(dods_float32 &val) override; + /** @copydoc UnMarshaller::get_float64 */ void get_float64(dods_float64 &val) override; + /** @copydoc UnMarshaller::get_uint16 */ void get_uint16(dods_uint16 &val) override; + /** @copydoc UnMarshaller::get_uint32 */ void get_uint32(dods_uint32 &val) override; + /** @copydoc UnMarshaller::get_str */ void get_str(string &val) override; + /** @copydoc UnMarshaller::get_url */ void get_url(string &val) override; + /** @copydoc UnMarshaller::get_opaque */ void get_opaque(char *val, unsigned int len) override; + /** @copydoc UnMarshaller::get_int */ void get_int(int &val) override; + /** @copydoc UnMarshaller::get_vector(char **, unsigned int &, Vector &) */ void get_vector(char **val, unsigned int &num, Vector &vec) override; + /** @copydoc UnMarshaller::get_vector(char **, unsigned int &, int, Vector &) */ void get_vector(char **val, unsigned int &num, int width, Vector &vec) override; + /** + * @brief Deserialize vector elements using explicit DAP type information. + * @param val Destination pointer for vector data. + * @param num Number of elements decoded. + * @param width Bytes per element. + * @param type DAP type of each element. + */ virtual void get_vector(char **val, unsigned int &num, int width, Type type); void dump(ostream &strm) const override; diff --git a/XDRUtils.h b/XDRUtils.h index f10a925a5..04a7639e0 100644 --- a/XDRUtils.h +++ b/XDRUtils.h @@ -54,6 +54,7 @@ extern "C" bool_t xdr_str(XDR *xdrs, string &buf); namespace libdap { +/** @brief Utility helpers for mapping DAP types to XDR coder functions. */ class XDRUtils { private: XDRUtils() {} @@ -62,6 +63,11 @@ class XDRUtils { // xdr_coder is used as an argument to xdr procedures that encode groups // of things (e.g., xdr_array()). Each leaf class's constructor must set // this. + /** + * @brief Returns the XDR coder function for a DAP type. + * @param t DAP type to encode or decode. + * @return XDR procedure pointer for `t`. + */ static xdrproc_t xdr_coder(const Type &t); }; diff --git a/XMLWriter.h b/XMLWriter.h index c14ae277d..af478f02b 100644 --- a/XMLWriter.h +++ b/XMLWriter.h @@ -36,6 +36,7 @@ namespace libdap { +/** @brief Small RAII wrapper around libxml2's `xmlTextWriter` APIs. */ class XMLWriter { private: // Various xml writer stuff @@ -49,11 +50,19 @@ class XMLWriter { void m_cleanup(); public: + /** + * @brief Builds a writer backed by an in-memory XML buffer. + * @param pad Indentation string used for pretty output. + * @param ENCODING XML output encoding label. + */ XMLWriter(const std::string &pad = " ", const std::string &ENCODING = "ISO-8859-1"); virtual ~XMLWriter(); + /** @brief Returns the underlying libxml2 writer pointer. */ xmlTextWriterPtr get_writer() const { return d_writer; } + /** @brief Returns the serialized document bytes as a C string. */ const char *get_doc(); + /** @brief Returns the serialized document size in bytes. */ unsigned int get_doc_size(); }; diff --git a/ce_parser.h b/ce_parser.h index 3c5e5690b..f062d53c1 100644 --- a/ce_parser.h +++ b/ce_parser.h @@ -4,18 +4,40 @@ namespace libdap { +/** @brief Carries inputs and outputs for the CE parser. */ struct ce_parser_arg { + /// Constraint evaluator used during parse. ConstraintEvaluator *eval; + /// DDS used to resolve variable names. DDS *dds; ce_parser_arg() : eval(0), dds(0) {} + + /** @brief Build parser arguments from evaluator and DDS pointers. + * @param e Constraint evaluator. + * @param d DDS used by the parser. + */ ce_parser_arg(ConstraintEvaluator *e, DDS *d) : eval(e), dds(d) {} virtual ~ce_parser_arg() {} + /** @brief Get the configured constraint evaluator. + * @return Evaluator pointer, or null. + */ ConstraintEvaluator *get_eval() { return eval; } + + /** @brief Set the constraint evaluator. + * @param obj Evaluator pointer. + */ void set_eval(ConstraintEvaluator *obj) { eval = obj; } + /** @brief Get the configured DDS. + * @return DDS pointer, or null. + */ DDS *get_dds() { return dds; } + + /** @brief Set the DDS used by the parser. + * @param obj DDS pointer. + */ void set_dds(DDS *obj) { dds = obj; } }; diff --git a/chunked_istream.h b/chunked_istream.h index 1489f9638..e592449d7 100644 --- a/chunked_istream.h +++ b/chunked_istream.h @@ -39,6 +39,7 @@ namespace libdap { +/** @brief Stream buffer that decodes DAP4 chunked input frames. */ class chunked_inbuf : public std::streambuf { private: std::istream &d_is; @@ -108,13 +109,17 @@ class chunked_inbuf : public std::streambuf { int_type read_next_chunk(); + /** @brief Returns unread bytes currently available in the buffer. */ int bytes_in_buffer() const { return (egptr() - gptr()); } // d_twiddle_bytes is false initially and is set to the correct value // once the first chunk is read. + /** @brief Returns whether byte-swapping is required for multi-byte values. */ bool twiddle_bytes() const { return d_twiddle_bytes; } + /** @brief Returns true if an error chunk has been read. */ bool error() const { return d_error; } + /** @brief Returns the last error message extracted from an error chunk. */ std::string error_message() const { return d_error_message; } protected: @@ -123,13 +128,20 @@ class chunked_inbuf : public std::streambuf { virtual std::streamsize xsgetn(char *s, std::streamsize num); }; +/** @brief `std::istream` wrapper for DAP4 chunked input streams. */ class chunked_istream : public std::istream { protected: - chunked_inbuf d_cbuf; + chunked_inbuf d_cbuf; ///< Backing chunked stream buffer. public: + /** + * @brief Builds a chunked input stream wrapper. + * @param is Source stream. + * @param size Initial internal chunk buffer size. + */ chunked_istream(std::istream &is, int size) : std::istream(&d_cbuf), d_cbuf(is, size) {} + /** @brief Reads the next chunk header/body into the internal buffer. */ int read_next_chunk() { return d_cbuf.read_next_chunk(); } /** @@ -149,7 +161,9 @@ class chunked_istream : public std::istream { * although that can be inferred. */ bool twiddle_bytes() const { return d_cbuf.twiddle_bytes(); } + /** @brief Returns true if the underlying chunked buffer is in error state. */ bool error() const { return d_cbuf.error(); } + /** @brief Returns the last error message reported by the underlying chunked buffer. */ std::string error_message() const { return d_cbuf.error_message(); } }; diff --git a/chunked_ostream.h b/chunked_ostream.h index 13ccf1722..d7ffec4ea 100644 --- a/chunked_ostream.h +++ b/chunked_ostream.h @@ -53,12 +53,17 @@ class chunked_outbuf : public std::streambuf { friend class chunked_ostream; protected: - std::ostream &d_os; // Write stuff here - int d_buf_size = 0; // Size of the data buffer - char *d_buffer = nullptr; // Data buffer - bool d_big_endian = false; + std::ostream &d_os; ///< Destination stream. + int d_buf_size = 0; ///< Size of the write buffer. + char *d_buffer = nullptr; ///< Write buffer storage. + bool d_big_endian = false; ///< True when local host byte order is big-endian. public: + /** + * @brief Builds a chunked output buffer. + * @param os Destination stream. + * @param buf_size Chunk payload buffer size. + */ chunked_outbuf(std::ostream &os, int buf_size) : d_os(os), d_buf_size(buf_size) { if (d_buf_size & CHUNK_TYPE_MASK) throw std::out_of_range( @@ -120,12 +125,13 @@ class chunked_outbuf : public std::streambuf { */ class chunked_ostream : public std::ostream { protected: - chunked_outbuf d_cbuf; + chunked_outbuf d_cbuf; ///< Backing chunked stream buffer. public: /** * Get a chunked_ostream with a buffer. * @note The buffer size must not be more than 2^24 bytes (0x00ffffff) + * @param os Destination stream. * @param buf_size The size of the buffer in bytes. */ chunked_ostream(std::ostream &os, int buf_size) : std::ostream(&d_cbuf), d_cbuf(os, buf_size) {} diff --git a/configure.ac b/configure.ac index 4ab001e68..173b2e919 100644 --- a/configure.ac +++ b/configure.ac @@ -13,6 +13,10 @@ dnl base value for the build number. jhrg 3/22/21 AC_INIT([libdap],[3.21.1],[opendap-tech@opendap.org]) +# Get today's date in ISO 8601 format (YYYY-MM-DD) +CONFIG_DATE=$(date +%Y-%m-%d) +AC_SUBST([CONFIG_DATE]) + dnl As an alternative, we can... dnl Read the version number from the file VERSION. The file must contain dnl only the version number in the form x.y.z or x.y.z-b. Newlines are @@ -582,7 +586,6 @@ AC_CONFIG_FILES([Makefile libdap.pc libdapclient.pc libdapserver.pc - main_page.doxygen doxy.conf abi_checker.xml diff --git a/crc.h b/crc.h index a58b165f0..e570b8ffa 100644 --- a/crc.h +++ b/crc.h @@ -40,8 +40,10 @@ static const uint32_t kCrc32Table[256] = { 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d, }; // kCrc32Table +/** @brief Incremental CRC-32 checksum calculator. */ class Crc32 { public: + /// 32-bit checksum value type. typedef uint32_t checksum; /** diff --git a/d4_ce/D4CEScanner.h b/d4_ce/D4CEScanner.h index 3fc09b80e..233174d98 100644 --- a/d4_ce/D4CEScanner.h +++ b/d4_ce/D4CEScanner.h @@ -48,10 +48,19 @@ namespace libdap { +/** @brief Flex scanner adapter for the DAP4 constraint-expression parser. */ class D4CEScanner : public d4_ceFlexLexer { public: + /** @brief Construct a scanner that reads from a C++ stream. + * @param in Input stream for tokenization. + */ D4CEScanner(std::istream &in) : d4_ceFlexLexer(&in), yylval(0), loc(0) {}; + /** @brief Lex the next token for the Bison parser. + * @param lval Semantic value output. + * @param l Source location output. + * @return Token id or 0 at end of input. + */ int yylex(libdap::D4CEParser::semantic_type *lval, libdap::location *l) { loc = l; yylval = lval; diff --git a/d4_ce/D4ConstraintEvaluator.h b/d4_ce/D4ConstraintEvaluator.h index c6be87a30..6bab5e63e 100644 --- a/d4_ce/D4ConstraintEvaluator.h +++ b/d4_ce/D4ConstraintEvaluator.h @@ -126,24 +126,54 @@ class D4ConstraintEvaluator { public: D4ConstraintEvaluator() = default; + /** + * @brief Builds a constraint evaluator bound to a DMR. + * @param dmr Dataset metadata root used for name lookup and projection edits. + */ explicit D4ConstraintEvaluator(DMR *dmr) : d_dmr(dmr) {} virtual ~D4ConstraintEvaluator() = default; + /** + * @brief Parses and applies a DAP4 constraint expression. + * @param expr Constraint expression text. + * @return True when parsing and application succeed. + */ bool parse(const std::string &expr); + /** @brief Returns whether scanner tracing is enabled. */ bool trace_scanning() const { return d_trace_scanning; } + /** @brief Enables or disables scanner tracing. + * @param ts True to enable scanner tracing. + */ void set_trace_scanning(bool ts) { d_trace_scanning = ts; } + /** @brief Returns whether parser tracing is enabled. */ bool trace_parsing() const { return d_trace_parsing; } + /** @brief Enables or disables parser tracing. + * @param tp True to enable parser tracing. + */ void set_trace_parsing(bool tp) { d_trace_parsing = tp; } + /** @brief Returns the last parse/evaluation result flag. */ bool result() const { return d_result; } + /** @brief Sets the last parse/evaluation result flag. + * @param r Result value. + */ void set_result(bool r) { d_result = r; } + /** @brief Returns the bound DMR pointer. */ DMR *dmr() const { return d_dmr; } + /** @brief Binds this evaluator to a DMR. + * @param dmr Dataset metadata root. + */ void set_dmr(DMR *dmr) { d_dmr = dmr; } + /** + * @brief Throws a parse error with source location context. + * @param l Parser/scanner location of the error. + * @param m Error message. + */ [[noreturn]] static void error(const libdap::location &l, const std::string &m); }; diff --git a/d4_function/D4FunctionEvaluator.h b/d4_function/D4FunctionEvaluator.h index 4e99a7af3..09d05bb54 100644 --- a/d4_function/D4FunctionEvaluator.h +++ b/d4_function/D4FunctionEvaluator.h @@ -73,16 +73,34 @@ class D4FunctionEvaluator { public: D4FunctionEvaluator() = default; + /** + * @brief Builds a function evaluator. + * @param dmr Dataset metadata root. + * @param sf_list Registry of callable server functions. + */ D4FunctionEvaluator(DMR *dmr, ServerFunctionsList *sf_list) : d_dmr(dmr), d_sf_list(sf_list) {} virtual ~D4FunctionEvaluator() = default; + /** + * @brief Parses a DAP4 function-expression string. + * @param expr Function expression text. + * @return True when parsing succeeds. + */ bool parse(const std::string &expr); + /** @brief Returns whether scanner tracing is enabled. */ bool trace_scanning() const { return d_trace_scanning; } + /** @brief Enables or disables scanner tracing. + * @param ts True to enable scanner tracing. + */ void set_trace_scanning(bool ts) { d_trace_scanning = ts; } + /** @brief Returns whether parser tracing is enabled. */ bool trace_parsing() const { return d_trace_parsing; } + /** @brief Enables or disables parser tracing. + * @param tp True to enable parser tracing. + */ void set_trace_parsing(bool tp) { d_trace_parsing = tp; } /** Get the result of parsing the function(s) @@ -90,21 +108,53 @@ class D4FunctionEvaluator { * @return The result(s) packages in a D4RValueList */ D4RValueList *result() const { return d_result; } + /** + * @brief Sets the parsed result list. + * @param rv_list Result list ownership pointer. + */ void set_result(D4RValueList *rv_list) { d_result = rv_list; } + /** + * @brief Evaluates the parsed function expression against a DMR. + * @param dmr Destination or context DMR for function results. + * @param function_result Alias name used by some implementations for the destination DMR. + */ void eval(DMR *dmr); + /** @brief Returns the current argument-length hint used for list constants. */ unsigned long long get_arg_length_hint() const { return d_arg_length_hint; } + /** @brief Sets the argument-length hint used for list constants. + * @param alh Hint value. + */ void set_arg_length_hint(unsigned long long alh) { d_arg_length_hint = alh; } + /** @brief Returns the bound DMR pointer. */ DMR *dmr() const { return d_dmr; } + /** @brief Binds this evaluator to a DMR. + * @param dmr Dataset metadata root. + */ void set_dmr(DMR *dmr) { d_dmr = dmr; } + /** @brief Returns the server-function registry used for lookup. */ ServerFunctionsList *sf_list() const { return d_sf_list; } + /** @brief Sets the server-function registry used for lookup. + * @param sf_list Function registry. + */ void set_sf_list(ServerFunctionsList *sf_list) { d_sf_list = sf_list; } + /** + * @brief Initializes an argument vector with one seed value. + * @tparam t Argument element type. + * @param val First value inserted in the returned vector. + * @return Newly allocated argument vector. + */ template std::vector *init_arg_list(t val); + /** + * @brief Throws a parse/evaluation error with source location context. + * @param l Parser/scanner location of the error. + * @param m Error message. + */ [[noreturn]] static void error(const libdap::location &l, const std::string &m); }; diff --git a/d4_function/D4FunctionScanner.h b/d4_function/D4FunctionScanner.h index e71b5c9bc..382a4a61d 100644 --- a/d4_function/D4FunctionScanner.h +++ b/d4_function/D4FunctionScanner.h @@ -48,10 +48,19 @@ namespace libdap { +/** @brief Flex scanner adapter for the DAP4 server-function parser. */ class D4FunctionScanner : public d4_functionFlexLexer { public: + /** @brief Construct a scanner that reads from a C++ stream. + * @param in Input stream for tokenization. + */ D4FunctionScanner(std::istream &in) : d4_functionFlexLexer(&in), yylval(0), loc(0) {}; + /** @brief Lex the next token for the Bison parser. + * @param lval Semantic value output. + * @param l Source location output. + * @return Token id or 0 at end of input. + */ int yylex(libdap::D4FunctionParser::semantic_type *lval, libdap::location *l) { loc = l; yylval = lval; diff --git a/doxy.conf.in b/doxy.conf.in index 20585b8ca..76fcc3718 100644 --- a/doxy.conf.in +++ b/doxy.conf.in @@ -133,7 +133,7 @@ ALWAYS_DETAILED_SEC = YES # operators of the base classes will not be shown. # The default value is: NO. -INLINE_INHERITED_MEMB = YES +INLINE_INHERITED_MEMB = NO # If the FULL_PATH_NAMES tag is set to YES, doxygen will prepend the full path # before files name in the file list and in the header files. If set to NO the @@ -229,6 +229,8 @@ TAB_SIZE = # newlines. ALIASES = +ALIASES += today="@CONFIG_DATE@" +ALIASES += package_version="@PACKAGE_VERSION@" # This tag can be used to specify a number of word-keyword mappings (TCL only). # A mapping has the form "name=value". For example adding "class=itcl::class" @@ -416,8 +418,8 @@ LOOKUP_CACHE_SIZE = 0 # normally produced when WARNINGS is set to YES. # The default value is: NO. -# EXTRACT_ALL = NO -EXTRACT_ALL = YES +EXTRACT_ALL = NO +# EXTRACT_ALL = YES # If the EXTRACT_PRIVATE tag is set to YES, all private members of a class will # be included in the documentation. diff --git a/escaping.h b/escaping.h index 1198aa487..d29053e03 100644 --- a/escaping.h +++ b/escaping.h @@ -72,6 +72,12 @@ string id2xml(string in, const string ¬_allowed = "><&'\""); string xml2id(string in); string esc2underscore(string s); + +/** @brief Replace escaped octal bytes with their ASCII character values. + * @param s Source string that may contain escaped octal bytes. + * @param escape Regular-expression pattern used to find escape sequences. + * @return Converted string. + */ string char2ASCII(string s, const string escape = "%[0-7][0-9a-fA-F]"); string escattr(string s); string escattr_xml(string s); diff --git a/fdiostream.h b/fdiostream.h index 94cd0ab40..761b1907d 100644 --- a/fdiostream.h +++ b/fdiostream.h @@ -49,16 +49,17 @@ namespace libdap { */ class fdoutbuf : public std::streambuf { protected: - int fd; // file descriptor - bool close; - static const int bufferSize = 4096; // Size of the data buffer - char buffer[bufferSize]; // data buffer + int fd; ///< File descriptor. + bool close; ///< True to close `fd` when the buffer is destroyed. + static const int bufferSize = 4096; ///< Size of the data buffer. + char buffer[bufferSize]; ///< Write buffer. public: fdoutbuf(int _fd, bool _close); virtual ~fdoutbuf(); protected: + /** @brief Flushes buffered output bytes to the file descriptor. */ int flushBuffer(); virtual int overflow(int c); @@ -76,7 +77,7 @@ class fdoutbuf : public std::streambuf { */ class fdostream : public std::ostream { protected: - fdoutbuf buf; + fdoutbuf buf; ///< Backing stream buffer. public: /** Make a new fdostream and initialize it to use a specific file descriptor. @@ -98,11 +99,11 @@ class fdostream : public std::ostream { */ class fdinbuf : public std::streambuf { protected: - int fd; // file descriptor - bool close; - static const int bufferSize = 4096; // Size of the data buffer - static const int putBack = 128; - char buffer[bufferSize]; // data buffer + int fd; ///< File descriptor. + bool close; ///< True to close `fd` when the buffer is destroyed. + static const int bufferSize = 4096; ///< Size of the data buffer. + static const int putBack = 128; ///< Put-back area size. + char buffer[bufferSize]; ///< Read buffer. public: fdinbuf(int _fd, bool close); @@ -123,9 +124,14 @@ class fdinbuf : public std::streambuf { */ class fdistream : public std::istream { protected: - fdinbuf buf; + fdinbuf buf; ///< Backing stream buffer. public: + /** + * @brief Builds an input stream from a file descriptor. + * @param fd Source file descriptor. + * @param close True to close `fd` when this stream is destroyed. + */ fdistream(int fd, bool close = false) : std::istream(&buf), buf(fd, close) {} }; @@ -139,11 +145,11 @@ class fdistream : public std::istream { */ class fpinbuf : public std::streambuf { protected: - FILE *fp; // FILE * - bool close; - static const int bufferSize = 4096; // Size of the data buffer - static const int putBack = 128; - char buffer[bufferSize]; // data buffer + FILE *fp; ///< Source FILE pointer. + bool close; ///< True to close `fp` when the buffer is destroyed. + static const int bufferSize = 4096; ///< Size of the data buffer. + static const int putBack = 128; ///< Put-back area size. + char buffer[bufferSize]; ///< Read buffer. public: fpinbuf(FILE *_fp, bool _close); @@ -165,9 +171,14 @@ class fpinbuf : public std::streambuf { */ class fpistream : public std::istream { protected: - fpinbuf buf; + fpinbuf buf; ///< Backing stream buffer. public: + /** + * @brief Builds an input stream from a `FILE*`. + * @param fp Source file pointer. + * @param close True to close `fp` when this stream is destroyed. + */ fpistream(FILE *fp, bool close = false) : std::istream(&buf), buf(fp, close) {} }; diff --git a/geo/gse_parser.h b/geo/gse_parser.h index a6f88a9e4..4a38c873e 100644 --- a/geo/gse_parser.h +++ b/geo/gse_parser.h @@ -44,19 +44,49 @@ class GSEClause; /** Argument to the GSE parser. Assumes all errors will be signaled by throws; Error objects are not returned. */ struct gse_arg { - GSEClause *_gsec; // The gse parsed. + /// Parsed clause result. + GSEClause *_gsec; // The gse parsed. + /// Grid being constrained by the parsed expression. libdap::Grid *_grid; // The Grid being constrained. - int _status; // The parser's status. + /// Parser success/failure status. + int _status; // The parser's status. gse_arg() : _gsec(0), _grid(0), _status(1) {} + + /** @brief Build parser args with a target grid. + * @param g Grid being constrained. + */ gse_arg(libdap::Grid *g) : _gsec(0), _grid(g), _status(1) {} virtual ~gse_arg() {} + /** @brief Store the parsed clause. + * @param gsec Parsed GSE clause object. + */ void set_gsec(GSEClause *gsec) { _gsec = gsec; } + + /** @brief Get the parsed clause. + * @return Parsed clause pointer. + */ GSEClause *get_gsec() { return _gsec; } + + /** @brief Set the grid being constrained. + * @param g Grid pointer. + */ void set_grid(libdap::Grid *g) { _grid = g; } + + /** @brief Get the grid being constrained. + * @return Grid pointer. + */ libdap::Grid *get_grid() { return _grid; } + + /** @brief Set parser status. + * @param stat Non-zero for success, zero for failure. + */ void set_status(int stat) { _status = stat; } + + /** @brief Get parser status. + * @return Non-zero for success, zero for failure. + */ int get_status() { return _status; } }; diff --git a/http_dap/HTTPCacheTable.h b/http_dap/HTTPCacheTable.h index 649667570..9648944c0 100644 --- a/http_dap/HTTPCacheTable.h +++ b/http_dap/HTTPCacheTable.h @@ -113,30 +113,43 @@ class HTTPCacheTable { friend class WriteOneCacheEntry; public: + /** @brief Returns cache filename for this entry. */ std::string get_cachename() const { return cachename; } + /** @brief Returns response ETag value. */ std::string get_etag() const { return etag; } + /** @brief Returns `Last-Modified` timestamp. */ time_t get_lm() const { return lm; } + /** @brief Returns `Expires` timestamp. */ time_t get_expires() const { return expires; } + /** @brief Returns parsed `Cache-Control: max-age` value. */ time_t get_max_age() const { return max_age; } + /** @brief Sets cached response body size in bytes. @param sz Body size in bytes. */ void set_size(unsigned long sz) { size = sz; } + /** @brief Returns computed freshness lifetime. */ time_t get_freshness_lifetime() const { return freshness_lifetime; } + /** @brief Returns response-time timestamp used for age calculations. */ time_t get_response_time() const { return response_time; } + /** @brief Returns corrected initial age value. */ time_t get_corrected_initial_age() const { return corrected_initial_age; } + /** @brief Returns `must-revalidate` directive state. */ bool get_must_revalidate() const { return must_revalidate; } + /** @brief Sets `no-cache` directive state. @param state New state. */ void set_no_cache(bool state) { no_cache = state; } + /** @brief Returns `no-cache` directive state. */ bool is_no_cache() const { return no_cache; } + /** @brief Acquires read lock accounting for concurrent readers. */ void lock_read_response() { // if the response_lock cannot be acquired, it might be a reader or a writer. If it is a writer, then // we need to wait for the writer to finish. If it is a reader, then we don't care and increment the @@ -149,6 +162,7 @@ class HTTPCacheTable { readers++; // Record number of readers } + /** @brief Releases a previously acquired read lock. */ void unlock_read_response() { std::lock_guard lock(d_readers_lock); readers--; @@ -157,8 +171,10 @@ class HTTPCacheTable { } } + /** @brief Acquires exclusive write lock for this entry. */ void lock_write_response() { std::lock(d_response_read_lock, d_response_write_lock); } + /** @brief Releases exclusive write lock for this entry. */ void unlock_write_response() { d_response_read_lock.unlock(); d_response_write_lock.unlock(); @@ -166,6 +182,7 @@ class HTTPCacheTable { CacheEntry() = default; + /** @brief Builds an entry with URL and computed hash. @param u Cached resource URL. */ explicit CacheEntry(std::string u) : url(std::move(u)) { hash = get_hash(url); } }; // CacheEntry @@ -175,7 +192,9 @@ class HTTPCacheTable { // vector (that's how hash collisions are resolved). Search the inner // vector for a specific match. + /** @brief Bucket of cache-entry pointers for one hash slot. */ using CacheEntries = std::vector; + /** @brief Full hash table of cache-entry buckets. */ using CacheTable = std::vector; friend class HTTPCacheTest; @@ -200,6 +219,11 @@ class HTTPCacheTable { void remove_cache_entry(const HTTPCacheTable::CacheEntry *entry); public: + /** + * @brief Builds a cache table rooted at `cache_root`. + * @param cache_root Cache root directory. + * @param block_size Filesystem block size used for accounting. + */ HTTPCacheTable(const std::string &cache_root, int block_size); HTTPCacheTable(const HTTPCacheTable &) = delete; HTTPCacheTable &operator=(const HTTPCacheTable &) = delete; @@ -243,9 +267,19 @@ class HTTPCacheTable { const std::vector &headers); // These should move back to HTTPCache + /** + * @brief Associates an open response stream with a read-locked cache entry. + * @param entry Cache entry that owns the response body. + * @param body Open response stream. + */ void bind_entry_to_data(CacheEntry *entry, FILE *body); + /** + * @brief Removes a response-stream to cache-entry association. + * @param body Open response stream previously bound to an entry. + */ void uncouple_entry_from_data(FILE *body); + /** @brief Returns true if any responses are currently read-locked. */ bool is_locked_read_responses() const; }; diff --git a/http_dap/HTTPConnect.h b/http_dap/HTTPConnect.h index 5b791f4d1..2854f3b72 100644 --- a/http_dap/HTTPConnect.h +++ b/http_dap/HTTPConnect.h @@ -128,8 +128,13 @@ class HTTPConnect { void set_xdap_protocol(int major, int minor); + /** @brief Returns whether responses should be materialized as C++ streams. */ bool use_cpp_streams() const { return d_use_cpp_streams; } + /** + * @brief Enables/disables C++ stream based response objects. + * @param use_cpp_streams True to use C++ streams, false to use `FILE*` streams. + */ void set_use_cpp_streams(bool use_cpp_streams) { std::lock_guard lock(d_connect_mutex); d_use_cpp_streams = use_cpp_streams; diff --git a/http_dap/ResponseTooBigErr.h b/http_dap/ResponseTooBigErr.h index d9bf0c243..c422e1ad1 100644 --- a/http_dap/ResponseTooBigErr.h +++ b/http_dap/ResponseTooBigErr.h @@ -43,6 +43,10 @@ namespace libdap { class ResponseTooBigErr : public Error { public: + /** + * @brief Builds a cache-size error with message text. + * @param msg Error message. + */ ResponseTooBigErr(const string &msg); ResponseTooBigErr(); }; diff --git a/http_dap/save/mp_lock_guard.h b/http_dap/save/mp_lock_guard.h index 746dfb361..f3c76358f 100644 --- a/http_dap/save/mp_lock_guard.h +++ b/http_dap/save/mp_lock_guard.h @@ -47,8 +47,16 @@ class mp_lock_guard_logger { mp_lock_guard_logger() = default; virtual ~mp_lock_guard_logger() = default; + /** + * @brief Writes a non-fatal diagnostic message. + * @param msg Message text. + */ virtual void log(const std::string &msg) const = 0; + /** + * @brief Reports a fatal lock-guard error. + * @param msg Message text. + */ virtual void error(const std::string &msg) const = 0; }; @@ -62,8 +70,10 @@ class mp_lock_guard_logger_default : public mp_lock_guard_logger { mp_lock_guard_logger_default() = default; ~mp_lock_guard_logger_default() override = default; + /** @copydoc mp_lock_guard_logger::log */ void log(const std::string &msg) const override { std::cerr << "~mp_lock_guard: " << msg << std::endl; } + /** @copydoc mp_lock_guard_logger::error */ void error(const std::string &msg) const override { throw std::runtime_error("mp_lock_guard: " + msg); } }; @@ -78,6 +88,7 @@ class mp_lock_guard_logger_default : public mp_lock_guard_logger { */ class mp_lock_guard { public: + /** @brief Lock operation mode for `mp_lock_guard`. */ enum class operation { read, write }; private: @@ -126,6 +137,7 @@ class mp_lock_guard { * @param fd The file descriptor of the cache control file. * @param op The operation to perform. If op is 'write' then the lock is * a write lock; if op is 'read' then the lock is a read lock. + * @param logger Logger implementation used for diagnostics and errors. */ mp_lock_guard(int fd, operation op, const mp_lock_guard_logger &logger = mp_lock_guard_logger_default()) : d_fd(fd), d_op(op), d_logger(logger) { diff --git a/main_page.doxygen b/main_page.doxygen new file mode 100644 index 000000000..f52e15067 --- /dev/null +++ b/main_page.doxygen @@ -0,0 +1,81 @@ +// -*- C++ -*- + +// $Id: main_page.doxygen 21281 2009-08-18 06:38:17Z tomss $ + +// Documentation for the main page of the doxygen-generated reference manual + +/** \mainpage + +Documentation build date: \today + +\section intro Introduction + +This reference documentation corresponds to version \package_version of libdap, a C++ +implementation of DAP2, with some extensions. The libdap library +includes classes and functions which implement DAP 2.0 as well as utilities +which simplify building clients and servers for DAP 2.0 and DAP 4.0. + +\section conventions Doxygen Conventions + +This section lists some conventions used by the Doxygen comments +which are used to generate this Reference Guide. Follow these conventions +when adding to or modifying the reference documentation. + +\subsection general General + +
    +
  • When using the name of a parameter, use italics (the \c e +command or \c em tag).
  • +
  • Use the \c c command or \c code tag when talking about literal text.
  • +
  • When talking about functions or methods, using func() +or func(arg0, ..., agrN) will get Doxygen to insert a link to +its documentation.
  • +
  • Typos: If you're using emacs, the command \c ispell-comments-and-strings +may help in removing typos in the comments (and strings ...)
  • +
+ +\subsection classes Classes + +Classes should be documented in the header (\c .h) file where they are +defined. + +Commands that should be used for the documentation of classes: + +
+
author
Use this to attribute authorship. Include this for +all the classes except internal ones which are not visible to users of the +library.
+
+ +\subsection methods Methods and Functions + +Methods should be documented in the implementation (\c .cc) files where +they are defined. You can put the \c brief documentation in the header file, +but that may be more confusing than keeping all the method documentation in +one place. + +Functions should be documented in their implementation files. + +Commands that should be used for the documentation of public methods and +non-static functions: + +
+
param
Include for all parameters. Doxygen complains if an +overloaded method changes a parameter name, so scan the warnings and try to +keep the names in sync..
+ +
return
Include for all methods that return something unless the +method is so simple its full description starts off with "Returns..."
+ +
brief
Include for all methods. In doxy.conf I have turned off +the option that generates the \c brief entry from the first sentence of the +detailed doc and the option that includes the \c brief documentation in the +detailed documentation. So, the \c brief doc will appear only with the +summary information and not with the detailed documentation for the +method.
+ +
exception
Document the exceptions using the \c exception +command.
+ +
+*/ diff --git a/parser-util.h b/parser-util.h index 3e3897703..bb0a52e28 100644 --- a/parser-util.h +++ b/parser-util.h @@ -25,6 +25,8 @@ #ifndef PARSER_UTIL_H_ #define PARSER_UTIL_H_ +#include + namespace libdap { /** Given a string (const char *src), save it to the @@ -39,16 +41,14 @@ namespace libdap { @return void @brief Save a string to a temporary variable during the parse. - */ -#if 0 -void save_str(char *dst, const char *src, const int line_num); -#endif +*/ void save_str(std::string &dst, const char *src, const int); bool is_keyword(std::string id, const std::string &keyword); /** - * @defgroup check_type + * @name check types + * Check types * @{ * @brief Can the given string be converted into a byte, ...? */ @@ -73,7 +73,7 @@ int check_url(const char *val); /** @} */ /** - * @defgroup check type and set value + * @name check type and set value * @{ * @brief Like 'test and set,' check a type and set a value in one go. */ @@ -84,7 +84,8 @@ int check_float64(const char *val, double &v); /** @} */ /** - * @defgroup get_type + * @name get type + * Get the type * @{ * @brief Convert the string to a value; throw if the conversion fails. */ diff --git a/parser.h b/parser.h index dcce37ee5..b636627ae 100644 --- a/parser.h +++ b/parser.h @@ -65,11 +65,18 @@ namespace libdap { */ struct parser_arg { + /// Parsed object pointer returned on success. void *_object; // nominally a pointer to an object + /// Error object returned on parse failure. Error *_error; // a pointer to an Error object - int _status; // parser status + /// Non-zero on success; zero on error. + int _status; // parser status parser_arg() : _object(0), _error(0), _status(1) {} + + /** @brief Build parser args initialized with an output object. + * @param obj Parsed-object destination pointer. + */ parser_arg(void *obj) : _object(obj), _error(0), _status(1) {} virtual ~parser_arg() { if (_error) { @@ -78,11 +85,34 @@ struct parser_arg { } } + /** @brief Get the parsed object pointer. + * @return Object pointer. + */ void *object() { return _object; } + + /** @brief Set the parsed object pointer. + * @param obj Parsed-object pointer. + */ void set_object(void *obj) { _object = obj; } + + /** @brief Get the parse error object. + * @return Error pointer, or null. + */ Error *error() { return _error; } + + /** @brief Set the parse error object. + * @param obj Error pointer. + */ void set_error(Error *obj) { _error = obj; } + + /** @brief Get parser status. + * @return Non-zero on success; zero on failure. + */ int status() { return _status; } + + /** @brief Set parser status. + * @param val Non-zero for success, zero for failure. + */ void set_status(int val = 0) { _status = val; } }; diff --git a/main_page.doxygen.in b/retired/main_page.doxygen.in similarity index 93% rename from main_page.doxygen.in rename to retired/main_page.doxygen.in index 1a2758595..f52e15067 100644 --- a/main_page.doxygen.in +++ b/retired/main_page.doxygen.in @@ -6,14 +6,14 @@ /** \mainpage -\showdate "%A %Y-%m-%d" 2025-03-24 +Documentation build date: \today \section intro Introduction -This reference documentation corresponds to version @PACKAGE_VERSION@ of libdap, a C++ +This reference documentation corresponds to version \package_version of libdap, a C++ implementation of DAP2, with some extensions. The libdap library includes classes and functions which implement DAP 2.0 as well as utilities -which simplify building clients and servers for DAP 2.0 and DAP4.0. +which simplify building clients and servers for DAP 2.0 and DAP 4.0. \section conventions Doxygen Conventions diff --git a/tests/run_das_response_test.py b/tests/run_das_response_test.py new file mode 100644 index 000000000..f94aa1de5 --- /dev/null +++ b/tests/run_das_response_test.py @@ -0,0 +1,35 @@ +#!/usr/bin/env python3 +import sys, subprocess, difflib, pathlib + +if len(sys.argv)!=5 and len(sys.argv)!=3: + print(f"Usage: {sys.argv[0]} [ ]", file=sys.stderr) + sys.exit(1) + +if len(sys.argv)==5: + exe, input_path, baseline_path, out_diff = sys.argv[1:] + inp = pathlib.Path(input_path).read_text() + # run das-test + proc = subprocess.run([exe, "-p"], input=inp.encode(), + stdout=subprocess.PIPE, stderr=subprocess.STDOUT) + out_lines = proc.stdout.decode().splitlines() + base_lines = pathlib.Path(baseline_path).read_text().splitlines() + + diff = list(difflib.unified_diff( + base_lines, out_lines, + fromfile=baseline_path, tofile=str(out_diff) + )) + if diff: + # write unified diff for CTest logs + pathlib.Path(out_diff).write_text("\n".join(diff)) + sys.exit(1) +elif len(sys.argv)==3: + exe, input_path = sys.argv[1:] + inp = pathlib.Path(input_path).read_text() + proc = subprocess.run([exe, "-p"], input=inp.encode(), + stdout=subprocess.PIPE, stderr=subprocess.STDOUT) + out_lines = proc.stdout.decode().splitlines() + print(f"Output:") + for line in out_lines: + print(line) + +sys.exit(0) diff --git a/unit-tests/D4FilterClauseTest.cc b/unit-tests/D4FilterClauseTest.cc index f879c61d2..ea1511a6e 100644 --- a/unit-tests/D4FilterClauseTest.cc +++ b/unit-tests/D4FilterClauseTest.cc @@ -178,7 +178,7 @@ class D4FilterClauseTest : public TestFixture { CPPUNIT_ASSERT(not_equal->value(dmr)); } - /** @defgroup type_conv Tests for type promotion + /** @name type_conv Tests for type promotion * @{ */ void Byte_and_int_test() {