OSVR Framework (Internal Development Docs)  0.6-1962-g59773924
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
JSONResolvePossibleRef.cpp
Go to the documentation of this file.
1 
11 // Copyright 2015 Sensics, Inc.
12 //
13 // Licensed under the Apache License, Version 2.0 (the "License");
14 // you may not use this file except in compliance with the License.
15 // You may obtain a copy of the License at
16 //
17 // http://www.apache.org/licenses/LICENSE-2.0
18 //
19 // Unless required by applicable law or agreed to in writing, software
20 // distributed under the License is distributed on an "AS IS" BASIS,
21 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
22 // See the License for the specific language governing permissions and
23 // limitations under the License.
24 
25 // Internal Includes
26 #include "JSONResolvePossibleRef.h"
27 
28 // Library/third-party includes
29 #include <json/reader.h>
30 #include <boost/filesystem.hpp>
31 
32 // Standard includes
33 #include <fstream>
34 #include <string>
35 #include <utility>
36 #include <tuple>
37 
38 using std::make_pair;
39 using std::tie;
40 
41 namespace osvr {
42 namespace server {
43 
48  static inline std::pair<FileLoadAttempt, Json::Value>
49  attemptFileLoad(std::string const &fullFn) {
50 
51  Json::Value ret{Json::nullValue};
52  auto attempt = FileLoadAttempt{fullFn};
53 
54  std::ifstream file{fullFn};
55  if (!file) {
56  attempt.status = FileLoadStatus::CouldNotOpenFile;
57  return make_pair(attempt, ret);
58  }
59 
60  Json::Reader reader;
61  if (!reader.parse(file, ret)) {
62  attempt.status = FileLoadStatus::CouldNotParseFile;
63  attempt.details = reader.getFormattedErrorMessages();
64 
65  ret = Json::nullValue;
66  return make_pair(attempt, ret);
67  }
68 
69  attempt.status = FileLoadStatus::FileOpenedAndParsed;
70  return make_pair(attempt, ret);
71  }
72 
77  static inline std::pair<bool, Json::Value>
78  loadFromFile(FileLoadAttempts &attempts, std::string const &fn,
79  std::vector<std::string> const &searchPath) {
80  Json::Value ret{Json::nullValue};
81  for (auto const &path : searchPath) {
82  auto fullFn = boost::filesystem::path(path) / fn;
83  FileLoadAttempt attempt;
84  tie(attempt, ret) = attemptFileLoad(fullFn.string());
85  attempts.push_back(attempt);
86  if (attempt.status == FileLoadStatus::FileOpenedAndParsed) {
87  return make_pair(true, ret);
88  }
89  }
90 
91  // Last ditch effort, or only attempt if no search path provided
92  // This effectively uses the current working directory.
93  FileLoadAttempt attempt;
94  tie(attempt, ret) = attemptFileLoad(fn);
95  attempts.push_back(attempt);
96  return make_pair(FileLoadStatus::FileOpenedAndParsed == attempt.status,
97  ret);
98  }
99 
100  ResolveRefResult
101  resolvePossibleRefWithDetails(Json::Value const &input,
102  bool stringAcceptableResult,
103  std::vector<std::string> const &searchPath) {
104  ResolveRefResult ret;
105  ret.result = Json::nullValue;
106 
107  if (input.isString()) {
108  tie(ret.resolved, ret.result) =
109  loadFromFile(ret.fileAttempts, input.asString(), searchPath);
110  if (ret.resolved) {
111  ret.handledAs = ValueHandledAs::Filename;
112  return ret;
113  }
114  if (stringAcceptableResult) {
115  ret.result = input;
116  ret.handledAs = ValueHandledAs::String;
117  }
118  // If given a string, whether or not that's acceptable, we'll be
119  // done at the end here.
120  return ret;
121  }
122 
123  // Rough parsing of some json ref
124  if (input.isObject() && input.isMember("$ref")) {
126  tie(ret.resolved, ret.result) = loadFromFile(
127  ret.fileAttempts, input["$ref"].asString(), searchPath);
128  if (ret.resolved) {
129  ret.handledAs = ValueHandledAs::JsonRefToFile;
130  return ret;
131  }
132  }
133 
134  ret.result = input;
135  return ret;
136  }
137 
138  Json::Value resolvePossibleRef(Json::Value const &input,
139  bool stringAcceptableResult,
140  std::vector<std::string> const &searchPath) {
142  auto ret = resolvePossibleRefWithDetails(input, stringAcceptableResult,
143  searchPath);
144  return ret.result;
145  }
146 
147  const char *fileLoadStatusToString(FileLoadStatus status) {
148  switch (status) {
149  case FileLoadStatus::CouldNotOpenFile:
150  return "Could not open file";
151 
152  case FileLoadStatus::CouldNotParseFile:
153  return "Could not parse file, ";
154 
155  case FileLoadStatus::FileOpenedAndParsed:
156  return "File opened and parsed";
157  }
158  return "";
159  }
160 } // namespace server
161 } // namespace osvr
Json::Value resolvePossibleRef(Json::Value const &input, bool stringAcceptableResult, std::vector< std::string > const &searchPath)
Given an input that might be a filename, might be a JSON Pointer-style $ref object, and might just directly be an object, return the object desired.
ResolveRefResult resolvePossibleRefWithDetails(Json::Value const &input, bool stringAcceptableResult, std::vector< std::string > const &searchPath)