Skip to content

Commit c75d183

Browse files
committed
core: introduce cache
1 parent 2bd643d commit c75d183

10 files changed

Lines changed: 304 additions & 59 deletions

File tree

Makefile

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -70,14 +70,14 @@ LDFLAGS += -L$(BUILDDIR) $(LTO_FLAGS)
7070
LDLIBS += $(LIBS) `pkg-config --static --libs glfw3 tesseract zbar`
7171
CXXFLAGS += $(LTO_FLAGS) -fvisibility-inlines-hidden -fvisibility=hidden -Iinclude -Iinclude/libs -std=$(CXXSTD) $(VARS) -DVERSION=\"$(VERSION)\"
7272

73-
LIBS = \
73+
LIBS := \
7474
$(BUILDDIR)/libimgui.a \
7575
$(BUILDDIR)/libfmt.a \
7676
$(BUILDDIR)/libclip.a \
7777
$(BUILDDIR)/libtray.a \
7878
$(BUILDDIR)/libtiny-process-library.a
7979

80-
OBJ += \
80+
EXTRA_OBJ := \
8181
$(BUILDDIR)/toml.o \
8282
$(BUILDDIR)/tinyfiledialogs.o \
8383
$(BUILDDIR)/getopt.o
@@ -118,8 +118,8 @@ $(BUILDDIR)/getopt.o:
118118
genver:
119119
./scripts/generateVersion.sh
120120

121-
$(BUILDDIR)/$(TARGET): genver $(OBJ) $(LIBS)
122-
$(CXX) -o $@ $(OBJ) $(LDFLAGS) $(LDLIBS)
121+
$(BUILDDIR)/$(TARGET): genver $(OBJ) $(EXTRA_OBJ) $(LIBS)
122+
$(CXX) -o $@ $(OBJ) $(EXTRA_OBJ) $(LDFLAGS) $(LDLIBS)
123123

124124
dist: $(TARGET)
125125
zip -j $(NAME)-v$(VERSION).zip LICENSE README.md $(BUILDDIR)/$(TARGET)

include/cache.hpp

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
#ifndef _CACHE_HPP_
2+
#define _CACHE_HPP_
3+
4+
#include <string>
5+
#include <unordered_map>
6+
7+
#define TOML_HEADER_ONLY 0
8+
#include "toml++/toml.hpp"
9+
#include "util.hpp"
10+
11+
enum class CacheFilesEnum
12+
{
13+
Colors,
14+
COUNT
15+
};
16+
17+
struct cache_entry_t
18+
{
19+
const std::string file_path;
20+
const std::string toml_path;
21+
toml::table tbl = {};
22+
};
23+
24+
extern std::unordered_map<CacheFilesEnum, cache_entry_t> g_cache_files;
25+
26+
class Cache
27+
{
28+
public:
29+
Cache(const std::string& cache_dir);
30+
~Cache();
31+
32+
Result<> LoadCacheFile(cache_entry_t& entry);
33+
void GenerateCacheFile(const cache_entry_t& entry);
34+
35+
const std::string& GetCacheDirPath() const { return m_cache_dir_path; }
36+
37+
/**
38+
* Get value of a cache variables
39+
* @param value The cache variable "path" (e.g "cache.source-path")
40+
* @param fallback Default value if couldn't retrive value
41+
*/
42+
template <typename T>
43+
static T GetValue(const cache_entry_t& entry, const T& fallback, bool dont_expand_var = false)
44+
{
45+
const std::optional<T>& ret = entry.tbl.at_path(entry.toml_path).value<T>();
46+
if constexpr (toml::is_string<T>)
47+
if (!dont_expand_var)
48+
return ret ? expand_var(ret.value()) : expand_var(fallback);
49+
else
50+
return ret ? ret.value() : fallback;
51+
else
52+
return ret.value_or(fallback);
53+
}
54+
55+
/**
56+
* Set value of a cache variables
57+
* @param path The cache variable "path" (e.g "cache.source-path")
58+
*/
59+
template <typename T>
60+
static void SetValue(cache_entry_t& entry, const T& value)
61+
{
62+
std::string path = entry.toml_path;
63+
toml::table* tbl = &entry.tbl;
64+
65+
while (true)
66+
{
67+
const auto& dot = path.find('.');
68+
if (dot == std::string_view::npos)
69+
{
70+
tbl->insert_or_assign(std::string(path), value);
71+
break;
72+
}
73+
74+
const std::string& segment = path.substr(0, dot);
75+
path = path.substr(dot + 1);
76+
77+
auto* node = tbl->get(segment);
78+
if (!node || !node->is_table())
79+
{
80+
tbl->insert_or_assign(segment, toml::table{});
81+
node = tbl->get(segment);
82+
}
83+
tbl = node->as_table();
84+
}
85+
}
86+
87+
private:
88+
std::string m_cache_dir_path;
89+
};
90+
91+
extern std::unique_ptr<Cache> g_cache;
92+
93+
#endif // !_CACHE_HPP_

