/* * Status.h * * This source file is part of the FoundationDB open source project * * Copyright 2013-2018 Apple Inc. and the FoundationDB project authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef FDBCLIENT_STATUS_H #define FDBCLIENT_STATUS_H #include "fdbclient/JSONDoc.h" // Reads the entire string s as a JSON value // Throws if no value can be parsed or if s contains data after the first JSON value // Trailing whitespace in s is allowed json_spirit::mValue readJSONStrictly(const std::string& s); struct StatusObject : json_spirit::mObject { typedef json_spirit::mObject Map; typedef json_spirit::mArray Array; StatusObject() {} StatusObject(json_spirit::mObject const& o) : json_spirit::mObject(o) {} }; template void load(Ar& ar, StatusObject& statusObj) { std::string value; int32_t length; ar >> length; value.resize(length); ar.serializeBytes(&value[0], (int)value.length()); json_spirit::mValue mv; json_spirit::read_string(value, mv); statusObj = StatusObject(mv.get_obj()); ASSERT(ar.protocolVersion().isValid()); } template void save(Ar& ar, StatusObject const& statusObj) { std::string value = json_spirit::write_string(json_spirit::mValue(statusObj)); ar << (int32_t)value.length(); ar.serializeBytes((void*)&value[0], (int)value.length()); ASSERT(ar.protocolVersion().isValid()); } struct StatusArray : json_spirit::mArray { StatusArray() {} StatusArray(json_spirit::mArray const& o) : json_spirit::mArray(o.begin(), o.end()) {} }; struct StatusValue : json_spirit::mValue { StatusValue() {} StatusValue(json_spirit::mValue const& o) : json_spirit::mValue(o) {} }; inline StatusObject makeMessage(const char* name, const char* description) { StatusObject out; out["name"] = name; out["description"] = description; return out; } // Typedef to cover older code that was written when this class was only a reader and called StatusObjectReader typedef JSONDoc StatusObjectReader; // Template specialization for get because is convenient to get() an // element from an object directly into a JSONDoc to have a handle to that sub-doc. template <> inline bool JSONDoc::get(const std::string path, StatusObjectReader& out, bool split) { bool r = has(path, split); if (r) out = pLast->get_obj(); return r; } // Takes an object by reference so make usage look clean and avoid the client doing object["messages"] which will create // the key. inline bool findMessagesByName(StatusObjectReader object, std::set to_find) { if (!object.has("messages") || object.last().type() != json_spirit::array_type) return false; StatusObject::Array const& messages = object.last().get_array(); // Iterate over message array and look up each name in to_find. // Not using StatusObjectReader here because it would throw if an i in messages is NOT an mObject for (auto i : messages) { // Since we are looking for a positive match, any exceptions thrown when trying to read // the object in the messages array will be perceived as not-a-match and therefore ignored. try { if (to_find.count(i.get_obj().at("name").get_str())) return true; } catch (std::exception&) { } } return false; } #endif