diff --git a/src/layui/layui/rdbMarkerBrowserDialog.cc b/src/layui/layui/rdbMarkerBrowserDialog.cc index 56d32c2cf..f31e1233a 100644 --- a/src/layui/layui/rdbMarkerBrowserDialog.cc +++ b/src/layui/layui/rdbMarkerBrowserDialog.cc @@ -387,7 +387,7 @@ BEGIN_PROTECTED } else { - rdb->save (rdb->filename ()); + rdb->save (rdb->filename (), rdb->binary ()); rdb->reset_modified (); } @@ -459,7 +459,7 @@ BEGIN_PROTECTED throw tl::Exception (tl::to_string (tr ("The current report database is not saved.\nSave it to some file with 'Save As', before saving it as waiver DB."))); } - rdb->write (rdb->filename () + ".w"); + rdb->write (rdb->filename () + ".w", rdb->binary ()); END_PROTECTED } @@ -475,11 +475,13 @@ BEGIN_PROTECTED if (rdb) { // prepare and open the file dialog - lay::FileDialog save_dialog (this, tl::to_string (QObject::tr ("Save Marker Database File")), "KLayout RDB files (*.lyrdb)"); + lay::FileDialog save_dialog (this, tl::to_string (QObject::tr ("Save Marker Database File")), tl::to_string (tr ("KLayout RDB files (*.lyrdb);;KLayout binary RDB files (*.rdb);;All files (*)"))); std::string fn (rdb->filename ()); if (save_dialog.get_save (fn)) { - rdb->save (fn); + bool binary = (tl::extension (fn) == "rdb"); + + rdb->save (fn, binary); rdb->reset_modified (); // update the RDB title strings diff --git a/src/rdb/rdb/gsiDeclRdb.cc b/src/rdb/rdb/gsiDeclRdb.cc index 920334d43..41d6355e2 100644 --- a/src/rdb/rdb/gsiDeclRdb.cc +++ b/src/rdb/rdb/gsiDeclRdb.cc @@ -1677,10 +1677,12 @@ Class decl_ReportDatabase ("rdb", "ReportDatabase", "The reader recognizes the format automatically and will choose the appropriate decoder. 'gzip' compressed files are uncompressed " "automatically.\n" ) + - gsi::method ("save", &rdb::Database::save, gsi::arg ("filename"), + gsi::method ("save", &rdb::Database::save, gsi::arg ("filename"), gsi::arg ("binary", false), "@brief Saves the database to the given file\n" "@param filename The file to which to save the database\n" - "The database is always saved in KLayout's XML-based format.\n" + "The database is saved in KLayout's XML-based format if 'binary' is false or a ProtocolBuffer-based binary format if 'binary' is true.\n" + "\n" + "The 'binary' argument has been added in version 0.29.7." ), "@brief The report database object\n" "A report database is organized around a set of items which are associated with cells and categories. " diff --git a/src/rdb/rdb/rdb.cc b/src/rdb/rdb/rdb.cc index 289c21d68..cbdfbe880 100644 --- a/src/rdb/rdb/rdb.cc +++ b/src/rdb/rdb/rdb.cc @@ -1767,6 +1767,7 @@ Database::clear () m_generator = ""; m_filename = ""; + m_binary = false; m_description = ""; m_name = ""; m_topcell = ""; @@ -1819,6 +1820,7 @@ Database::load (std::string fn) tl::log << "Loading RDB from " << fn; clear (); + set_binary (false); tl::InputStream stream (fn); diff --git a/src/rdb/rdb/rdb.h b/src/rdb/rdb/rdb.h index 3747ada65..b5f4f4180 100644 --- a/src/rdb/rdb/rdb.h +++ b/src/rdb/rdb/rdb.h @@ -2044,7 +2044,7 @@ public: ~Database (); /** - * @brief Get the database description + * @brief Gets the database description */ const std::string &description () const { @@ -2052,7 +2052,7 @@ public: } /** - * @brief Set the database description + * @brief Sets the database description */ void set_description (const std::string &description) { @@ -2061,7 +2061,7 @@ public: } /** - * @brief Get the database original file + * @brief Gets the database original file * * The original file describes what original file the marker database * was derived from. @@ -2072,7 +2072,7 @@ public: } /** - * @brief Set the database original file + * @brief Sets the database original file */ void set_original_file (const std::string &original_file) { @@ -2081,7 +2081,7 @@ public: } /** - * @brief Get the database name + * @brief Gets the database name */ const std::string &name () const { @@ -2089,7 +2089,7 @@ public: } /** - * @brief Set the database name + * @brief Sets the database name */ void set_name (const std::string &name) { @@ -2097,7 +2097,7 @@ public: } /** - * @brief Get the file name + * @brief Gets the file name */ const std::string &filename () const { @@ -2105,7 +2105,7 @@ public: } /** - * @brief Set the file name + * @brief Sets the file name */ void set_filename (const std::string &filename) { @@ -2114,7 +2114,24 @@ public: } /** - * @brief Get the generator name + * @brief Gets a value indicating whether the database was saved to binary format + */ + bool binary () const + { + return m_binary; + } + + /** + * @brief Sets a value indicating whether the database was saved to binary format + */ + void set_binary (bool bin) + { + set_modified (); + m_binary = bin; + } + + /** + * @brief Gets the generator name */ const std::string &generator () const { @@ -2122,7 +2139,7 @@ public: } /** - * @brief Set the generator name + * @brief Sets the generator name */ void set_generator (const std::string &generator) { @@ -2131,7 +2148,7 @@ public: } /** - * @brief Set the top cell name + * @brief Sets the top cell name */ void set_top_cell_name (const std::string &topcell) { @@ -2140,7 +2157,7 @@ public: } /** - * @brief Return the top cell name + * @brief Returns the top cell name */ const std::string &top_cell_name () const { @@ -2148,7 +2165,7 @@ public: } /* - * @brief Get the reference to the tags collection (const version) + * @brief Gets the reference to the tags collection (const version) */ const Tags &tags () const { @@ -2156,14 +2173,14 @@ public: } /** - * @brief Import tags + * @brief Imports tags * * This method is provided for persistency application only. It should not be used otherwise. */ void import_tags (const Tags &tags); /** - * @brief Get the reference to the categories collection (const version) + * @brief Gets the reference to the categories collection (const version) */ const Categories &categories () const { @@ -2171,7 +2188,7 @@ public: } /** - * @brief Get the reference to the categories collection (non-const version) + * @brief Gets the reference to the categories collection (non-const version) */ Categories &categories_non_const () { @@ -2179,7 +2196,7 @@ public: } /** - * @brief Import categories + * @brief Imports categories * * This method is provided for persistency application only. It should not be used otherwise. * This will take over the ownership over the Categories object. @@ -2187,17 +2204,17 @@ public: void import_categories (Categories *categories); /** - * @brief Create a category and register it + * @brief Creates a category and register it */ Category *create_category (const std::string &name); /** - * @brief Create a category as a subcategory and register it + * @brief Creates a category as a subcategory and register it */ Category *create_category (Category *parent, const std::string &name); /** - * @brief Create a category as a subcategory in the container and register it + * @brief Creates a category as a subcategory in the container and register it * * Hint: this method does not set the parent properly and must not be used * under normal circumstances. It is provided as a internal method and @@ -2206,7 +2223,7 @@ public: Category *create_category (Categories *container, const std::string &name); /** - * @brief Get the category pointer for a category name (const version) + * @brief Gets the category pointer for a category name (const version) * * This method returns 0 if the category name is invalid. */ @@ -2216,7 +2233,7 @@ public: } /** - * @brief Get the category pointer for a category id (const version) + * @brief Gets the category pointer for a category id (const version) * * This method returns 0 if the category is invalid. */ @@ -2226,21 +2243,21 @@ public: } /** - * @brief Get the category pointer for a category name (non-const version) + * @brief Gets the category pointer for a category name (non-const version) * * This method returns 0 if the category name is invalid. */ Category *category_by_name_non_const (const std::string &name); /** - * @brief Get the category pointer for a category id (non-const version) + * @brief Gets the category pointer for a category id (non-const version) * * This method returns 0 if the category is invalid. */ Category *category_by_id_non_const (id_type id); /** - * @brief Access to the cell collection (const) + * @brief Gets the cell collection (const) */ const Cells &cells () const { @@ -2248,7 +2265,7 @@ public: } /** - * @brief Access to the cell collection + * @brief Gets the cell collection */ Cells &cells_non_const () { @@ -2256,14 +2273,14 @@ public: } /** - * @brief Import cells + * @brief Imports cells * * This method is provided for persistency application only. It should not be used otherwise. */ void import_cells (const Cells &cells); /** - * @brief Create a cell and register it + * @brief Creates a cell and registers it * * If a cell with that name already exists, a variant is created */ @@ -2273,7 +2290,7 @@ public: } /** - * @brief Create a cell variant and register it + * @brief Creates a cell variant and registers it * * A cell with name name/variant combination must not exist already. * If the variant string is empty, this method behaves the same as the @@ -2285,14 +2302,14 @@ public: Cell *create_cell (const std::string &name, const std::string &variant, const std::string &layout_name); /** - * @brief Get all variants registered for a given cell name (not qname!) + * @brief Gets all variants registered for a given cell name (not qname!) * * @return a vector of id's corresponding to the given variants or an empty vector if the name is not valid or the cell has no variants */ const std::vector &variants (const std::string &name); /** - * @brief Get the cell pointer for a cell name or name:variant combination (const version) + * @brief Gets the cell pointer for a cell name or name:variant combination (const version) * * This method returns 0 if the cell name or name:variant combination is invalid. */ @@ -2302,7 +2319,7 @@ public: } /** - * @brief Get the cell pointer for a cell id (const version) + * @brief Gets the cell pointer for a cell id (const version) * * This method returns 0 if the cell id is invalid. */ @@ -2312,21 +2329,21 @@ public: } /** - * @brief Get the cell pointer for a cell name or name:variant combination (non-const version) + * @brief Gets the cell pointer for a cell name or name:variant combination (non-const version) * * This method returns 0 if the cell name or name:variant combination is invalid. */ Cell *cell_by_qname_non_const (const std::string &qname); /** - * @brief Get the cell pointer for a cell id (non-const version) + * @brief Gets the cell pointer for a cell id (non-const version) * * This method returns 0 if the cell id is invalid. */ Cell *cell_by_id_non_const (id_type id); /** - * @brief Report the number of items in total + * @brief Reports the number of items in total */ size_t num_items () const { @@ -2334,7 +2351,7 @@ public: } /** - * @brief Report the number of items visited + * @brief Reports the number of items visited */ size_t num_items_visited () const { @@ -2342,37 +2359,37 @@ public: } /** - * @brief Report the number of items for a given cell and category id + * @brief Reports the number of items for a given cell and category id */ size_t num_items (id_type cell_id, id_type category_id) const; /** - * @brief Report the number of items visited + * @brief Reports the number of items visited */ size_t num_items_visited (id_type cell_id, id_type category_id) const; /** - * @brief Create a new item for the given cell and category (both given by id) + * @brief Creates a new item for the given cell and category (both given by id) */ Item *create_item (id_type cell_id, id_type category_id); /** - * @brief Set a tag's description + * @brief Sets a tag's description */ void set_tag_description (id_type tag_id, const std::string &description); /** - * @brief Set an item to visited state or reset the state + * @brief Sets an item to visited state or reset the state */ void set_item_visited (const Item *item, bool visited); /** - * @brief Add a tag to the given item + * @brief Adds a tag to the given item */ void add_item_tag (const Item *item, id_type tag); /** - * @brief Remove a tag from the given item + * @brief Removes a tag from the given item */ void remove_item_tag (const Item *item, id_type tag); @@ -2383,23 +2400,23 @@ public: #if defined(HAVE_QT) /** - * @brief Set the image of an item + * @brief Sets the image of an item */ void set_item_image (const Item *item, const QImage &image); #endif /** - * @brief Set the image string of an item + * @brief Sets the image string of an item */ void set_item_image_str (const Item *item, const std::string &image_str); /** - * @brief Set the multiplicity of an item + * @brief Sets the multiplicity of an item */ void set_item_multiplicity (const Item *item, size_t n); /** - * @brief Get the items collection (const version) + * @brief Gets the items collection (const version) */ const Items &items () const { @@ -2407,7 +2424,7 @@ public: } /** - * @brief Get the items collection (non-const version) + * @brief Gets the items collection (non-const version) */ Items &items_non_const () { @@ -2415,7 +2432,7 @@ public: } /** - * @brief Set the items collection + * @brief Sets the items collection * * This method is provided for persistency application only. It should not be used otherwise. * This will take ownership over the items collection. @@ -2423,32 +2440,32 @@ public: void set_items (Items *items); /** - * @brief Get an iterator pair that delivers the const items (ItemRef) for a given cell + * @brief Gets an iterator pair that delivers the const items (ItemRef) for a given cell */ std::pair items_by_cell (id_type cell_id) const; /** - * @brief Get an iterator pair that delivers the non-const items (ItemRef) for a given cell + * @brief Gets an iterator pair that delivers the non-const items (ItemRef) for a given cell */ std::pair items_by_cell (id_type cell_id); /** - * @brief Get an iterator that delivers the const items (ItemRef) for a given category + * @brief Gets an iterator that delivers the const items (ItemRef) for a given category */ std::pair items_by_category (id_type category_id) const; /** - * @brief Get an iterator that delivers the non-const items (ItemRef) for a given category + * @brief Gets an iterator that delivers the non-const items (ItemRef) for a given category */ std::pair items_by_category (id_type category_id); /** - * @brief Get an iterator that delivers the const items (ItemRef) for a given cell and category + * @brief Gets an iterator that delivers the const items (ItemRef) for a given cell and category */ std::pair items_by_cell_and_category (id_type cell_id, id_type category_id) const; /** - * @brief Get an iterator that delivers the non-const items (ItemRef) for a given cell and category + * @brief Gets an iterator that delivers the non-const items (ItemRef) for a given cell and category */ std::pair items_by_cell_and_category (id_type cell_id, id_type category_id); @@ -2461,7 +2478,7 @@ public: } /** - * @brief Reset the modified file + * @brief Resets the modified file */ void reset_modified () { @@ -2469,19 +2486,19 @@ public: } /** - * @brief Save the database to a file + * @brief Saves the database to a file */ - void save (const std::string &filename); + void save (const std::string &filename, bool binary = false); /** - * @brief Write the database to a file + * @brief Writes the database to a file * * This function is like "save", but does not update the file name attribute. */ - void write (const std::string &filename); + void write (const std::string &filename, bool binary = false); /** - * @brief Load the database from a file + * @brief Loads the database from a file * * Note: This clears the existing database. * The argument intentionally is a copy, so we can call @@ -2510,6 +2527,7 @@ public: private: std::string m_generator; std::string m_filename; + bool m_binary; std::string m_description; std::string m_original_file; std::string m_name; diff --git a/src/rdb/rdb/rdbFile.cc b/src/rdb/rdb/rdbFile.cc index 1544ffcaf..35995c872 100644 --- a/src/rdb/rdb/rdbFile.cc +++ b/src/rdb/rdb/rdbFile.cc @@ -71,81 +71,96 @@ make_rdb_structure () { static tl::XMLElementList categories_format = - tl::make_element_with_parent_ref (&rdb::Categories::begin, &rdb::Categories::end, &rdb::Categories::import_category, "category", - tl::make_member (&rdb::Category::name, &rdb::Category::set_name, "name") + - tl::make_member (&rdb::Category::description, &rdb::Category::set_description, "description") + - tl::make_element_with_parent_ref (&rdb::Category::sub_categories, &rdb::Category::import_sub_categories, "categories", + tl::make_element_with_parent_ref (&rdb::Categories::begin, &rdb::Categories::end, &rdb::Categories::import_category, "category#1", + tl::make_member (&rdb::Category::name, &rdb::Category::set_name, "name#1") + + tl::make_member (&rdb::Category::description, &rdb::Category::set_description, "description#2") + + tl::make_element_with_parent_ref (&rdb::Category::sub_categories, &rdb::Category::import_sub_categories, "categories#3", &categories_format ) ) ; - return tl::XMLStruct ("report-database", - tl::make_member (&rdb::Database::description, &rdb::Database::set_description, "description") + - tl::make_member (&rdb::Database::original_file, &rdb::Database::set_original_file, "original-file") + - tl::make_member (&rdb::Database::generator, &rdb::Database::set_generator, "generator") + - tl::make_member (&rdb::Database::top_cell_name, &rdb::Database::set_top_cell_name, "top-cell") + - tl::make_element (&rdb::Database::tags, &rdb::Database::import_tags, "tags", - tl::make_element (&rdb::Tags::begin_tags, &rdb::Tags::end_tags, &rdb::Tags::import_tag, "tag", - tl::make_member (&rdb::Tag::name, &rdb::Tag::set_name, "name") + - tl::make_member (&rdb::Tag::description, &rdb::Tag::set_description, "description") + return tl::XMLStruct ("report-database#0", + tl::make_member (&rdb::Database::description, &rdb::Database::set_description, "description#1") + + tl::make_member (&rdb::Database::original_file, &rdb::Database::set_original_file, "original-file#2") + + tl::make_member (&rdb::Database::generator, &rdb::Database::set_generator, "generator#3") + + tl::make_member (&rdb::Database::top_cell_name, &rdb::Database::set_top_cell_name, "top-cell#4") + + tl::make_element (&rdb::Database::tags, &rdb::Database::import_tags, "tags#5", + tl::make_element (&rdb::Tags::begin_tags, &rdb::Tags::end_tags, &rdb::Tags::import_tag, "tag#1", + tl::make_member (&rdb::Tag::name, &rdb::Tag::set_name, "name#1") + + tl::make_member (&rdb::Tag::description, &rdb::Tag::set_description, "description#2") ) ) + - tl::make_element_with_parent_ref (&rdb::Database::categories, &rdb::Database::import_categories, "categories", + tl::make_element_with_parent_ref (&rdb::Database::categories, &rdb::Database::import_categories, "categories#6", &categories_format ) + - tl::make_element_with_parent_ref (&rdb::Database::cells, &rdb::Database::import_cells, "cells", + tl::make_element_with_parent_ref (&rdb::Database::cells, &rdb::Database::import_cells, "cells#7", // must be sorted cells (children after parents)! - tl::make_element_with_parent_ref (&rdb::Cells::begin, &rdb::Cells::end, &rdb::Cells::import_cell, "cell", - tl::make_member (&rdb::Cell::name, &rdb::Cell::set_name, "name") + - tl::make_member (&rdb::Cell::variant, &rdb::Cell::set_variant, "variant") + - tl::make_member (&rdb::Cell::layout_name, &rdb::Cell::set_layout_name, "layout-name") + - tl::make_element_with_parent_ref (&rdb::Cell::references, &rdb::Cell::import_references, "references", - tl::make_element_with_parent_ref (&rdb::References::begin, &rdb::References::end, &rdb::References::insert, "ref", - tl::make_member (&rdb::Reference::parent_cell_qname, &rdb::Reference::set_parent_cell_qname, "parent") + - tl::make_member (&rdb::Reference::trans_str, &rdb::Reference::set_trans_str, "trans") + tl::make_element_with_parent_ref (&rdb::Cells::begin, &rdb::Cells::end, &rdb::Cells::import_cell, "cell#1", + tl::make_member (&rdb::Cell::name, &rdb::Cell::set_name, "name#1") + + tl::make_member (&rdb::Cell::variant, &rdb::Cell::set_variant, "variant#2") + + tl::make_member (&rdb::Cell::layout_name, &rdb::Cell::set_layout_name, "layout-name#3") + + tl::make_element_with_parent_ref (&rdb::Cell::references, &rdb::Cell::import_references, "references#4", + tl::make_element_with_parent_ref (&rdb::References::begin, &rdb::References::end, &rdb::References::insert, "ref#1", + tl::make_member (&rdb::Reference::parent_cell_qname, &rdb::Reference::set_parent_cell_qname, "parent#1") + + tl::make_member (&rdb::Reference::trans_str, &rdb::Reference::set_trans_str, "trans#2") ) ) ) ) + - tl::make_element_with_parent_ref (&rdb::Database::items, &rdb::Database::set_items, "items", - tl::make_element_with_parent_ref (&rdb::Items::begin, &rdb::Items::end, &rdb::Items::add_item, "item", - tl::make_member (&rdb::Item::tag_str, &rdb::Item::set_tag_str, "tags") + - tl::make_member (&rdb::Item::category_name, &rdb::Item::set_category_name, "category") + - tl::make_member (&rdb::Item::cell_qname, &rdb::Item::set_cell_qname, "cell") + - tl::make_member (&rdb::Item::visited, &rdb::Item::set_visited, "visited") + - tl::make_member (&rdb::Item::multiplicity, &rdb::Item::set_multiplicity, "multiplicity") + - tl::make_member (&rdb::Item::comment, &rdb::Item::set_comment, "comment") + - tl::make_member (&rdb::Item::image_str, &rdb::Item::set_image_str, "image") + - tl::make_element (&rdb::Item::values, &rdb::Item::set_values, "values", - tl::make_member (&rdb::Values::begin, &rdb::Values::end, &rdb::Values::add, "value", ValueConverter ()) - ) + tl::make_element_with_parent_ref (&rdb::Database::items, &rdb::Database::set_items, "items#8", + tl::make_element_with_parent_ref (&rdb::Items::begin, &rdb::Items::end, &rdb::Items::add_item, "item#1", + tl::make_member (&rdb::Item::tag_str, &rdb::Item::set_tag_str, "tags#1") + + tl::make_member (&rdb::Item::category_name, &rdb::Item::set_category_name, "category#2") + + tl::make_member (&rdb::Item::cell_qname, &rdb::Item::set_cell_qname, "cell#3") + + tl::make_member (&rdb::Item::visited, &rdb::Item::set_visited, "visited#4") + + tl::make_member (&rdb::Item::multiplicity, &rdb::Item::set_multiplicity, "multiplicity#5") + + tl::make_member (&rdb::Item::comment, &rdb::Item::set_comment, "comment#6") + + tl::make_member (&rdb::Item::image_str, &rdb::Item::set_image_str, "image#7") + + tl::make_element (&rdb::Item::values, &rdb::Item::set_values, "values#8", + tl::make_member (&rdb::Values::begin, &rdb::Values::end, &rdb::Values::add, "value#1", ValueConverter ()) ) ) ) ); } static tl::XMLStruct s_rdb_struct = make_rdb_structure (); +static tl::RegisteredClass rdb_struct_def (&s_rdb_struct, 0, "KLayout-RDB", false); // ------------------------------------------------------------- // Implementation of rdb::Database::save and write // TODO: move this somewhere else - with generalized functionality void -rdb::Database::save (const std::string &fn) +rdb::Database::save (const std::string &fn, bool binary) { - write (fn); + write (fn, binary); set_filename (fn); + set_binary (binary); } void -rdb::Database::write (const std::string &fn) +rdb::Database::write (const std::string &fn, bool binary) { tl::OutputStream os (fn, tl::OutputStream::OM_Auto); - s_rdb_struct.write (os, *this); - if (tl::verbosity () >= 10) { - tl::log << "Saved RDB to " << fn; + if (binary) { + + tl::ProtocolBufferWriter writer (os); + s_rdb_struct.write (writer, *this); + + if (tl::verbosity () >= 10) { + tl::log << tl::to_string (tr ("Saved binary RDB to ")) << fn; + } + + } else { + + s_rdb_struct.write (os, *this); + + if (tl::verbosity () >= 10) { + tl::log << tl::to_string (tr ("Saved RDB to ")) << fn; + } + } } @@ -156,8 +171,8 @@ class StandardReader : public ReaderBase { public: - StandardReader (tl::InputStream &stream) - : m_input_stream (stream) + StandardReader (tl::InputStream &stream, bool binary) + : m_input_stream (stream), m_binary (binary) { // .. nothing yet .. } @@ -165,17 +180,30 @@ public: virtual void read (Database &db) { tl::SelfTimer timer (tl::verbosity () >= 11, "Reading marker database file"); - tl::XMLStreamSource in (m_input_stream, tl::to_string (tr ("Reading RDB"))); - s_rdb_struct.parse (in, db); + + if (m_binary) { + + tl::ProtocolBufferReader reader (m_input_stream); + s_rdb_struct.parse (reader, db); + db.set_binary (true); + + } else { + + tl::XMLStreamSource in (m_input_stream, tl::to_string (tr ("Reading RDB"))); + s_rdb_struct.parse (in, db); + db.set_binary (false); + + } } virtual const char *format () const { - return "KLayout-RDB"; + return m_binary ? "KLayout-RDB-PB" : "KLayout-RDB"; } private: tl::InputStream &m_input_stream; + bool m_binary; }; class StandardFormatDeclaration @@ -203,10 +231,46 @@ class StandardFormatDeclaration virtual ReaderBase *create_reader (tl::InputStream &s) const { - return new StandardReader (s); + return new StandardReader (s, false); } }; static tl::RegisteredClass format_decl (new StandardFormatDeclaration (), 0, "KLayout-RDB"); +class BinaryFormatDeclaration + : public FormatDeclaration +{ + virtual std::string format_name () const { return "KLayout-RDB-PB"; } + virtual std::string format_desc () const { return "KLayout binary report database format"; } + virtual std::string file_format () const { return "KLayout binary RDB files (*.rdb *.rdb.gz)"; } + + virtual bool detect (tl::InputStream &stream) const + { + static const char header[] = { + // ProtocolBuffer wire format, LEN record with ID 0 and string "report-database". + 0x02, 0x0f, 0x72, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2d, 0x64, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65 + }; + + const char *h = stream.get (sizeof (header)); + if (! h) { + return false; + } + + for (size_t i = 0; i < sizeof (header); ++i) { + if (h[i] != header[i]) { + return false; + } + } + + return true; + } + + virtual ReaderBase *create_reader (tl::InputStream &s) const + { + return new StandardReader (s, true); + } +}; + +static tl::RegisteredClass pb_format_decl (new BinaryFormatDeclaration (), 1, "KLayout-RDB-PB"); + }