]> git.tdb.fi Git - builder.git/blobdiff - source/cache.cpp
Replace DependencyCache with a more generic cache
[builder.git] / source / cache.cpp
diff --git a/source/cache.cpp b/source/cache.cpp
new file mode 100644 (file)
index 0000000..70f4120
--- /dev/null
@@ -0,0 +1,144 @@
+#include <msp/core/maputils.h>
+#include <msp/fs/stat.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_dir()/"../cache"),
+       changed(false)
+{ }
+
+void Cache::set_value(const Target *tgt, const string &k, const string &v)
+{
+       ValueList 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);
+       DataMap::iterator i = data.find(key);
+       if(i==data.end())
+               i = data.insert(DataMap::value_type(key, ValueList())).first;
+       i->second.push_back(v);
+       changed = true;
+}
+
+void Cache::set_values(const Target *tgt, const string &k, const ValueList &v)
+{
+       data[Key(tgt->get_name(), k)] = v;
+       changed = true;
+}
+
+const string &Cache::get_value(const Target *tgt, const string &k)
+{
+       const ValueList &values = get_values(tgt, k);
+       if(values.empty())
+               throw logic_error("values.empty()");
+       return values.front();
+}
+
+const Cache::ValueList &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;
+                       ValueList &values = data[key];
+                       for(unsigned count = read_count(in); count; --count)
+                               values.push_back(read_string(in));
+               }
+
+               mtime = st.get_modify_time();
+       }
+}
+
+void Cache::save() const
+{
+       if(data.empty() || !changed)
+               return;
+
+       package.get_builder().get_logger().log("files", format("Writing %s", filename));
+       IO::BufferedFile out(filename.str(), IO::M_WRITE);
+
+       for(DataMap::const_iterator i=data.begin(); i!=data.end(); ++i)
+       {
+               write_string(out, i->first.first);
+               write_string(out, i->first.second);
+               write_count(out, i->second.size());
+               for(ValueList::const_iterator j=i->second.begin(); j!=i->second.end(); ++j)
+                       write_string(out, *j);
+       }
+}