cppfig 0.1.0
Modern C++20 compile-time type-safe configuration library
Loading...
Searching...
No Matches
serializer.h
Go to the documentation of this file.
1#pragma once
2
3#include <concepts>
4#include <filesystem>
5#include <fstream>
6#include <istream>
7#include <iterator>
8#include <string>
9#include <string_view>
10
11#include "cppfig/status.h"
12#include "cppfig/value.h"
13
14namespace cppfig {
15
21template <typename S>
22concept Serializer = requires(const Value& data, std::istream& is) {
23 typename S::data_type;
24 { S::Parse(is) } -> std::same_as<StatusOr<Value>>;
25 { S::Stringify(data) } -> std::convertible_to<std::string>;
26};
27
34template <typename S>
35concept MergingSerializer = Serializer<S> && requires(std::string_view existing, const Value& data) {
36 { S::Merge(existing, data) } -> std::convertible_to<std::string>;
37};
38
40template <Serializer S>
41auto ReadFile(const std::string& path) -> StatusOr<Value>
42{
43 std::ifstream file(path);
44 if (!file.is_open()) {
45 return NotFoundError("Could not open file: " + path);
46 }
47 return S::Parse(file);
48}
49
55template <Serializer S>
56auto RenderFile(const std::string& path, const Value& data) -> std::string
57{
58 if constexpr (MergingSerializer<S>) {
59 std::ifstream existing(path);
60 if (existing.is_open()) {
61 const std::string text((std::istreambuf_iterator<char>(existing)), std::istreambuf_iterator<char>());
62 return S::Merge(text, data);
63 }
64 }
65 return S::Stringify(data);
66}
67
75template <Serializer S>
76auto WriteFile(const std::string& path, const Value& data) -> Status
77{
78 namespace fs = std::filesystem;
79
80 const std::string text = RenderFile<S>(path, data);
81
82 const fs::path target(path);
83 const fs::path temp_path = target.parent_path() / (target.filename().string() + ".tmp");
84
85 {
86 std::ofstream file(temp_path);
87 if (!file.is_open()) {
88 return InternalError("Could not write to file: " + path);
89 }
90
91 file << text;
92 file.close();
93
94 if (file.fail()) {
95 std::error_code remove_error;
96 fs::remove(temp_path, remove_error);
97 return InternalError("Failed to write to file: " + path);
98 }
99 }
100
101 // Carry the existing file's permissions over to the replacement, so an
102 // atomic save does not silently reset the mode of a deployed config.
103 std::error_code status_error;
104 const auto existing = fs::status(target, status_error);
105 if (!status_error && fs::exists(existing)) {
106 std::error_code permissions_error;
107 fs::permissions(temp_path, existing.permissions(), fs::perm_options::replace, permissions_error);
108 }
109
110 std::error_code error_code;
111 fs::rename(temp_path, target, error_code);
112 if (error_code) {
113 std::error_code remove_error;
114 fs::remove(temp_path, remove_error);
115 return InternalError("Failed to replace file: " + path + ": " + error_code.message());
116 }
117
118 return OkStatus();
119}
120
121} // namespace cppfig
A value-or-error type, similar to std::expected (C++23).
Definition status.h:102
A lightweight status object carrying an error code and message.
Definition status.h:25
A self-contained, recursive value type for configuration data.
Definition value.h:32
Concept for serializers that can update a document in place.
Definition serializer.h:35
Concept for serializer types.
Definition serializer.h:22
C++20 compile-time type-safe configuration library.
Definition conf.h:17
auto NotFoundError(std::string message) -> Status
Returns a NotFound error status.
Definition status.h:57
auto ReadFile(const std::string &path) -> StatusOr< Value >
Helper to read a file into a Value tree via a serializer.
Definition serializer.h:41
auto InternalError(std::string message) -> Status
Returns an Internal error status.
Definition status.h:69
auto OkStatus() -> Status
Returns an OK status.
Definition status.h:54
auto WriteFile(const std::string &path, const Value &data) -> Status
Helper to write a Value tree to a file via a serializer.
Definition serializer.h:76
auto RenderFile(const std::string &path, const Value &data) -> std::string
Renders the file text for a Value tree.
Definition serializer.h:56