Persist.h
Go to the documentation of this file.
1 /** Persist structured information.
2  *
3  * Any and all structured information that needs to be loaded or saved
4  * uses the methods in WireCell::Persist to do so. The transient data
5  * model is that of JsonCPP's Json::Value. The persistent format is
6  * either JSON or if the toolkit has support compiled in, Jsonnet.
7  *
8  * Note, "external" data which may be voluminous, complex or otherwise
9  * inconvenient to convert to JSON would not use WireCell::Persist but
10  * rather be brought between files and an IData model using an
11  * ISink/ISource.
12  *
13  * See also WireCellUtil/Configuration.h for how the configuration
14  * layer uses Json::Value objects. Large configuration items like
15  * wire geometry and field response are also loaded as JSON.
16  */
17 
18 #ifndef WIRECELL_PERSIST
19 #define WIRECELL_PERSIST
20 
21 #include <json/json.h>
22 #include "libjsonnet++.h"
23 #include <boost/filesystem.hpp>
24 #include <vector>
25 #include <string>
26 
27 namespace WireCell {
28  namespace Persist {
29 
30  /// Return true file exists (no file resolution performed).
31  bool exists(const std::string& filename);
32 
33 
34  /** Return full path to a file of the given filename. If the
35  * file is not directly located and is a relative path then
36  * the file will be first located in the current working
37  * directory. Failing that if the `WIRECELL_PATH` environment
38  * variable is defined and set as a `:`-separated list it will
39  * be checked. Failure to resolve returns an empty string. */
40  std::string resolve(const std::string& filename);
41 
42  /** Return a string holding the entire contents of the file.
43  * File resolution is performed. WireCell::IOError is thrown
44  * if file is not found. */
45  std::string slurp(const std::string& filename);
46 
47 
48  /// Save the data structure held by the given top Json::Value
49  /// in to a file of the given name. The format of the file is
50  /// determined by the file name extension. Valid extensions
51  /// are:
52  ///
53  /// - .json :: JSON text format
54  /// - .json.bz2 :: JSON text format compressed with bzip2
55  ///
56  /// If `pretty` is true then format the JSON text with
57  /// indents. If also compressed, this formatting can actually
58  /// lead to *smaller* files.
59  void dump(const std::string& filename, const Json::Value& top, bool pretty=false);
60 
61  /// As above but dump to a JSON text string.
62  // fixme: no "pretty" for dumps() is implemented.
63  std::string dumps(const Json::Value& top, bool pretty=false);
64 
65  /// This can hold either Jsonnet external variable/value pairs
66  /// The value is a string representation of a simple scalar
67  /// value, or a data structure if used as code. This type may
68  /// also be used to hold JSON path/value pairs.
69  typedef std::map<std::string, std::string> externalvars_t;
70 
71  /** Load a file and return the top JSON value.
72 
73  If extension is `.jsonnet` and Jsonnet support is compiled
74  in, evaluate the file and use the resulting JSON. Other
75  supported extensions include raw (`.json`) or compressed
76  (`.json.bz2`) files.
77 
78  WireCell::IOError is thrown if file is not found.
79  */
80  Json::Value load(const std::string& filename,
81  const externalvars_t& extvar = externalvars_t(),
82  const externalvars_t& extcode = externalvars_t());
83 
84  /** Load a JSON or Jsonnet string, returning a Json::Value. */
85  Json::Value loads(const std::string& text,
86  const externalvars_t& extvar = externalvars_t(),
87  const externalvars_t& extcode = externalvars_t());
88 
89  /** Explicitly evaluate contents of file with Jsonnet. If no
90  support for Jsonnet is built, return the contents of
91  file. Return empty string if Jsonnet evaluation failes.
92 
93  WireCell::IOError is thrown if file is not found.
94  WireCell::ValueError is thrown parsing fails.
95  */
97  const externalvars_t& extvar = externalvars_t(),
98  const externalvars_t& extcode = externalvars_t());
99 
100  /** Explicitly evaluate text with JSonnet. If no support for
101  Jsonnet is built, return the text. Return empty string if
102  Jsonnet evaluation failes.
103 
104  WireCell::ValueError is thrown parsing fails.
105  */
107  const externalvars_t& extvar = externalvars_t(),
108  const externalvars_t& extcode = externalvars_t());
109 
110  /** Explicitly convert JSON text to Json::Value object */
111  Json::Value json2object(const std::string& text);
112 
113 
114  /** Convert a collection to a Json::Value */
115  // not really about persistence....
116  template <typename Iterable>
117  Json::Value iterable2json(Iterable const& cont) {
118  Json::Value v;
119  for (auto&& element: cont) {
120  v.append(element);
121  }
122  return v;
123  }
124 
125  // This provides a super set of the functionality as the above
126  // free functions. It wraps a persistent Jsonnet parser and
127  // in particular allows more control over the load path.
128  class Parser {
129  public:
130  typedef std::vector<std::string> pathlist_t;
131 
132  Parser(const pathlist_t& load_paths = pathlist_t(),
133  const externalvars_t& extvar = externalvars_t(),
134  const externalvars_t& extcode = externalvars_t());
135 
136  // Load a Jonnet file (or .json or .json.bz2) and return the Json object
137  Json::Value load(const std::string& filename);
138 
139  // Load Jsonnet text and return the Json object
140  Json::Value loads(const std::string& text);
141 
142  // Resolve absolute path to a file against load path
143  std::string resolve(const std::string& filename);
144 
145  private:
146  jsonnet::Jsonnet m_jsonnet;
147  std::vector<boost::filesystem::path> m_load_paths;
148 
149  };
150  }
151 }
152 
153 
154 #endif
std::string evaluate_jsonnet_file(const std::string &filename, const externalvars_t &extvar=externalvars_t(), const externalvars_t &extcode=externalvars_t())
Definition: Persist.cxx:185
std::string resolve(const std::string &filename)
Below is a reimplimenatiaon of the above but in class form..... /.
Definition: Persist.cxx:258
std::vector< boost::filesystem::path > m_load_paths
Definition: Persist.h:147
std::vector< std::string > pathlist_t
Definition: Persist.h:130
std::string dumps(const Json::Value &top, bool pretty=false)
As above but dump to a JSON text string.
Definition: Persist.cxx:58
std::string evaluate_jsonnet_text(const std::string &text, const externalvars_t &extvar=externalvars_t(), const externalvars_t &extcode=externalvars_t())
Definition: Persist.cxx:205
Json::Value json2object(const std::string &text)
Definition: Persist.cxx:161
std::string string
Definition: nybbler.cc:12
std::map< std::string, std::string > externalvars_t
Definition: Persist.h:69
string filename
Definition: train.py:213
Parser(const pathlist_t &load_paths=pathlist_t(), const externalvars_t &extvar=externalvars_t(), const externalvars_t &extcode=externalvars_t())
Definition: Persist.cxx:221
GenericValue< UTF8<> > Value
GenericValue with UTF8 encoding.
Definition: document.h:2106
Json::Value load(const std::string &filename, const externalvars_t &extvar=externalvars_t(), const externalvars_t &extcode=externalvars_t())
Definition: Persist.cxx:121
bool exists(const std::string &filename)
Return true file exists (no file resolution performed).
Definition: Persist.cxx:79
Definition: Main.h:22
Json::Value loads(const std::string &text, const externalvars_t &extvar=externalvars_t(), const externalvars_t &extcode=externalvars_t())
Definition: Persist.cxx:152
Json::Value load(const std::string &filename)
Definition: Persist.cxx:276
void dump(const std::string &filename, const Json::Value &top, bool pretty=false)
Definition: Persist.cxx:37
jsonnet::Jsonnet m_jsonnet
Definition: Persist.h:146
std::string slurp(const std::string &filename)
Definition: Persist.cxx:65
std::string resolve(const std::string &filename)
Definition: Persist.cxx:99
Json::Value loads(const std::string &text)
Definition: Persist.cxx:312
Json::Value iterable2json(Iterable const &cont)
Definition: Persist.h:117