1 #include <msp/core/maputils.h>
2 #include <msp/fs/dir.h>
3 #include <msp/fs/stat.h>
4 #include <msp/fs/utils.h>
5 #include <msp/io/file.h>
6 #include <msp/io/print.h>
7 #include <msp/strings/utils.h>
10 #include "sourcepackage.h"
18 unsigned read_count(IO::Base &in)
20 unsigned char head = in.get();
23 unsigned char tail = in.get();
24 return (head&0x3F)<<8 | tail;
30 string read_string(IO::Base &in)
32 unsigned len = read_count(in);
34 len = in.read(buf, len);
35 return string(buf, len);
38 void write_count(IO::Base &out, unsigned count)
44 out.put(0xC0 | (count>>8));
48 throw invalid_argument("write_count");
51 void write_string(IO::Base &out, const string &str)
53 write_count(out, str.size());
60 Cache::Cache(SourcePackage &p):
62 filename(package.get_temp_directory()/"../cache")
65 void Cache::set_value(const Target *tgt, const string &k, const string &v)
69 set_values(tgt, k, vl);
72 void Cache::append_value(const Target *tgt, const string &k, const string &v)
74 Key key(tgt->get_name(), k);
75 auto i = data.find(key);
77 i = data.insert({ key, Values() }).first;
78 i->second.push_back(v);
80 package.get_builder().get_logger().log("cache", "Updated key %s %s+ %s", tgt->get_name(), k, v);
83 void Cache::set_values(const Target *tgt, const string &k, const Values &v)
85 data[Key(tgt->get_name(), k)] = v;
87 package.get_builder().get_logger().log("cache", "Updated key %s %s: %s", tgt->get_name(), k, join(v.begin(), v.end()));
90 const string &Cache::get_value(const Target *tgt, const string &k)
92 const Values &values = get_values(tgt, k);
94 throw logic_error("values.empty()");
95 return values.front();
98 const Cache::Values &Cache::get_values(const Target *tgt, const string &k)
100 return get_item(data, Key(tgt->get_name(), k));
103 bool Cache::has_key(const Target *tgt, const string &k)
105 return data.count(Key(tgt->get_name(), k));
110 if(FS::Stat st = FS::stat(filename))
112 package.get_builder().get_logger().log("files", "Reading %s", filename);
113 IO::BufferedFile in(filename.str());
118 key.first = read_string(in);
119 key.second = read_string(in);
120 if(key.first.empty() || key.second.empty())
122 Values &values = data[key];
123 for(unsigned count = read_count(in); count; --count)
124 values.push_back(read_string(in));
125 package.get_builder().get_logger().log("cache", "Loaded key %s %s: %s", key.first, key.second, join(values.begin(), values.end()));
128 mtime = st.get_modify_time();
132 void Cache::save() const
134 if(data.empty() || !changed)
137 FS::Path dir = FS::dirname(filename);
139 FS::mkpath(dir, 0755);
140 package.get_builder().get_logger().log("files", "Writing %s", filename);
141 IO::BufferedFile out(filename.str(), IO::M_WRITE);
143 for(const auto &kvp: data)
145 write_string(out, kvp.first.first);
146 write_string(out, kvp.first.second);
147 write_count(out, kvp.second.size());
148 for(const string &v: kvp.second)
149 write_string(out, v);