1 #pragma once
2
3 #define CACHE_FILE_NAME(x) ("redasm_cache_" + std::to_string(x) + ".tmp")
4
5 #include "cache_map.h"
6 #include "../../redasm_context.h"
7 #include "../serializer.h"
8 #include "../utils.h"
9 #include <ios>
10
11 namespace REDasm {
12
13 template<typename Key, typename Value> std::unordered_set<std::string> cache_map<Key, Value>::m_activenames;
14
cache_map()15 template<typename Key, typename Value> cache_map<Key, Value>::cache_map(): m_filepath(generateFilePath())
16 {
17 m_file.exceptions(std::fstream::failbit);
18 m_file.open(m_filepath, std::ios::in | std::ios::out | std::ios::trunc | std::ios::binary);
19
20 if(!m_file.is_open())
21 REDasm::log("Cannot write cache @ " + REDasm::quoted(m_filepath));
22 }
23
~cache_map()24 template<typename Key, typename Value> cache_map<Key, Value>::~cache_map()
25 {
26 m_activenames.erase(m_filepath);
27
28 if(!m_file.is_open())
29 return;
30
31 m_file.close();
32 std::remove(m_filepath.c_str());
33 }
34
size() const35 template<typename Key, typename Value> u64 cache_map<Key, Value>::size() const { return m_offsets.size(); }
36
commit(const Key & key,const Value & value)37 template<typename Key, typename Value> void cache_map<Key, Value>::commit(const Key& key, const Value &value)
38 {
39 m_file.seekp(0, std::ios::end); // Ignore old key -> value reference, if any
40 m_offsets[key] = m_file.tellp();
41
42 Serializer<Value>::write(m_file, value);
43 }
44
erase(const cache_map<Key,Value>::iterator & it)45 template<typename Key, typename Value> void cache_map<Key, Value>::erase(const cache_map<Key, Value>::iterator &it)
46 {
47 auto oit = m_offsets.find(it.key);
48
49 if(oit == m_offsets.end())
50 return;
51
52 m_offsets.erase(oit);
53 }
54
value(const Key & key)55 template<typename Key, typename Value> Value cache_map<Key, Value>::value(const Key &key)
56 {
57 auto it = m_offsets.find(key);
58
59 if(it == m_offsets.end())
60 return Value();
61
62 Value value;
63
64 auto v = m_file.rdstate();
65 m_file.seekg(it->second, std::ios::beg);
66 v = m_file.rdstate();
67
68 Serializer<Value>::read(m_file, value);
69 return value;
70 }
71
operator [](const Key & key)72 template<typename Key, typename Value> Value cache_map<Key, Value>::operator[](const Key& key) { return this->value(key); }
73
generateFilePath()74 template<typename Key, typename Value> std::string cache_map<Key, Value>::generateFilePath()
75 {
76 std::string filepath = REDasm::makePath(Context::settings.tempPath, CACHE_FILE_NAME(0));
77 auto it = m_activenames.find(filepath);
78
79 for(size_t i = 1; it != m_activenames.end(); i++)
80 {
81 filepath = REDasm::makePath(Context::settings.tempPath, CACHE_FILE_NAME(i));
82 it = m_activenames.find(filepath);
83 }
84
85 m_activenames.insert(filepath);
86 return filepath;
87 }
88
89 } // namespace REDasm
90