Euphoria
json.cc
Go to the documentation of this file.
1 // Copyright (2015) Gustav
2 
3 #include "io/json.h"
4 
5 #include "assert/assert.h"
6 #include "log/log.h"
7 
9 #include "base/stringmerger.h"
10 #include "base/functional.h"
11 
12 
13 #include "io/vfs.h"
14 #include "io/vfs_path.h"
15 
16 #include <fstream>
17 
18 namespace eu::io
19 {
20  std::string
22  {
23  // todo(Gustav): walk vfs tree to display what part of the file exists
24  // For example:
25  // ~/folder/dir/file.txt is requested
26  // dir/file.txt is missing in ~/folder/
27  // or
28  // ~/folder/[dir/file.txt] exists...
29 
30  constexpr std::size_t max_items = 3;
31 
32  const auto files = fs->list_files(p.get_directory());
33  const auto file_name = p.get_file_with_extension();
34  const auto values = map<std::string>
35  (
36  search::find_closest<search::Match>
37  (
38  max_items, files,
39  [&](const auto& value) -> search::Match
40  {
41  // todo(Gustav): ignore directories?
42  return {value.name, file_name};
43  }
44  ),
45  [](const search::Match& m)
46  {
47  return m.name;
48  }
49  );
50 
51  const auto all_entries = string_mergers::array.merge(map<std::string>(files, [](const auto& f) { return f.name; }));
52  const auto closest = string_mergers::english_or.merge(values);
53  return fmt::format("File {} was requrested with roots: {}. All entries: {}. Did you mean {}?", p, fs->get_roots_as_string(), all_entries, closest);
54  }
55 
58  (
59  FileSystem* fs,
60  const FilePath& file_name
61  )
62  {
63  const auto source = fs->read_file_to_string(file_name);
64  if (!source)
65  {
67  }
68 
69  const auto result = jsonh::Parse(*source, jsonh::parse_flags::Json);
70  if (!result)
71  {
72  std::ostringstream ss;
73  ss << "Parse error:\n";
74  for (const auto& err : result.errors)
75  {
76  const auto& loc = err.location;
77  ss << "file("
78  << loc.line << ":"
79  << loc.column << "): "
80  << err.message << "\n";
81  }
83  }
84 
85  return JsonResult::create_value({result.doc, *result.root});
86  }
87 
88  std::string
89  could_be(const std::string& invalid_value, const std::vector<std::string>& possible_values)
90  {
91  constexpr std::size_t max_items = 3;
92  const auto values = map<std::string>
93  (
94  search::find_closest<search::Match>
95  (
96  max_items, possible_values,
97  [&](const auto& value) -> search::Match
98  {
99  return {value, invalid_value};
100  }
101  ),
102  [](const search::Match& m)
103  {
104  return m.name;
105  }
106  );
107  return string_mergers::english_or.merge(values);
108  }
109 
110 
111  std::optional<jsonh::Value>
112  ObjectQuery::get(const std::string& name)
113  {
114  const auto ret = object->object.find(name);
115 
116  if (ret != object->object.end())
117  {
118  found.emplace(name);
119  return ret->second;
120  }
121  else
122  {
123  missing.emplace(name);
124  return std::nullopt;
125  }
126  }
127 
128  ObjectQuery::ObjectQuery(const jsonh::Object* o)
129  : object(o)
130  {
131  }
132 
133  std::optional<std::string>
135  {
136  std::vector<std::string> errors;
137 
138  const auto miss = std::vector<std::string>(missing.begin(), missing.end());
139 
140  for (const auto& x : object->object)
141  {
142  const auto& key = x.first;
143  if (found.find(key) != found.end()) { continue; }
144 
145  // todo(Gustav): add file, line and column
146  errors.emplace_back(fmt::format("existing key {} was not read, could be {}", key, could_be(key, miss)));
147  }
148 
149  for (const auto& r : required)
150  {
151  errors.emplace_back(fmt::format("required key {} was missing from json object", r));
152  }
153 
154  if (errors.empty()) { return std::nullopt; }
155 
156  // todo(Gustav): join with newlines instead?
157  else { return string_mergers::english_and.merge(errors); }
158  }
159 }
160 
Definition: enum.h:8
JsonResult read_json_file(FileSystem *fs, const FilePath &file_name)
Definition: json.cc:58
std::string could_be(const std::string &invalid_value, const std::vector< std::string > &possible_values)
Definition: json.cc:89
std::string get_string_from_path_for_debugging(FileSystem *fs, const FilePath &p)
Definition: json.cc:21
Result< Json, JsonError > JsonResult
Definition: json.h:24
constexpr StringMerger english_and
Definition: stringmerger.h:89
constexpr StringMerger english_or
Definition: stringmerger.h:90
constexpr StringMerger array
Definition: stringmerger.h:91
static Self create_error(const Error &error)
Definition: result.h:21
static Self create_value(const T &t)
Definition: result.h:15
std::string merge(const std::vector< std::string > &strings) const
Definition: stringmerger.cc:11
std::optional< std::string > read_file_to_string(const FilePath &path)
Definition: vfs.cc:171
std::string get_roots_as_string()
Definition: vfs.cc:157
std::vector< ListedFile > list_files(const DirPath &path)
Definition: vfs.cc:127
std::optional< std::string > get_missing_errors_message()
Definition: json.cc:134
ObjectQuery(const jsonh::Object *o)
Definition: json.cc:128
const jsonh::Object * object
Definition: json.h:41
std::vector< std::string > required
Definition: json.h:45
std::set< std::string > found
Definition: json.h:43
std::optional< jsonh::Value > get(const std::string &name)
Definition: json.cc:112
std::set< std::string > missing
Definition: json.h:44