X-Git-Url: https://git.dogcows.com/gitweb?a=blobdiff_plain;f=src%2Fstlplus%2Fsubsystems%2Flibrary_manager.hpp;fp=src%2Fstlplus%2Fsubsystems%2Flibrary_manager.hpp;h=96e1afd93a1aa882c25e1bdc57e73d76b7162ede;hb=6b0a0d0efafe34d48ab344fca3b479553bd4e62c;hp=0000000000000000000000000000000000000000;hpb=85783316365181491a3e3c0c63659972477cebba;p=chaz%2Fyoink diff --git a/src/stlplus/subsystems/library_manager.hpp b/src/stlplus/subsystems/library_manager.hpp new file mode 100644 index 0000000..96e1afd --- /dev/null +++ b/src/stlplus/subsystems/library_manager.hpp @@ -0,0 +1,708 @@ +#ifndef STLPLUS_LIBRARY_MANAGER +#define STLPLUS_LIBRARY_MANAGER +//////////////////////////////////////////////////////////////////////////////// + +// Author: Andy Rushton +// Copyright: (c) Southampton University 1999-2004 +// (c) Andy Rushton 2004-2009 +// License: BSD License, see ../docs/license.html + +// Generalised library manager. + +// Manages library units in a set of library directories. A unit is both a file +// on-disk and a data-structure in memory. To use the library manager, you need +// to: + +// - design a type based on lm_unit with serialising functions read/write +// - decide on a file extension for the type +// - decide on a description of the type +// - write a create callback for this type +// - register the file extension, description and callback with the library manager + +//////////////////////////////////////////////////////////////////////////////// +#include "subsystems_fixes.hpp" +#include "ini_manager.hpp" +#include "smart_ptr.hpp" +#include +#include +#include +#include +#include +#include + +namespace stlplus +{ + + //////////////////////////////////////////////////////////////////////////////// + // Internals + //////////////////////////////////////////////////////////////////////////////// + + class lm_library; + class library_manager; + + //////////////////////////////////////////////////////////////////////////////// + // unit names + //////////////////////////////////////////////////////////////////////////////// + + class lm_unit_name + { + public: + lm_unit_name(const std::string& name = std::string(), const std::string& type = std::string()); + ~lm_unit_name(void); + + const std::string& name(void) const; + void set_name(const std::string& name); + void lowercase(void); + + const std::string& type(void) const; + void set_type(const std::string& type); + + bool write(std::ostream& context) const; + bool read(std::istream& context); + + std::string to_string(void) const; + bool print(std::ostream&) const; + + private: + std::string m_name; + std::string m_type; + }; + + std::ostream& operator << (std::ostream&, const lm_unit_name&); + bool operator == (const lm_unit_name& l, const lm_unit_name& r); + bool operator < (const lm_unit_name& l, const lm_unit_name& r); + + //////////////////////////////////////////////////////////////////////////////// + // dependencies + //////////////////////////////////////////////////////////////////////////////// + + // dependencies on external files + + class lm_file_dependency + { + public: + lm_file_dependency(void); + lm_file_dependency(const std::string& library_path, const std::string& path, unsigned line = 0, unsigned column = 0); + ~lm_file_dependency(void); + + // a path can be retrieved as either a relative path to the library or as a + // full path by providing the library path as an argument + const std::string& path(void) const; + std::string path_full(const std::string& library_path) const; + void set_path(const std::string& library_path, const std::string& path); + + unsigned line(void) const; + void set_line(unsigned line = 0); + + unsigned column(void) const; + void set_column(unsigned column = 0); + + bool write(std::ostream& context) const; + bool read(std::istream& context); + + bool print(std::ostream&) const; + + private: + std::string m_path; // file dependencies are stored as paths relative to the containing library + unsigned m_line; // line - starts at 1, 0 means no line/column information + unsigned m_column; // column - starts at 0 + }; + + std::ostream& operator <<(std::ostream&, const lm_file_dependency&); + + // dependencies on other units + + class lm_unit_dependency + { + public: + lm_unit_dependency(void); + lm_unit_dependency(const std::string& library, const lm_unit_name& name); + ~lm_unit_dependency(void); + + const std::string& library(void) const; + void set_library(const std::string& library); + + const lm_unit_name& unit_name(void) const; + void set_unit_name(const lm_unit_name& unit_name); + + const std::string& name(void) const; + void set_name(const std::string& name); + + const std::string& type(void) const; + void set_type(const std::string& type); + + bool write(std::ostream& context) const; + bool read(std::istream& context); + + bool print(std::ostream&) const; + + private: + std::string m_library; + lm_unit_name m_name; + }; + + std::ostream& operator<<(std::ostream&, const lm_unit_dependency&); + + // the set of all dependencies + + class lm_dependencies + { + public: + lm_dependencies(void); + lm_dependencies(const lm_dependencies&); + lm_dependencies& operator=(const lm_dependencies&); + ~lm_dependencies(void); + + // source file dependency + void set_source_file(const lm_file_dependency&); + bool source_file_present(void) const; + const lm_file_dependency& source_file(void) const; + + // other file dependencies + unsigned file_add(const lm_file_dependency& dependency); + unsigned file_size(void) const; + const lm_file_dependency& file_dependency(unsigned) const; + void file_erase(unsigned); + + // unit dependencies + unsigned unit_add(const lm_unit_dependency& dependency); + unsigned unit_size(void) const; + const lm_unit_dependency& unit_dependency(unsigned) const; + void unit_erase(unsigned); + + void clear(void); + bool empty(void) const; + + bool write(std::ostream& context) const; + bool read(std::istream& context); + + bool print(std::ostream&) const; + + private: + lm_file_dependency* m_source; // source file dependency (optional) + std::vector m_files; // other file dependencies + std::vector m_units; // unit dependencies + }; + + std::ostream& operator << (std::ostream&, const lm_dependencies&); + + //////////////////////////////////////////////////////////////////////////////// + // library unit superclass + // user's units must be derivatives of lm_unit and overload all the virtuals + + class lm_unit + { + friend class lm_library; + public: + //////////////////////////////////////// + // constructor/destructor + + lm_unit(const lm_unit_name& name, lm_library* library); + virtual ~lm_unit(void); + + //////////////////////////////////////// + // Header data + + // unit name + const lm_unit_name& unit_name(void) const; + const std::string& name(void) const; + const std::string& type(void) const; + + // dependencies + // all file dependencies are converted for internal use to a path relative to the library + // they can be retrieved either in this form or as a full path + + // source file dependency + void set_source_file(const lm_file_dependency&); + bool source_file_present(void) const; + const lm_file_dependency& source_file(void) const; + + // other file dependencies + unsigned file_add(const lm_file_dependency& dependency); + unsigned file_size(void) const; + const lm_file_dependency& file_dependency(unsigned) const; + void file_erase(unsigned); + + // unit dependencies + unsigned unit_add(const lm_unit_dependency& dependency); + unsigned unit_size(void) const; + const lm_unit_dependency& unit_dependency(unsigned) const; + void unit_erase(unsigned); + + const lm_dependencies& dependencies(void) const; + void set_dependencies(const lm_dependencies&); + void clear_dependencies(void); + bool empty_dependencies(void) const; + + // dependency checking + + bool out_of_date(void) const; + bool up_to_date(void) const; + lm_dependencies out_of_date_reason(void) const; + + // supplementary data + + const std::string& supplementary_data(void) const; + void set_supplementary_data(const std::string& data); + + //////////////////////////////////////// + // unit data management + + bool load(void); + bool save(void); + bool loaded(void) const; + void mark(void); + + // file modified time - only changes after a save + + time_t modified(void) const; + + //////////////////////////////////////// + // containing library manager details + + // get the owning library + const lm_library* library(void) const; + lm_library* library(void); + + // owning library name and path + const std::string& library_name(void) const; + const std::string& library_path(void) const; + + //////////////////////////////////////// + // error handling - these apply to the last read/write operation + + bool error(void) const; + + //////////////////////////////////////// + // functions that customise subclasses of this superclass + // You MUST provide at least: + // - read - either read operation can be overloaded + // - write - either write operation can be overloaded + // - clone + + // read(filename) is the one actually called to read your data + // the default read(filename) simply calls read(istream) to actually read the file + // the default read(istream) does nothing but fail by returning false so you must overload one or other + + // you can just overload read(istream) if you want to use IOstream, or you + // can overload read(filename) to use any I/O system + + virtual bool read(const std::string& filename, void* type_data); + virtual bool read(std::istream& file, void* type_data); + + // as above, but for writing the data type + + // write(filename) is the one actually called to write your data + // the default write(filename) simply calls write(ostream) to actually write the file + // the default write(ostream) does nothing but fail by returning false so you must overload one or other + + // you can just overload write(ostream) if you want to use IOstream, or you + // can overload write(filename) to use any I/O system + + virtual bool write(const std::string& filename, void* type_data); + virtual bool write(std::ostream& file, void* type_data); + + // purge clears any memory associated with the unit - makes the unit unloaded + // the default does nothing + virtual bool purge(void); + + // the clone function creates a new-ed copy of the subclass + virtual lm_unit* clone(void) const; + + // the default print routines print header-only information + // you can overload these to provide a debug printout of the data structure + virtual bool print(std::ostream&) const; + virtual bool print_long(std::ostream&) const; + + protected: + // header file management + std::string filename(void) const; + std::string header_filename(void) const; + bool write_header(void); + bool read_header(void); + + private: + // header fields + lm_unit_name m_name; // name + lm_dependencies m_dependencies; // file and unit dependencies + std::string m_supplement; // supplementary data + bool m_header_modified; // header modified + + // internal fields + bool m_loaded; // loaded flag + bool m_marked; // mark - determines whether the unit needs saving + + // library manager fields + lm_library* m_library; // parent library + + // error handling fields + bool m_error; // error flag if load or save fails - from IOstream + }; + + // Iostream print calls the short print method + std::ostream& operator << (std::ostream& str, const lm_unit& u); + + //////////////////////////////////////////////////////////////////////////////// + // other types used in the library manager + //////////////////////////////////////////////////////////////////////////////// + + // user types + + typedef smart_ptr_nocopy lm_unit_ptr; + typedef lm_unit* (*lm_create_callback)(const lm_unit_name& unit_name, lm_library* parent_library, void* type_data); + + // internal types used in the library manager but made global because they are shared + + struct lm_callback_entry + { + lm_create_callback m_callback; + std::string m_description; + void* m_type_data; + + lm_callback_entry(lm_create_callback callback = 0, const std::string& description = std::string(), void* type_data = 0) : + m_callback(callback), m_description(description), m_type_data(type_data) {} + }; + + //////////////////////////////////////////////////////////////////////////////// + // Library + // Must be contained in a library_manager + // Manages objects of class lm_unit and its subclasses + //////////////////////////////////////////////////////////////////////////////// + + class lm_library + { + public: + friend class library_manager; + friend class lm_unit; + + ////////////////////////////////////////////////////////////////////////////// + // constructors/destructor - lm_library should only ever be constructed by library_manager + + lm_library(library_manager* manager); + lm_library(const lm_library&); + lm_library& operator = (const lm_library&); + ~lm_library(void); + + public: + + const library_manager* manager(void) const; + library_manager* manager(void); + + ////////////////////////////////////////////////////////////////////////////// + // initialisers + + bool create(const std::string& name, const std::string& path, bool writable); + bool open(const std::string& path); + + ////////////////////////////////////////////////////////////////////////////// + // management of types + + bool load_type(const std::string& type); + bool load_types(void); + bool remove_type(const std::string& type); + + ////////////////////////////////////////////////////////////////////////////// + // whole library operations + + bool load(void); + bool save(void); + bool purge(void); + bool close(void); + bool erase(void); + + const std::string& name(void) const; + const std::string& path(void) const; + + ////////////////////////////////////////////////////////////////////////////// + // managing read/write status + + bool set_read_write(bool writable); + bool set_writable(void); + bool set_read_only(void); + bool writable(void) const; + bool read_only(void) const; + bool os_writable(void) const; + bool os_read_only(void) const; + bool lm_writable(void) const; + bool lm_read_only(void) const; + + ////////////////////////////////////////////////////////////////////////////// + // unit management + + bool exists(const lm_unit_name& name) const; + lm_unit_ptr create(const lm_unit_name&); + bool loaded(const lm_unit_name& name) const; + bool load(const lm_unit_name& unit); + bool purge(const lm_unit_name& unit); + bool save(const lm_unit_name& unit); + bool erase(const lm_unit_name& name); + bool mark(const lm_unit_name& name); + time_t modified(const lm_unit_name& name) const; + + bool erase_by_source(const std::string& source_file); + + const lm_unit_ptr find(const lm_unit_name& name) const; + lm_unit_ptr find(const lm_unit_name& name); + + std::vector names(void) const; + std::vector names(const std::string& type) const; + std::vector handles(void) const; + std::vector handles(const std::string& type) const; + + ////////////////////////////////////////////////////////////////////////////// + // dependency checking + + bool out_of_date(const lm_unit_name& name) const; + bool up_to_date(const lm_unit_name& name) const; + lm_dependencies out_of_date_reason(const lm_unit_name& name) const; + + std::pair tidy(void); + + ////////////////////////////////////////////////////////////////////////////// + // do-everything print function + + bool pretty_print(std::ostream& str, + bool print_units = false, // print the unit names not just the library names + const std::string& type = std::string()) const; // print just this type ("" means all) + + //////////////////////////////////////////////////////////////////////////////// + // diagnostic print routines + + bool print(std::ostream& str) const; + bool print_long(std::ostream& str) const; + + private: + + std::map::iterator local_find(const lm_unit_name& name); + std::map::const_iterator local_find(const lm_unit_name& name) const; + + std::string m_name; // name + std::string m_path; // path + bool m_writable; // writable + std::map m_units; // units + library_manager* m_manager; // parent library manager + }; + + std::ostream& operator << (std::ostream& str, const lm_library& lib); + + //////////////////////////////////////////////////////////////////////////////// + // Library Manager + //////////////////////////////////////////////////////////////////////////////// + + class library_manager + { + public: + friend class lm_library; + friend class lm_unit; + + //////////////////////////////////////////////////////////////////////////////// + // static functions allow you to test whether a directory is a library before opening it + // you can also find the library's name without opening it + + static bool is_library(const std::string& path, const std::string& owner); + static std::string library_name(const std::string& path, const std::string& owner); + + // non-static forms test for libraries with the same owner as the library manager + + bool is_library(const std::string& path); + std::string library_name(const std::string& path); + + ////////////////////////////////////////////////////////////////////////////// + // tructors + + explicit library_manager(const std::string& owner, bool library_case = false, bool unit_case = false); + ~library_manager(void); + + ////////////////////////////////////////////////////////////////////////////// + // case sensitivity + + bool library_case(void) const; + void set_library_case(bool library_case); + + bool unit_case(void) const; + void set_unit_case(bool library_case); + + ////////////////////////////////////////////////////////////////////////////// + // type handling + // only units of types added in this way will be recognised + + bool add_type(const std::string& type, + const std::string& description, + lm_create_callback fn = 0, + void* type_data = 0); + bool remove_type(const std::string& type); + std::vector types(void) const; + + std::string description(const std::string& type) const; + lm_create_callback callback(const std::string& type) const; + void* type_data(const std::string& type) const; + + ////////////////////////////////////////////////////////////////////////////// + // Library mappings + // The library manager implements two different styles of library mappings + // - mapping file + // - ini file + // mapping file handling uses a simple text file to store the mappings in an internally-defined format + // ini file handling stores library mappings using the ini_manager component + // These modes are switched on by simply specifying a mapping file or an ini file to hold the mappings + + // mapping file methods + + // set but do not load - use this when you want to create a new mapping file + void set_mapping_file(const std::string& mapping_file); + // set and load - use this with an existing mapping file + bool load_mappings (const std::string& mapping_file); + // return the mapping file string + std::string mapping_file(); + + // ini file methods - the ini manager must be pre-loaded with the list of ini files to manage + + // set and load - this will create the relevant sections in the local ini file if not present already + bool set_ini_manager(ini_manager* ini_files, const std::string& library_section, const std::string& work_section); + ini_manager* get_ini_manager(void) const; + + // save to the library mapping handler, whichever kind it is + bool save_mappings (void); + + ////////////////////////////////////////////////////////////////////////////// + // library management + + // operations on a single library + // test whether a named library exists + bool exists(const std::string& name) const; + // create a new libarry in the specified directory + lm_library* create(const std::string& name, const std::string& path, bool writable = true); + // open an existing library + lm_library* open(const std::string& path); + // load all units in the library + bool load(const std::string& name); + // save all marked units in the library + bool save(const std::string& name); + // purge all loaded units in the library + bool purge(const std::string& name); + // close the library - remove it from the manager but leave on disk + bool close(const std::string& name); + // erase the library - delete the directory and remove the library from the manager + bool erase(const std::string& name); + + // operations on all libraries - as above but applied to all the libraries in the manager + bool load(void); + bool save(void); + bool purge(void); + bool close(void); + bool erase(void); + + // get name and path of a library - name can differ in case if the library manager is case-insensitive + std::string name(const std::string& library) const; + std::string path(const std::string& library) const; + + // control and test read/write status + bool set_writable(const std::string& library); + bool set_read_only(const std::string& library); + bool writable(const std::string& library) const; + bool read_only(const std::string& library) const; + bool os_writable(const std::string& library) const; + bool os_read_only(const std::string& library) const; + bool lm_writable(const std::string& library) const; + bool lm_read_only(const std::string& library) const; + + // find a library in the manager - returns null if not found + lm_library* find(const std::string& name); + const lm_library* find(const std::string& name) const; + + // get the set of all library names + std::vector names(void) const; + // get the set of all libraries + std::vector handles(void) const; + std::vector handles(void); + + ////////////////////////////////////////////////////////////////////////////// + // current library management + + bool setwork(const std::string& library); + bool unsetwork(void); + const lm_library* work(void) const; + lm_library* work(void); + std::string work_name(void) const; + + ////////////////////////////////////////////////////////////////////////////// + // unit management within a library + // Note: you can also manipulate the library class through a handle returned by find() or handles() + + bool exists(const std::string& library, const lm_unit_name& name) const; + lm_unit_ptr create(const std::string& library, const lm_unit_name& name); + bool loaded(const std::string& library, const lm_unit_name& name) const; + bool load(const std::string& library, const lm_unit_name& name); + bool purge(const std::string& library, const lm_unit_name& name); + bool save(const std::string& library, const lm_unit_name& name); + bool erase(const std::string& library, const lm_unit_name& name); + bool mark(const std::string& library, const lm_unit_name& name); + time_t modified(const std::string& library, const lm_unit_name& name) const; + + bool erase_by_source(const std::string& source_file); + + const lm_unit_ptr find(const std::string& library, const lm_unit_name& name) const; + lm_unit_ptr find(const std::string& library, const lm_unit_name& name); + + std::vector names(const std::string& library) const; + std::vector names(const std::string& library, const std::string& type) const; + std::vector handles(const std::string& library) const; + std::vector handles(const std::string& library, const std::string& type) const; + + ////////////////////////////////////////////////////////////////////////////// + // dependency checking + + bool out_of_date(const std::string& library, const lm_unit_name& name) const; + bool up_to_date(const std::string& library, const lm_unit_name& name) const; + lm_dependencies out_of_date_reason(const std::string& library, const lm_unit_name& name) const; + + // delete out of date units from a library or all libraries + // return the number of units tidied and a flag to say whether all units were successfully tidied + std::pair tidy(const std::string& library); + std::pair tidy(void); + + ////////////////////////////////////////////////////////////////////////////// + // do-everything print routine! + + bool pretty_print(std::ostream& str, + bool print_units = false, // print the unit names not just the library names + const std::string& library = std::string(), // print just the specified library ("" means all) + const std::string& type = std::string()) const; // print just this type ("" means all) + + //////////////////////////////////////////////////////////////////////////////// + // diagnostic print routines + + bool print(std::ostream& str) const; + bool print_long(std::ostream& str) const; + + ////////////////////////////////////////////////////////////////////////////// + // internals + + private: + // NOT a copyable object + library_manager(const library_manager&); + library_manager& operator = (const library_manager&); + + protected: + std::list::iterator local_find(const std::string& name); + std::list::const_iterator local_find(const std::string& name) const; + + std::string m_owner; // owner application name + std::string m_mapping_file; // mapping file method of library management + ini_manager* m_ini_files; // ini manager method of library management + std::string m_ini_section; // ini manager method of library management + std::string m_ini_work; // ini manager method of library management + std::list m_libraries; // libraries + std::string m_work; // work library + std::map m_callbacks; // callbacks + bool m_library_case; // case sensitivity for library names + bool m_unit_case; // case sensitivity for unit names + }; + + std::ostream& operator << (std::ostream& str, const library_manager& libraries); + + //////////////////////////////////////////////////////////////////////////////// + +} // end namespace stlplus + +#endif