+++ /dev/null
-#include <msp/core/maputils.h>
-#include <msp/fs/dir.h>
-#include <msp/fs/stat.h>
-#include <msp/fs/utils.h>
-#include <msp/io/file.h>
-#include <msp/io/print.h>
-#include <msp/strings/utils.h>
-#include "builder.h"
-#include "cache.h"
-#include "sourcepackage.h"
-#include "target.h"
-
-using namespace std;
-using namespace Msp;
-
-namespace {
-
-unsigned read_count(IO::Base &in)
-{
- unsigned char head = in.get();
- if((head&0xC0)==0xC0)
- {
- unsigned char tail = in.get();
- return (head&0x3F)<<8 | tail;
- }
- else
- return head;
-}
-
-string read_string(IO::Base &in)
-{
- unsigned len = read_count(in);
- char buf[0x4000];
- len = in.read(buf, len);
- return string(buf, len);
-}
-
-void write_count(IO::Base &out, unsigned count)
-{
- if(count<0xC0)
- out.put(count);
- else if(count<0x4000)
- {
- out.put(0xC0 | (count>>8));
- out.put(count&0xFF);
- }
- else
- throw invalid_argument("write_count");
-}
-
-void write_string(IO::Base &out, const string &str)
-{
- write_count(out, str.size());
- out.write(str);
-}
-
-}
-
-
-Cache::Cache(SourcePackage &p):
- package(p),
- filename(package.get_temp_directory()/"../cache"),
- changed(false)
-{ }
-
-void Cache::set_value(const Target *tgt, const string &k, const string &v)
-{
- Values vl;
- vl.push_back(v);
- set_values(tgt, k, vl);
-}
-
-void Cache::append_value(const Target *tgt, const string &k, const string &v)
-{
- Key key(tgt->get_name(), k);
- auto i = data.find(key);
- if(i==data.end())
- i = data.insert({ key, Values() }).first;
- i->second.push_back(v);
- changed = true;
- package.get_builder().get_logger().log("cache", format("Updated key %s %s+ %s", tgt->get_name(), k, v));
-}
-
-void Cache::set_values(const Target *tgt, const string &k, const Values &v)
-{
- data[Key(tgt->get_name(), k)] = v;
- changed = true;
- package.get_builder().get_logger().log("cache", format("Updated key %s %s: %s", tgt->get_name(), k, join(v.begin(), v.end())));
-}
-
-const string &Cache::get_value(const Target *tgt, const string &k)
-{
- const Values &values = get_values(tgt, k);
- if(values.empty())
- throw logic_error("values.empty()");
- return values.front();
-}
-
-const Cache::Values &Cache::get_values(const Target *tgt, const string &k)
-{
- return get_item(data, Key(tgt->get_name(), k));
-}
-
-bool Cache::has_key(const Target *tgt, const string &k)
-{
- return data.count(Key(tgt->get_name(), k));
-}
-
-void Cache::load()
-{
- if(FS::Stat st = FS::stat(filename))
- {
- package.get_builder().get_logger().log("files", format("Reading %s", filename));
- IO::BufferedFile in(filename.str());
-
- while(!in.eof())
- {
- Key key;
- key.first = read_string(in);
- key.second = read_string(in);
- if(key.first.empty() || key.second.empty())
- break;
- Values &values = data[key];
- for(unsigned count = read_count(in); count; --count)
- values.push_back(read_string(in));
- package.get_builder().get_logger().log("cache", format("Loaded key %s %s: %s", key.first, key.second, join(values.begin(), values.end())));
- }
-
- mtime = st.get_modify_time();
- }
-}
-
-void Cache::save() const
-{
- if(data.empty() || !changed)
- return;
-
- FS::Path dir = FS::dirname(filename);
- if(!FS::exists(dir))
- FS::mkpath(dir, 0755);
- package.get_builder().get_logger().log("files", format("Writing %s", filename));
- IO::BufferedFile out(filename.str(), IO::M_WRITE);
-
- for(const auto &kvp: data)
- {
- write_string(out, kvp.first.first);
- write_string(out, kvp.first.second);
- write_count(out, kvp.second.size());
- for(const string &v: kvp.second)
- write_string(out, v);
- }
-
- changed = false;
-}