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