initial; functional, might as well release
[sispare-qt.git] / util.cc
blob7ecb62d200b5e91836c77922791383068a99b259
1 /*
2 * Copyright (c) 2021, S. Gilles <sgilles@sgilles.net>
4 * Permission to use, copy, modify, and/or distribute this software
5 * for any purpose with or without fee is hereby granted, provided
6 * that the above copyright notice and this permission notice appear
7 * in all copies.
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
10 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
11 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
12 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
13 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
14 * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
15 * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
16 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 #include "util.hh"
20 #include <fstream>
21 #include <iostream>
23 /* Find the right "~/.data/sispare" or "~/.sispare" or something */
24 std::filesystem::path
25 Util::find_data_dir()
27 char *xdg_data_home = getenv("XDG_DATA_HOME");
29 if (xdg_data_home) {
30 return std::filesystem::path(xdg_data_home) / "sispare";
33 char *home = getenv("HOME");
35 if (home) {
36 return std::filesystem::path(home) / ".sispare";
39 throw std::runtime_error("You have no $HOME. I give up.");
42 /* Print exception, maybe with stack trace */
43 void
44 Util::output_nested_ex(const std::exception& ex, int level)
46 if (level == 0) {
47 std::cerr << "Error:" << std::endl;
50 std::cerr << std::string(level, '.') << ex.what() << std::endl;
51 try {
52 std::rethrow_if_nested(ex);
53 } catch (const std::exception& ex2) {
54 output_nested_ex(ex2, level + 1);
55 } catch (...) {}
58 /* Slurp file into string (for reading A/B sides). throws on failure */
59 std::string
60 Util::slurp(const std::filesystem::path& path)
62 std::ifstream ii(path, std::ios::in | std::ios::binary);
64 if (ii) {
65 std::string slurped;
67 ii.seekg(0, std::ios::end);
68 slurped.resize(ii.tellg());
69 ii.seekg(0, std::ios::beg);
70 ii.read(&slurped[0], slurped.size());
71 ii.close();
73 /* Remove trailing newline */
74 if (std::isspace(slurped.back())) {
75 slurped.pop_back();
78 return slurped;
81 std::ostringstream err;
83 err << "Cannot read " << path;
84 throw std::runtime_error(err.str());