void Path::makePath(const JSONCPP_STRING& path, const InArgs& in) { const char* current = path.c_str(); const char* end = current + path.length(); InArgs::const_iterator itInArg = in.begin(); while (current != end) { if (*current == '[') { ++current; if (*current == '%') addPathInArg(path, in, itInArg, PathArgument::kindIndex); else { ArrayIndex index = 0; for (; current != end && *current >= '0' && *current <= '9'; ++current) index = index * 10 + ArrayIndex(*current - '0'); args_.push_back(index); } if (current == end || *++current != ']') invalidPath(path, int(current - path.c_str())); } else if (*current == '%') { addPathInArg(path, in, itInArg, PathArgument::kindKey); ++current; } else if (*current == '.' || *current == ']') { ++current; } else { const char* beginName = current; while (current != end && !strchr("[.", *current)) ++current; args_.push_back(JSONCPP_STRING(beginName, current)); } } }
static int rewriteValueTree( const JSONCPP_STRING& rewritePath, const Json::Value& root, Options::writeFuncType write, JSONCPP_STRING* rewrite) { *rewrite = write(root); FILE* fout = fopen(rewritePath.c_str(), "wt"); if (!fout) { printf("Failed to create rewrite file: %s\n", rewritePath.c_str()); return 2; } fprintf(fout, "%s\n", rewrite->c_str()); fclose(fout); return 0; }
static JSONCPP_STRING removeSuffix(const JSONCPP_STRING& path, const JSONCPP_STRING& extension) { if (extension.length() >= path.length()) return JSONCPP_STRING(""); JSONCPP_STRING suffix = path.substr(path.length() - extension.length()); if (suffix != extension) return JSONCPP_STRING(""); return path.substr(0, path.length() - extension.length()); }
Json::Value getDOM(std::string const& path) { JSONCPP_STRING input = readInputTestFile(path.c_str()); if (input.empty()) { throw std::runtime_error("Empty input file"); } Json::Features mode = Json::Features::strictMode(); mode.allowComments_ = true; Json::Value root; Json::Reader reader(mode); bool parsingSuccessful = reader.parse(input.data(), input.data() + input.size(), root); if (!parsingSuccessful) { throw std::runtime_error( std::string("Failed to parse file: ") + reader.getFormattedErrorMessages()); } return root; }
static int runTest(Options const& opts) { int exitCode = 0; JSONCPP_STRING input = readInputTestFile(opts.path.c_str()); if (input.empty()) { printf("Failed to read input or empty input: %s\n", opts.path.c_str()); return 3; } JSONCPP_STRING basePath = removeSuffix(opts.path, ".json"); if (!opts.parseOnly && basePath.empty()) { printf("Bad input path. Path does not end with '.expected':\n%s\n", opts.path.c_str()); return 3; } JSONCPP_STRING const actualPath = basePath + ".actual"; JSONCPP_STRING const rewritePath = basePath + ".rewrite"; JSONCPP_STRING const rewriteActualPath = basePath + ".actual-rewrite"; Json::Value root; exitCode = parseAndSaveValueTree( input, actualPath, "input", opts.features, opts.parseOnly, &root); if (exitCode || opts.parseOnly) { return exitCode; } JSONCPP_STRING rewrite; exitCode = rewriteValueTree(rewritePath, root, opts.write, &rewrite); if (exitCode) { return exitCode; } Json::Value rewriteRoot; exitCode = parseAndSaveValueTree( rewrite, rewriteActualPath, "rewrite", opts.features, opts.parseOnly, &rewriteRoot); if (exitCode) { return exitCode; } return 0; }
static int parseAndSaveValueTree(const JSONCPP_STRING& input, const JSONCPP_STRING& actual, const JSONCPP_STRING& kind, const Json::Features& features, bool parseOnly, Json::Value* root) { Json::Reader reader(features); bool parsingSuccessful = reader.parse(input.data(), input.data() + input.size(), *root); if (!parsingSuccessful) { printf("Failed to parse %s file: \n%s\n", kind.c_str(), reader.getFormattedErrorMessages().c_str()); return 1; } if (!parseOnly) { FILE* factual = fopen(actual.c_str(), "wt"); if (!factual) { printf("Failed to create %s actual file.\n", kind.c_str()); return 2; } printValueTree(factual, *root); fclose(factual); } return 0; }
static void printValueTree(FILE* fout, Json::Value& value, const JSONCPP_STRING& path = ".") { if (value.hasComment(Json::commentBefore)) { fprintf(fout, "%s\n", value.getComment(Json::commentBefore).c_str()); } switch (value.type()) { case Json::nullValue: fprintf(fout, "%s=null\n", path.c_str()); break; case Json::intValue: fprintf(fout, "%s=%s\n", path.c_str(), Json::valueToString(value.asLargestInt()).c_str()); break; case Json::uintValue: fprintf(fout, "%s=%s\n", path.c_str(), Json::valueToString(value.asLargestUInt()).c_str()); break; case Json::realValue: fprintf(fout, "%s=%s\n", path.c_str(), normalizeFloatingPointStr(value.asDouble()).c_str()); break; case Json::stringValue: fprintf(fout, "%s=\"%s\"\n", path.c_str(), value.asString().c_str()); break; case Json::booleanValue: fprintf(fout, "%s=%s\n", path.c_str(), value.asBool() ? "true" : "false"); break; case Json::arrayValue: { fprintf(fout, "%s=[]\n", path.c_str()); Json::ArrayIndex size = value.size(); for (Json::ArrayIndex index = 0; index < size; ++index) { static char buffer[16]; #if defined(_MSC_VER) && defined(__STDC_SECURE_LIB__) sprintf_s(buffer, sizeof(buffer), "[%d]", index); #else snprintf(buffer, sizeof(buffer), "[%d]", index); #endif printValueTree(fout, value[index], path + buffer); } } break; case Json::objectValue: { fprintf(fout, "%s={}\n", path.c_str()); Json::Value::Members members(value.getMemberNames()); std::sort(members.begin(), members.end()); JSONCPP_STRING suffix = *(path.end() - 1) == '.' ? "" : "."; for (Json::Value::Members::iterator it = members.begin(); it != members.end(); ++it) { const JSONCPP_STRING name = *it; printValueTree(fout, value[name], path + suffix + name); } } break; default: break; } if (value.hasComment(Json::commentAfter)) { fprintf(fout, "%s\n", value.getComment(Json::commentAfter).c_str()); } }
Value::Value(const JSONCPP_STRING& value) { initBasic(stringValue, true); value_.string_ = duplicateAndPrefixStringValue(value.data(), static_cast<unsigned>(value.length())); }
PathArgument::PathArgument(const JSONCPP_STRING& key) : key_(key.c_str()), index_(), kind_(kindKey) {}
void Value::setComment(const JSONCPP_STRING& comment, CommentPlacement placement) { setComment(comment.c_str(), comment.length(), placement); }
bool Value::isMember(JSONCPP_STRING const& key) const { return isMember(key.data(), key.data() + key.length()); }
Value Value::removeMember(const JSONCPP_STRING& key) { return removeMember(key.c_str()); }
bool Value::removeMember(JSONCPP_STRING const& key, Value* removed) { return removeMember(key.data(), key.data() + key.length(), removed); }
Value Value::get(JSONCPP_STRING const& key, Value const& defaultValue) const { return get(key.data(), key.data() + key.length(), defaultValue); }
static JSONCPP_STRING valueToQuotedStringN(const char* value, unsigned length) { if (value == NULL) return ""; // Not sure how to handle unicode... if (strnpbrk(value, "\"\\\b\f\n\r\t", length) == NULL && !containsControlCharacter0(value, length)) return JSONCPP_STRING("\"") + value + "\""; // We have to walk value and escape any special characters. // Appending to JSONCPP_STRING is not efficient, but this should be rare. // (Note: forward slashes are *not* rare, but I am not escaping them.) JSONCPP_STRING::size_type maxsize = length * 2 + 3; // allescaped+quotes+NULL JSONCPP_STRING result; result.reserve(maxsize); // to avoid lots of mallocs result += "\""; char const* end = value + length; for (const char* c = value; c != end; ++c) { switch (*c) { case '\"': result += "\\\""; break; case '\\': result += "\\\\"; break; case '\b': result += "\\b"; break; case '\f': result += "\\f"; break; case '\n': result += "\\n"; break; case '\r': result += "\\r"; break; case '\t': result += "\\t"; break; // case '/': // Even though \/ is considered a legal escape in JSON, a bare // slash is also legal, so I see no reason to escape it. // (I hope I am not misunderstanding something.) // blep notes: actually escaping \/ may be useful in javascript to avoid </ // sequence. // Should add a flag to allow this compatibility mode and prevent this // sequence from occurring. default: if ((isControlCharacter(*c)) || (*c == 0)) { JSONCPP_OSTRINGSTREAM oss; oss << "\\u" << std::hex << std::uppercase << std::setfill('0') << std::setw(4) << static_cast<int>(*c); result += oss.str(); } else { result += *c; } break; } } result += "\""; return result; }