include/config.hpp

Lines changed: 22 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
#include "fmt/format.h"
99

1010
// util.hpp
11-
std::string expand_var(std::string ret, bool dont = false);
11+
std::string expand_var(std::string ret);
1212
bool hexstr_to_col(const std::string_view hex, uint32_t& out);
1313

1414
#define TOML_HEADER_ONLY 0
@@ -153,23 +153,6 @@ class Config
153153
m_overrides[key] = std::move(o);
154154
}
155155

156-
const std::string& GetConfigPath() const { return m_config_path; }
157-
const std::string& GetThemePath() const { return m_theme_path; }
158-
const std::string& GetConfigDirPath() const { return m_config_dir_path; }
159-
160-
private:
161-
// Parsed config from LoadConfigFile()
162-
toml::table m_tbl;
163-
164-
// Parsed theme from LoadThemeFile()
165-
toml::table m_theme_tbl;
166-
167-
std::unordered_map<std::string, override_config_value_t> m_overrides;
168-
169-
std::string m_config_path;
170-
std::string m_theme_path;
171-
std::string m_config_dir_path;
172-
173156
/**
174157
* Get value of config variables
175158
* @param value The config variable "path" (e.g "config.source-path")
@@ -200,7 +183,10 @@ class Config
200183
const std::optional<T>& ret =
201184
is_theme ? m_theme_tbl.at_path(value).value<T>() : m_tbl.at_path(value).value<T>();
202185
if constexpr (toml::is_string<T>)
203-
return ret ? expand_var(ret.value(), dont_expand_var) : expand_var(fallback, dont_expand_var);
186+
if (!dont_expand_var)
187+
return ret ? expand_var(ret.value()) : expand_var(fallback);
188+
else
189+
return ret ? ret.value() : fallback;
204190
else
205191
return ret.value_or(fallback);
206192
}
@@ -254,6 +240,23 @@ class Config
254240
out);
255241
return out;
256242
}
243+
244+
const std::string& GetConfigPath() const { return m_config_path; }
245+
const std::string& GetThemePath() const { return m_theme_path; }
246+
const std::string& GetConfigDirPath() const { return m_config_dir_path; }
247+
248+
private:
249+
// Parsed config from LoadConfigFile()
250+
toml::table m_tbl;
251+
252+
// Parsed theme from LoadThemeFile()
253+
toml::table m_theme_tbl;
254+
255+
std::unordered_map<std::string, override_config_value_t> m_overrides;
256+
257+
std::string m_config_path;
258+
std::string m_theme_path;
259+
std::string m_config_dir_path;
257260
};
258261

259262
extern std::unique_ptr<Config> g_config;

include/screen_capture.hpp

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
#define _SCREEN_CAPTURE_HPP_
33

44
#include <cstdint>
5-
#include <functional>
65
#include <span>
76
#include <vector>
87

@@ -36,8 +35,6 @@ enum class SessionType
3635
Unknown
3736
};
3837

39-
using CaptureCallback = std::function<void(capture_result_t)>;
40-
4138
Result<capture_result_t> capture_full_screen_x11();
4239
Result<capture_result_t> capture_full_screen_wayland();
4340
Result<capture_result_t> capture_full_screen_spectacle();

include/screenshot_tool.hpp

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include <unordered_map>
1111
#include <utility>
1212

13+
#include "cache.hpp"
1314
#include "config.hpp"
1415
#include "imgui/imgui.h"
1516
#include "imgui/imgui_internal.h"
@@ -107,9 +108,9 @@ struct annotation_t
107108
ToolType type = ToolType::kNone;
108109
point_t start;
109110
point_t end;
110-
std::string text; // For text tool
111-
std::vector<point_t> points; // For pencil tool
112-
uint32_t color = 0xFF0000FF; // RGBA
111+
std::string text; // For text tool
112+
std::vector<point_t> points; // For pencil tool
113+
rgba_t color = rgba_t::from_rgba(0xFF0000FF); // RGBA
113114
float thickness = 3.0f;
114115
};
115116

@@ -131,7 +132,11 @@ struct inputs_results_t
131132
class ScreenshotTool
132133
{
133134
public:
134-
ScreenshotTool() : m_io(dummy), m_inputs{ g_config->File.ocr_path, g_config->File.ocr_model, {}, "", {}, "", "" } {}
135+
ScreenshotTool()
136+
: m_io(dummy),
137+
m_inputs{ g_config->File.ocr_path, g_config->File.ocr_model, {}, "", {}, "", "" },
138+
m_current_color(rgba_t(Cache::GetValue(g_cache_files[CacheFilesEnum::Colors], 0xFF0000FF)))
139+
{}
135140

136141
Result<> Start();
137142
Result<> StartWindow();
@@ -223,7 +228,7 @@ class ScreenshotTool
223228
ToolType m_current_tool = ToolType::kNone;
224229
std::vector<annotation_t> m_annotations;
225230
annotation_t m_current_annotation;
226-
uint32_t m_current_color = 0xFF0000FF;
231+
rgba_t m_current_color;
227232
std::array<float, idx(ToolType::Count)> m_tool_thickness;
228233
ImVec4 m_picker_color{ 1, 0, 0, 1 };
229234
bool m_is_drawing = false;

include/util.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -238,8 +238,10 @@ fs::path get_runtime_dir();
238238
#endif
239239
fs::path get_font_path(const std::string& font);
240240
fs::path get_home_config_dir();
241+
fs::path get_home_cache_dir();
241242
fs::path get_home_dir();
242243
fs::path get_config_dir();
244+
fs::path get_cache_dir();
243245

244246
Result<capture_result_t> load_image_rgba(const std::string& path);
245247
Result<std::string> get_config_image_out_fmt();

src/cache.cpp

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
#include "cache.hpp"
2+
3+
#include <filesystem>
4+
#include <fstream>
5+
#include <string>
6+
7+
#include "fmt/format.h"
8+
#include "toml++/toml.hpp"
9+
#include "util.hpp"
10+
11+
std::unordered_map<CacheFilesEnum, cache_entry_t> g_cache_files = {
12+
{ CacheFilesEnum::Colors, { "colors.toml", "cache.default-color-picker-color" } }
13+
};
14+
15+
static fs::path old_pwd;
16+
static void cd(const fs::path& path)
17+
{
18+
if (!path.empty())
19+
{
20+
old_pwd = fs::current_path();
21+
fs::current_path(path);
22+
}
23+
}
24+
25+
static void cd_back()
26+
{
27+
if (!old_pwd.empty())
28+
fs::current_path(old_pwd);
29+
}
30+
31+
// https://github.com/hyprwm/Hyprland/blob/2d2a5bebff72c73cd27db3b9e954b8fa2a7623e8/hyprpm/src/core/DataState.cpp#L24
32+
static bool write_cache(const std::string& str, const std::string& to)
33+
{
34+
// create temp file in a safe temp root
35+
const fs::path& temp_state = (fs::temp_directory_path() / ".temp-state");
36+
std::ofstream of(temp_state, std::ios::trunc);
37+
if (!of.good())
38+
return false;
39+
40+
of << str;
41+
of.close();
42+
43+
return fs::copy_file(temp_state, to, fs::copy_options::overwrite_existing);
44+
}
45+
46+
Cache::Cache(const std::string& cache_dir) : m_cache_dir_path(cache_dir)
47+
{
48+
if (!fs::exists(cache_dir))
49+
{
50+
warn("oshot cache folder was not found, Creating folders at {}!", cache_dir);
51+
fs::create_directories(cache_dir);
52+
}
53+
54+
for (int i = 0; i < int(idx(CacheFilesEnum::COUNT)); ++i)
55+
LoadCacheFile(g_cache_files[enum_<CacheFilesEnum>(i)]);
56+
}
57+
58+
Cache::~Cache()
59+
{
60+
for (const auto& [_, cache] : g_cache_files)
61+
GenerateCacheFile(cache);
62+
}
63+
64+
Result<> Cache::LoadCacheFile(cache_entry_t& entry)
65+
{
66+
// Since the filename (default.theme-file) will be likely
67+
// related to relative path of the config directory, let's
68+
// snapshot and switch to that directory.
69+
cd(m_cache_dir_path);
70+
71+
if (fs::exists(entry.file_path))
72+
{
73+
try
74+
{
75+
entry.tbl = toml::parse_file(entry.file_path);
76+
}
77+
catch (const toml::parse_error& err)
78+
{
79+
// Snap back
80+
cd_back();
81+
return Err(
82+
fmt::format("Parsing cache file '{}' failed:\n"
83+
"{}\n"
84+
"\t(error occurred at line {} column {})",
85+
entry.file_path,
86+
err.description(),
87+
err.source().begin.line,
88+
err.source().begin.column));
89+
}
90+
}
91+
92+
cd_back();
93+
return Ok();
94+
}
95+
96+
void Cache::GenerateCacheFile(const cache_entry_t& entry)
97+
{
98+
cd(m_cache_dir_path);
99+
100+
std::stringstream ss;
101+
ss << "# AUTO-GENERATED FILE. DO NOT EDIT THIS FILE.\n";
102+
ss << "# YOU GONNA MESS SHIT UP. unless you know what you doing ofc\n";
103+
ss << entry.tbl;
104+
105+
if (!write_cache(ss.str(), entry.file_path))
106+
error("Failed to write cache entry at path '{}'", entry.file_path);
107+
cd_back();
108+
}

0 commit comments

Comments
 (0)