diff options
-rw-r--r-- | tools/minicargo/build.cpp | 47 | ||||
-rw-r--r-- | tools/minicargo/helpers.h | 176 | ||||
-rw-r--r-- | tools/minicargo/main.cpp | 39 | ||||
-rw-r--r-- | tools/minicargo/manifest.cpp | 109 | ||||
-rw-r--r-- | tools/minicargo/manifest.h | 39 | ||||
-rw-r--r-- | tools/minicargo/repository.cpp | 70 | ||||
-rw-r--r-- | tools/minicargo/repository.h | 29 | ||||
-rw-r--r-- | tools/minicargo/toml.cpp | 13 | ||||
-rw-r--r-- | tools/minicargo/toml.h | 19 | ||||
-rw-r--r-- | vsproject/minicargo/minicargo.vcxproj | 2 | ||||
-rw-r--r-- | vsproject/minicargo/minicargo.vcxproj.filters | 6 |
11 files changed, 507 insertions, 42 deletions
diff --git a/tools/minicargo/build.cpp b/tools/minicargo/build.cpp index ace0dd13..352a4dcd 100644 --- a/tools/minicargo/build.cpp +++ b/tools/minicargo/build.cpp @@ -18,6 +18,7 @@ struct BuildList }; ::std::vector<BuildEnt> m_list; + void add_dependencies(const PackageManifest& p, unsigned level); void add_package(const PackageManifest& p, unsigned level); void sort_list(); @@ -85,13 +86,16 @@ private: void MiniCargo_Build(const PackageManifest& manifest) { BuildList list; - // Generate sorted dependency list - for (const auto& dep : manifest.dependencies()) + + list.add_dependencies(manifest, 0); + + list.sort_list(); + // dedup? + for(const auto& p : list.iter()) { - list.add_package(dep.get_package(), 1); + DEBUG("WILL BUILD " << p.name() << " from " << p.manifest_path()); } - // Build dependencies Builder builder; for(const auto& p : list.iter()) @@ -106,6 +110,17 @@ void MiniCargo_Build(const PackageManifest& manifest) builder.build_library(manifest); } +void BuildList::add_dependencies(const PackageManifest& p, unsigned level) +{ + for (const auto& dep : p.dependencies()) + { + if( dep.is_optional() ) + { + continue ; + } + add_package(dep.get_package(), level+1); + } +} void BuildList::add_package(const PackageManifest& p, unsigned level) { for(auto& ent : m_list) @@ -125,17 +140,32 @@ void BuildList::add_package(const PackageManifest& p, unsigned level) void BuildList::sort_list() { ::std::sort(m_list.begin(), m_list.end(), [](const auto& a, const auto& b){ return a.level < b.level; }); + + for(auto it = m_list.begin(); it != m_list.end(); ) + { + auto it2 = ::std::find_if(m_list.begin(), it, [&](const auto& x){ return x.package == it->package; }); + if( it2 != it ) + { + it = m_list.erase(it); + } + else + { + ++it; + } + } } bool Builder::build_target(const PackageManifest& manifest, const PackageTarget& target) const { - auto outfile = ::helpers::path("output") / ::format("lib", target.m_name, ".hir"); + auto outdir = ::helpers::path("output"); + auto outfile = outdir / ::format("lib", target.m_name, ".hir"); StringList args; args.push_back(::helpers::path(manifest.manifest_path()).parent() / ::helpers::path(target.m_path)); args.push_back("--crate-name"); args.push_back(target.m_name.c_str()); args.push_back("--crate-type"); args.push_back("rlib"); args.push_back("-o"); args.push_back(outfile); + args.push_back("-L"); args.push_back(outdir); return this->spawn_process(args, outfile + "_dbg.txt"); } @@ -157,6 +187,7 @@ bool Builder::spawn_process(const StringList& args, const ::helpers::path& logfi STARTUPINFO si = { 0 }; si.cb = sizeof(si); +#if 1 si.dwFlags = STARTF_USESTDHANDLES; si.hStdInput = NULL; si.hStdError = GetStdHandle(STD_ERROR_HANDLE); @@ -169,8 +200,12 @@ bool Builder::spawn_process(const StringList& args, const ::helpers::path& logfi WriteFile(si.hStdOutput, cmdline_str.data(), cmdline_str.size(), &tmp, NULL); WriteFile(si.hStdOutput, "\n", 1, &tmp, NULL); } +#endif PROCESS_INFORMATION pi = { 0 }; - CreateProcessA("x64\\Release\\mrustc.exe", (LPSTR)cmdline_str.c_str(), NULL, NULL, TRUE, 0, "MRUSTC_DEBUG=\0", NULL, &si, &pi); + char env[] = + "MRUSTC_DEBUG=""\0" + ; + CreateProcessA("x64\\Release\\mrustc.exe", (LPSTR)cmdline_str.c_str(), NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi); CloseHandle(si.hStdOutput); WaitForSingleObject(pi.hProcess, INFINITE); DWORD status = 1; diff --git a/tools/minicargo/helpers.h b/tools/minicargo/helpers.h index d9fe7e3c..35e791f1 100644 --- a/tools/minicargo/helpers.h +++ b/tools/minicargo/helpers.h @@ -4,14 +4,37 @@ namespace helpers { +class string_view +{ + const char* m_start; + const size_t m_len; +public: + string_view(const char* s, size_t n): + m_start(s), m_len(n) + { + } + + bool operator==(const ::std::string& s) const { + return *this == s.c_str(); + } + bool operator==(const char* s) const { + if(::std::strncmp(m_start, s, m_len) != 0) + return false; + return s[m_len] == '\0'; + } + friend ::std::string& operator+=(::std::string& x, const string_view& sv) { + x.append(sv.m_start, sv.m_start+sv.m_len); + return x; + } +}; /// Path helper class (because I don't want to include boost) class path { #ifdef _WIN32 - const char SEP = '\\'; + static const char SEP = '\\'; #else - const char SEP = '/'; + static const char SEP = '/'; #endif ::std::string m_str; @@ -96,6 +119,155 @@ public: return m_str; } + class ComponentsIter + { + const path& p; + size_t pos; + size_t end; + + friend class path; + ComponentsIter(const path& p, size_t i): p(p), pos(i) { + end = p.m_str.find(SEP, pos); + if(end == ::std::string::npos) + end = p.m_str.size(); + } + public: + string_view operator*() const { + return string_view(p.m_str.c_str() + pos, end - pos); + } + void operator++() { + if(end == p.m_str.size()) + pos = end; + else + { + pos = end+1; + end = p.m_str.find(SEP, pos); + if(end == ::std::string::npos) + end = p.m_str.size(); + } + } + bool operator!=(const ComponentsIter& x) const { + return pos != x.pos; + } + }; + ComponentsIter begin() const { + return ComponentsIter(*this, 0); + } + ComponentsIter end() const { + return ComponentsIter(*this, m_str.size()); + } + + path normalise() const + { + path rv; + rv.m_str.reserve( m_str.size()+1 ); + + for(auto comp : *this) + { + if( comp == "." ) { + // Ignore. + } + else if( comp == ".." ) + { + // If the path is empty, OR the last element is a "..", push the element + if( rv.m_str.empty() + || (rv.m_str.size() == 3 && rv.m_str[0] == '.' && rv.m_str[1] == '.' && rv.m_str[2] == SEP) + || (rv.m_str.size() > 4 && *(rv.m_str.end()-4) == SEP && *(rv.m_str.end()-3) == '.' && *(rv.m_str.end()-2) == '.' && *(rv.m_str.end()-1) == SEP ) + ) + { + // Push + rv.m_str += comp; + rv.m_str += SEP; + } + else + { + rv.m_str.pop_back(); + auto pos = rv.m_str.find_last_of(SEP); + if(pos == ::std::string::npos) + { + rv.m_str.resize(0); + } + else if( pos == 0 ) + { + // Keep. + } + else + { + rv.m_str.resize(pos+1); + } + } + } + else { + rv.m_str += comp; + rv.m_str += SEP; + } + } + rv.m_str.pop_back(); + return rv; + } +#if 0 + void normalise_in_place() + { + size_t insert_point = 0; + + for(size_t read_pos = 0; read_pos < m_str.size(); read_pos ++) + { + auto pos = m_str.find_first_of(SEP, read_pos); + if(pos == ::std::string::npos) + pos = m_str.size(); + auto comp = string_view(m_str.c_str() + read_pos, pos - read_pos); + + bool append; + if(comp == ".") + { + // Advance read without touching insert + append = false; + } + else if( comp == ".." ) + { + // Consume parent (if not a relative component already) + // Move insertion point back to the previous separator + auto pos = m_str.find_last_of(SEP, insert_point); + if(pos == ::std::string::npos) + { + // Only one component currently (or empty) + append = true; + } + else if(string_view(m_str.c_str() + pos+1, insert_point - pos-1) == "..") + { + // Last component is ".." - keep adding + append = true; + } + else + { + insert_point = pos; + append = false; + } + } + else + { + append = true; + } + + if(append) + { + if( read_pos != insert_point ) + { + //assert(read_pos > insert_point); + while(read_pos < pos) + { + m_str[insert_point++] = m_str[read_pos++]; + } + } + } + else + { + read_pos = pos; + } + } + } +#endif + friend ::std::ostream& operator<<(::std::ostream& os, const path& p) { return os << p.m_str; diff --git a/tools/minicargo/main.cpp b/tools/minicargo/main.cpp index c2fe4c2e..236b9d77 100644 --- a/tools/minicargo/main.cpp +++ b/tools/minicargo/main.cpp @@ -6,9 +6,11 @@ */ #include <iostream> #include <cstring> // strcmp +#include <map> #include "debug.h" #include "manifest.h" #include "helpers.h" +#include "repository.h" extern void MiniCargo_Build(const PackageManifest& manifest); @@ -22,6 +24,8 @@ struct ProgramOptions const char* output_directory = nullptr; + const char* vendor_dir = nullptr; + int parse(int argc, const char* argv[]); void usage() const; }; @@ -33,19 +37,34 @@ int main(int argc, const char* argv[]) return 1; } - // 1. Load the Cargo.toml file from the passed directory - auto m = PackageManifest::load_from_toml( ::helpers::path(opts.directory ? opts.directory : ".") / "Cargo.toml" ); + try + { + // Load package database + Repository repo; + // TODO: load repository from a local cache + if( opts.vendor_dir ) + { + repo.load_vendored(opts.vendor_dir); + } + + // 1. Load the Cargo.toml file from the passed directory + auto dir = ::helpers::path(opts.directory ? opts.directory : "."); + auto m = PackageManifest::load_from_toml( dir / "Cargo.toml" ); + + m.load_dependencies(repo); - // 2. Recursively load dependency manifests - for(const auto& dep : m.dependencies()) + // 3. Build dependency tree + MiniCargo_Build(m); + } + catch(const ::std::exception& e) { - throw "TODO: Deps"; + ::std::cerr << "EXCEPTION: " << e.what() << ::std::endl; + ::std::cout << "Press enter to exit..." << ::std::endl; + ::std::cin.get(); + return 1; } - // 3. Build dependency tree - MiniCargo_Build(m); - - ::std::cout << "Press any key to exit..." << ::std::endl; + ::std::cout << "Press enter to exit..." << ::std::endl; ::std::cin.get(); return 0; } @@ -106,9 +125,9 @@ void ProgramOptions::usage() const } - void Debug_Print(::std::function<void(::std::ostream& os)> cb) { cb(::std::cout); ::std::cout << ::std::endl; } + diff --git a/tools/minicargo/manifest.cpp b/tools/minicargo/manifest.cpp index 90bb68a5..d068b7bf 100644 --- a/tools/minicargo/manifest.cpp +++ b/tools/minicargo/manifest.cpp @@ -6,10 +6,7 @@ #include "helpers.h" #include <cassert> #include <algorithm> -#include <sstream> -#ifdef _WIN32 -#include <Windows.h> -#endif +#include "repository.h" static ::std::vector<::std::shared_ptr<PackageManifest>> g_loaded_manifests; @@ -32,6 +29,7 @@ PackageManifest PackageManifest::load_from_toml(const ::std::string& path) for(auto key_val : toml_file) { assert(key_val.path.size() > 0); + DEBUG(key_val.path << " = " << key_val.value); const auto& section = key_val.path[0]; if( section == "package" ) { @@ -60,6 +58,20 @@ PackageManifest PackageManifest::load_from_toml(const ::std::string& path) { rv.m_version = PackageVersion::from_string(key_val.value.as_string()); } + else if( key == "build" ) + { + if(rv.m_build_script != "" ) + { + // TODO: Warn/error + throw ::std::runtime_error("Build script path set twice"); + } + rv.m_build_script = key_val.value.as_string(); + if(rv.m_build_script == "") + { + // TODO: Error + throw ::std::runtime_error("Build script path cannot be empty"); + } + } else { // Unknown value in `package` @@ -145,22 +157,28 @@ PackageManifest PackageManifest::load_from_toml(const ::std::string& path) // Set path specification of the named depenency ref.m_path = key_val.value.as_string(); } - else if (attr == "git") + else if( attr == "git" ) { // Load from git repo. TODO("Support git dependencies"); } - else if (attr == "branch") + else if( attr == "branch" ) { // Specify git branch TODO("Support git dependencies (branch)"); } - else if( attr == "version") + else if( attr == "version" ) { assert(key_val.path.size() == 3); // Parse version specifier ref.m_version = PackageVersionSpec::from_string(key_val.value.as_string()); } + else if( attr == "optional" ) + { + assert(key_val.path.size() == 3); + ref.m_optional = key_val.value.as_bool(); + // TODO: Add a feature with the same name as the dependency. + } else { // TODO: Error @@ -168,11 +186,23 @@ PackageManifest PackageManifest::load_from_toml(const ::std::string& path) } } } + else if( section == "build-dependencies" ) + { + // TODO: Build deps + } else if( section == "patch" ) { //const auto& repo = key_val.path[1]; TODO("Support repository patches"); } + else if( section == "target" ) + { + // TODO: Target opts? + } + else if( section == "features" ) + { + // TODO: Features + } else { // Unknown manifest section @@ -203,36 +233,40 @@ namespace assert(kv.path.size() == base_idx + 1); target.m_enable_test = kv.value.as_bool(); } - else if (key == "doctest") + else if( key == "doctest" ) { assert(kv.path.size() == base_idx + 1); target.m_enable_doctest = kv.value.as_bool(); } - else if (key == "bench") + else if( key == "bench" ) { assert(kv.path.size() == base_idx + 1); target.m_enable_bench = kv.value.as_bool(); } - else if (key == "doc") + else if( key == "doc" ) { assert(kv.path.size() == base_idx + 1); target.m_enable_doc = kv.value.as_bool(); } - else if (key == "plugin") + else if( key == "plugin" ) { assert(kv.path.size() == base_idx + 1); target.m_is_plugin = kv.value.as_bool(); } - else if (key == "proc-macro") + else if( key == "proc-macro" ) { assert(kv.path.size() == base_idx + 1); target.m_is_proc_macro = kv.value.as_bool(); } - else if (key == "harness") + else if( key == "harness" ) { assert(kv.path.size() == base_idx + 1); target.m_is_own_harness = kv.value.as_bool(); } + else if( key == "crate-type" ) + { + // TODO: Support crate types + } else { throw ::std::runtime_error( ::format("TODO: Handle target option `", key, "`") ); @@ -250,10 +284,49 @@ const PackageTarget& PackageManifest::get_library() const return *it; } -const PackageManifest& PackageRef::get_package() const +void PackageManifest::load_dependencies(Repository& repo) { - DEBUG("TODO: PackageRef::get_package()"); - throw ""; + DEBUG("Loading depencencies for " << m_name); + auto base_path = ::helpers::path(m_manifest_path).parent(); + + // 2. Recursively load dependency manifests + for(auto& dep : m_dependencies) + { + if( dep.m_optional ) + { + // TODO: Check for feature that enables this (option to a feature with no '/') + continue ; + } + dep.load_manifest(repo, base_path); + } +} + +void PackageRef::load_manifest(Repository& repo, const ::helpers::path& base_path) +{ + // If the path isn't set, check for: + // - Git (checkout and use) + // - Version and repository (check vendored, check cache, download into cache) + if( ! this->has_path() ) + { + if( this->has_git() ) + { + DEBUG("Load dependency " << this->name() << " from git"); + throw "TODO: Git"; + } + else + { + DEBUG("Load dependency " << this->name() << " from repo"); + m_manifest = repo.find(this->name(), this->get_version()); + } + } + else + { + DEBUG("Load dependency " << m_name << " from path " << m_path); + // Search for a copy of this already loaded + m_manifest = repo.from_path(base_path / ::helpers::path(m_path) / "Cargo.toml"); + } + + m_manifest->load_dependencies(repo); } PackageVersion PackageVersion::from_string(const ::std::string& s) @@ -275,4 +348,8 @@ PackageVersionSpec PackageVersionSpec::from_string(const ::std::string& s) PackageVersionSpec rv; throw ""; return rv; +} +bool PackageVersionSpec::accepts(const PackageVersion& v) const +{ + throw ""; }
\ No newline at end of file diff --git a/tools/minicargo/manifest.h b/tools/minicargo/manifest.h index 054347fb..0e6c2d81 100644 --- a/tools/minicargo/manifest.h +++ b/tools/minicargo/manifest.h @@ -3,8 +3,10 @@ #include <string> #include <vector> #include <memory> +#include "helpers.h" class PackageManifest; +class Repository; struct PackageVersion { @@ -13,6 +15,15 @@ struct PackageVersion unsigned patch; static PackageVersion from_string(const ::std::string& s); + bool operator<(const PackageVersion& x) const { + if( major < x.major ) return true; + if( major > x.major ) return false; + if( minor < x.minor ) return true; + if( minor > x.minor ) return false; + if( minor < x.patch ) return true; + if( patch > x.patch ) return false; + return false; + } }; struct PackageVersionSpec { @@ -28,10 +39,14 @@ struct PackageVersionSpec Type ty; PackageVersion ver; }; + // TODO: Just upper and lower? ::std::vector<Bound> m_bounds; - // TODO: Just upper and lower? + // Construct from a string static PackageVersionSpec from_string(const ::std::string& s); + + /// Check if this spec accepts the passed version + bool accepts(const PackageVersion& v) const; }; class PackageRef @@ -40,6 +55,7 @@ class PackageRef ::std::string m_name; PackageVersionSpec m_version; + bool m_optional = false; ::std::string m_path; ::std::shared_ptr<PackageManifest> m_manifest; @@ -49,7 +65,22 @@ class PackageRef } public: - const PackageManifest& get_package() const; + const ::std::string& name() const { return m_name; } + //const ::std::string& get_repo_name() const { return m_repo; } + const PackageVersionSpec& get_version() const { return m_version; } + + bool is_optional() const { return m_optional; } + + const bool has_path() const { return m_path != ""; } + const ::std::string& path() const { return m_path; } + const bool has_git() const { return false; } + + const PackageManifest& get_package() const { + if(!m_manifest) throw ::std::runtime_error("Manifest not loaded for package " + m_name); + return *m_manifest; + } + + void load_manifest(Repository& repo, const ::helpers::path& base_path); }; struct PackageTarget @@ -98,6 +129,8 @@ class PackageManifest ::std::string m_name; PackageVersion m_version; + ::std::string m_build_script; + ::std::vector<PackageRef> m_dependencies; ::std::vector<PackageTarget> m_targets; @@ -122,4 +155,6 @@ public: const ::std::vector<PackageRef>& dependencies() const { return m_dependencies; } + + void load_dependencies(Repository& repo); }; diff --git a/tools/minicargo/repository.cpp b/tools/minicargo/repository.cpp new file mode 100644 index 00000000..0a097f66 --- /dev/null +++ b/tools/minicargo/repository.cpp @@ -0,0 +1,70 @@ +/* + */ +#include "repository.h" +#include "debug.h" + +void Repository::load_cache(const ::helpers::path& path) +{ + throw ""; +} +void Repository::load_vendored(const ::helpers::path& path) +{ + // Enumerate folders in this folder, try to open Cargo.toml files + // Extract package name and version from each manifest +} + +::std::shared_ptr<PackageManifest> Repository::from_path(::helpers::path path) +{ + DEBUG("Repository::from_path(" << path << ")"); + // 1. Normalise path + path = path.normalise(); + DEBUG("path = " << path); + + auto it = m_path_cache.find(path); + if(it == m_path_cache.end()) + { + ::std::shared_ptr<PackageManifest> rv ( new PackageManifest(PackageManifest::load_from_toml(path)) ); + + m_path_cache.insert( ::std::make_pair(::std::move(path), rv) ); + + return rv; + } + else + { + return it->second; + } +} +::std::shared_ptr<PackageManifest> Repository::find(const ::std::string& name, const PackageVersionSpec& version) +{ + auto itp = m_cache.equal_range(name); + + Entry* best = nullptr; + for(auto i = itp.first; i != itp.second; ++i) + { + if( version.accepts(i->second.version) ) + { + if( !best || best->version < i->second.version ) + { + best = &i->second; + } + } + } + + if( best ) + { + if( !best->loaded_manifest ) + { + if( best->manifest_path == "" ) + { + throw "TODO: Download package"; + } + best->loaded_manifest = ::std::shared_ptr<PackageManifest>( new PackageManifest(PackageManifest::load_from_toml(best->manifest_path)) ); + } + + return best->loaded_manifest; + } + else + { + return {}; + } +} diff --git a/tools/minicargo/repository.h b/tools/minicargo/repository.h new file mode 100644 index 00000000..0b186077 --- /dev/null +++ b/tools/minicargo/repository.h @@ -0,0 +1,29 @@ +#pragma once + +#include <string> +#include <map> +#include "helpers.h" +#include "manifest.h" + +class Repository +{ + struct Entry + { + /// Path to the Cargo.toml file in the package root + ::std::string manifest_path; + /// Package version + PackageVersion version; + /// (Cached) loaded manifest + ::std::shared_ptr<PackageManifest> loaded_manifest; + }; + + ::std::multimap<::std::string, Entry> m_cache; + // path => manifest + ::std::map<::std::string, ::std::shared_ptr<PackageManifest>> m_path_cache; +public: + void load_cache(const ::helpers::path& path); + void load_vendored(const ::helpers::path& path); + + ::std::shared_ptr<PackageManifest> from_path(::helpers::path path); + ::std::shared_ptr<PackageManifest> find(const ::std::string& name, const PackageVersionSpec& version); +}; diff --git a/tools/minicargo/toml.cpp b/tools/minicargo/toml.cpp index 7d4b0685..fe81fa3c 100644 --- a/tools/minicargo/toml.cpp +++ b/tools/minicargo/toml.cpp @@ -158,14 +158,14 @@ TomlKeyValue TomlFile::get_next_value() { case Token::Type::String: rv.path = m_current_block; - rv.path.insert(rv.path.begin(), m_current_composite.begin(), m_current_composite.end()); + rv.path.insert(rv.path.end(), m_current_composite.begin(), m_current_composite.end()); rv.path.push_back(key_name); rv.value = TomlValue { t.m_data }; break; case Token::Type::SquareOpen: rv.path = m_current_block; - rv.path.insert(rv.path.begin(), m_current_composite.begin(), m_current_composite.end()); + rv.path.insert(rv.path.end(), m_current_composite.begin(), m_current_composite.end()); rv.path.push_back(key_name); rv.value.m_type = TomlValue::Type::List; @@ -197,14 +197,14 @@ TomlKeyValue TomlFile::get_next_value() if( t.m_data == "true" ) { rv.path = m_current_block; - rv.path.insert(rv.path.begin(), m_current_composite.begin(), m_current_composite.end()); + rv.path.insert(rv.path.end(), m_current_composite.begin(), m_current_composite.end()); rv.path.push_back(key_name); rv.value = TomlValue { true }; } else if( t.m_data == "false" ) { rv.path = m_current_block; - rv.path.insert(rv.path.begin(), m_current_composite.begin(), m_current_composite.end()); + rv.path.insert(rv.path.end(), m_current_composite.begin(), m_current_composite.end()); rv.path.push_back(key_name); rv.value = TomlValue { false }; @@ -242,7 +242,7 @@ TomlKeyValue TomlFile::get_next_value() Token Token::lex_from(::std::ifstream& is) { auto rv = Token::lex_from_inner(is); - DEBUG("lex_from: " << rv); + //DEBUG("lex_from: " << rv); return rv; } Token Token::lex_from_inner(::std::ifstream& is) @@ -307,7 +307,7 @@ Token Token::lex_from_inner(::std::ifstream& is) if(isalpha(c)) { // Identifier - while(isalnum(c) || c == '-') + while(isalnum(c) || c == '-' || c == '_') { str += (char)c; c = is.get(); @@ -317,6 +317,7 @@ Token Token::lex_from_inner(::std::ifstream& is) } else { + throw ::std::runtime_error(::format("Unexpected chracter '", (char)c, "' in file")); throw ""; } } diff --git a/tools/minicargo/toml.h b/tools/minicargo/toml.h index 1c8f90d5..17517ca3 100644 --- a/tools/minicargo/toml.h +++ b/tools/minicargo/toml.h @@ -2,6 +2,7 @@ #include <fstream> #include <vector> +#include <string> #include <unordered_map> class TomlFileIter; @@ -91,6 +92,24 @@ struct TomlValue } return m_int_value != 0; } + + friend ::std::ostream& operator<<(::std::ostream& os, const TomlValue& x) { + switch(x.m_type) + { + case Type::Boolean: os << (x.m_int_value != 0 ? "true" : "false"); break; + case Type::Integer: os << x.m_int_value; break; + case Type::List: + os << "["; + for(auto& e : x.m_sub_values) + os << e << ","; + os << "]"; + break; + case Type::String: + os << "\"" << x.m_str_value << "\""; + break; + } + return os; + } }; struct TomlKeyValue diff --git a/vsproject/minicargo/minicargo.vcxproj b/vsproject/minicargo/minicargo.vcxproj index 9c82ff56..9fe4e4a7 100644 --- a/vsproject/minicargo/minicargo.vcxproj +++ b/vsproject/minicargo/minicargo.vcxproj @@ -113,12 +113,14 @@ <ClCompile Include="..\..\tools\minicargo\build.cpp" /> <ClCompile Include="..\..\tools\minicargo\main.cpp" /> <ClCompile Include="..\..\tools\minicargo\manifest.cpp" /> + <ClCompile Include="..\..\tools\minicargo\repository.cpp" /> <ClCompile Include="..\..\tools\minicargo\toml.cpp" /> </ItemGroup> <ItemGroup> <ClInclude Include="..\..\tools\minicargo\debug.h" /> <ClInclude Include="..\..\tools\minicargo\helpers.h" /> <ClInclude Include="..\..\tools\minicargo\manifest.h" /> + <ClInclude Include="..\..\tools\minicargo\repository.h" /> <ClInclude Include="..\..\tools\minicargo\toml.h" /> </ItemGroup> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> diff --git a/vsproject/minicargo/minicargo.vcxproj.filters b/vsproject/minicargo/minicargo.vcxproj.filters index b21142bb..be88124d 100644 --- a/vsproject/minicargo/minicargo.vcxproj.filters +++ b/vsproject/minicargo/minicargo.vcxproj.filters @@ -27,6 +27,9 @@ <ClCompile Include="..\..\tools\minicargo\toml.cpp"> <Filter>Source Files</Filter> </ClCompile> + <ClCompile Include="..\..\tools\minicargo\repository.cpp"> + <Filter>Source Files</Filter> + </ClCompile> </ItemGroup> <ItemGroup> <ClInclude Include="..\..\tools\minicargo\helpers.h"> @@ -41,5 +44,8 @@ <ClInclude Include="..\..\tools\minicargo\debug.h"> <Filter>Header Files</Filter> </ClInclude> + <ClInclude Include="..\..\tools\minicargo\repository.h"> + <Filter>Header Files</Filter> + </ClInclude> </ItemGroup> </Project>
\ No newline at end of file |