X-Git-Url: https://git.dogcows.com/gitweb?a=blobdiff_plain;f=src%2Fstlplus%2Fsubsystems%2Flibrary_manager.cpp;fp=src%2Fstlplus%2Fsubsystems%2Flibrary_manager.cpp;h=0000000000000000000000000000000000000000;hb=5846afb00833cc72fe72422ca896d2387c712cb4;hp=0daf1be4c0adb0adf28829e6344936e657d59873;hpb=a97500609dc3c1b11f9786d32bc458eb00de4c36;p=chaz%2Fyoink diff --git a/src/stlplus/subsystems/library_manager.cpp b/src/stlplus/subsystems/library_manager.cpp deleted file mode 100644 index 0daf1be..0000000 --- a/src/stlplus/subsystems/library_manager.cpp +++ /dev/null @@ -1,2332 +0,0 @@ -//////////////////////////////////////////////////////////////////////////////// - -// Author: Andy Rushton -// Copyright: (c) Southampton University 1999-2004 -// (c) Andy Rushton 2004-2009 -// License: BSD License, see ../docs/license.html - -//////////////////////////////////////////////////////////////////////////////// -#include "library_manager.hpp" -#include "file_system.hpp" -#include -#include -#include - -//////////////////////////////////////////////////////////////////////////////// - -static const char* LibraryNameExtension = "lmn"; -static const char* HeaderExtension = "lmh"; - -//////////////////////////////////////////////////////////////////////////////// -// local operations -//////////////////////////////////////////////////////////////////////////////// - -typedef std::map lm_callback_map; - -static std::string lowercase(const std::string& val) -{ - std::string text = val; - for (unsigned i = 0; i < text.size(); i++) - text[i] = tolower(text[i]); - return text; -} - -// Context file and library operations -// These must be readable/writeable without a library data structure present -// so that the name of the library is known before creation - -static bool read_context(const std::string& path, const std::string& owner, std::string& name, bool& writable) -{ - std::string spec = stlplus::create_filespec(path, owner, LibraryNameExtension); - name = ""; - writable = false; - if (!stlplus::file_exists(spec)) return false; - std::ifstream input(spec.c_str()); - input >> name >> writable; - return !input.fail(); -} - -static bool write_context(const std::string& path, const std::string& owner, const std::string& name, bool writable) -{ - std::string spec = stlplus::create_filespec(path, owner, LibraryNameExtension); - std::ofstream output(spec.c_str()); - output << name << " " << writable << std::endl; - return !output.fail(); -} - -static bool create_library(const std::string& path, const std::string& owner, const std::string& name, bool writable) -{ - std::string spec = stlplus::create_filespec(path, owner, LibraryNameExtension); - if (stlplus::is_present(path) && !stlplus::is_folder(path)) return false; - if (!stlplus::folder_exists(path) && !stlplus::folder_create(path)) return false; - return write_context(path, owner, name, writable); -} - -static bool erase_library(const std::string& path, const std::string& owner) -{ - // check that it is a library before deleting it! - std::string spec = stlplus::create_filespec(path, owner, LibraryNameExtension); - if (!stlplus::file_exists(spec)) return false; - return stlplus::folder_delete(path, true); -} - -// dependency checking - -typedef std::map,stlplus::lm_dependencies> visited_map; - -static stlplus::lm_dependencies& out_of_date_check (visited_map& visited, - const stlplus::library_manager* manager, - const std::string& library, - const stlplus::lm_unit_name& name) -{ - // the visited field contains an entry if a unit has been visited - it also contains the reason for out-of-date-ness - // this is initially set empty (up to date) since the unit has to be added - // before it is checked just in case there is a recursive loop - // the dependencies field is filled in if the unit is subsequently found to be out of date - std::pair full_name = std::make_pair(library,name); - // first check whether this unit has already been visited - this should in - // principle never happen because the same test is performed before trying - // to recurse, so consider this to be paranoid-mode programming - visited_map::iterator found = visited.find(full_name); - if (found != visited.end()) - return found->second; - // now add this unit to prevent recursion loops later. This entry is added - // to when out-of-date dependencies are found and is also the return value - // of the function - visited[full_name] = stlplus::lm_dependencies(); - // now find the unit - const stlplus::lm_unit_ptr unit = manager->find(library,name); - if (!unit) - { - // if a unit is missing it fails with a dependency on itself - this is a - // bit of a work-around, but this again is paranoid-mode programming since - // the calling function (this function calling itself recursively) should - // check the unit's existence before recursing - visited[full_name].unit_add(stlplus::lm_unit_dependency(library,name)); - } - else - { - // we're onto the real checks now - first get the datestamp of this unit: - // all dependencies must be older than this - time_t unit_modified = unit->modified(); - // check dependency on source file if there is one - if (unit->source_file_present()) - { - std::string source_file = unit->source_file().path_full(unit->library_path()); - time_t source_modified = stlplus::file_modified(source_file); - if (source_modified == 0 || source_modified > unit_modified) - { - visited[full_name].set_source_file(unit->source_file()); - } - } - // now check the other file dependencies - for (unsigned i = 0; i < unit->file_size(); i++) - { - // a file dependency is a dependency on a file outside of the library system - const stlplus::lm_file_dependency& dependency = unit->file_dependency(i); - std::string file_full = dependency.path_full(unit->library_path()); - time_t source_modified = stlplus::file_modified(file_full); - if (source_modified == 0 || source_modified > unit_modified) - { - visited[full_name].file_add(dependency); - } - } - // now check and recurse on unit dependencies - for (unsigned j = 0; j < unit->unit_size(); j++) - { - const stlplus::lm_unit_dependency& dependency = unit->unit_dependency(j); - std::pair other_name = std::make_pair(dependency.library(), dependency.unit_name()); - // perform the datestamp checking at this level and only recurse if this does not detect an error - const stlplus::lm_unit_ptr other_unit = manager->find(other_name.first, other_name.second); - if (!other_unit) - { - visited[full_name].unit_add(dependency); - } - else - { - time_t other_modified = other_unit->modified(); - if (other_modified == 0 || other_modified > unit_modified) - { - visited[full_name].unit_add(dependency); - } - else - { - // prevent recursion before doing it - visited_map::iterator other_found = visited.find(other_name); - if (other_found != visited.end()) - { - // if the unit was found to be out of date on the previous visit, add it to the failed dependencies - if (!other_found->second.empty()) - { - visited[full_name].unit_add(dependency); - } - } - else - { - // the unit hasn't been visited before, so recurse on it now - stlplus::lm_dependencies other_dependencies = - out_of_date_check(visited, manager, other_name.first, other_name.second); - if (!other_dependencies.empty()) - { - visited[full_name].unit_add(dependency); - } - } - } - } - } - } - return visited[full_name]; -} - -//////////////////////////////////////////////////////////////////////////////// -// class lm_unit_name - -stlplus::lm_unit_name::lm_unit_name(const std::string& name, const std::string& type) : - m_name(name), m_type(type) -{ -} - -stlplus::lm_unit_name::~lm_unit_name(void) -{ -} - -const std::string& stlplus::lm_unit_name::name(void) const -{ - return m_name; -} - -void stlplus::lm_unit_name::set_name(const std::string& name) -{ - m_name = name; -} - -void stlplus::lm_unit_name::lowercase(void) -{ - m_name = ::lowercase(m_name); -} - -const std::string& stlplus::lm_unit_name::type(void) const -{ - return m_type; -} - -void stlplus::lm_unit_name::set_type(const std::string& type) -{ - m_type = type; -} - -bool stlplus::lm_unit_name::write(std::ostream& context) const -{ - context << m_name << " " << m_type; - return !context.fail(); -} - -bool stlplus::lm_unit_name::read(std::istream& context) -{ - context >> m_name >> m_type; - return !context.fail(); -} - -std::string stlplus::lm_unit_name::to_string(void) const -{ - return m_name + ":" + m_type; -} - -bool stlplus::lm_unit_name::print(std::ostream& str) const -{ - str << to_string(); - return !str.fail(); -} - -std::ostream& stlplus::operator << (std::ostream& str, const stlplus::lm_unit_name& name) -{ - name.print(str); - return str; -} - -bool stlplus::operator == (const stlplus::lm_unit_name& l, const stlplus::lm_unit_name& r) -{ - return l.name() == r.name() && l.type() == r.type(); -} - -bool stlplus::operator < (const stlplus::lm_unit_name& l, const stlplus::lm_unit_name& r) -{ - // sort by name then type - return (l.name() != r.name()) ? l.name() < r.name() : l.type() < r.type(); -} - -//////////////////////////////////////////////////////////////////////////////// -// dependencies - -// file dependencies - -stlplus::lm_file_dependency::lm_file_dependency(void) : m_line(0), m_column(0) -{ -} - -stlplus::lm_file_dependency::lm_file_dependency(const std::string& library_path, const std::string& path, unsigned line, unsigned column) -{ - set_path(library_path, path); - set_line(line); - set_column(column); -} - -stlplus::lm_file_dependency::~lm_file_dependency(void) -{ -} - -const std::string& stlplus::lm_file_dependency::path(void) const -{ - return m_path; -} - -std::string stlplus::lm_file_dependency::path_full(const std::string& library_path) const -{ - return filespec_to_path(library_path, m_path); -} - -void stlplus::lm_file_dependency::set_path(const std::string& library_path, const std::string& path) -{ - m_path = filespec_to_relative_path(library_path, path); -} - -unsigned stlplus::lm_file_dependency::line(void) const -{ - return m_line; -} - -void stlplus::lm_file_dependency::set_line(unsigned line) -{ - m_line = line; -} - -unsigned stlplus::lm_file_dependency::column(void) const -{ - return m_column; -} - -void stlplus::lm_file_dependency::set_column(unsigned column) -{ - m_column = column; -} - -bool stlplus::lm_file_dependency::write(std::ostream& context) const -{ - context << m_path << " " << m_line << " " << m_column; - return !context.fail(); -} - -bool stlplus::lm_file_dependency::read(std::istream& context) -{ - context >> m_path >> m_line >> m_column; - return !context.fail(); -} - -bool stlplus::lm_file_dependency::print(std::ostream& str) const -{ - str << "file: " << m_path; - if (m_line != 0) - str << ":" << m_line << ":" << m_column; - return !str.fail(); -} - -std::ostream& stlplus::operator << (std::ostream& str, const stlplus::lm_file_dependency& dependency) -{ - dependency.print(str); - return str; -} - -// unit dependency - -stlplus::lm_unit_dependency::lm_unit_dependency(void) -{ -} - -stlplus::lm_unit_dependency::lm_unit_dependency(const std::string& library, const lm_unit_name& name) : - m_library(library), m_name(name) -{ -} - -stlplus::lm_unit_dependency::~lm_unit_dependency(void) -{ -} - -const std::string& stlplus::lm_unit_dependency::library(void) const -{ - return m_library; -} - -void stlplus::lm_unit_dependency::set_library(const std::string& library) -{ - m_library = library; -} - -const stlplus::lm_unit_name& stlplus::lm_unit_dependency::unit_name(void) const -{ - return m_name; -} - -void stlplus::lm_unit_dependency::set_unit_name(const lm_unit_name& unit_name) -{ - m_name = unit_name; -} - -const std::string& stlplus::lm_unit_dependency::name(void) const -{ - return m_name.name(); -} - -void stlplus::lm_unit_dependency::set_name(const std::string& name) -{ - m_name.set_name(name); -} - -const std::string& stlplus::lm_unit_dependency::type(void) const -{ - return m_name.type(); -} - -void stlplus::lm_unit_dependency::set_type(const std::string& type) -{ - m_name.set_type(type); -} - -bool stlplus::lm_unit_dependency::write(std::ostream& context) const -{ - context << m_library; - m_name.write(context); - return !context.fail(); -} - -bool stlplus::lm_unit_dependency::read(std::istream& context) -{ - context >> m_library; - m_name.read(context);; - return !context.fail(); -} - -bool stlplus::lm_unit_dependency::print(std::ostream& str) const -{ - str << "unit: " << m_library << "." << m_name; - return !str.fail(); -} - -std::ostream& stlplus::operator << (std::ostream& str, const stlplus::lm_unit_dependency& dependency) -{ - dependency.print(str); - return str; -} - -// dependencies - -stlplus::lm_dependencies::lm_dependencies(void) : m_source(0) -{ -} - -stlplus::lm_dependencies::lm_dependencies(const lm_dependencies& r) : m_source(0) -{ - *this = r; -} - -stlplus::lm_dependencies& stlplus::lm_dependencies::operator=(const stlplus::lm_dependencies& r) -{ - if (m_source) - delete m_source; - m_source = 0; - if (r.m_source) - m_source = new lm_file_dependency(*r.m_source); - m_files = r.m_files; - m_units = r.m_units; - return *this; -} - -stlplus::lm_dependencies::~lm_dependencies(void) -{ - if (m_source) - delete m_source; -} - -void stlplus::lm_dependencies::set_source_file(const lm_file_dependency& source) -{ - if (m_source) - delete m_source; - m_source = new lm_file_dependency(source); -} - -bool stlplus::lm_dependencies::source_file_present(void) const -{ - return (m_source != 0); -} - -const stlplus::lm_file_dependency& stlplus::lm_dependencies::source_file(void) const -{ - return *m_source; -} - -unsigned stlplus::lm_dependencies::file_add(const lm_file_dependency& dependency) -{ - m_files.push_back(dependency); - return m_files.size()-1; -} - -unsigned stlplus::lm_dependencies::file_size(void) const -{ - return m_files.size(); -} - -const stlplus::lm_file_dependency& stlplus::lm_dependencies::file_dependency(unsigned i) const -{ - return m_files[i]; -} - -void stlplus::lm_dependencies::file_erase(unsigned i) -{ - m_files.erase(m_files.begin()+i); -} - -unsigned stlplus::lm_dependencies::unit_add(const lm_unit_dependency& dependency) -{ - m_units.push_back(dependency); - return m_units.size()-1; -} - -unsigned stlplus::lm_dependencies::unit_size(void) const -{ - return m_units.size(); -} - -const stlplus::lm_unit_dependency& stlplus::lm_dependencies::unit_dependency(unsigned i) const -{ - return m_units[i]; -} - -void stlplus::lm_dependencies::unit_erase(unsigned i) -{ - m_units.erase(m_units.begin()+i); -} - -void stlplus::lm_dependencies::clear(void) -{ - if (m_source) - delete m_source; - m_source = 0; - m_files.clear(); - m_units.clear(); -} - -bool stlplus::lm_dependencies::empty(void) const -{ - return (m_source == 0) && m_files.empty() && m_units.empty(); -} - -bool stlplus::lm_dependencies::write(std::ostream& context) const -{ - context << (m_source ? true : false) << " "; - if (m_source) m_source->write(context); - context << std::endl; - context << m_files.size() << std::endl; - for (unsigned i = 0; i < m_files.size(); i++) - { - m_files[i].write(context); - context << std::endl; - } - context << m_units.size() << std::endl; - for (unsigned j = 0; j < m_units.size(); j++) - { - m_units[j].write(context); - context << std::endl; - } - return !context.fail(); -} - -bool stlplus::lm_dependencies::read(std::istream& context) -{ - clear(); - bool source_present = false; - context >> source_present; - if (source_present) - { - m_source = new lm_file_dependency(); - m_source->read(context); - } - unsigned files_size = 0; - context >> files_size; - for (unsigned i = 0; i < files_size; i++) - { - m_files.push_back(lm_file_dependency()); - m_files.back().read(context); - } - unsigned units_size = 0; - context >> units_size; - for (unsigned j = 0; j < units_size; j++) - { - m_units.push_back(lm_unit_dependency()); - m_units.back().read(context); - } - return !context.fail(); -} - -bool stlplus::lm_dependencies::print(std::ostream& str) const -{ - if (m_source) - str << " source file: " << *m_source << std::endl; - for (unsigned i = 0; i < m_files.size(); i++) - str << " " << m_files[i] << std::endl; - for (unsigned j = 0; j < m_units.size(); j++) - str << " " << m_units[j] << std::endl; - return !str.fail(); -} - -std::ostream& stlplus::operator << (std::ostream& str, const stlplus::lm_dependencies& dependencies) -{ - dependencies.print(str); - return str; -} - -//////////////////////////////////////////////////////////////////////////////// -// lm_unit -//////////////////////////////////////////////////////////////////////////////// - -stlplus::lm_unit::lm_unit(const lm_unit_name& name, lm_library* library) : - m_name(name), m_header_modified(false), m_loaded(false), m_marked(false), m_library(library), m_error(false) -{ - read_header(); -} - -stlplus::lm_unit::~lm_unit(void) -{ - write_header(); -} - -//////////////////////////////////////// -// Header data - -const stlplus::lm_unit_name& stlplus::lm_unit::unit_name(void) const -{ - return m_name; -} - -const std::string& stlplus::lm_unit::name(void) const -{ - return m_name.name(); -} - -const std::string& stlplus::lm_unit::type(void) const -{ - return m_name.type(); -} - -// dependencies - -// source file dependency - -void stlplus::lm_unit::set_source_file(const lm_file_dependency& dependency) -{ - m_header_modified = true; - m_dependencies.set_source_file(dependency); -} - -bool stlplus::lm_unit::source_file_present(void) const -{ - return m_dependencies.source_file_present(); -} - -const stlplus::lm_file_dependency& stlplus::lm_unit::source_file(void) const -{ - return m_dependencies.source_file(); -} - -// other file dependencies - -unsigned stlplus::lm_unit::file_add(const lm_file_dependency& dependency) -{ - m_header_modified = true; - return m_dependencies.file_add(dependency); -} - -unsigned stlplus::lm_unit::file_size(void) const -{ - return m_dependencies.file_size(); -} - -const stlplus::lm_file_dependency& stlplus::lm_unit::file_dependency(unsigned i) const -{ - return m_dependencies.file_dependency(i); -} - -void stlplus::lm_unit::file_erase(unsigned i) -{ - m_header_modified = true; - m_dependencies.file_erase(i); -} - -// unit dependencies - -unsigned stlplus::lm_unit::unit_add(const lm_unit_dependency& dependency) -{ - m_header_modified = true; - return m_dependencies.unit_add(dependency); -} - -unsigned stlplus::lm_unit::unit_size(void) const -{ - return m_dependencies.unit_size(); -} - -const stlplus::lm_unit_dependency& stlplus::lm_unit::unit_dependency(unsigned i) const -{ - return m_dependencies.unit_dependency(i); -} - -void stlplus::lm_unit::unit_erase(unsigned i) -{ - m_header_modified = true; - m_dependencies.unit_erase(i); -} - -const stlplus::lm_dependencies& stlplus::lm_unit::dependencies(void) const -{ - return m_dependencies; -} - -void stlplus::lm_unit::set_dependencies(const lm_dependencies& dependencies) -{ - m_header_modified = true; - m_dependencies = dependencies; -} - -void stlplus::lm_unit::clear_dependencies(void) -{ - m_header_modified = true; - m_dependencies.clear(); -} - -bool stlplus::lm_unit::empty_dependencies(void) const -{ - return m_dependencies.empty(); -} - -// dependency checking - -bool stlplus::lm_unit::out_of_date(void) const -{ - return m_library->out_of_date(m_name); -} - -bool stlplus::lm_unit::up_to_date(void) const -{ - return m_library->up_to_date(m_name); -} - -stlplus::lm_dependencies stlplus::lm_unit::out_of_date_reason(void) const -{ - return m_library->out_of_date_reason(m_name); -} - -// supplementary data - -const std::string& stlplus::lm_unit::supplementary_data(void) const -{ - return m_supplement; -} - -void stlplus::lm_unit::set_supplementary_data(const std::string& data) -{ - m_supplement = data; - m_header_modified = true; -} - -//////////////////////////////////////// -// unit data management - -bool stlplus::lm_unit::load(void) -{ - if (out_of_date()) return false; - if (m_loaded) return true; - // get the user data for this type - lm_callback_map::iterator callback = m_library->m_manager->m_callbacks.find(type()); - if (callback == m_library->m_manager->m_callbacks.end()) return false; - void* data = callback->second.m_type_data; - bool result = read(filename(), data); - m_loaded = true; - return result; -} - -bool stlplus::lm_unit::save(void) -{ - if (!m_marked) return true; - if (!m_loaded) return false; - // get the user data for this type - lm_callback_map::iterator callback = m_library->m_manager->m_callbacks.find(type()); - if (callback == m_library->m_manager->m_callbacks.end()) return false; - void* data = callback->second.m_type_data; - bool result = write(filename(), data); - if (result) m_marked = false; - return result; -} - -bool stlplus::lm_unit::loaded(void) const -{ - return m_loaded; -} - -void stlplus::lm_unit::mark(void) -{ - m_marked = true; -} - -time_t stlplus::lm_unit::modified(void) const -{ - return file_modified(filename()); -} - -//////////////////////////////////////// -// containing library manager details - -const stlplus::lm_library* stlplus::lm_unit::library(void) const -{ - return m_library; -} - -stlplus::lm_library* stlplus::lm_unit::library(void) -{ - return m_library; -} - -const std::string& stlplus::lm_unit::library_name(void) const -{ - return m_library->name(); -} - -const std::string& stlplus::lm_unit::library_path(void) const -{ - return m_library->path(); -} - -// error handling - these apply to the last read/write operation - -bool stlplus::lm_unit::error(void) const -{ - return m_error; -} - -// functions that customise subclasses of this superclass - -bool stlplus::lm_unit::read(const std::string& filespec, void* type_data) -{ - std::ifstream input(filespec.c_str()); - bool result = read(input, type_data); - if (input.fail()) - { - result = false; - m_error = true; - } - return result; -} - -bool stlplus::lm_unit::read(std::istream&, void*) -{ - return false; -} - -bool stlplus::lm_unit::write(const std::string& filespec, void* type_data) -{ - std::ofstream output(filespec.c_str()); - bool result = write(output, type_data); - if (output.fail()) - { - result = false; - m_error = true; - } - return result; -} - -bool stlplus::lm_unit::write(std::ostream&, void*) -{ - return false; -} - -bool stlplus::lm_unit::purge(void) -{ - return true; -} - -stlplus::lm_unit* stlplus::lm_unit::clone(void) const -{ - return new lm_unit(*this); -} - -bool stlplus::lm_unit::print(std::ostream& str) const -{ - str << m_name << " " << (m_loaded ? "loaded" : "") << " " << (m_marked ? "needs saving" : ""); - return !str.fail(); -} - -bool stlplus::lm_unit::print_long(std::ostream& str) const -{ - str << "header:" << std::endl; - str << " name: " << m_name.name() << std::endl; - str << " type: " << library()->manager()->description(m_name.type()) << std::endl; - str << " dependencies:" << std::endl; - // Note: I've inlined this rather than call the above-defined print for dependencies - // This is so that I can use the library manager to look up the descriptions of unit types - // I can also convert paths so that they are relative to the current directory rather than the library - // print the source file dependency if present - if (m_dependencies.source_file_present()) - { - str << " source file: "; - str << filespec_to_relative_path(m_dependencies.source_file().path_full(library()->path())); - if (m_dependencies.source_file().line() != 0) - str << ":" << m_dependencies.source_file().line() << ":" << m_dependencies.source_file().column(); - str << std::endl; - } - // now print other file dependencies - // convert these to relative paths too - for (unsigned f = 0; f < m_dependencies.file_size(); f++) - { - str << " file: "; - str << filespec_to_relative_path(m_dependencies.file_dependency(f).path_full(library()->path())); - if (m_dependencies.file_dependency(f).line() != 0) - str << ":" << m_dependencies.file_dependency(f).line() << ":" << m_dependencies.file_dependency(f).column(); - str << std::endl; - } - // now print unit dependencies - // convert unit types to their descriptive strings - for (unsigned u = 0; u < m_dependencies.unit_size(); u++) - { - str << " " << library()->manager()->description(m_dependencies.unit_dependency(u).type()) << ": "; - str << m_dependencies.unit_dependency(u).library() << "." << m_dependencies.unit_dependency(u).name(); - str << std::endl; - } - if (!m_supplement.empty()) - { - str << " supplementary data: " << m_supplement << std::endl; - } - return !str.fail(); -} - -// header file management - -std::string stlplus::lm_unit::filename(void) const -{ - return stlplus::create_filespec(library_path(), m_name.name(), m_name.type()); -} - -std::string stlplus::lm_unit::header_filename(void) const -{ - return stlplus::create_filespec(library_path(), m_name.name(), m_name.type() + std::string(HeaderExtension)); -} - -bool stlplus::lm_unit::read_header(void) -{ - if (file_exists(header_filename())) - { - std::ifstream input(header_filename().c_str()); - m_dependencies.read(input); - input.get(); - std::getline(input, m_supplement); - } - m_header_modified = false; - return true; -} - -bool stlplus::lm_unit::write_header(void) -{ - if (!m_header_modified) return true; - std::ofstream output(header_filename().c_str()); - m_dependencies.write(output); - output << m_supplement << std::endl; - m_header_modified = false; - return true; -} - -// print diagnostics - -std::ostream& stlplus::operator << (std::ostream& str, const stlplus::lm_unit& u) -{ - u.print(str); - return str; -} - -//////////////////////////////////////////////////////////////////////////////// -// lm_library -//////////////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////////////// -// constructors/destructors -// copy operations only legal on unopened libraries - -stlplus::lm_library::lm_library(library_manager* manager) : m_writable(false), m_manager(manager) -{ -} - -stlplus::lm_library::lm_library(const lm_library& library) : m_writable(library.m_writable), m_manager(library.m_manager) -{ -} - -stlplus::lm_library& stlplus::lm_library::operator = (const stlplus::lm_library& library) -{ - m_writable = library.m_writable; - m_manager = library.m_manager; - return *this; -} - -stlplus::lm_library::~lm_library(void) -{ - close(); -} - -const stlplus::library_manager* stlplus::lm_library::manager(void) const -{ - return m_manager; -} - -stlplus::library_manager* stlplus::lm_library::manager(void) -{ - return m_manager; -} - -////////////////////////////////////////////////////////////////////////////// -// initialisers - -bool stlplus::lm_library::create(const std::string& name, const std::string& path, bool writable) -{ - close(); - if (!create_library(path, m_manager->m_owner, name, writable)) return false; - return open(path); -} - -bool stlplus::lm_library::open(const std::string& path) -{ - close(); - if (!read_context(path, m_manager->m_owner, m_name, m_writable)) return false; - // convert path to full path on load - m_path = folder_to_path(path); - return load_types(); -} - -////////////////////////////////////////////////////////////////////////////// -// management of types - -bool stlplus::lm_library::load_type(const std::string& type) -{ - lm_callback_map::iterator callback = m_manager->m_callbacks.find(type); - if (callback == m_manager->m_callbacks.end()) return false; - // a null callback means create a dummy unit from the baseclass only - lm_create_callback fn = callback->second.m_callback; - void* data = callback->second.m_type_data; - // for each file in the library folder that matches the type of the create callback, create an unloaded unit - std::vector files = folder_wildcard(m_path, stlplus::create_filename("*", type), false, true); - for (unsigned i = 0; i < files.size(); i++) - { - // key by unit name - lowercase name if case-insensitive - lm_unit_name uname(basename_part(files[i]),type); - if (!m_manager->m_unit_case) uname.lowercase(); - lm_unit_ptr unit; - // if there's a callback, use it to create the subclass, else create the - // superclass which only contains header information - if (fn) - unit.set(fn(uname,this,data)); - else - unit.set(new lm_unit(uname,this)); - m_units[uname] = unit; - } - return true; -} - -bool stlplus::lm_library::load_types(void) -{ - bool result = true; - for (lm_callback_map::const_iterator i = m_manager->m_callbacks.begin(); i != m_manager->m_callbacks.end(); i++) - result &= load_type(i->first); - return result; -} - -bool stlplus::lm_library::remove_type(const std::string& type) -{ - bool result = true; - std::vector units = names(type); - for (std::vector::iterator i = units.begin(); i != units.end(); i++) - { - lm_unit_name name(*i, type); - std::map::iterator ni = local_find(name); - if (ni != m_units.end()) - m_units.erase(ni); - } - return result; -} - -////////////////////////////////////////////////////////////////////////////// -// whole library operations - -bool stlplus::lm_library::load(void) -{ - bool result = true; - for (std::map::iterator i = m_units.begin(); i != m_units.end(); i++) - result &= i->second->load(); - return result; -} - -bool stlplus::lm_library::save(void) -{ - bool result = true; - for (std::map::iterator i = m_units.begin(); i != m_units.end(); i++) - result &= i->second->save(); - return result; -} - -bool stlplus::lm_library::purge(void) -{ - bool result = true; - for (std::map::iterator i = m_units.begin(); i != m_units.end(); i++) - result &= i->second->purge(); - return result; -} - -bool stlplus::lm_library::close(void) -{ - bool result = save(); - m_units.clear(); - m_path = ""; - m_writable = false; - return result; -} - -bool stlplus::lm_library::erase(void) -{ - // preserve the path because close destroys it - std::string path = m_path; - return close() && erase_library(path, m_manager->m_owner); -} - -const std::string& stlplus::lm_library::name(void) const -{ - return m_name; -} - -const std::string& stlplus::lm_library::path(void) const -{ - return m_path; -} - -////////////////////////////////////////////////////////////////////////////// -// managing read/write status - -bool stlplus::lm_library::set_read_write(bool writable) -{ - if (m_writable == writable) return true; - if (os_read_only()) return false; - m_writable = writable; - if (!write_context(m_path, m_manager->m_owner, m_name, m_writable)) - read_context(m_path, m_manager->m_owner, m_name, m_writable); - return m_writable == writable; -} - -bool stlplus::lm_library::set_writable(void) -{ - return set_read_write(true); -} - -bool stlplus::lm_library::set_read_only(void) -{ - return set_read_write(false); -} - -bool stlplus::lm_library::writable(void) const -{ - return os_writable() && lm_writable(); -} - -bool stlplus::lm_library::read_only(void) const -{ - return os_read_only() || lm_read_only(); -} - -bool stlplus::lm_library::os_writable(void) const -{ - return folder_writable(path()); -} - -bool stlplus::lm_library::os_read_only(void) const -{ - return !folder_writable(path()); -} - -bool stlplus::lm_library::lm_writable(void) const -{ - return m_writable; -} - -bool stlplus::lm_library::lm_read_only(void) const -{ - return !m_writable; -} - -////////////////////////////////////////////////////////////////////////////// -// unit management - -std::map::iterator stlplus::lm_library::local_find(const lm_unit_name& name) -{ - // implement the case-sensitivity - lm_unit_name local = name; - if (!m_manager->m_unit_case) local.lowercase(); - return m_units.find(local); -} - -std::map::const_iterator stlplus::lm_library::local_find(const lm_unit_name& name) const -{ - // implement the case-sensitivity - lm_unit_name local = name; - if (!m_manager->m_unit_case) local.set_name(lowercase(local.name())); - return m_units.find(local); -} - -bool stlplus::lm_library::exists(const lm_unit_name& name) const -{ - return find(name).present(); -} - -stlplus::lm_unit_ptr stlplus::lm_library::create(const stlplus::lm_unit_name& name) -{ - if (read_only()) return lm_unit_ptr(); - // preserve the unit's name, but use a lowercase key in case-insensitive mode - lm_unit_name uname = name; - if (!m_manager->m_unit_case) uname.lowercase(); - // remove any existing unit with the same name - erase(uname); - // use the callbacks to create a new unit - lm_callback_map::iterator callback = m_manager->m_callbacks.find(name.type()); - if (callback == m_manager->m_callbacks.end()) return lm_unit_ptr(); - lm_unit_ptr new_unit; - new_unit.set(callback->second.m_callback(name,this,callback->second.m_type_data)); - new_unit->m_loaded = true; - // add it to the library manager - m_units[uname] = new_unit; - return m_units[uname]; -} - -bool stlplus::lm_library::loaded(const lm_unit_name& name) const -{ - lm_unit_ptr unit = find(name); - return unit && unit->loaded(); -} - -bool stlplus::lm_library::load(const lm_unit_name& name) -{ - lm_unit_ptr unit = find(name); - if (!unit) return false; - return unit->load(); -} - -bool stlplus::lm_library::purge(const lm_unit_name& name) -{ - lm_unit_ptr unit = find(name); - if (!unit) return false; - bool result = save(name); - result &= unit->purge(); - unit->m_loaded = false; - return result; -} - -bool stlplus::lm_library::save(const lm_unit_name& name) -{ - if (read_only()) return false; - lm_unit_ptr unit = find(name); - if (!unit) return false; - return unit->save(); -} - -bool stlplus::lm_library::erase(const lm_unit_name& name) -{ - if (read_only()) return false; - std::map::iterator i = local_find(name); - if (i == m_units.end()) return false; - std::string spec = i->second->filename(); - std::string header_spec = i->second->header_filename(); - m_units.erase(i); - file_delete(spec); - file_delete(header_spec); - return true; -} - -bool stlplus::lm_library::mark(const lm_unit_name& name) -{ - if (read_only()) return false; - lm_unit_ptr unit = find(name); - if (!unit) return false; - unit->mark(); - return true; -} - -time_t stlplus::lm_library::modified(const lm_unit_name& name) const -{ - lm_unit_ptr unit = find(name); - return unit ? unit->modified() : 0; -} - -bool stlplus::lm_library::erase_by_source(const std::string& source_file) -{ - if (read_only()) return false; - if (source_file.empty()) return false; - bool result = false; - std::string source_file_full = filespec_to_path(source_file); - // erase by unit name so that I don't have to deal with an iterator to a changing map - std::vector units = names(); - for (std::vector::iterator i = units.begin(); i != units.end(); i++) - { - lm_unit_ptr unit = find(*i); - if (unit && unit->source_file_present()) - { - std::string file_full = unit->source_file().path_full(unit->library_path()); - if (file_full == source_file_full) - { - erase(*i); - result = true; - } - } - } - return result; -} - -const stlplus::lm_unit_ptr stlplus::lm_library::find(const stlplus::lm_unit_name& name) const -{ - std::map::const_iterator i = local_find(name); - if (i == m_units.end()) return lm_unit_ptr(); - return i->second; -} - -stlplus::lm_unit_ptr stlplus::lm_library::find(const stlplus::lm_unit_name& name) -{ - std::map::iterator i = local_find(name); - if (i == m_units.end()) return lm_unit_ptr(); - return i->second; -} - -std::vector stlplus::lm_library::names(void) const -{ - std::vector result; - for (std::map::const_iterator i = m_units.begin(); i != m_units.end(); i++) - result.push_back(i->second->unit_name()); - return result; -} - -std::vector stlplus::lm_library::names(const std::string& type) const -{ - std::vector result; - for (std::map::const_iterator i = m_units.begin(); i != m_units.end(); i++) - if (i->first.type() == type) - result.push_back(i->second->name()); - return result; -} - -std::vector stlplus::lm_library::handles(void) const -{ - std::vector result; - for (std::map::const_iterator i = m_units.begin(); i != m_units.end(); i++) - result.push_back(i->second); - return result; -} - -std::vector stlplus::lm_library::handles(const std::string& type) const -{ - std::vector result; - for (std::map::const_iterator i = m_units.begin(); i != m_units.end(); i++) - if (i->first.type() == type) - result.push_back(i->second); - return result; -} - -//////////////////////////////////////////////////////////////////////////////// -// dependency checking - -bool stlplus::lm_library::out_of_date(const stlplus::lm_unit_name& name) const -{ - return m_manager->out_of_date(m_name, name); -} - -bool stlplus::lm_library::up_to_date(const stlplus::lm_unit_name& name) const -{ - return m_manager->up_to_date(m_name, name); -} - -stlplus::lm_dependencies stlplus::lm_library::out_of_date_reason(const stlplus::lm_unit_name& unit) const -{ - return m_manager->out_of_date_reason(m_name, unit); -} - -std::pair stlplus::lm_library::tidy(void) -{ - std::pair result = std::make_pair(true,0); - // erase every unit that is out of date - // this will potentially make other units out of date, so keep erasing until - // everything is up to date or an error occurs - for (;;) - { - std::vector units = names(); - unsigned initial_count = result.second; - for (std::vector::iterator i = units.begin(); i != units.end(); i++) - { - if (out_of_date(*i)) - { - if (!erase(*i)) - result.first = false; - else - result.second++; - } - } - if (!result.first) break; - if (result.second == initial_count) break; - } - return result; -} - -//////////////////////////////////////////////////////////////////////////////// -// do-everything print routine! - -bool stlplus::lm_library::pretty_print(std::ostream& str, - bool print_units, - const std::string& type) const -{ - // print the library information - if (this == m_manager->work()) - str << "->> "; - else - str << " "; - str << name() << " in directory " << folder_to_relative_path(path()); - if (read_only()) str << " (locked)"; - str << std::endl; - // select the units - if (print_units) - { - // separate into a block per unit kind - for (lm_callback_map::const_iterator j = m_manager->m_callbacks.begin(); j != m_manager->m_callbacks.end(); j++) - { - // select the requested unit kind - if (type.empty() || type == j->first) - { - // get all the units of this kind - std::vector unit_names = names(j->first); - if (!unit_names.empty()) - { - str << " " << j->second.m_description << std::endl; - for (unsigned k = 0; k < unit_names.size(); k++) - { - lm_dependencies reason = out_of_date_reason(stlplus::lm_unit_name(unit_names[k],j->first)); - str << " - " << unit_names[k]; - if (!reason.empty()) str << " (out of date)"; - str << std::endl; - if (!reason.empty()) - { - if (reason.source_file_present()) - { - const lm_file_dependency& file = reason.source_file(); - str << " * source file " << filespec_to_relative_path(file.path_full(path())) << " has changed" << std::endl; - } - for (unsigned i1 = 0; i1 < reason.file_size(); i1++) - { - const lm_file_dependency& file = reason.file_dependency(i1); - str << " * file " << filespec_to_relative_path(file.path_full(path())) << " has changed" << std::endl; - } - for (unsigned i2 = 0; i2 < reason.unit_size(); i2++) - { - const lm_unit_dependency& file = reason.unit_dependency(i2); - lm_callback_map::const_iterator entry = m_manager->m_callbacks.find(file.type()); - str << " * " << entry->second.m_description << " " << file.library() << "." << file.name() << " has changed" << std::endl; - } - } - } - } - } - } - } - return true; -} - -//////////////////////////////////////////////////////////////////////////////// -// diagnostic print routines - -bool stlplus::lm_library::print(std::ostream& str) const -{ - str << name() << " in " << path() << " " << (writable() ? "writable" : "read-only") << std::endl; - for (std::map::const_iterator i = m_units.begin(); i != m_units.end(); i++) - i->second->print(str); - return !str.fail(); -} - -bool stlplus::lm_library::print_long(std::ostream& str) const -{ - str << name() << " in " << path() << " " << (writable() ? "writable" : "read-only") << std::endl; - for (std::map::const_iterator i = m_units.begin(); i != m_units.end(); i++) - i->second->print_long(str); - return !str.fail(); -} - -std::ostream& stlplus::operator << (std::ostream& str, const stlplus::lm_library& lib) -{ - lib.print(str); - return str; -} - -//////////////////////////////////////////////////////////////////////////////// -// library manager -//////////////////////////////////////////////////////////////////////////////// - -// 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 - -bool stlplus::library_manager::is_library(const std::string& path, const std::string& owner) -{ - std::string spec = stlplus::create_filespec(path, owner, LibraryNameExtension); - return file_exists(spec); -} - -std::string stlplus::library_manager::library_name(const std::string& path, const std::string& owner) -{ - std::string name; - bool writable = false; - if (!read_context(path, owner, name, writable)) - return std::string(); - return name; -} - -bool stlplus::library_manager::is_library(const std::string& path) -{ - return is_library(path, m_owner); -} - -std::string stlplus::library_manager::library_name(const std::string& path) -{ - return library_name(path, m_owner); -} - -////////////////////////////////////////////////////////////////////////////// -// tructors - -stlplus::library_manager::library_manager(const std::string& owner, bool library_case, bool unit_case) : - m_owner(owner), m_ini_files(0), m_library_case(library_case), m_unit_case(unit_case) -{ -} - -stlplus::library_manager::~library_manager(void) -{ - close(); -} - -////////////////////////////////////////////////////////////////////////////// -// case sensitivity - -bool stlplus::library_manager::library_case(void) const -{ - return m_library_case; -} - -void stlplus::library_manager::set_library_case(bool library_case) -{ - m_library_case = library_case; -} - -bool stlplus::library_manager::unit_case(void) const -{ - return m_unit_case; -} - -void stlplus::library_manager::set_unit_case(bool unit_case) -{ - m_unit_case = unit_case; -} - -//////////////////////////////////////////////////////////////////////////////// -// type handling - -bool stlplus::library_manager::add_type(const std::string& type, - const std::string& description, - lm_create_callback fn, - void* type_data) -{ - bool result = true; - m_callbacks[type] = lm_callback_entry(fn, description, type_data); - for (std::list::iterator i = m_libraries.begin(); i != m_libraries.end(); i++) - result &= i->load_type(type); - return result; -} - -bool stlplus::library_manager::remove_type(const std::string& type) -{ - bool result = true; - for (std::list::iterator i = m_libraries.begin(); i != m_libraries.end(); i++) - result &= i->remove_type(type); - m_callbacks.erase(type); - return result; -} - -std::vector stlplus::library_manager::types(void) const -{ - std::vector result; - for (lm_callback_map::const_iterator i = m_callbacks.begin(); i != m_callbacks.end(); i++) - result.push_back(i->first); - return result; -} - -std::string stlplus::library_manager::description(const std::string& type) const -{ - lm_callback_map::const_iterator found = m_callbacks.find(type); - if (found == m_callbacks.end()) return std::string(); - return found->second.m_description; -} - -stlplus::lm_create_callback stlplus::library_manager::callback(const std::string& type) const -{ - lm_callback_map::const_iterator found = m_callbacks.find(type); - if (found == m_callbacks.end()) return 0; - return found->second.m_callback; -} - -void* stlplus::library_manager::type_data(const std::string& type) const -{ - lm_callback_map::const_iterator found = m_callbacks.find(type); - if (found == m_callbacks.end()) return 0; - return found->second.m_type_data; -} - -////////////////////////////////////////////////////////////////////////////// -// mapping file handling - -void stlplus::library_manager::set_mapping_file(const std::string& mapping_file) -{ - m_mapping_file = mapping_file; -} - -bool stlplus::library_manager::load_mappings(const std::string& mapping_file) -{ - m_mapping_file = mapping_file; - if (!file_exists(mapping_file)) - { - return false; - } - std::ifstream input(mapping_file.c_str()); - if (input.fail()) - return false; - // each line of the map file is a path to a library - // the first line is the work library - may be empty - // mappings are saved as paths relative to the mapping file and converted to full paths on load - bool result = true; - unsigned line = 1; - for (std::string path = ""; std::getline(input,path); line++) - { - if (path.empty()) continue; - std::string full_path = folder_to_path(folder_part(m_mapping_file), path); - if (!is_library(full_path)) - { - result = false; - } - else - { - lm_library* lib = open(full_path); - if (!lib) - result = false; - else if (line == 1) - setwork(lib->name()); - } - } - return result; -} - -std::string stlplus::library_manager::mapping_file() -{ - return m_mapping_file; -} - -bool stlplus::library_manager::set_ini_manager(ini_manager* ini_files, const std::string& library_section, const std::string& work_name) -{ - if (!ini_files) return false; - bool result = true; - m_ini_files = ini_files; - m_ini_section = library_section; - m_ini_work = work_name; - // now load the existing library mappings if present - in any case create the sections - // Note: a library mapping is saved as a path relative to the ini file - on load convert it to a path relative to the current directory - if (m_ini_files->section_exists(m_ini_section)) - { - std::vector library_names = m_ini_files->variable_names(m_ini_section); - std::string work_name; - for (unsigned i = 0; i < library_names.size(); i++) - { - std::string library_name = library_names[i]; - // if the variable name is the work name, then this is a mapping to an existing library name - // if it is null, then it is masking a global library definition so ignore it - // otherwise it is a mapping to a directory containing the library - if (library_name.empty()) - { - } - else if (library_name == m_ini_work) - { - work_name = m_ini_files->variable_value(m_ini_section, library_name); - } - else - { - std::string value = m_ini_files->variable_value(m_ini_section, library_name); - std::string filename = m_ini_files->variable_filename(m_ini_section, library_name); - // get the path to the ini file defining this library, strip off the ini filename to get the folder - // then combine this with the library path from that ini file to the library to get a full path to the library - // whew! - std::string full_path = folder_to_path(folder_part(filename),value); - if (!is_library(full_path)) - result = false; - else - { - lm_library* lib = open(full_path); - if (!lib) - result = false; - } - } - } - // work must be set after all the libraries have been opened because it is - // illegal to set work to a library that doesn't already exist in the - // library manager - if (work_name.empty()) - unsetwork(); - else - result &= setwork(work_name); - } - return result; -} - -stlplus::ini_manager* stlplus::library_manager::get_ini_manager(void) const -{ - return m_ini_files; -} - -bool stlplus::library_manager::save_mappings (void) -{ - bool result = true; - // save to mapping file or ini manager or both - if (!m_mapping_file.empty()) - { - if (m_libraries.size() == 0) - { - // if the file would be empty, delete it - if (!file_delete(m_mapping_file)) - result = false; - } - else - { - std::ofstream output(m_mapping_file.c_str()); - if (output.fail()) - { - result = false; - } - else - { - // each line of the map file is a path to a library - // the first line is the work library - // mappings are saved as relative paths to the mapping file and converted to full paths on load - if (!work_name().empty()) - output << folder_to_relative_path(folder_part(m_mapping_file), path(work_name())); - output << std::endl; - std::vector libraries = names(); - for (unsigned i = 0; i < libraries.size(); ++i) - { - if (libraries[i] != work_name()) - output << folder_to_relative_path(folder_part(m_mapping_file), path(libraries[i])) << std::endl; - } - if (output.fail()) - result = false; - } - } - } - if (m_ini_files) - { - // this is somewhat tricky! - // first remove all local mappings - // then need to compare the surviving library mappings with the contents of the library manager - // if there's a library in the ini files not in the library manager, mask it with an empty local declaration - // if there's a library in the ini files with the same mapping as the library manager, do nothing - // if there's a library in the ini files with a different mapping write that library mapping - // if there's a mapping missing from the ini files, write it - // finally write the work mapping if there is one - // clear all local mappings - // TODO - rework this so that the ini files only change if the mappings change - m_ini_files->clear_section(m_ini_section); - m_ini_files->add_comment(m_ini_section, "generated automatically by the library manager"); - // look for globally defined library mappings that need to be overridden in the local ini file - std::vector ini_names = m_ini_files->variable_names(m_ini_section); - for (unsigned i = 0; i < ini_names.size(); i++) - { - std::string ini_name = ini_names[i]; - // check for a global library that needs to be locally masked - if (!exists(ini_name)) - m_ini_files->add_variable(m_ini_section, ini_name, ""); - else - { - // check for a library that is locally remapped - std::string value = m_ini_files->variable_value(m_ini_section, ini_name); - std::string filename = m_ini_files->variable_filename(m_ini_section, ini_name); - std::string full_ini_path = folder_to_path(folder_part(filename), value); - std::string full_lib_path = folder_to_path(path(ini_name)); - if (full_ini_path != full_lib_path) - { - // write the path relative to the ini file - std::string relative_path = folder_to_relative_path(folder_part(filename), full_lib_path); - m_ini_files->add_variable(m_ini_section, ini_name, relative_path); - } - } - } - // now scan the library for mappings that aren't yet in the ini file - std::vector lib_names = names(); - for (unsigned j = 0; j < lib_names.size(); j++) - { - std::string lib_name = lib_names[j]; - if (std::find(ini_names.begin(), ini_names.end(), lib_name) == ini_names.end()) - { - // write the path relative to the ini file - std::string full_lib_path = folder_to_path(path(lib_name)); - std::string filename = m_ini_files->variable_filename(m_ini_section, lib_name); - std::string relative_path = folder_to_relative_path(folder_part(filename), full_lib_path); - m_ini_files->add_variable(m_ini_section, lib_name, relative_path); - } - } - // write the work library - also write a blank value if work is not set but is defined in another library - if (!work_name().empty()) - m_ini_files->add_variable(m_ini_section, m_ini_work, work_name()); - else if (m_ini_files->variable_exists(m_ini_section, m_ini_work)) - m_ini_files->add_variable(m_ini_section, m_ini_work, ""); - m_ini_files->add_blank(m_ini_section); - // remove the section from the ini file manager if there's nothing in it - if (m_ini_files->empty_section(m_ini_section)) - m_ini_files->erase_section(m_ini_section); - if (!m_ini_files->save()) - result = false; - } - return result; -} - -////////////////////////////////////////////////////////////////////////////// -// library management - -bool stlplus::library_manager::exists(const std::string& name) const -{ - return find(name) != 0; -} - -stlplus::lm_library* stlplus::library_manager::create(const std::string& name, const std::string& path, bool writable) -{ - if (!create_library(path, m_owner, name, writable)) return 0; - return open(path); -} - -stlplus::lm_library* stlplus::library_manager::open(const std::string& path) -{ - std::string name; - bool writable = false; - if (!read_context(path, m_owner, name, writable)) return 0; - // remove any pre-existing library with the same name - close(name); - // add the library to the manager and open it - m_libraries.push_back(lm_library(this)); - if (!m_libraries.back().open(folder_to_path(path))) - { - // remove the library in the event of an error - m_libraries.erase(--m_libraries.end()); - return 0; - } - return &m_libraries.back(); -} - -bool stlplus::library_manager::load(const std::string& name) -{ - std::list::iterator found = local_find(name); - if (found == m_libraries.end()) return false; - return found->load(); -} - -bool stlplus::library_manager::save(const std::string& name) -{ - std::list::iterator found = local_find(name); - if (found == m_libraries.end()) return false; - return found->save(); -} - -bool stlplus::library_manager::purge(const std::string& name) -{ - std::list::iterator found = local_find(name); - if (found == m_libraries.end()) return false; - return found->purge(); -} - -bool stlplus::library_manager::close(const std::string& name) -{ - bool result= true; - std::list::iterator found = local_find(name); - if (found == m_libraries.end()) return false; - result &= found->close(); - m_libraries.erase(found); - if (name == m_work) m_work = ""; - return result; -} - -bool stlplus::library_manager::erase(const std::string& name) -{ - bool result= true; - std::list::iterator found = local_find(name); - if (found == m_libraries.end()) return false; - result &= found->erase(); - m_libraries.erase(found); - if (name == m_work) m_work = ""; - return result; -} - -// operations on all libraries - as above but applied to all the libraries in the manager - -bool stlplus::library_manager::load(void) -{ - bool result = true; - for (std::list::iterator i = m_libraries.begin(); i != m_libraries.end(); i++) - result &= i->load(); - return result; -} - -bool stlplus::library_manager::save(void) -{ - bool result = true; - for (std::list::iterator i = m_libraries.begin(); i != m_libraries.end(); i++) - result &= i->save(); - return result; -} - -bool stlplus::library_manager::purge(void) -{ - bool result = true; - for (std::list::iterator i = m_libraries.begin(); i != m_libraries.end(); i++) - result &= i->purge(); - return result; -} - -bool stlplus::library_manager::close(void) -{ - bool result = true; - for (std::list::iterator i = m_libraries.begin(); i != m_libraries.end(); ) - { - std::list::iterator next = i; - next++; - result &= i->close(); - m_libraries.erase(i); - i = next; - } - return result; -} - -bool stlplus::library_manager::erase(void) -{ - bool result = true; - for (std::list::iterator i = m_libraries.begin(); i != m_libraries.end(); ) - { - std::list::iterator next = i; - next++; - result &= i->erase(); - m_libraries.erase(i); - i = next; - } - return result; -} - -// get name and path of a library - name can differ in case if the library manager is case-insensitive - -std::string stlplus::library_manager::name(const std::string& name) const -{ - std::list::const_iterator found = local_find(name); - if (found == m_libraries.end()) return std::string(); - return found->name(); -} - -std::string stlplus::library_manager::path(const std::string& name) const -{ - std::list::const_iterator found = local_find(name); - if (found == m_libraries.end()) return std::string(); - return found->path(); -} - -// control and test read/write status - -bool stlplus::library_manager::set_writable(const std::string& name) -{ - std::list::iterator found = local_find(name); - if (found == m_libraries.end()) return false; - return found->set_writable(); -} - -bool stlplus::library_manager::set_read_only(const std::string& name) -{ - std::list::iterator found = local_find(name); - if (found == m_libraries.end()) return false; - return found->set_read_only(); -} - -bool stlplus::library_manager::writable(const std::string& name) const -{ - std::list::const_iterator found = local_find(name); - if (found == m_libraries.end()) return false; - return found->writable(); -} - -bool stlplus::library_manager::read_only(const std::string& name) const -{ - std::list::const_iterator found = local_find(name); - if (found == m_libraries.end()) return false; - return found->read_only(); -} - -bool stlplus::library_manager::os_writable(const std::string& library) const -{ - std::list::const_iterator found = local_find(library); - if (found == m_libraries.end()) return false; - return found->os_writable(); -} - -bool stlplus::library_manager::os_read_only(const std::string& library) const -{ - std::list::const_iterator found = local_find(library); - if (found == m_libraries.end()) return false; - return found->os_read_only(); -} - -bool stlplus::library_manager::lm_writable(const std::string& library) const -{ - std::list::const_iterator found = local_find(library); - if (found == m_libraries.end()) return false; - return found->lm_writable(); -} - -bool stlplus::library_manager::lm_read_only(const std::string& library) const -{ - std::list::const_iterator found = local_find(library); - if (found == m_libraries.end()) return false; - return found->lm_read_only(); -} - -// find a library in the manager - returns null if not found - -stlplus::lm_library* stlplus::library_manager::find(const std::string& name) -{ - std::list::iterator found = local_find(name); - if (found == m_libraries.end()) return 0; - return &(*found); -} - -const stlplus::lm_library* stlplus::library_manager::find(const std::string& name) const -{ - std::list::const_iterator found = local_find(name); - if (found == m_libraries.end()) return 0; - return &(*found); -} - -// get the set of all library names - -std::vector stlplus::library_manager::names(void) const -{ - std::vector result; - for (std::list::const_iterator i = m_libraries.begin(); i != m_libraries.end(); i++) - result.push_back(i->name()); - return result; -} - -// get the set of all libraries - -std::vector stlplus::library_manager::handles(void) const -{ - std::vector result; - for (std::list::const_iterator i = m_libraries.begin(); i != m_libraries.end(); i++) - result.push_back(&(*i)); - return result; -} - -std::vector stlplus::library_manager::handles(void) -{ - std::vector result; - for (std::list::iterator i = m_libraries.begin(); i != m_libraries.end(); i++) - result.push_back(&(*i)); - return result; -} - -////////////////////////////////////////////////////////////////////////////// -// current library management - -bool stlplus::library_manager::setwork(const std::string& name) -{ - unsetwork(); - std::list::const_iterator found = local_find(name); - if (found == m_libraries.end()) return false; - m_work = found->name(); - return true; -} - -bool stlplus::library_manager::unsetwork(void) -{ - m_work = ""; - return true; -} - -const stlplus::lm_library* stlplus::library_manager::work(void) const -{ - if (m_work.empty()) return 0; - return find(m_work); -} - -stlplus::lm_library* stlplus::library_manager::work(void) -{ - if (m_work.empty()) return 0; - return find(m_work); -} - -std::string stlplus::library_manager::work_name(void) const -{ - return m_work; -} - -////////////////////////////////////////////////////////////////////////////// -// unit management within a library - -bool stlplus::library_manager::exists(const std::string& name, const stlplus::lm_unit_name& unit) const -{ - std::list::const_iterator found = local_find(name); - if (found == m_libraries.end()) return false; - return found->exists(unit); -} - -stlplus::lm_unit_ptr stlplus::library_manager::create(const std::string& name, const stlplus::lm_unit_name& unit) -{ - std::list::iterator found = local_find(name); - if (found == m_libraries.end()) return stlplus::lm_unit_ptr(); - return found->create(unit); -} - -bool stlplus::library_manager::loaded(const std::string& name, const stlplus::lm_unit_name& unit) const -{ - std::list::const_iterator found = local_find(name); - if (found == m_libraries.end()) return stlplus::lm_unit_ptr(); - return found->loaded(unit); -} - -bool stlplus::library_manager::load(const std::string& name, const stlplus::lm_unit_name& unit) -{ - std::list::iterator found = local_find(name); - if (found == m_libraries.end()) return stlplus::lm_unit_ptr(); - return found->load(unit); -} - -bool stlplus::library_manager::purge(const std::string& name, const stlplus::lm_unit_name& unit) -{ - std::list::iterator found = local_find(name); - if (found == m_libraries.end()) return false; - return found->purge(unit); -} - -bool stlplus::library_manager::save(const std::string& name, const stlplus::lm_unit_name& unit) -{ - std::list::iterator found = local_find(name); - if (found == m_libraries.end()) return false; - return found->save(unit); -} - -bool stlplus::library_manager::erase(const std::string& name, const stlplus::lm_unit_name& unit) -{ - std::list::iterator found = local_find(name); - if (found == m_libraries.end()) return false; - return found->erase(unit); -} - -bool stlplus::library_manager::mark(const std::string& name, const stlplus::lm_unit_name& unit) -{ - std::list::iterator found = local_find(name); - if (found == m_libraries.end()) return false; - return found->mark(unit); -} - -time_t stlplus::library_manager::modified(const std::string& name, const stlplus::lm_unit_name& unit) const -{ - std::list::const_iterator found = local_find(name); - if (found == m_libraries.end()) return 0; - return found->modified(unit); -} - -bool stlplus::library_manager::erase_by_source(const std::string& source_file) -{ - bool result = true; - for (std::list::iterator i = m_libraries.begin(); i != m_libraries.end(); i++) - if (i->writable()) - result &= i->erase_by_source(source_file); - return result; -} - -const stlplus::lm_unit_ptr stlplus::library_manager::find(const std::string& name, const stlplus::lm_unit_name& unit) const -{ - std::list::const_iterator found = local_find(name); - if (found == m_libraries.end()) - return stlplus::lm_unit_ptr(); - return found->find(unit); -} - -stlplus::lm_unit_ptr stlplus::library_manager::find(const std::string& name, const stlplus::lm_unit_name& unit) -{ - std::list::iterator found = local_find(name); - if (found == m_libraries.end()) return stlplus::lm_unit_ptr(); - return found->find(unit); -} - -std::vector stlplus::library_manager::names(const std::string& name) const -{ - std::list::const_iterator found = local_find(name); - if (found == m_libraries.end()) return std::vector(); - return found->names(); -} - -std::vector stlplus::library_manager::names(const std::string& name, const std::string& type) const -{ - std::list::const_iterator found = local_find(name); - if (found == m_libraries.end()) return std::vector(); - return found->names(type); -} - -std::vector stlplus::library_manager::handles(const std::string& name) const -{ - std::list::const_iterator found = local_find(name); - if (found == m_libraries.end()) return std::vector(); - return found->handles(); -} - -std::vector stlplus::library_manager::handles(const std::string& name, const std::string& type) const -{ - std::list::const_iterator found = local_find(name); - if (found == m_libraries.end()) return std::vector(); - return found->handles(type); -} - -////////////////////////////////////////////////////////////////////////////// -// dependency checking -// done at the top level because a global view of the libraries is required - -bool stlplus::library_manager::out_of_date(const std::string& library, const stlplus::lm_unit_name& name) const -{ - return !up_to_date(library, name); -} - -bool stlplus::library_manager::up_to_date(const std::string& library, const stlplus::lm_unit_name& name) const -{ - lm_dependencies reason = out_of_date_reason(library, name); - return reason.empty(); -} - -stlplus::lm_dependencies stlplus::library_manager::out_of_date_reason(const std::string& library, const stlplus::lm_unit_name& name) const -{ - std::map,lm_dependencies> visited; - return out_of_date_check(visited, this, library, name); -} - -std::pair stlplus::library_manager::tidy(const std::string& library) -{ - std::list::iterator found = local_find(library); - if (found == m_libraries.end()) return std::make_pair(false,0); - return found->tidy(); -} - -std::pair stlplus::library_manager::tidy(void) -{ - std::pair result = std::make_pair(true,0); - for (std::list::iterator i = m_libraries.begin(); i != m_libraries.end(); i++) - { - if (i->writable()) - { - std::pair library_result = i->tidy(); - result.second += library_result.second; - result.first &= library_result.first; - } - } - return result; -} - -////////////////////////////////////////////////////////////////////////////// -// do-everything print routine! - -bool stlplus::library_manager::pretty_print(std::ostream& str, - bool print_units, - const std::string& lib, - const std::string& type) const -{ - bool library_found = false; - for (std::list::const_iterator l = m_libraries.begin(); l != m_libraries.end(); l++) - { - // select the library - if (lib.empty() || lib == l->name()) - { - l->pretty_print(str, print_units, type); - library_found = true; - } - } - if (!library_found) - { - if (lib.empty()) - str << "there are no libraries in the library list" << std::endl; - else - str << "there is no library called " << lib << " in the library list" << std::endl; - return false; - } - return true; -} - -//////////////////////////////////////////////////////////////////////////////// -// diagnostic print routines - -bool stlplus::library_manager::print(std::ostream& str) const -{ - for (std::list::const_iterator l = m_libraries.begin(); l != m_libraries.end(); l++) - l->print(str); - return str; -} - -bool stlplus::library_manager::print_long(std::ostream& str) const -{ - for (std::list::const_iterator l = m_libraries.begin(); l != m_libraries.end(); l++) - l->print_long(str); - return str; -} - -// find a library by name - -std::list::iterator stlplus::library_manager::local_find(const std::string& name) -{ - for (std::list::iterator i = m_libraries.begin(); i != m_libraries.end(); i++) - { - if (m_library_case) - { - if (i->name() == name) return i; - } - else - { - if (lowercase(i->name()) == lowercase(name)) return i; - } - } - return m_libraries.end(); -} - -std::list::const_iterator stlplus::library_manager::local_find(const std::string& name) const -{ - for (std::list::const_iterator i = m_libraries.begin(); i != m_libraries.end(); i++) - { - if (m_library_case) - { - if (i->name() == name) return i; - } - else - { - if (lowercase(i->name()) == lowercase(name)) return i; - } - } - return m_libraries.end(); -} - -std::ostream& stlplus::operator << (std::ostream& str, const stlplus::library_manager& manager) -{ - manager.print(str); - return str; -} - -////////////////////////////////////////////////////////////////////////////////