You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@quickstep.apache.org by ji...@apache.org on 2016/11/18 21:25:22 UTC
[1/3] incubator-quickstep git commit: Initial commit
Repository: incubator-quickstep
Updated Branches:
refs/heads/viz [created] c618f9ec1
http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/c618f9ec/viz/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/viz/CMakeLists.txt b/viz/CMakeLists.txt
new file mode 100644
index 0000000..3521560
--- /dev/null
+++ b/viz/CMakeLists.txt
@@ -0,0 +1,66 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you 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.
+
+add_subdirectory(configs)
+add_subdirectory(rules)
+
+# Declare micro-libs:
+add_library(quickstep_viz_VizAnalyzer VizAnalyzer.cpp VizAnalyzer.hpp)
+add_library(quickstep_viz_VizContext VizContext.cpp VizContext.hpp)
+add_library(quickstep_viz_VizEngine VizEngine.cpp VizEngine.hpp)
+add_library(quickstep_viz_VizHelper VizHelper.cpp VizHelper.hpp)
+add_library(quickstep_viz_VizObject VizObject.cpp VizObject.hpp)
+
+# Link dependencies:
+target_link_libraries(quickstep_viz_VizAnalyzer
+ quickstep_catalog_CatalogTypedefs
+ quickstep_queryexecution_QueryExecutionTypedefs
+ quickstep_queryoptimizer_expressions_AttributeReference
+ quickstep_queryoptimizer_expressions_ExpressionUtil
+ quickstep_queryoptimizer_physical_Aggregate
+ quickstep_queryoptimizer_physical_Physical
+ quickstep_queryoptimizer_physical_PhysicalType
+ quickstep_utility_Macros
+ quickstep_viz_VizObject)
+target_link_libraries(quickstep_viz_VizContext
+ quickstep_utility_Macros
+ quickstep_viz_VizObject)
+target_link_libraries(quickstep_viz_VizEngine
+ quickstep_utility_ExecutionDAGVisualizer
+ quickstep_utility_Macros
+ quickstep_utility_PlanVisualizer
+ quickstep_viz_VizAnalyzer
+ quickstep_viz_VizContext
+ quickstep_viz_configs_DumpRelation
+ quickstep_viz_configs_VizConfig
+ quickstep_viz_rules_VizRule
+ quickstep_viz_rules_Grouping)
+target_link_libraries(quickstep_viz_VizHelper
+ quickstep_queryexecution_QueryExecutionTypedefs
+ quickstep_queryoptimizer_LogicalGenerator
+ quickstep_queryoptimizer_OptimizerContext
+ quickstep_queryoptimizer_PhysicalGenerator
+ quickstep_queryoptimizer_physical_Physical
+ quickstep_viz_VizAnalyzer
+ quickstep_viz_VizContext
+ quickstep_viz_VizEngine
+ quickstep_utility_Macros)
+target_link_libraries(quickstep_viz_VizObject
+ quickstep_catalog_CatalogTypedefs
+ quickstep_utility_Macros
+ quickstep_utility_StringUtil
+ quickstep_utility_TreeStringSerializable)
http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/c618f9ec/viz/VizAnalyzer.cpp
----------------------------------------------------------------------
diff --git a/viz/VizAnalyzer.cpp b/viz/VizAnalyzer.cpp
new file mode 100644
index 0000000..b070bab
--- /dev/null
+++ b/viz/VizAnalyzer.cpp
@@ -0,0 +1,97 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ **/
+
+#include "viz/VizAnalyzer.hpp"
+
+#include <cstddef>
+#include <unordered_map>
+#include <vector>
+
+#include "query_optimizer/expressions/AttributeReference.hpp"
+#include "query_optimizer/expressions/ExpressionUtil.hpp"
+#include "query_optimizer/physical/Aggregate.hpp"
+#include "query_optimizer/physical/Physical.hpp"
+#include "query_optimizer/physical/PhysicalType.hpp"
+
+#include "glog/logging.h"
+
+namespace quickstep {
+namespace viz {
+
+namespace E = ::quickstep::optimizer::expressions;
+namespace P = ::quickstep::optimizer::physical;
+
+bool VizAnalyzer::findGroupByAttributes(
+ std::vector<attribute_id> *group_by_attribute_ids) const {
+ std::vector<E::AttributeReferencePtr> group_by_attributes;
+ if (findGroupByAttributesInternal(physical_plan_, &group_by_attributes)) {
+ CHECK(!group_by_attributes.empty());
+
+ std::unordered_map<E::ExprId, attribute_id> attr_id_map;
+ const std::vector<E::AttributeReferencePtr> query_result_attributes =
+ physical_plan_->getOutputAttributes();
+ for (std::size_t i = 0; i < query_result_attributes.size(); ++i) {
+ attr_id_map.emplace(query_result_attributes[i]->id(), i);
+ }
+
+ for (const auto &attr : group_by_attributes) {
+ const auto attr_it = attr_id_map.find(attr->id());
+ CHECK(attr_it != attr_id_map.end());
+ group_by_attribute_ids->emplace_back(attr_it->second);
+ }
+ return true;
+ }
+ return false;
+}
+
+bool VizAnalyzer::findGroupByAttributesInternal(
+ const P::PhysicalPtr &physical_plan,
+ std::vector<E::AttributeReferencePtr> *group_by_attributes) const {
+ switch (physical_plan->getPhysicalType()) {
+ case P::PhysicalType::kTopLevelPlan: // Fall through
+ case P::PhysicalType::kSort:
+ case P::PhysicalType::kSelection: {
+ if (!findGroupByAttributesInternal(physical_plan->children().at(0),
+ group_by_attributes)) {
+ return false;
+ }
+ if (!E::SubsetOfExpressions(*group_by_attributes,
+ physical_plan->getOutputAttributes())) {
+ return false;
+ }
+ return true;
+ }
+ case P::PhysicalType::kAggregate: {
+ const P::AggregatePtr &aggregate =
+ std::static_pointer_cast<const P::Aggregate>(physical_plan);
+ if (aggregate->grouping_expressions().empty()) {
+ return false;
+ }
+ *group_by_attributes = E::ToRefVector(aggregate->grouping_expressions());
+ return true;
+ }
+ default:
+ return false;
+ }
+}
+
+
+
+} // namespace viz
+} // namespace quickstep
http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/c618f9ec/viz/VizAnalyzer.hpp
----------------------------------------------------------------------
diff --git a/viz/VizAnalyzer.hpp b/viz/VizAnalyzer.hpp
new file mode 100644
index 0000000..5bcf24c
--- /dev/null
+++ b/viz/VizAnalyzer.hpp
@@ -0,0 +1,116 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 QUICKSTEP_VIZ_VIZ_ANALYZER_HPP_
+#define QUICKSTEP_VIZ_VIZ_ANALYZER_HPP_
+
+#include <cstddef>
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "catalog/CatalogTypedefs.hpp"
+#include "query_execution/QueryExecutionTypedefs.hpp"
+#include "query_optimizer/expressions/AttributeReference.hpp"
+#include "query_optimizer/physical/Physical.hpp"
+#include "utility/Macros.hpp"
+#include "viz/VizObject.hpp"
+
+#include "glog/logging.h"
+
+namespace quickstep {
+
+class CatalogDatabase;
+class CatalogRelation;
+class QueryPlan;
+class StorageManager;
+
+namespace viz {
+
+/** \addtogroup Viz
+ * @{
+ */
+
+class VizAnalyzer : public VizObject {
+ public:
+ VizAnalyzer(const optimizer::physical::PhysicalPtr &physical_plan,
+ const QueryPlan *execution_plan,
+ const std::vector<WorkOrderTimeEntry> *profiling_stats,
+ const CatalogRelation *query_result_relation,
+ const CatalogDatabase *catalog_database,
+ StorageManager *storage_manager)
+ : physical_plan_(physical_plan),
+ execution_plan_(execution_plan),
+ profiling_stats_(profiling_stats),
+ query_result_relation_(query_result_relation),
+ catalog_database_(catalog_database),
+ storage_manager_(storage_manager) {}
+
+ std::string getName() const override {
+ return "VizAnalyzer";
+ }
+
+ inline const optimizer::physical::PhysicalPtr& getQueryPlan() const {
+ return physical_plan_;
+ }
+
+ const QueryPlan* getExecutionPlan() const {
+ return execution_plan_;
+ }
+
+ const std::vector<WorkOrderTimeEntry>* getProfilingStats() const {
+ return profiling_stats_;
+ }
+
+ const CatalogRelation *getRelation() const {
+ return query_result_relation_;
+ }
+
+ const CatalogDatabase *getDatabase() const {
+ return catalog_database_;
+ }
+
+ StorageManager *getStorageManager() const {
+ return storage_manager_;
+ }
+
+ bool findGroupByAttributes(
+ std::vector<attribute_id> *group_by_attribute_ids) const;
+
+ private:
+ bool findGroupByAttributesInternal(
+ const optimizer::physical::PhysicalPtr &physical_plan,
+ std::vector<optimizer::expressions::AttributeReferencePtr> *group_by_attributes) const;
+
+ const optimizer::physical::PhysicalPtr physical_plan_;
+ const QueryPlan *execution_plan_;
+ const std::vector<WorkOrderTimeEntry> *profiling_stats_;
+ const CatalogRelation *query_result_relation_;
+ const CatalogDatabase *catalog_database_;
+ StorageManager *storage_manager_;
+
+ DISALLOW_COPY_AND_ASSIGN(VizAnalyzer);
+};
+
+/** @} */
+
+} // namespace viz
+} // namespace quickstep
+
+#endif // QUICKSTEP_VIZ_VIZ_ANALYZER_HPP_
http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/c618f9ec/viz/VizContext.cpp
----------------------------------------------------------------------
diff --git a/viz/VizContext.cpp b/viz/VizContext.cpp
new file mode 100644
index 0000000..243622c
--- /dev/null
+++ b/viz/VizContext.cpp
@@ -0,0 +1,51 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ **/
+
+#include "viz/VizContext.hpp"
+
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "viz/VizObject.hpp"
+
+namespace quickstep {
+namespace viz {
+
+void VizContext::getFieldStringItems(
+ std::vector<std::string> *inline_field_names,
+ std::vector<std::string> *inline_field_values,
+ std::vector<std::string> *non_container_child_field_names,
+ std::vector<const VizObject *> *non_container_child_fields,
+ std::vector<std::string> *container_child_field_names,
+ std::vector<std::vector<const VizObject *>> *container_child_fields) const {
+ inline_field_names->emplace_back("depth");
+ inline_field_values->emplace_back(std::to_string(depth_));
+ for (const auto &pair : objects_) {
+ non_container_child_field_names->emplace_back(pair.first);
+ non_container_child_fields->emplace_back(pair.second.get());
+ }
+ if (parent_ != nullptr) {
+ non_container_child_field_names->emplace_back("parent");
+ non_container_child_fields->emplace_back(parent_.get());
+ }
+}
+
+} // namespace viz
+} // namespace quickstep
http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/c618f9ec/viz/VizContext.hpp
----------------------------------------------------------------------
diff --git a/viz/VizContext.hpp b/viz/VizContext.hpp
new file mode 100644
index 0000000..6a29c30
--- /dev/null
+++ b/viz/VizContext.hpp
@@ -0,0 +1,133 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 QUICKSTEP_VIZ_VIZ_CONTEXT_HPP_
+#define QUICKSTEP_VIZ_VIZ_CONTEXT_HPP_
+
+#include <cstddef>
+#include <map>
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "utility/Macros.hpp"
+#include "viz/VizObject.hpp"
+
+#include "glog/logging.h"
+
+namespace quickstep {
+namespace viz {
+
+/** \addtogroup Viz
+ * @{
+ */
+
+class VizContext;
+typedef std::shared_ptr<const VizContext> VizContextPtr;
+
+class VizContext : public VizObject {
+ public:
+ VizContext()
+ : parent_(nullptr),
+ depth_(0) {}
+
+ explicit VizContext(const VizContextPtr &parent)
+ : parent_(parent),
+ depth_(parent->depth_+1) {}
+
+ std::string getName() const override {
+ return "VizContext";
+ }
+
+ inline bool hasLocal(const std::string &key) const {
+ return objects_.find(key) != objects_.end();
+ }
+
+ bool has(const std::string &key) const {
+ return hasLocal(key) || (parent_ != nullptr && parent_->has(key));
+ }
+
+ inline void set(const std::string &key,
+ VizObject *object) {
+ objects_[key].reset(object);
+ }
+
+ template <typename VizObjectT>
+ inline VizObjectT *getLocal(const std::string &key) {
+ CHECK(hasLocal(key));
+ VizObjectT *object = dynamic_cast<VizObjectT *>(objects_.at(key).get());
+
+ CHECK(object != nullptr);
+ return object;
+ }
+
+ template <typename VizObjectT>
+ inline const VizObjectT *getLocal(const std::string &key) const {
+ CHECK(hasLocal(key));
+ const VizObjectT *object =
+ dynamic_cast<const VizObjectT *>(objects_.at(key).get());
+
+ CHECK(object != nullptr);
+ return object;
+ }
+
+ template <typename VizObjectT>
+ const VizObjectT *get(const std::string &key) const {
+ if (hasLocal(key)) {
+ return getLocal<VizObjectT>(key);
+ } else {
+ CHECK(parent_ != nullptr);
+ return parent_->get<VizObjectT>(key);
+ }
+ }
+
+ template <typename VizObjectT, typename FunctorT>
+ void forEach(const std::string &key, FunctorT &functor) const {
+ if (parent_ != nullptr) {
+ parent_->forEach<VizObjectT, FunctorT>(key, functor);
+ }
+ if (hasLocal(key)) {
+ functor(getLocal<VizObjectT>(key));
+ }
+ }
+
+ protected:
+ void getFieldStringItems(
+ std::vector<std::string> *inline_field_names,
+ std::vector<std::string> *inline_field_values,
+ std::vector<std::string> *non_container_child_field_names,
+ std::vector<const VizObject *> *non_container_child_fields,
+ std::vector<std::string> *container_child_field_names,
+ std::vector<std::vector<const VizObject *>> *container_child_fields) const override;
+
+ private:
+ const VizContextPtr parent_;
+ const std::size_t depth_;
+
+ std::map<std::string, std::unique_ptr<VizObject>> objects_;
+
+ DISALLOW_COPY_AND_ASSIGN(VizContext);
+};
+
+/** @} */
+
+} // namespace viz
+} // namespace quickstep
+
+#endif // QUICKSTEP_VIZ_VIZ_CONTEXT_HPP_
http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/c618f9ec/viz/VizEngine.cpp
----------------------------------------------------------------------
diff --git a/viz/VizEngine.cpp b/viz/VizEngine.cpp
new file mode 100644
index 0000000..263da9e
--- /dev/null
+++ b/viz/VizEngine.cpp
@@ -0,0 +1,74 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ **/
+
+#include "viz/VizEngine.hpp"
+
+#include "utility/PlanVisualizer.hpp"
+#include "utility/ExecutionDAGVisualizer.hpp"
+#include "viz/VizAnalyzer.hpp"
+#include "viz/configs/DumpRelation.hpp"
+#include "viz/rules/Grouping.hpp"
+#include "viz/rules/VizRule.hpp"
+
+#include "json.hpp"
+
+namespace quickstep {
+namespace viz {
+
+using nlohmann::json;
+
+void VizEngine::execute() {
+ rules_.emplace_back(new Grouping(context_base_));
+
+ while (!rules_.empty()) {
+ std::unique_ptr<VizRule> rule(rules_.front().release());
+ rules_.pop_front();
+
+ rule->execute();
+
+ for (auto &derived_rule : rule->derived_rules_) {
+ rules_.emplace_back(derived_rule.release());
+ }
+ for (auto &result_conf : rule->result_confs_) {
+ confs_.emplace_back(result_conf.release());
+ }
+ }
+
+ json viz = json::array();
+ for (auto &conf : confs_) {
+ viz.push_back(conf->toJSON());
+ }
+
+ const VizAnalyzer *analyzer = context_base_->get<VizAnalyzer>("VizAnalyzer");
+ PlanVisualizer plan_visualizer;
+ ExecutionDAGVisualizer dag_visualizer(*analyzer->getExecutionPlan());
+ if (analyzer->getProfilingStats() != nullptr) {
+ dag_visualizer.bindProfilingStats(*analyzer->getProfilingStats());
+ }
+
+ json output = json::object();
+ output["plan"] = plan_visualizer.visualize(analyzer->getQueryPlan());
+ output["dag"] = dag_visualizer.toDOT();
+ output["results"] = DumpRelation(context_base_).toJSON();
+ output["viz"] = viz;
+ std::cerr << output.dump(2) << "\n";
+}
+
+} // namespace viz
+} // namespace quickstep
http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/c618f9ec/viz/VizEngine.hpp
----------------------------------------------------------------------
diff --git a/viz/VizEngine.hpp b/viz/VizEngine.hpp
new file mode 100644
index 0000000..bf4dcc3
--- /dev/null
+++ b/viz/VizEngine.hpp
@@ -0,0 +1,60 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 QUICKSTEP_VIZ_VIZ_ENGINE_HPP_
+#define QUICKSTEP_VIZ_VIZ_ENGINE_HPP_
+
+#include <deque>
+#include <memory>
+#include <vector>
+
+#include "utility/Macros.hpp"
+#include "viz/VizContext.hpp"
+#include "viz/configs/VizConfig.hpp"
+#include "viz/rules/VizRule.hpp"
+
+namespace quickstep {
+namespace viz {
+
+/** \addtogroup Viz
+ * @{
+ */
+
+class VizEngine {
+ public:
+ explicit VizEngine(const VizContextPtr &context_base)
+ : context_base_(context_base) {}
+
+ void execute();
+
+ private:
+ const VizContextPtr context_base_;
+
+ std::deque<std::unique_ptr<VizRule>> rules_;
+ std::vector<std::unique_ptr<VizConfig>> confs_;
+
+ DISALLOW_COPY_AND_ASSIGN(VizEngine);
+ };
+
+/** @} */
+
+} // namespace viz
+} // namespace quickstep
+
+#endif // QUICKSTEP_VIZ_VIZ_ENGINE_HPP_
http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/c618f9ec/viz/VizHelper.cpp
----------------------------------------------------------------------
diff --git a/viz/VizHelper.cpp b/viz/VizHelper.cpp
new file mode 100644
index 0000000..4abb632
--- /dev/null
+++ b/viz/VizHelper.cpp
@@ -0,0 +1,76 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ **/
+
+#include "viz/VizHelper.hpp"
+
+#include <memory>
+#include <vector>
+
+#include "query_execution/QueryExecutionTypedefs.hpp"
+#include "query_optimizer/LogicalGenerator.hpp"
+#include "query_optimizer/OptimizerContext.hpp"
+#include "query_optimizer/PhysicalGenerator.hpp"
+#include "query_optimizer/physical/Physical.hpp"
+#include "viz/VizAnalyzer.hpp"
+#include "viz/VizContext.hpp"
+#include "viz/VizEngine.hpp"
+
+#include "glog/logging.h"
+
+namespace quickstep {
+namespace viz {
+
+namespace O = ::quickstep::optimizer;
+namespace P = ::quickstep::optimizer::physical;
+
+void VizHelper::Visualize(const ParseStatement &parse_statement,
+ const QueryPlan *execution_plan,
+ const std::vector<WorkOrderTimeEntry> *profiling_stats,
+ const CatalogRelation *query_result_relation,
+ const CatalogDatabase *catalog_database,
+ StorageManager *storage_manager) {
+ // TODO(jianqiao): give some output for empty relation.
+ if (query_result_relation == nullptr) {
+ return;
+ }
+
+ O::OptimizerContext optimizer_context;
+ O::LogicalGenerator logical_generator(&optimizer_context);
+ O::PhysicalGenerator physical_generator;
+
+ const P::PhysicalPtr physical_plan =
+ physical_generator.generatePlan(
+ logical_generator.generatePlan(*catalog_database, parse_statement));
+
+ std::unique_ptr<VizContext> context_base(new VizContext());
+ context_base->set("VizAnalyzer",
+ new VizAnalyzer(physical_plan,
+ execution_plan,
+ profiling_stats,
+ query_result_relation,
+ catalog_database,
+ storage_manager));
+
+ VizEngine viz_engine(VizContextPtr(context_base.release()));
+ viz_engine.execute();
+}
+
+
+} // namespace viz
+} // namespace quickstep
http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/c618f9ec/viz/VizHelper.hpp
----------------------------------------------------------------------
diff --git a/viz/VizHelper.hpp b/viz/VizHelper.hpp
new file mode 100644
index 0000000..3d38698
--- /dev/null
+++ b/viz/VizHelper.hpp
@@ -0,0 +1,62 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 QUICKSTEP_VIZ_VIZ_HELPER_HPP_
+#define QUICKSTEP_VIZ_VIZ_HELPER_HPP_
+
+#include <vector>
+
+#include "query_execution/QueryExecutionTypedefs.hpp"
+#include "utility/Macros.hpp"
+
+namespace quickstep {
+
+class CatalogDatabase;
+class CatalogRelation;
+class ParseStatement;
+class QueryPlan;
+class StorageManager;
+
+namespace viz {
+
+/** \addtogroup Viz
+ * @{
+ */
+
+class VizHelper {
+ public:
+ static void Visualize(const ParseStatement &parse_statement,
+ const QueryPlan *execution_plan,
+ const std::vector<WorkOrderTimeEntry> *profiling_stats,
+ const CatalogRelation *query_result_relation,
+ const CatalogDatabase *catalog_database,
+ StorageManager *storage_manager);
+
+ private:
+ VizHelper() {}
+
+ DISALLOW_COPY_AND_ASSIGN(VizHelper);
+};
+
+/** @} */
+
+} // namespace viz
+} // namespace quickstep
+
+#endif // QUICKSTEP_VIZ_VIZ_HELPER_HPP_
http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/c618f9ec/viz/VizObject.cpp
----------------------------------------------------------------------
diff --git a/viz/VizObject.cpp b/viz/VizObject.cpp
new file mode 100644
index 0000000..0bf2b55
--- /dev/null
+++ b/viz/VizObject.cpp
@@ -0,0 +1,64 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ **/
+
+#include "viz/VizObject.hpp"
+
+#include <memory>
+#include <sstream>
+#include <string>
+#include <vector>
+
+#include "utility/StringUtil.hpp"
+
+namespace quickstep {
+namespace viz {
+
+void VizObject::getFieldStringItems(
+ std::vector<std::string> *inline_field_names,
+ std::vector<std::string> *inline_field_values,
+ std::vector<std::string> *non_container_child_field_names,
+ std::vector<const VizObject *> *non_container_child_fields,
+ std::vector<std::string> *container_child_field_names,
+ std::vector<std::vector<const VizObject *>> *container_child_fields) const {
+}
+
+void AttributeIdVector::getFieldStringItems(
+ std::vector<std::string> *inline_field_names,
+ std::vector<std::string> *inline_field_values,
+ std::vector<std::string> *non_container_child_field_names,
+ std::vector<const VizObject *> *non_container_child_fields,
+ std::vector<std::string> *container_child_field_names,
+ std::vector<std::vector<const VizObject *>> *container_child_fields) const {
+ inline_field_names->emplace_back("attribute_ids");
+ inline_field_values->emplace_back(JoinToString(attribute_ids_, ","));
+}
+
+void StringValue::getFieldStringItems(
+ std::vector<std::string> *inline_field_names,
+ std::vector<std::string> *inline_field_values,
+ std::vector<std::string> *non_container_child_field_names,
+ std::vector<const VizObject *> *non_container_child_fields,
+ std::vector<std::string> *container_child_field_names,
+ std::vector<std::vector<const VizObject *>> *container_child_fields) const {
+ inline_field_names->emplace_back("value");
+ inline_field_values->emplace_back(value_);
+}
+
+} // namespace viz
+} // namespace quickstep
http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/c618f9ec/viz/VizObject.hpp
----------------------------------------------------------------------
diff --git a/viz/VizObject.hpp b/viz/VizObject.hpp
new file mode 100644
index 0000000..3c86294
--- /dev/null
+++ b/viz/VizObject.hpp
@@ -0,0 +1,120 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 QUICKSTEP_VIZ_VIZ_OBJECT_HPP_
+#define QUICKSTEP_VIZ_VIZ_OBJECT_HPP_
+
+#include <string>
+#include <vector>
+
+#include "catalog/CatalogTypedefs.hpp"
+#include "utility/Macros.hpp"
+#include "utility/TreeStringSerializable.hpp"
+
+namespace quickstep {
+namespace viz {
+
+/** \addtogroup Viz
+ * @{
+ */
+
+class VizObject : public TreeStringSerializable<const VizObject *> {
+ public:
+ virtual ~VizObject() {}
+
+ protected:
+ VizObject() {}
+
+ void getFieldStringItems(
+ std::vector<std::string> *inline_field_names,
+ std::vector<std::string> *inline_field_values,
+ std::vector<std::string> *non_container_child_field_names,
+ std::vector<const VizObject *> *non_container_child_fields,
+ std::vector<std::string> *container_child_field_names,
+ std::vector<std::vector<const VizObject *>> *container_child_fields) const override;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(VizObject);
+};
+
+// ----------------------------------------------------------------------------
+// Light-weight VizObject subclasses.
+
+class AttributeIdVector : public VizObject {
+ public:
+ AttributeIdVector(const std::vector<attribute_id> &attribute_ids)
+ : attribute_ids_(attribute_ids) {}
+
+ std::string getName() const override {
+ return "AttributeIdVector";
+ }
+
+ inline const std::vector<attribute_id>& getAttributeIds() const {
+ return attribute_ids_;
+ }
+
+ protected:
+ void getFieldStringItems(
+ std::vector<std::string> *inline_field_names,
+ std::vector<std::string> *inline_field_values,
+ std::vector<std::string> *non_container_child_field_names,
+ std::vector<const VizObject *> *non_container_child_fields,
+ std::vector<std::string> *container_child_field_names,
+ std::vector<std::vector<const VizObject *>> *container_child_fields) const override;
+
+ private:
+ const std::vector<attribute_id> attribute_ids_;
+
+ DISALLOW_COPY_AND_ASSIGN(AttributeIdVector);
+};
+
+class StringValue : public VizObject {
+ public:
+ StringValue(const std::string &value)
+ : value_(value) {}
+
+ std::string getName() const override {
+ return "StringValue";
+ }
+
+ inline const std::string& value() const {
+ return value_;
+ }
+
+ protected:
+ void getFieldStringItems(
+ std::vector<std::string> *inline_field_names,
+ std::vector<std::string> *inline_field_values,
+ std::vector<std::string> *non_container_child_field_names,
+ std::vector<const VizObject *> *non_container_child_fields,
+ std::vector<std::string> *container_child_field_names,
+ std::vector<std::vector<const VizObject *>> *container_child_fields) const override;
+
+ private:
+ const std::string value_;
+
+ DISALLOW_COPY_AND_ASSIGN(StringValue);
+};
+
+/** @} */
+
+} // namespace viz
+} // namespace quickstep
+
+#endif // QUICKSTEP_VIZ_VIZ_OBJECT_HPP_
http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/c618f9ec/viz/configs/BarChart.hpp
----------------------------------------------------------------------
diff --git a/viz/configs/BarChart.hpp b/viz/configs/BarChart.hpp
new file mode 100644
index 0000000..f000513
--- /dev/null
+++ b/viz/configs/BarChart.hpp
@@ -0,0 +1,78 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 QUICKSTEP_VIZ_CONFIGS_BAR_CHART_HPP_
+#define QUICKSTEP_VIZ_CONFIGS_BAR_CHART_HPP_
+
+#include "catalog/CatalogTypedefs.hpp"
+#include "utility/Macros.hpp"
+#include "viz/configs/VizConfig.hpp"
+#include "viz/VizContext.hpp"
+
+#include "json.hpp"
+
+namespace quickstep {
+
+class CatalogRelation;
+class StorageManager;
+
+namespace viz {
+
+/** \addtogroup Viz
+ * @{
+ */
+
+class BarChart : public VizConfig {
+ public:
+ BarChart(const attribute_id dimension_attr_id,
+ const attribute_id measure_attr_id,
+ const VizContextPtr &context)
+ : VizConfig(context),
+ dimension_attr_id_(dimension_attr_id),
+ measure_attr_id_(measure_attr_id) {}
+
+ ~BarChart() override {}
+
+ nlohmann::json toJSON() override {
+ nlohmann::json data = nlohmann::json::array();
+ data.push_back(copyColumn(dimension_attr_id_));
+ data.push_back(copyColumn(measure_attr_id_));
+
+ nlohmann::json ret;
+ ret["type"] = "BarChart";
+ ret["trace"] = copyTrace();
+ ret["schema"] = copySchema({dimension_attr_id_, measure_attr_id_});
+ ret["data"] = data;
+
+ return ret;
+ }
+
+ private:
+ const attribute_id dimension_attr_id_;
+ const attribute_id measure_attr_id_;
+
+ DISALLOW_COPY_AND_ASSIGN(BarChart);
+ };
+
+/** @} */
+
+} // namespace viz
+} // namespace quickstep
+
+#endif // QUICKSTEP_VIZ_CONFIGS_BAR_CHART_HPP_
http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/c618f9ec/viz/configs/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/viz/configs/CMakeLists.txt b/viz/configs/CMakeLists.txt
new file mode 100644
index 0000000..a33bf78
--- /dev/null
+++ b/viz/configs/CMakeLists.txt
@@ -0,0 +1,48 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you 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.
+
+# Declare micro-libs:
+add_library(quickstep_viz_configs_BarChart ../../empty_src.cpp BarChart.hpp)
+add_library(quickstep_viz_configs_DumpRelation ../../empty_src.cpp DumpRelation.hpp)
+add_library(quickstep_viz_configs_VizConfig VizConfig.cpp VizConfig.hpp)
+
+# Link dependencies:
+target_link_libraries(quickstep_viz_configs_BarChart
+ quickstep_catalog_CatalogTypedefs
+ quickstep_utility_Macros
+ quickstep_viz_VizContext
+ quickstep_viz_configs_VizConfig)
+target_link_libraries(quickstep_viz_configs_DumpRelation
+ quickstep_catalog_CatalogAttribute
+ quickstep_catalog_CatalogRelation
+ quickstep_catalog_CatalogTypedefs
+ quickstep_utility_Macros
+ quickstep_viz_VizAnalyzer
+ quickstep_viz_VizContext
+ quickstep_viz_configs_VizConfig)
+target_link_libraries(quickstep_viz_configs_VizConfig
+ quickstep_catalog_CatalogAttribute
+ quickstep_catalog_CatalogRelation
+ quickstep_catalog_CatalogRelationSchema
+ quickstep_catalog_CatalogTypedefs
+ quickstep_storage_StorageManager
+ quickstep_storage_ValueAccessor
+ quickstep_storage_ValueAccessorUtil
+ quickstep_utility_Macros
+ quickstep_viz_VizAnalyzer
+ quickstep_viz_VizContext
+ quickstep_viz_VizObject)
http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/c618f9ec/viz/configs/DumpRelation.hpp
----------------------------------------------------------------------
diff --git a/viz/configs/DumpRelation.hpp b/viz/configs/DumpRelation.hpp
new file mode 100644
index 0000000..efcff2f
--- /dev/null
+++ b/viz/configs/DumpRelation.hpp
@@ -0,0 +1,79 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 QUICKSTEP_VIZ_CONFIGS_DUMP_RELATION_HPP_
+#define QUICKSTEP_VIZ_CONFIGS_DUMP_RELATION_HPP_
+
+#include "catalog/CatalogAttribute.hpp"
+#include "catalog/CatalogRelation.hpp"
+#include "catalog/CatalogTypedefs.hpp"
+#include "utility/Macros.hpp"
+#include "viz/configs/VizConfig.hpp"
+#include "viz/VizAnalyzer.hpp"
+#include "viz/VizContext.hpp"
+
+#include "json.hpp"
+
+namespace quickstep {
+
+class CatalogRelation;
+class StorageManager;
+
+namespace viz {
+
+/** \addtogroup Viz
+ * @{
+ */
+
+class DumpRelation : public VizConfig {
+ public:
+ DumpRelation(const VizContextPtr &context)
+ : VizConfig(context) {}
+
+ ~DumpRelation() override {}
+
+ nlohmann::json toJSON() override {
+ const CatalogRelation *relation =
+ context_->get<VizAnalyzer>("VizAnalyzer")->getRelation();
+ std::vector<attribute_id> attr_ids;
+
+ nlohmann::json data = nlohmann::json::array();
+ for (const CatalogAttribute &attr : *relation) {
+ data.push_back(copyColumn(attr.getID()));
+ attr_ids.emplace_back(attr.getID());
+ }
+
+ nlohmann::json ret;
+ ret["type"] = "DumpRelation";
+ ret["schema"] = copySchema(attr_ids);
+ ret["data"] = data;
+
+ return ret;
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(DumpRelation);
+ };
+
+/** @} */
+
+} // namespace viz
+} // namespace quickstep
+
+#endif // QUICKSTEP_VIZ_CONFIGS_DUMP_RELATION_HPP_
http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/c618f9ec/viz/configs/VizConfig.cpp
----------------------------------------------------------------------
diff --git a/viz/configs/VizConfig.cpp b/viz/configs/VizConfig.cpp
new file mode 100644
index 0000000..3a15931
--- /dev/null
+++ b/viz/configs/VizConfig.cpp
@@ -0,0 +1,91 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ **/
+
+#include "viz/configs/VizConfig.hpp"
+
+#include <memory>
+
+#include "catalog/CatalogAttribute.hpp"
+#include "catalog/CatalogRelation.hpp"
+#include "catalog/CatalogRelationSchema.hpp"
+#include "catalog/CatalogTypedefs.hpp"
+#include "storage/StorageManager.hpp"
+#include "storage/ValueAccessor.hpp"
+#include "storage/ValueAccessorUtil.hpp"
+#include "viz/VizAnalyzer.hpp"
+#include "viz/VizContext.hpp"
+#include "viz/VizObject.hpp"
+
+#include "json.hpp"
+
+namespace quickstep {
+namespace viz {
+
+using nlohmann::json;
+
+VizConfig::VizConfig(const VizContextPtr &context)
+ : context_(context) {
+ const VizAnalyzer *analyzer =
+ context_->get<VizAnalyzer>("VizAnalyzer");
+ relation_ = analyzer->getRelation();
+ storage_manager_ = analyzer->getStorageManager();
+}
+
+json VizConfig::copyColumn(const attribute_id column_id) {
+ json values = json::array();
+ for (const block_id bid : relation_->getBlocksSnapshot()) {
+ BlockReference block = storage_manager_->getBlock(bid, *relation_);
+ std::unique_ptr<ValueAccessor> accessor(
+ block->getTupleStorageSubBlock().createValueAccessor());
+ const Type &type = relation_->getAttributeById(column_id)->getType();
+ InvokeOnValueAccessorNotAdapter(
+ accessor.get(),
+ [&](auto *accessor) -> void { // NOLINT(build/c++11)
+ while (accessor->next()) {
+ values.push_back(
+ type.printValueToString(accessor->getTypedValue(column_id)));
+ }
+ });
+ }
+ return values;
+}
+
+json VizConfig::copySchema(const std::vector<attribute_id> &attr_ids) {
+ json schema = json::array();
+ for (const attribute_id attr_id : attr_ids) {
+ const CatalogAttribute *attr = relation_->getAttributeById(attr_id);
+ json attr_info;
+ attr_info["name"] = attr->getDisplayName();
+ attr_info["type"] = attr->getType().getName();
+ schema.push_back(attr_info);
+ }
+ return schema;
+}
+
+json VizConfig::copyTrace() {
+ json trace = json::array();
+ auto copy_trace_functor = [&trace](const StringValue *str_value) -> void {
+ trace.push_back(str_value->value());
+ };
+ context_->forEach<StringValue>("trace", copy_trace_functor);
+ return trace;
+}
+
+} // namespace viz
+} // namespace quickstep
http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/c618f9ec/viz/configs/VizConfig.hpp
----------------------------------------------------------------------
diff --git a/viz/configs/VizConfig.hpp b/viz/configs/VizConfig.hpp
new file mode 100644
index 0000000..65f7efe
--- /dev/null
+++ b/viz/configs/VizConfig.hpp
@@ -0,0 +1,68 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 QUICKSTEP_VIZ_CONFIGS_VIZ_CONFIG_HPP_
+#define QUICKSTEP_VIZ_CONFIGS_VIZ_CONFIG_HPP_
+
+#include "catalog/CatalogTypedefs.hpp"
+#include "utility/Macros.hpp"
+#include "viz/VizContext.hpp"
+
+#include "json.hpp"
+
+namespace quickstep {
+
+class CatalogRelation;
+class CatalogRelationSchema;
+class StorageManager;
+
+namespace viz {
+
+/** \addtogroup Viz
+ * @{
+ */
+
+class VizConfig {
+ public:
+ virtual ~VizConfig() {}
+
+ virtual nlohmann::json toJSON() = 0;
+
+ protected:
+ explicit VizConfig(const VizContextPtr &context);
+
+
+ nlohmann::json copyColumn(const attribute_id column_id);
+ nlohmann::json copySchema(const std::vector<attribute_id> &attr_ids);
+ nlohmann::json copyTrace();
+
+ const VizContextPtr context_;
+ const CatalogRelation *relation_;
+ StorageManager *storage_manager_;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(VizConfig);
+ };
+
+/** @} */
+
+} // namespace viz
+} // namespace quickstep
+
+#endif // QUICKSTEP_VIZ_CONFIGS_VIZ_CONFIG_HPP_
http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/c618f9ec/viz/rules/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/viz/rules/CMakeLists.txt b/viz/rules/CMakeLists.txt
new file mode 100644
index 0000000..640a678
--- /dev/null
+++ b/viz/rules/CMakeLists.txt
@@ -0,0 +1,43 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you 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.
+
+# Declare micro-libs:
+add_library(quickstep_viz_rules_Grouping ../../empty_src.cpp Grouping.hpp)
+add_library(quickstep_viz_rules_OneDimensionOneMeasure
+ ../../empty_src.cpp
+ OneDimensionOneMeasure.hpp)
+add_library(quickstep_viz_rules_VizRule ../../empty_src.cpp VizRule.hpp)
+
+# Link dependencies:
+target_link_libraries(quickstep_viz_rules_Grouping
+ quickstep_catalog_CatalogAttribute
+ quickstep_catalog_CatalogRelation
+ quickstep_catalog_CatalogTypedefs
+ quickstep_utility_Macros
+ quickstep_viz_VizAnalyzer
+ quickstep_viz_rules_OneDimensionOneMeasure)
+target_link_libraries(quickstep_viz_rules_OneDimensionOneMeasure
+ quickstep_catalog_CatalogTypedefs
+ quickstep_utility_Macros
+ quickstep_viz_VizAnalyzer
+ quickstep_viz_VizContext
+ quickstep_viz_VizObject
+ quickstep_viz_configs_BarChart)
+target_link_libraries(quickstep_viz_rules_VizRule
+ quickstep_utility_Macros
+ quickstep_viz_VizContext
+ quickstep_viz_configs_VizConfig)
http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/c618f9ec/viz/rules/Grouping.hpp
----------------------------------------------------------------------
diff --git a/viz/rules/Grouping.hpp b/viz/rules/Grouping.hpp
new file mode 100644
index 0000000..c20cef1
--- /dev/null
+++ b/viz/rules/Grouping.hpp
@@ -0,0 +1,100 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 QUICKSTEP_VIZ_RULES_GROUPING_HPP_
+#define QUICKSTEP_VIZ_RULES_GROUPING_HPP_
+
+#include <memory>
+#include <unordered_set>
+#include <vector>
+
+#include "catalog/CatalogAttribute.hpp"
+#include "catalog/CatalogRelation.hpp"
+#include "catalog/CatalogTypedefs.hpp"
+#include "utility/Macros.hpp"
+#include "viz/VizAnalyzer.hpp"
+#include "viz/rules/OneDimensionOneMeasure.hpp"
+
+namespace quickstep {
+namespace viz {
+
+/** \addtogroup Viz
+ * @{
+ */
+
+class Grouping : public VizRule {
+ public:
+ Grouping(const VizContextPtr &context)
+ : VizRule(context) {}
+
+ ~Grouping() override {}
+
+ void execute() override {
+ const VizAnalyzer *analyzer =
+ context_->get<VizAnalyzer>("VizAnalyzer");
+
+ std::vector<attribute_id> group_by_attribute_ids;
+ if (analyzer->findGroupByAttributes(&group_by_attribute_ids)) {
+ std::unordered_set<attribute_id> group_by_attr_id_set(
+ group_by_attribute_ids.begin(),
+ group_by_attribute_ids.end());
+ std::vector<attribute_id> residual_attribute_ids;
+ for (const CatalogAttribute &attr : *analyzer->getRelation()) {
+ if (group_by_attr_id_set.find(attr.getID()) == group_by_attr_id_set.end()) {
+ residual_attribute_ids.emplace_back(attr.getID());
+ }
+ }
+
+ std::unique_ptr<VizContext> new_context(new VizContext(context_));
+ new_context->set("trace", new StringValue("Grouping"));
+ new_context->set("Dimensions",
+ new AttributeIdVector(group_by_attribute_ids));
+ new_context->set("Measures",
+ new AttributeIdVector(residual_attribute_ids));
+
+ dispatchWithGrouping(analyzer,
+ VizContextPtr(new_context.release()),
+ group_by_attribute_ids.size(),
+ residual_attribute_ids.size());
+ } else {
+ // TODO
+ }
+ }
+
+ private:
+ void dispatchWithGrouping(const VizAnalyzer *analyzer,
+ const VizContextPtr new_context,
+ const std::size_t num_dimension_attrs,
+ const std::size_t num_measure_attrs) {
+ if (num_dimension_attrs == 1) {
+ if (num_measure_attrs == 1) {
+ derive(new OneDimensionOneMeasure(new_context));
+ }
+ }
+ }
+
+ DISALLOW_COPY_AND_ASSIGN(Grouping);
+ };
+
+/** @} */
+
+} // namespace viz
+} // namespace quickstep
+
+#endif // QUICKSTEP_VIZ_RULES_GROUPING_HPP_
http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/c618f9ec/viz/rules/OneDimensionOneMeasure.hpp
----------------------------------------------------------------------
diff --git a/viz/rules/OneDimensionOneMeasure.hpp b/viz/rules/OneDimensionOneMeasure.hpp
new file mode 100644
index 0000000..565ec1b
--- /dev/null
+++ b/viz/rules/OneDimensionOneMeasure.hpp
@@ -0,0 +1,73 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 QUICKSTEP_VIZ_RULES_ONE_DIMENSION_ONE_MEASURE_HPP_
+#define QUICKSTEP_VIZ_RULES_ONE_DIMENSION_ONE_MEASURE_HPP_
+
+#include "catalog/CatalogTypedefs.hpp"
+#include "utility/Macros.hpp"
+#include "viz/VizAnalyzer.hpp"
+#include "viz/VizContext.hpp"
+#include "viz/VizObject.hpp"
+#include "viz/configs/BarChart.hpp"
+
+namespace quickstep {
+namespace viz {
+
+/** \addtogroup Viz
+ * @{
+ */
+
+class OneDimensionOneMeasure : public VizRule {
+ public:
+ OneDimensionOneMeasure(const VizContextPtr &context)
+ : VizRule(context) {}
+
+ ~OneDimensionOneMeasure() override {}
+
+ void execute() override {
+ const AttributeIdVector *dimensions =
+ context_->get<AttributeIdVector>("Dimensions");
+ CHECK_EQ(1uL, dimensions->getAttributeIds().size());
+
+ const AttributeIdVector *measures =
+ context_->get<AttributeIdVector>("Measures");
+ CHECK_EQ(1uL, measures->getAttributeIds().size());
+
+ std::unique_ptr<VizContext> new_context(new VizContext(context_));
+ new_context->set("trace", new StringValue("OneDimensionOneMeasure"));
+
+ const VizContextPtr new_context_ptr(new_context.release());
+
+ // Barchart or Linechart
+ yield(new BarChart(dimensions->getAttributeIds().front(),
+ measures->getAttributeIds().front(),
+ new_context_ptr));
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(OneDimensionOneMeasure);
+ };
+
+/** @} */
+
+} // namespace viz
+} // namespace quickstep
+
+#endif // QUICKSTEP_VIZ_RULES_ONE_DIMENSION_ONE_MEASURE_HPP_
http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/c618f9ec/viz/rules/VizRule.hpp
----------------------------------------------------------------------
diff --git a/viz/rules/VizRule.hpp b/viz/rules/VizRule.hpp
new file mode 100644
index 0000000..f034e9e
--- /dev/null
+++ b/viz/rules/VizRule.hpp
@@ -0,0 +1,68 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 QUICKSTEP_VIZ_RULES_VIZ_RULE_HPP_
+#define QUICKSTEP_VIZ_RULES_VIZ_RULE_HPP_
+
+#include "utility/Macros.hpp"
+#include "viz/VizContext.hpp"
+#include "viz/configs/VizConfig.hpp"
+
+namespace quickstep {
+namespace viz {
+
+/** \addtogroup Viz
+ * @{
+ */
+
+class VizRule {
+ public:
+ virtual ~VizRule() {}
+
+ virtual void execute() = 0;
+
+ inline void derive(VizRule *rule) {
+ derived_rules_.emplace_back(rule);
+ }
+
+ inline void yield(VizConfig *conf) {
+ result_confs_.emplace_back(conf);
+ }
+
+ protected:
+ explicit VizRule(const VizContextPtr &context)
+ : context_(context) {}
+
+ const VizContextPtr context_;
+
+ private:
+ friend class VizEngine;
+
+ std::vector<std::unique_ptr<VizRule>> derived_rules_;
+ std::vector<std::unique_ptr<VizConfig>> result_confs_;
+
+ DISALLOW_COPY_AND_ASSIGN(VizRule);
+ };
+
+/** @} */
+
+} // namespace viz
+} // namespace quickstep
+
+#endif // QUICKSTEP_VIZ_RULES_VIZ_RULE_HPP_
[3/3] incubator-quickstep git commit: Initial commit
Posted by ji...@apache.org.
Initial commit
Project: http://git-wip-us.apache.org/repos/asf/incubator-quickstep/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-quickstep/commit/c618f9ec
Tree: http://git-wip-us.apache.org/repos/asf/incubator-quickstep/tree/c618f9ec
Diff: http://git-wip-us.apache.org/repos/asf/incubator-quickstep/diff/c618f9ec
Branch: refs/heads/viz
Commit: c618f9ec1182bef7a6c4bdf3be316b03a723137c
Parents: 7095987
Author: Jianqiao Zhu <ji...@cs.wisc.edu>
Authored: Tue Nov 15 22:43:27 2016 -0600
Committer: Jianqiao Zhu <ji...@cs.wisc.edu>
Committed: Fri Nov 18 15:25:05 2016 -0600
----------------------------------------------------------------------
CMakeLists.txt | 7 +-
cli/QuickstepCli.cpp | 14 +-
third_party/json/json.hpp | 10794 ++++++++++++++++++++++++++++
viz/CMakeLists.txt | 66 +
viz/VizAnalyzer.cpp | 97 +
viz/VizAnalyzer.hpp | 116 +
viz/VizContext.cpp | 51 +
viz/VizContext.hpp | 133 +
viz/VizEngine.cpp | 74 +
viz/VizEngine.hpp | 60 +
viz/VizHelper.cpp | 76 +
viz/VizHelper.hpp | 62 +
viz/VizObject.cpp | 64 +
viz/VizObject.hpp | 120 +
viz/configs/BarChart.hpp | 78 +
viz/configs/CMakeLists.txt | 48 +
viz/configs/DumpRelation.hpp | 79 +
viz/configs/VizConfig.cpp | 91 +
viz/configs/VizConfig.hpp | 68 +
viz/rules/CMakeLists.txt | 43 +
viz/rules/Grouping.hpp | 100 +
viz/rules/OneDimensionOneMeasure.hpp | 73 +
viz/rules/VizRule.hpp | 68 +
23 files changed, 12379 insertions(+), 3 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/c618f9ec/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 6191de0..bb069a2 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -725,6 +725,9 @@ if (ENABLE_DISTRIBUTED)
include_directories(${CMAKE_CURRENT_BINARY_DIR}/third_party/tmb/include)
endif()
+# Add third_party json (temporary).
+include_directories("${THIRD_PARTY_SOURCE_DIR}/json")
+
# Add all of the module subdirectories. CMakeLists.txt in each of the subdirectories
# defines how to build that module's libraries.
add_subdirectory(catalog)
@@ -740,6 +743,7 @@ add_subdirectory(threading)
add_subdirectory(transaction)
add_subdirectory(types)
add_subdirectory(utility)
+add_subdirectory(viz)
add_subdirectory(yarn)
# Build the quickstep_cli_shell executable.
@@ -775,7 +779,8 @@ target_link_libraries(quickstep_cli_shell
quickstep_utility_Macros
quickstep_utility_PtrVector
quickstep_utility_SqlError
- quickstep_utility_StringUtil)
+ quickstep_utility_StringUtil
+ quickstep_viz_VizHelper)
if (ENABLE_HDFS)
target_link_libraries(quickstep_cli_shell
quickstep_storage_FileManagerHdfs)
http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/c618f9ec/cli/QuickstepCli.cpp
----------------------------------------------------------------------
diff --git a/cli/QuickstepCli.cpp b/cli/QuickstepCli.cpp
index 31215f6..a506cd6 100644
--- a/cli/QuickstepCli.cpp
+++ b/cli/QuickstepCli.cpp
@@ -82,6 +82,7 @@ typedef quickstep::LineReaderDumb LineReaderImpl;
#include "utility/PtrVector.hpp"
#include "utility/SqlError.hpp"
#include "utility/StringUtil.hpp"
+#include "viz/VizHelper.hpp"
#include "gflags/gflags.h"
@@ -361,7 +362,7 @@ int main(int argc, char* argv[]) {
&storage_manager,
-1, // Don't pin the Foreman thread.
num_numa_nodes_system,
- quickstep::FLAGS_profile_and_report_workorder_perf || quickstep::FLAGS_visualize_execution_dag);
+ true /* profile_individual_workorders */);
// Start the worker threads.
for (Worker &worker : workers) {
@@ -456,7 +457,16 @@ int main(int argc, char* argv[]) {
main_thread_client_id, &bus);
end = std::chrono::steady_clock::now();
- const CatalogRelation *query_result_relation = query_handle->getQueryResultRelation();
+ const CatalogRelation *query_result_relation =
+ query_handle->getQueryResultRelation();
+
+ quickstep::viz::VizHelper::Visualize(statement,
+ query_handle->getQueryPlanMutable(),
+ &foreman.getWorkOrderProfilingResults(query_handle->query_id()),
+ query_result_relation,
+ query_processor->getDefaultDatabase(),
+ query_processor->getStorageManager());
+
if (query_result_relation) {
PrintToScreen::PrintRelation(*query_result_relation,
&storage_manager,
[2/3] incubator-quickstep git commit: Initial commit
Posted by ji...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/c618f9ec/third_party/json/json.hpp
----------------------------------------------------------------------
diff --git a/third_party/json/json.hpp b/third_party/json/json.hpp
new file mode 100644
index 0000000..4447412
--- /dev/null
+++ b/third_party/json/json.hpp
@@ -0,0 +1,10794 @@
+/*
+ __ _____ _____ _____
+ __| | __| | | | JSON for Modern C++
+| | |__ | | | | | | version 2.0.7
+|_____|_____|_____|_|___| https://github.com/nlohmann/json
+
+Licensed under the MIT License <http://opensource.org/licenses/MIT>.
+Copyright (c) 2013-2016 Niels Lohmann <http://nlohmann.me>.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+*/
+
+#ifndef NLOHMANN_JSON_HPP
+#define NLOHMANN_JSON_HPP
+
+#include <algorithm>
+#include <array>
+#include <cassert>
+#include <cctype>
+#include <ciso646>
+#include <cmath>
+#include <cstddef>
+#include <cstdint>
+#include <cstdlib>
+#include <cstring>
+#include <functional>
+#include <initializer_list>
+#include <iomanip>
+#include <iostream>
+#include <iterator>
+#include <limits>
+#include <locale>
+#include <map>
+#include <memory>
+#include <numeric>
+#include <sstream>
+#include <stdexcept>
+#include <string>
+#include <type_traits>
+#include <utility>
+#include <vector>
+
+// exclude unsupported compilers
+#if defined(__clang__)
+ #define CLANG_VERSION (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__)
+ #if CLANG_VERSION < 30400
+ #error "unsupported Clang version - see https://github.com/nlohmann/json#supported-compilers"
+ #endif
+#elif defined(__GNUC__)
+ #define GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)
+ #if GCC_VERSION < 40900
+ #error "unsupported GCC version - see https://github.com/nlohmann/json#supported-compilers"
+ #endif
+#endif
+
+// disable float-equal warnings on GCC/clang
+#if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)
+ #pragma GCC diagnostic push
+ #pragma GCC diagnostic ignored "-Wfloat-equal"
+#endif
+
+// allow for portable deprecation warnings
+#if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)
+ #define JSON_DEPRECATED __attribute__((deprecated))
+#elif defined(_MSC_VER)
+ #define JSON_DEPRECATED __declspec(deprecated)
+#else
+ #define JSON_DEPRECATED
+#endif
+
+/*!
+@brief namespace for Niels Lohmann
+@see https://github.com/nlohmann
+@since version 1.0.0
+*/
+namespace nlohmann
+{
+
+
+/*!
+@brief unnamed namespace with internal helper functions
+@since version 1.0.0
+*/
+namespace
+{
+/*!
+@brief Helper to determine whether there's a key_type for T.
+
+Thus helper is used to tell associative containers apart from other containers
+such as sequence containers. For instance, `std::map` passes the test as it
+contains a `mapped_type`, whereas `std::vector` fails the test.
+
+@sa http://stackoverflow.com/a/7728728/266378
+@since version 1.0.0, overworked in version 2.0.6
+*/
+template<typename T>
+struct has_mapped_type
+{
+ private:
+ template <typename U, typename = typename U::mapped_type>
+ static int detect(U&&);
+
+ static void detect(...);
+ public:
+ static constexpr bool value =
+ std::is_integral<decltype(detect(std::declval<T>()))>::value;
+};
+
+/*!
+@brief helper class to create locales with decimal point
+
+This struct is used a default locale during the JSON serialization. JSON
+requires the decimal point to be `.`, so this function overloads the
+`do_decimal_point()` function to return `.`. This function is called by
+float-to-string conversions to retrieve the decimal separator between integer
+and fractional parts.
+
+@sa https://github.com/nlohmann/json/issues/51#issuecomment-86869315
+@since version 2.0.0
+*/
+struct DecimalSeparator : std::numpunct<char>
+{
+ char do_decimal_point() const
+ {
+ return '.';
+ }
+};
+
+}
+
+/*!
+@brief a class to store JSON values
+
+@tparam ObjectType type for JSON objects (`std::map` by default; will be used
+in @ref object_t)
+@tparam ArrayType type for JSON arrays (`std::vector` by default; will be used
+in @ref array_t)
+@tparam StringType type for JSON strings and object keys (`std::string` by
+default; will be used in @ref string_t)
+@tparam BooleanType type for JSON booleans (`bool` by default; will be used
+in @ref boolean_t)
+@tparam NumberIntegerType type for JSON integer numbers (`int64_t` by
+default; will be used in @ref number_integer_t)
+@tparam NumberUnsignedType type for JSON unsigned integer numbers (@c
+`uint64_t` by default; will be used in @ref number_unsigned_t)
+@tparam NumberFloatType type for JSON floating-point numbers (`double` by
+default; will be used in @ref number_float_t)
+@tparam AllocatorType type of the allocator to use (`std::allocator` by
+default)
+
+@requirement The class satisfies the following concept requirements:
+- Basic
+ - [DefaultConstructible](http://en.cppreference.com/w/cpp/concept/DefaultConstructible):
+ JSON values can be default constructed. The result will be a JSON null value.
+ - [MoveConstructible](http://en.cppreference.com/w/cpp/concept/MoveConstructible):
+ A JSON value can be constructed from an rvalue argument.
+ - [CopyConstructible](http://en.cppreference.com/w/cpp/concept/CopyConstructible):
+ A JSON value can be copy-constructed from an lvalue expression.
+ - [MoveAssignable](http://en.cppreference.com/w/cpp/concept/MoveAssignable):
+ A JSON value van be assigned from an rvalue argument.
+ - [CopyAssignable](http://en.cppreference.com/w/cpp/concept/CopyAssignable):
+ A JSON value can be copy-assigned from an lvalue expression.
+ - [Destructible](http://en.cppreference.com/w/cpp/concept/Destructible):
+ JSON values can be destructed.
+- Layout
+ - [StandardLayoutType](http://en.cppreference.com/w/cpp/concept/StandardLayoutType):
+ JSON values have
+ [standard layout](http://en.cppreference.com/w/cpp/language/data_members#Standard_layout):
+ All non-static data members are private and standard layout types, the class
+ has no virtual functions or (virtual) base classes.
+- Library-wide
+ - [EqualityComparable](http://en.cppreference.com/w/cpp/concept/EqualityComparable):
+ JSON values can be compared with `==`, see @ref
+ operator==(const_reference,const_reference).
+ - [LessThanComparable](http://en.cppreference.com/w/cpp/concept/LessThanComparable):
+ JSON values can be compared with `<`, see @ref
+ operator<(const_reference,const_reference).
+ - [Swappable](http://en.cppreference.com/w/cpp/concept/Swappable):
+ Any JSON lvalue or rvalue of can be swapped with any lvalue or rvalue of
+ other compatible types, using unqualified function call @ref swap().
+ - [NullablePointer](http://en.cppreference.com/w/cpp/concept/NullablePointer):
+ JSON values can be compared against `std::nullptr_t` objects which are used
+ to model the `null` value.
+- Container
+ - [Container](http://en.cppreference.com/w/cpp/concept/Container):
+ JSON values can be used like STL containers and provide iterator access.
+ - [ReversibleContainer](http://en.cppreference.com/w/cpp/concept/ReversibleContainer);
+ JSON values can be used like STL containers and provide reverse iterator
+ access.
+
+@invariant The member variables @a m_value and @a m_type have the following
+relationship:
+- If `m_type == value_t::object`, then `m_value.object != nullptr`.
+- If `m_type == value_t::array`, then `m_value.array != nullptr`.
+- If `m_type == value_t::string`, then `m_value.string != nullptr`.
+The invariants are checked by member function assert_invariant().
+
+@internal
+@note ObjectType trick from http://stackoverflow.com/a/9860911
+@endinternal
+
+@see [RFC 7159: The JavaScript Object Notation (JSON) Data Interchange
+Format](http://rfc7159.net/rfc7159)
+
+@since version 1.0.0
+
+@nosubgrouping
+*/
+template <
+ template<typename U, typename V, typename... Args> class ObjectType = std::map,
+ template<typename U, typename... Args> class ArrayType = std::vector,
+ class StringType = std::string,
+ class BooleanType = bool,
+ class NumberIntegerType = std::int64_t,
+ class NumberUnsignedType = std::uint64_t,
+ class NumberFloatType = double,
+ template<typename U> class AllocatorType = std::allocator
+ >
+class basic_json
+{
+ private:
+ /// workaround type for MSVC
+ using basic_json_t = basic_json<ObjectType, ArrayType, StringType,
+ BooleanType, NumberIntegerType, NumberUnsignedType, NumberFloatType,
+ AllocatorType>;
+
+ public:
+ // forward declarations
+ template<typename Base> class json_reverse_iterator;
+ class json_pointer;
+
+ /////////////////////
+ // container types //
+ /////////////////////
+
+ /// @name container types
+ /// The canonic container types to use @ref basic_json like any other STL
+ /// container.
+ /// @{
+
+ /// the type of elements in a basic_json container
+ using value_type = basic_json;
+
+ /// the type of an element reference
+ using reference = value_type&;
+ /// the type of an element const reference
+ using const_reference = const value_type&;
+
+ /// a type to represent differences between iterators
+ using difference_type = std::ptrdiff_t;
+ /// a type to represent container sizes
+ using size_type = std::size_t;
+
+ /// the allocator type
+ using allocator_type = AllocatorType<basic_json>;
+
+ /// the type of an element pointer
+ using pointer = typename std::allocator_traits<allocator_type>::pointer;
+ /// the type of an element const pointer
+ using const_pointer = typename std::allocator_traits<allocator_type>::const_pointer;
+
+ /// an iterator for a basic_json container
+ class iterator;
+ /// a const iterator for a basic_json container
+ class const_iterator;
+ /// a reverse iterator for a basic_json container
+ using reverse_iterator = json_reverse_iterator<typename basic_json::iterator>;
+ /// a const reverse iterator for a basic_json container
+ using const_reverse_iterator = json_reverse_iterator<typename basic_json::const_iterator>;
+
+ /// @}
+
+
+ /*!
+ @brief returns the allocator associated with the container
+ */
+ static allocator_type get_allocator()
+ {
+ return allocator_type();
+ }
+
+
+ ///////////////////////////
+ // JSON value data types //
+ ///////////////////////////
+
+ /// @name JSON value data types
+ /// The data types to store a JSON value. These types are derived from
+ /// the template arguments passed to class @ref basic_json.
+ /// @{
+
+ /*!
+ @brief a type for an object
+
+ [RFC 7159](http://rfc7159.net/rfc7159) describes JSON objects as follows:
+ > An object is an unordered collection of zero or more name/value pairs,
+ > where a name is a string and a value is a string, number, boolean, null,
+ > object, or array.
+
+ To store objects in C++, a type is defined by the template parameters
+ described below.
+
+ @tparam ObjectType the container to store objects (e.g., `std::map` or
+ `std::unordered_map`)
+ @tparam StringType the type of the keys or names (e.g., `std::string`).
+ The comparison function `std::less<StringType>` is used to order elements
+ inside the container.
+ @tparam AllocatorType the allocator to use for objects (e.g.,
+ `std::allocator`)
+
+ #### Default type
+
+ With the default values for @a ObjectType (`std::map`), @a StringType
+ (`std::string`), and @a AllocatorType (`std::allocator`), the default
+ value for @a object_t is:
+
+ @code {.cpp}
+ std::map<
+ std::string, // key_type
+ basic_json, // value_type
+ std::less<std::string>, // key_compare
+ std::allocator<std::pair<const std::string, basic_json>> // allocator_type
+ >
+ @endcode
+
+ #### Behavior
+
+ The choice of @a object_t influences the behavior of the JSON class. With
+ the default type, objects have the following behavior:
+
+ - When all names are unique, objects will be interoperable in the sense
+ that all software implementations receiving that object will agree on
+ the name-value mappings.
+ - When the names within an object are not unique, later stored name/value
+ pairs overwrite previously stored name/value pairs, leaving the used
+ names unique. For instance, `{"key": 1}` and `{"key": 2, "key": 1}` will
+ be treated as equal and both stored as `{"key": 1}`.
+ - Internally, name/value pairs are stored in lexicographical order of the
+ names. Objects will also be serialized (see @ref dump) in this order.
+ For instance, `{"b": 1, "a": 2}` and `{"a": 2, "b": 1}` will be stored
+ and serialized as `{"a": 2, "b": 1}`.
+ - When comparing objects, the order of the name/value pairs is irrelevant.
+ This makes objects interoperable in the sense that they will not be
+ affected by these differences. For instance, `{"b": 1, "a": 2}` and
+ `{"a": 2, "b": 1}` will be treated as equal.
+
+ #### Limits
+
+ [RFC 7159](http://rfc7159.net/rfc7159) specifies:
+ > An implementation may set limits on the maximum depth of nesting.
+
+ In this class, the object's limit of nesting is not constraint explicitly.
+ However, a maximum depth of nesting may be introduced by the compiler or
+ runtime environment. A theoretical limit can be queried by calling the
+ @ref max_size function of a JSON object.
+
+ #### Storage
+
+ Objects are stored as pointers in a @ref basic_json type. That is, for any
+ access to object values, a pointer of type `object_t*` must be
+ dereferenced.
+
+ @sa @ref array_t -- type for an array value
+
+ @since version 1.0.0
+
+ @note The order name/value pairs are added to the object is *not*
+ preserved by the library. Therefore, iterating an object may return
+ name/value pairs in a different order than they were originally stored. In
+ fact, keys will be traversed in alphabetical order as `std::map` with
+ `std::less` is used by default. Please note this behavior conforms to [RFC
+ 7159](http://rfc7159.net/rfc7159), because any order implements the
+ specified "unordered" nature of JSON objects.
+ */
+ using object_t = ObjectType<StringType,
+ basic_json,
+ std::less<StringType>,
+ AllocatorType<std::pair<const StringType,
+ basic_json>>>;
+
+ /*!
+ @brief a type for an array
+
+ [RFC 7159](http://rfc7159.net/rfc7159) describes JSON arrays as follows:
+ > An array is an ordered sequence of zero or more values.
+
+ To store objects in C++, a type is defined by the template parameters
+ explained below.
+
+ @tparam ArrayType container type to store arrays (e.g., `std::vector` or
+ `std::list`)
+ @tparam AllocatorType allocator to use for arrays (e.g., `std::allocator`)
+
+ #### Default type
+
+ With the default values for @a ArrayType (`std::vector`) and @a
+ AllocatorType (`std::allocator`), the default value for @a array_t is:
+
+ @code {.cpp}
+ std::vector<
+ basic_json, // value_type
+ std::allocator<basic_json> // allocator_type
+ >
+ @endcode
+
+ #### Limits
+
+ [RFC 7159](http://rfc7159.net/rfc7159) specifies:
+ > An implementation may set limits on the maximum depth of nesting.
+
+ In this class, the array's limit of nesting is not constraint explicitly.
+ However, a maximum depth of nesting may be introduced by the compiler or
+ runtime environment. A theoretical limit can be queried by calling the
+ @ref max_size function of a JSON array.
+
+ #### Storage
+
+ Arrays are stored as pointers in a @ref basic_json type. That is, for any
+ access to array values, a pointer of type `array_t*` must be dereferenced.
+
+ @sa @ref object_t -- type for an object value
+
+ @since version 1.0.0
+ */
+ using array_t = ArrayType<basic_json, AllocatorType<basic_json>>;
+
+ /*!
+ @brief a type for a string
+
+ [RFC 7159](http://rfc7159.net/rfc7159) describes JSON strings as follows:
+ > A string is a sequence of zero or more Unicode characters.
+
+ To store objects in C++, a type is defined by the template parameter
+ described below. Unicode values are split by the JSON class into
+ byte-sized characters during deserialization.
+
+ @tparam StringType the container to store strings (e.g., `std::string`).
+ Note this container is used for keys/names in objects, see @ref object_t.
+
+ #### Default type
+
+ With the default values for @a StringType (`std::string`), the default
+ value for @a string_t is:
+
+ @code {.cpp}
+ std::string
+ @endcode
+
+ #### String comparison
+
+ [RFC 7159](http://rfc7159.net/rfc7159) states:
+ > Software implementations are typically required to test names of object
+ > members for equality. Implementations that transform the textual
+ > representation into sequences of Unicode code units and then perform the
+ > comparison numerically, code unit by code unit, are interoperable in the
+ > sense that implementations will agree in all cases on equality or
+ > inequality of two strings. For example, implementations that compare
+ > strings with escaped characters unconverted may incorrectly find that
+ > `"a\\b"` and `"a\u005Cb"` are not equal.
+
+ This implementation is interoperable as it does compare strings code unit
+ by code unit.
+
+ #### Storage
+
+ String values are stored as pointers in a @ref basic_json type. That is,
+ for any access to string values, a pointer of type `string_t*` must be
+ dereferenced.
+
+ @since version 1.0.0
+ */
+ using string_t = StringType;
+
+ /*!
+ @brief a type for a boolean
+
+ [RFC 7159](http://rfc7159.net/rfc7159) implicitly describes a boolean as a
+ type which differentiates the two literals `true` and `false`.
+
+ To store objects in C++, a type is defined by the template parameter @a
+ BooleanType which chooses the type to use.
+
+ #### Default type
+
+ With the default values for @a BooleanType (`bool`), the default value for
+ @a boolean_t is:
+
+ @code {.cpp}
+ bool
+ @endcode
+
+ #### Storage
+
+ Boolean values are stored directly inside a @ref basic_json type.
+
+ @since version 1.0.0
+ */
+ using boolean_t = BooleanType;
+
+ /*!
+ @brief a type for a number (integer)
+
+ [RFC 7159](http://rfc7159.net/rfc7159) describes numbers as follows:
+ > The representation of numbers is similar to that used in most
+ > programming languages. A number is represented in base 10 using decimal
+ > digits. It contains an integer component that may be prefixed with an
+ > optional minus sign, which may be followed by a fraction part and/or an
+ > exponent part. Leading zeros are not allowed. (...) Numeric values that
+ > cannot be represented in the grammar below (such as Infinity and NaN)
+ > are not permitted.
+
+ This description includes both integer and floating-point numbers.
+ However, C++ allows more precise storage if it is known whether the number
+ is a signed integer, an unsigned integer or a floating-point number.
+ Therefore, three different types, @ref number_integer_t, @ref
+ number_unsigned_t and @ref number_float_t are used.
+
+ To store integer numbers in C++, a type is defined by the template
+ parameter @a NumberIntegerType which chooses the type to use.
+
+ #### Default type
+
+ With the default values for @a NumberIntegerType (`int64_t`), the default
+ value for @a number_integer_t is:
+
+ @code {.cpp}
+ int64_t
+ @endcode
+
+ #### Default behavior
+
+ - The restrictions about leading zeros is not enforced in C++. Instead,
+ leading zeros in integer literals lead to an interpretation as octal
+ number. Internally, the value will be stored as decimal number. For
+ instance, the C++ integer literal `010` will be serialized to `8`.
+ During deserialization, leading zeros yield an error.
+ - Not-a-number (NaN) values will be serialized to `null`.
+
+ #### Limits
+
+ [RFC 7159](http://rfc7159.net/rfc7159) specifies:
+ > An implementation may set limits on the range and precision of numbers.
+
+ When the default type is used, the maximal integer number that can be
+ stored is `9223372036854775807` (INT64_MAX) and the minimal integer number
+ that can be stored is `-9223372036854775808` (INT64_MIN). Integer numbers
+ that are out of range will yield over/underflow when used in a
+ constructor. During deserialization, too large or small integer numbers
+ will be automatically be stored as @ref number_unsigned_t or @ref
+ number_float_t.
+
+ [RFC 7159](http://rfc7159.net/rfc7159) further states:
+ > Note that when such software is used, numbers that are integers and are
+ > in the range \f$[-2^{53}+1, 2^{53}-1]\f$ are interoperable in the sense
+ > that implementations will agree exactly on their numeric values.
+
+ As this range is a subrange of the exactly supported range [INT64_MIN,
+ INT64_MAX], this class's integer type is interoperable.
+
+ #### Storage
+
+ Integer number values are stored directly inside a @ref basic_json type.
+
+ @sa @ref number_float_t -- type for number values (floating-point)
+
+ @sa @ref number_unsigned_t -- type for number values (unsigned integer)
+
+ @since version 1.0.0
+ */
+ using number_integer_t = NumberIntegerType;
+
+ /*!
+ @brief a type for a number (unsigned)
+
+ [RFC 7159](http://rfc7159.net/rfc7159) describes numbers as follows:
+ > The representation of numbers is similar to that used in most
+ > programming languages. A number is represented in base 10 using decimal
+ > digits. It contains an integer component that may be prefixed with an
+ > optional minus sign, which may be followed by a fraction part and/or an
+ > exponent part. Leading zeros are not allowed. (...) Numeric values that
+ > cannot be represented in the grammar below (such as Infinity and NaN)
+ > are not permitted.
+
+ This description includes both integer and floating-point numbers.
+ However, C++ allows more precise storage if it is known whether the number
+ is a signed integer, an unsigned integer or a floating-point number.
+ Therefore, three different types, @ref number_integer_t, @ref
+ number_unsigned_t and @ref number_float_t are used.
+
+ To store unsigned integer numbers in C++, a type is defined by the
+ template parameter @a NumberUnsignedType which chooses the type to use.
+
+ #### Default type
+
+ With the default values for @a NumberUnsignedType (`uint64_t`), the
+ default value for @a number_unsigned_t is:
+
+ @code {.cpp}
+ uint64_t
+ @endcode
+
+ #### Default behavior
+
+ - The restrictions about leading zeros is not enforced in C++. Instead,
+ leading zeros in integer literals lead to an interpretation as octal
+ number. Internally, the value will be stored as decimal number. For
+ instance, the C++ integer literal `010` will be serialized to `8`.
+ During deserialization, leading zeros yield an error.
+ - Not-a-number (NaN) values will be serialized to `null`.
+
+ #### Limits
+
+ [RFC 7159](http://rfc7159.net/rfc7159) specifies:
+ > An implementation may set limits on the range and precision of numbers.
+
+ When the default type is used, the maximal integer number that can be
+ stored is `18446744073709551615` (UINT64_MAX) and the minimal integer
+ number that can be stored is `0`. Integer numbers that are out of range
+ will yield over/underflow when used in a constructor. During
+ deserialization, too large or small integer numbers will be automatically
+ be stored as @ref number_integer_t or @ref number_float_t.
+
+ [RFC 7159](http://rfc7159.net/rfc7159) further states:
+ > Note that when such software is used, numbers that are integers and are
+ > in the range \f$[-2^{53}+1, 2^{53}-1]\f$ are interoperable in the sense
+ > that implementations will agree exactly on their numeric values.
+
+ As this range is a subrange (when considered in conjunction with the
+ number_integer_t type) of the exactly supported range [0, UINT64_MAX],
+ this class's integer type is interoperable.
+
+ #### Storage
+
+ Integer number values are stored directly inside a @ref basic_json type.
+
+ @sa @ref number_float_t -- type for number values (floating-point)
+ @sa @ref number_integer_t -- type for number values (integer)
+
+ @since version 2.0.0
+ */
+ using number_unsigned_t = NumberUnsignedType;
+
+ /*!
+ @brief a type for a number (floating-point)
+
+ [RFC 7159](http://rfc7159.net/rfc7159) describes numbers as follows:
+ > The representation of numbers is similar to that used in most
+ > programming languages. A number is represented in base 10 using decimal
+ > digits. It contains an integer component that may be prefixed with an
+ > optional minus sign, which may be followed by a fraction part and/or an
+ > exponent part. Leading zeros are not allowed. (...) Numeric values that
+ > cannot be represented in the grammar below (such as Infinity and NaN)
+ > are not permitted.
+
+ This description includes both integer and floating-point numbers.
+ However, C++ allows more precise storage if it is known whether the number
+ is a signed integer, an unsigned integer or a floating-point number.
+ Therefore, three different types, @ref number_integer_t, @ref
+ number_unsigned_t and @ref number_float_t are used.
+
+ To store floating-point numbers in C++, a type is defined by the template
+ parameter @a NumberFloatType which chooses the type to use.
+
+ #### Default type
+
+ With the default values for @a NumberFloatType (`double`), the default
+ value for @a number_float_t is:
+
+ @code {.cpp}
+ double
+ @endcode
+
+ #### Default behavior
+
+ - The restrictions about leading zeros is not enforced in C++. Instead,
+ leading zeros in floating-point literals will be ignored. Internally,
+ the value will be stored as decimal number. For instance, the C++
+ floating-point literal `01.2` will be serialized to `1.2`. During
+ deserialization, leading zeros yield an error.
+ - Not-a-number (NaN) values will be serialized to `null`.
+
+ #### Limits
+
+ [RFC 7159](http://rfc7159.net/rfc7159) states:
+ > This specification allows implementations to set limits on the range and
+ > precision of numbers accepted. Since software that implements IEEE
+ > 754-2008 binary64 (double precision) numbers is generally available and
+ > widely used, good interoperability can be achieved by implementations
+ > that expect no more precision or range than these provide, in the sense
+ > that implementations will approximate JSON numbers within the expected
+ > precision.
+
+ This implementation does exactly follow this approach, as it uses double
+ precision floating-point numbers. Note values smaller than
+ `-1.79769313486232e+308` and values greater than `1.79769313486232e+308`
+ will be stored as NaN internally and be serialized to `null`.
+
+ #### Storage
+
+ Floating-point number values are stored directly inside a @ref basic_json
+ type.
+
+ @sa @ref number_integer_t -- type for number values (integer)
+
+ @sa @ref number_unsigned_t -- type for number values (unsigned integer)
+
+ @since version 1.0.0
+ */
+ using number_float_t = NumberFloatType;
+
+ /// @}
+
+
+ ///////////////////////////
+ // JSON type enumeration //
+ ///////////////////////////
+
+ /*!
+ @brief the JSON type enumeration
+
+ This enumeration collects the different JSON types. It is internally used
+ to distinguish the stored values, and the functions @ref is_null(), @ref
+ is_object(), @ref is_array(), @ref is_string(), @ref is_boolean(), @ref
+ is_number() (with @ref is_number_integer(), @ref is_number_unsigned(), and
+ @ref is_number_float()), @ref is_discarded(), @ref is_primitive(), and
+ @ref is_structured() rely on it.
+
+ @note There are three enumeration entries (number_integer,
+ number_unsigned, and number_float), because the library distinguishes
+ these three types for numbers: @ref number_unsigned_t is used for unsigned
+ integers, @ref number_integer_t is used for signed integers, and @ref
+ number_float_t is used for floating-point numbers or to approximate
+ integers which do not fit in the limits of their respective type.
+
+ @sa @ref basic_json(const value_t value_type) -- create a JSON value with
+ the default value for a given type
+
+ @since version 1.0.0
+ */
+ enum class value_t : uint8_t
+ {
+ null, ///< null value
+ object, ///< object (unordered set of name/value pairs)
+ array, ///< array (ordered collection of values)
+ string, ///< string value
+ boolean, ///< boolean value
+ number_integer, ///< number value (signed integer)
+ number_unsigned, ///< number value (unsigned integer)
+ number_float, ///< number value (floating-point)
+ discarded ///< discarded by the the parser callback function
+ };
+
+
+ private:
+
+ /// helper for exception-safe object creation
+ template<typename T, typename... Args>
+ static T* create(Args&& ... args)
+ {
+ AllocatorType<T> alloc;
+ auto deleter = [&](T * object)
+ {
+ alloc.deallocate(object, 1);
+ };
+ std::unique_ptr<T, decltype(deleter)> object(alloc.allocate(1), deleter);
+ alloc.construct(object.get(), std::forward<Args>(args)...);
+ assert(object.get() != nullptr);
+ return object.release();
+ }
+
+ ////////////////////////
+ // JSON value storage //
+ ////////////////////////
+
+ /*!
+ @brief a JSON value
+
+ The actual storage for a JSON value of the @ref basic_json class. This
+ union combines the different storage types for the JSON value types
+ defined in @ref value_t.
+
+ JSON type | value_t type | used type
+ --------- | --------------- | ------------------------
+ object | object | pointer to @ref object_t
+ array | array | pointer to @ref array_t
+ string | string | pointer to @ref string_t
+ boolean | boolean | @ref boolean_t
+ number | number_integer | @ref number_integer_t
+ number | number_unsigned | @ref number_unsigned_t
+ number | number_float | @ref number_float_t
+ null | null | *no value is stored*
+
+ @note Variable-length types (objects, arrays, and strings) are stored as
+ pointers. The size of the union should not exceed 64 bits if the default
+ value types are used.
+
+ @since version 1.0.0
+ */
+ union json_value
+ {
+ /// object (stored with pointer to save storage)
+ object_t* object;
+ /// array (stored with pointer to save storage)
+ array_t* array;
+ /// string (stored with pointer to save storage)
+ string_t* string;
+ /// boolean
+ boolean_t boolean;
+ /// number (integer)
+ number_integer_t number_integer;
+ /// number (unsigned integer)
+ number_unsigned_t number_unsigned;
+ /// number (floating-point)
+ number_float_t number_float;
+
+ /// default constructor (for null values)
+ json_value() = default;
+ /// constructor for booleans
+ json_value(boolean_t v) noexcept : boolean(v) {}
+ /// constructor for numbers (integer)
+ json_value(number_integer_t v) noexcept : number_integer(v) {}
+ /// constructor for numbers (unsigned)
+ json_value(number_unsigned_t v) noexcept : number_unsigned(v) {}
+ /// constructor for numbers (floating-point)
+ json_value(number_float_t v) noexcept : number_float(v) {}
+ /// constructor for empty values of a given type
+ json_value(value_t t)
+ {
+ switch (t)
+ {
+ case value_t::object:
+ {
+ object = create<object_t>();
+ break;
+ }
+
+ case value_t::array:
+ {
+ array = create<array_t>();
+ break;
+ }
+
+ case value_t::string:
+ {
+ string = create<string_t>("");
+ break;
+ }
+
+ case value_t::boolean:
+ {
+ boolean = boolean_t(false);
+ break;
+ }
+
+ case value_t::number_integer:
+ {
+ number_integer = number_integer_t(0);
+ break;
+ }
+
+ case value_t::number_unsigned:
+ {
+ number_unsigned = number_unsigned_t(0);
+ break;
+ }
+
+ case value_t::number_float:
+ {
+ number_float = number_float_t(0.0);
+ break;
+ }
+
+ default:
+ {
+ break;
+ }
+ }
+ }
+
+ /// constructor for strings
+ json_value(const string_t& value)
+ {
+ string = create<string_t>(value);
+ }
+
+ /// constructor for objects
+ json_value(const object_t& value)
+ {
+ object = create<object_t>(value);
+ }
+
+ /// constructor for arrays
+ json_value(const array_t& value)
+ {
+ array = create<array_t>(value);
+ }
+ };
+
+ /*!
+ @brief checks the class invariants
+
+ This function asserts the class invariants. It needs to be called at the
+ end of every constructor to make sure that created objects respect the
+ invariant. Furthermore, it has to be called each time the type of a JSON
+ value is changed, because the invariant expresses a relationship between
+ @a m_type and @a m_value.
+ */
+ void assert_invariant() const
+ {
+ assert(m_type != value_t::object or m_value.object != nullptr);
+ assert(m_type != value_t::array or m_value.array != nullptr);
+ assert(m_type != value_t::string or m_value.string != nullptr);
+ }
+
+ public:
+ //////////////////////////
+ // JSON parser callback //
+ //////////////////////////
+
+ /*!
+ @brief JSON callback events
+
+ This enumeration lists the parser events that can trigger calling a
+ callback function of type @ref parser_callback_t during parsing.
+
+ @image html callback_events.png "Example when certain parse events are triggered"
+
+ @since version 1.0.0
+ */
+ enum class parse_event_t : uint8_t
+ {
+ /// the parser read `{` and started to process a JSON object
+ object_start,
+ /// the parser read `}` and finished processing a JSON object
+ object_end,
+ /// the parser read `[` and started to process a JSON array
+ array_start,
+ /// the parser read `]` and finished processing a JSON array
+ array_end,
+ /// the parser read a key of a value in an object
+ key,
+ /// the parser finished reading a JSON value
+ value
+ };
+
+ /*!
+ @brief per-element parser callback type
+
+ With a parser callback function, the result of parsing a JSON text can be
+ influenced. When passed to @ref parse(std::istream&, const
+ parser_callback_t) or @ref parse(const char*, const parser_callback_t),
+ it is called on certain events (passed as @ref parse_event_t via parameter
+ @a event) with a set recursion depth @a depth and context JSON value
+ @a parsed. The return value of the callback function is a boolean
+ indicating whether the element that emitted the callback shall be kept or
+ not.
+
+ We distinguish six scenarios (determined by the event type) in which the
+ callback function can be called. The following table describes the values
+ of the parameters @a depth, @a event, and @a parsed.
+
+ parameter @a event | description | parameter @a depth | parameter @a parsed
+ ------------------ | ----------- | ------------------ | -------------------
+ parse_event_t::object_start | the parser read `{` and started to process a JSON object | depth of the parent of the JSON object | a JSON value with type discarded
+ parse_event_t::key | the parser read a key of a value in an object | depth of the currently parsed JSON object | a JSON string containing the key
+ parse_event_t::object_end | the parser read `}` and finished processing a JSON object | depth of the parent of the JSON object | the parsed JSON object
+ parse_event_t::array_start | the parser read `[` and started to process a JSON array | depth of the parent of the JSON array | a JSON value with type discarded
+ parse_event_t::array_end | the parser read `]` and finished processing a JSON array | depth of the parent of the JSON array | the parsed JSON array
+ parse_event_t::value | the parser finished reading a JSON value | depth of the value | the parsed JSON value
+
+ @image html callback_events.png "Example when certain parse events are triggered"
+
+ Discarding a value (i.e., returning `false`) has different effects
+ depending on the context in which function was called:
+
+ - Discarded values in structured types are skipped. That is, the parser
+ will behave as if the discarded value was never read.
+ - In case a value outside a structured type is skipped, it is replaced
+ with `null`. This case happens if the top-level element is skipped.
+
+ @param[in] depth the depth of the recursion during parsing
+
+ @param[in] event an event of type parse_event_t indicating the context in
+ the callback function has been called
+
+ @param[in,out] parsed the current intermediate parse result; note that
+ writing to this value has no effect for parse_event_t::key events
+
+ @return Whether the JSON value which called the function during parsing
+ should be kept (`true`) or not (`false`). In the latter case, it is either
+ skipped completely or replaced by an empty discarded object.
+
+ @sa @ref parse(std::istream&, parser_callback_t) or
+ @ref parse(const char*, parser_callback_t) for examples
+
+ @since version 1.0.0
+ */
+ using parser_callback_t = std::function<bool(int depth,
+ parse_event_t event,
+ basic_json& parsed)>;
+
+
+ //////////////////
+ // constructors //
+ //////////////////
+
+ /// @name constructors and destructors
+ /// Constructors of class @ref basic_json, copy/move constructor, copy
+ /// assignment, static functions creating objects, and the destructor.
+ /// @{
+
+ /*!
+ @brief create an empty value with a given type
+
+ Create an empty JSON value with a given type. The value will be default
+ initialized with an empty value which depends on the type:
+
+ Value type | initial value
+ ----------- | -------------
+ null | `null`
+ boolean | `false`
+ string | `""`
+ number | `0`
+ object | `{}`
+ array | `[]`
+
+ @param[in] value_type the type of the value to create
+
+ @complexity Constant.
+
+ @throw std::bad_alloc if allocation for object, array, or string value
+ fails
+
+ @liveexample{The following code shows the constructor for different @ref
+ value_t values,basic_json__value_t}
+
+ @sa @ref basic_json(std::nullptr_t) -- create a `null` value
+ @sa @ref basic_json(boolean_t value) -- create a boolean value
+ @sa @ref basic_json(const string_t&) -- create a string value
+ @sa @ref basic_json(const object_t&) -- create a object value
+ @sa @ref basic_json(const array_t&) -- create a array value
+ @sa @ref basic_json(const number_float_t) -- create a number
+ (floating-point) value
+ @sa @ref basic_json(const number_integer_t) -- create a number (integer)
+ value
+ @sa @ref basic_json(const number_unsigned_t) -- create a number (unsigned)
+ value
+
+ @since version 1.0.0
+ */
+ basic_json(const value_t value_type)
+ : m_type(value_type), m_value(value_type)
+ {
+ assert_invariant();
+ }
+
+ /*!
+ @brief create a null object
+
+ Create a `null` JSON value. It either takes a null pointer as parameter
+ (explicitly creating `null`) or no parameter (implicitly creating `null`).
+ The passed null pointer itself is not read -- it is only used to choose
+ the right constructor.
+
+ @complexity Constant.
+
+ @exceptionsafety No-throw guarantee: this constructor never throws
+ exceptions.
+
+ @liveexample{The following code shows the constructor with and without a
+ null pointer parameter.,basic_json__nullptr_t}
+
+ @since version 1.0.0
+ */
+ basic_json(std::nullptr_t = nullptr) noexcept
+ : basic_json(value_t::null)
+ {
+ assert_invariant();
+ }
+
+ /*!
+ @brief create an object (explicit)
+
+ Create an object JSON value with a given content.
+
+ @param[in] val a value for the object
+
+ @complexity Linear in the size of the passed @a val.
+
+ @throw std::bad_alloc if allocation for object value fails
+
+ @liveexample{The following code shows the constructor with an @ref
+ object_t parameter.,basic_json__object_t}
+
+ @sa @ref basic_json(const CompatibleObjectType&) -- create an object value
+ from a compatible STL container
+
+ @since version 1.0.0
+ */
+ basic_json(const object_t& val)
+ : m_type(value_t::object), m_value(val)
+ {
+ assert_invariant();
+ }
+
+ /*!
+ @brief create an object (implicit)
+
+ Create an object JSON value with a given content. This constructor allows
+ any type @a CompatibleObjectType that can be used to construct values of
+ type @ref object_t.
+
+ @tparam CompatibleObjectType An object type whose `key_type` and
+ `value_type` is compatible to @ref object_t. Examples include `std::map`,
+ `std::unordered_map`, `std::multimap`, and `std::unordered_multimap` with
+ a `key_type` of `std::string`, and a `value_type` from which a @ref
+ basic_json value can be constructed.
+
+ @param[in] val a value for the object
+
+ @complexity Linear in the size of the passed @a val.
+
+ @throw std::bad_alloc if allocation for object value fails
+
+ @liveexample{The following code shows the constructor with several
+ compatible object type parameters.,basic_json__CompatibleObjectType}
+
+ @sa @ref basic_json(const object_t&) -- create an object value
+
+ @since version 1.0.0
+ */
+ template<class CompatibleObjectType, typename std::enable_if<
+ std::is_constructible<typename object_t::key_type, typename CompatibleObjectType::key_type>::value and
+ std::is_constructible<basic_json, typename CompatibleObjectType::mapped_type>::value, int>::type = 0>
+ basic_json(const CompatibleObjectType& val)
+ : m_type(value_t::object)
+ {
+ using std::begin;
+ using std::end;
+ m_value.object = create<object_t>(begin(val), end(val));
+ assert_invariant();
+ }
+
+ /*!
+ @brief create an array (explicit)
+
+ Create an array JSON value with a given content.
+
+ @param[in] val a value for the array
+
+ @complexity Linear in the size of the passed @a val.
+
+ @throw std::bad_alloc if allocation for array value fails
+
+ @liveexample{The following code shows the constructor with an @ref array_t
+ parameter.,basic_json__array_t}
+
+ @sa @ref basic_json(const CompatibleArrayType&) -- create an array value
+ from a compatible STL containers
+
+ @since version 1.0.0
+ */
+ basic_json(const array_t& val)
+ : m_type(value_t::array), m_value(val)
+ {
+ assert_invariant();
+ }
+
+ /*!
+ @brief create an array (implicit)
+
+ Create an array JSON value with a given content. This constructor allows
+ any type @a CompatibleArrayType that can be used to construct values of
+ type @ref array_t.
+
+ @tparam CompatibleArrayType An object type whose `value_type` is
+ compatible to @ref array_t. Examples include `std::vector`, `std::deque`,
+ `std::list`, `std::forward_list`, `std::array`, `std::set`,
+ `std::unordered_set`, `std::multiset`, and `unordered_multiset` with a
+ `value_type` from which a @ref basic_json value can be constructed.
+
+ @param[in] val a value for the array
+
+ @complexity Linear in the size of the passed @a val.
+
+ @throw std::bad_alloc if allocation for array value fails
+
+ @liveexample{The following code shows the constructor with several
+ compatible array type parameters.,basic_json__CompatibleArrayType}
+
+ @sa @ref basic_json(const array_t&) -- create an array value
+
+ @since version 1.0.0
+ */
+ template<class CompatibleArrayType, typename std::enable_if<
+ not std::is_same<CompatibleArrayType, typename basic_json_t::iterator>::value and
+ not std::is_same<CompatibleArrayType, typename basic_json_t::const_iterator>::value and
+ not std::is_same<CompatibleArrayType, typename basic_json_t::reverse_iterator>::value and
+ not std::is_same<CompatibleArrayType, typename basic_json_t::const_reverse_iterator>::value and
+ not std::is_same<CompatibleArrayType, typename array_t::iterator>::value and
+ not std::is_same<CompatibleArrayType, typename array_t::const_iterator>::value and
+ std::is_constructible<basic_json, typename CompatibleArrayType::value_type>::value, int>::type = 0>
+ basic_json(const CompatibleArrayType& val)
+ : m_type(value_t::array)
+ {
+ using std::begin;
+ using std::end;
+ m_value.array = create<array_t>(begin(val), end(val));
+ assert_invariant();
+ }
+
+ /*!
+ @brief create a string (explicit)
+
+ Create an string JSON value with a given content.
+
+ @param[in] val a value for the string
+
+ @complexity Linear in the size of the passed @a val.
+
+ @throw std::bad_alloc if allocation for string value fails
+
+ @liveexample{The following code shows the constructor with an @ref
+ string_t parameter.,basic_json__string_t}
+
+ @sa @ref basic_json(const typename string_t::value_type*) -- create a
+ string value from a character pointer
+ @sa @ref basic_json(const CompatibleStringType&) -- create a string value
+ from a compatible string container
+
+ @since version 1.0.0
+ */
+ basic_json(const string_t& val)
+ : m_type(value_t::string), m_value(val)
+ {
+ assert_invariant();
+ }
+
+ /*!
+ @brief create a string (explicit)
+
+ Create a string JSON value with a given content.
+
+ @param[in] val a literal value for the string
+
+ @complexity Linear in the size of the passed @a val.
+
+ @throw std::bad_alloc if allocation for string value fails
+
+ @liveexample{The following code shows the constructor with string literal
+ parameter.,basic_json__string_t_value_type}
+
+ @sa @ref basic_json(const string_t&) -- create a string value
+ @sa @ref basic_json(const CompatibleStringType&) -- create a string value
+ from a compatible string container
+
+ @since version 1.0.0
+ */
+ basic_json(const typename string_t::value_type* val)
+ : basic_json(string_t(val))
+ {
+ assert_invariant();
+ }
+
+ /*!
+ @brief create a string (implicit)
+
+ Create a string JSON value with a given content.
+
+ @param[in] val a value for the string
+
+ @tparam CompatibleStringType an string type which is compatible to @ref
+ string_t, for instance `std::string`.
+
+ @complexity Linear in the size of the passed @a val.
+
+ @throw std::bad_alloc if allocation for string value fails
+
+ @liveexample{The following code shows the construction of a string value
+ from a compatible type.,basic_json__CompatibleStringType}
+
+ @sa @ref basic_json(const string_t&) -- create a string value
+ @sa @ref basic_json(const typename string_t::value_type*) -- create a
+ string value from a character pointer
+
+ @since version 1.0.0
+ */
+ template<class CompatibleStringType, typename std::enable_if<
+ std::is_constructible<string_t, CompatibleStringType>::value, int>::type = 0>
+ basic_json(const CompatibleStringType& val)
+ : basic_json(string_t(val))
+ {
+ assert_invariant();
+ }
+
+ /*!
+ @brief create a boolean (explicit)
+
+ Creates a JSON boolean type from a given value.
+
+ @param[in] val a boolean value to store
+
+ @complexity Constant.
+
+ @liveexample{The example below demonstrates boolean
+ values.,basic_json__boolean_t}
+
+ @since version 1.0.0
+ */
+ basic_json(boolean_t val) noexcept
+ : m_type(value_t::boolean), m_value(val)
+ {
+ assert_invariant();
+ }
+
+ /*!
+ @brief create an integer number (explicit)
+
+ Create an integer number JSON value with a given content.
+
+ @tparam T A helper type to remove this function via SFINAE in case @ref
+ number_integer_t is the same as `int`. In this case, this constructor
+ would have the same signature as @ref basic_json(const int value). Note
+ the helper type @a T is not visible in this constructor's interface.
+
+ @param[in] val an integer to create a JSON number from
+
+ @complexity Constant.
+
+ @liveexample{The example below shows the construction of an integer
+ number value.,basic_json__number_integer_t}
+
+ @sa @ref basic_json(const int) -- create a number value (integer)
+ @sa @ref basic_json(const CompatibleNumberIntegerType) -- create a number
+ value (integer) from a compatible number type
+
+ @since version 1.0.0
+ */
+ template<typename T, typename std::enable_if<
+ not (std::is_same<T, int>::value) and
+ std::is_same<T, number_integer_t>::value, int>::type = 0>
+ basic_json(const number_integer_t val) noexcept
+ : m_type(value_t::number_integer), m_value(val)
+ {
+ assert_invariant();
+ }
+
+ /*!
+ @brief create an integer number from an enum type (explicit)
+
+ Create an integer number JSON value with a given content.
+
+ @param[in] val an integer to create a JSON number from
+
+ @note This constructor allows to pass enums directly to a constructor. As
+ C++ has no way of specifying the type of an anonymous enum explicitly, we
+ can only rely on the fact that such values implicitly convert to int. As
+ int may already be the same type of number_integer_t, we may need to
+ switch off the constructor @ref basic_json(const number_integer_t).
+
+ @complexity Constant.
+
+ @liveexample{The example below shows the construction of an integer
+ number value from an anonymous enum.,basic_json__const_int}
+
+ @sa @ref basic_json(const number_integer_t) -- create a number value
+ (integer)
+ @sa @ref basic_json(const CompatibleNumberIntegerType) -- create a number
+ value (integer) from a compatible number type
+
+ @since version 1.0.0
+ */
+ basic_json(const int val) noexcept
+ : m_type(value_t::number_integer),
+ m_value(static_cast<number_integer_t>(val))
+ {
+ assert_invariant();
+ }
+
+ /*!
+ @brief create an integer number (implicit)
+
+ Create an integer number JSON value with a given content. This constructor
+ allows any type @a CompatibleNumberIntegerType that can be used to
+ construct values of type @ref number_integer_t.
+
+ @tparam CompatibleNumberIntegerType An integer type which is compatible to
+ @ref number_integer_t. Examples include the types `int`, `int32_t`,
+ `long`, and `short`.
+
+ @param[in] val an integer to create a JSON number from
+
+ @complexity Constant.
+
+ @liveexample{The example below shows the construction of several integer
+ number values from compatible
+ types.,basic_json__CompatibleIntegerNumberType}
+
+ @sa @ref basic_json(const number_integer_t) -- create a number value
+ (integer)
+ @sa @ref basic_json(const int) -- create a number value (integer)
+
+ @since version 1.0.0
+ */
+ template<typename CompatibleNumberIntegerType, typename std::enable_if<
+ std::is_constructible<number_integer_t, CompatibleNumberIntegerType>::value and
+ std::numeric_limits<CompatibleNumberIntegerType>::is_integer and
+ std::numeric_limits<CompatibleNumberIntegerType>::is_signed,
+ CompatibleNumberIntegerType>::type = 0>
+ basic_json(const CompatibleNumberIntegerType val) noexcept
+ : m_type(value_t::number_integer),
+ m_value(static_cast<number_integer_t>(val))
+ {
+ assert_invariant();
+ }
+
+ /*!
+ @brief create an unsigned integer number (explicit)
+
+ Create an unsigned integer number JSON value with a given content.
+
+ @tparam T helper type to compare number_unsigned_t and unsigned int (not
+ visible in) the interface.
+
+ @param[in] val an integer to create a JSON number from
+
+ @complexity Constant.
+
+ @sa @ref basic_json(const CompatibleNumberUnsignedType) -- create a number
+ value (unsigned integer) from a compatible number type
+
+ @since version 2.0.0
+ */
+ template<typename T, typename std::enable_if<
+ not (std::is_same<T, int>::value) and
+ std::is_same<T, number_unsigned_t>::value, int>::type = 0>
+ basic_json(const number_unsigned_t val) noexcept
+ : m_type(value_t::number_unsigned), m_value(val)
+ {
+ assert_invariant();
+ }
+
+ /*!
+ @brief create an unsigned number (implicit)
+
+ Create an unsigned number JSON value with a given content. This
+ constructor allows any type @a CompatibleNumberUnsignedType that can be
+ used to construct values of type @ref number_unsigned_t.
+
+ @tparam CompatibleNumberUnsignedType An integer type which is compatible
+ to @ref number_unsigned_t. Examples may include the types `unsigned int`,
+ `uint32_t`, or `unsigned short`.
+
+ @param[in] val an unsigned integer to create a JSON number from
+
+ @complexity Constant.
+
+ @sa @ref basic_json(const number_unsigned_t) -- create a number value
+ (unsigned)
+
+ @since version 2.0.0
+ */
+ template<typename CompatibleNumberUnsignedType, typename std::enable_if <
+ std::is_constructible<number_unsigned_t, CompatibleNumberUnsignedType>::value and
+ std::numeric_limits<CompatibleNumberUnsignedType>::is_integer and
+ not std::numeric_limits<CompatibleNumberUnsignedType>::is_signed,
+ CompatibleNumberUnsignedType>::type = 0>
+ basic_json(const CompatibleNumberUnsignedType val) noexcept
+ : m_type(value_t::number_unsigned),
+ m_value(static_cast<number_unsigned_t>(val))
+ {
+ assert_invariant();
+ }
+
+ /*!
+ @brief create a floating-point number (explicit)
+
+ Create a floating-point number JSON value with a given content.
+
+ @param[in] val a floating-point value to create a JSON number from
+
+ @note [RFC 7159](http://www.rfc-editor.org/rfc/rfc7159.txt), section 6
+ disallows NaN values:
+ > Numeric values that cannot be represented in the grammar below (such as
+ > Infinity and NaN) are not permitted.
+ In case the parameter @a val is not a number, a JSON null value is created
+ instead.
+
+ @complexity Constant.
+
+ @liveexample{The following example creates several floating-point
+ values.,basic_json__number_float_t}
+
+ @sa @ref basic_json(const CompatibleNumberFloatType) -- create a number
+ value (floating-point) from a compatible number type
+
+ @since version 1.0.0
+ */
+ basic_json(const number_float_t val) noexcept
+ : m_type(value_t::number_float), m_value(val)
+ {
+ // replace infinity and NAN by null
+ if (not std::isfinite(val))
+ {
+ m_type = value_t::null;
+ m_value = json_value();
+ }
+
+ assert_invariant();
+ }
+
+ /*!
+ @brief create an floating-point number (implicit)
+
+ Create an floating-point number JSON value with a given content. This
+ constructor allows any type @a CompatibleNumberFloatType that can be used
+ to construct values of type @ref number_float_t.
+
+ @tparam CompatibleNumberFloatType A floating-point type which is
+ compatible to @ref number_float_t. Examples may include the types `float`
+ or `double`.
+
+ @param[in] val a floating-point to create a JSON number from
+
+ @note [RFC 7159](http://www.rfc-editor.org/rfc/rfc7159.txt), section 6
+ disallows NaN values:
+ > Numeric values that cannot be represented in the grammar below (such as
+ > Infinity and NaN) are not permitted.
+ In case the parameter @a val is not a number, a JSON null value is
+ created instead.
+
+ @complexity Constant.
+
+ @liveexample{The example below shows the construction of several
+ floating-point number values from compatible
+ types.,basic_json__CompatibleNumberFloatType}
+
+ @sa @ref basic_json(const number_float_t) -- create a number value
+ (floating-point)
+
+ @since version 1.0.0
+ */
+ template<typename CompatibleNumberFloatType, typename = typename std::enable_if<
+ std::is_constructible<number_float_t, CompatibleNumberFloatType>::value and
+ std::is_floating_point<CompatibleNumberFloatType>::value>::type>
+ basic_json(const CompatibleNumberFloatType val) noexcept
+ : basic_json(number_float_t(val))
+ {
+ assert_invariant();
+ }
+
+ /*!
+ @brief create a container (array or object) from an initializer list
+
+ Creates a JSON value of type array or object from the passed initializer
+ list @a init. In case @a type_deduction is `true` (default), the type of
+ the JSON value to be created is deducted from the initializer list @a init
+ according to the following rules:
+
+ 1. If the list is empty, an empty JSON object value `{}` is created.
+ 2. If the list consists of pairs whose first element is a string, a JSON
+ object value is created where the first elements of the pairs are
+ treated as keys and the second elements are as values.
+ 3. In all other cases, an array is created.
+
+ The rules aim to create the best fit between a C++ initializer list and
+ JSON values. The rationale is as follows:
+
+ 1. The empty initializer list is written as `{}` which is exactly an empty
+ JSON object.
+ 2. C++ has now way of describing mapped types other than to list a list of
+ pairs. As JSON requires that keys must be of type string, rule 2 is the
+ weakest constraint one can pose on initializer lists to interpret them
+ as an object.
+ 3. In all other cases, the initializer list could not be interpreted as
+ JSON object type, so interpreting it as JSON array type is safe.
+
+ With the rules described above, the following JSON values cannot be
+ expressed by an initializer list:
+
+ - the empty array (`[]`): use @ref array(std::initializer_list<basic_json>)
+ with an empty initializer list in this case
+ - arrays whose elements satisfy rule 2: use @ref
+ array(std::initializer_list<basic_json>) with the same initializer list
+ in this case
+
+ @note When used without parentheses around an empty initializer list, @ref
+ basic_json() is called instead of this function, yielding the JSON null
+ value.
+
+ @param[in] init initializer list with JSON values
+
+ @param[in] type_deduction internal parameter; when set to `true`, the type
+ of the JSON value is deducted from the initializer list @a init; when set
+ to `false`, the type provided via @a manual_type is forced. This mode is
+ used by the functions @ref array(std::initializer_list<basic_json>) and
+ @ref object(std::initializer_list<basic_json>).
+
+ @param[in] manual_type internal parameter; when @a type_deduction is set
+ to `false`, the created JSON value will use the provided type (only @ref
+ value_t::array and @ref value_t::object are valid); when @a type_deduction
+ is set to `true`, this parameter has no effect
+
+ @throw std::domain_error if @a type_deduction is `false`, @a manual_type
+ is `value_t::object`, but @a init contains an element which is not a pair
+ whose first element is a string; example: `"cannot create object from
+ initializer list"`
+
+ @complexity Linear in the size of the initializer list @a init.
+
+ @liveexample{The example below shows how JSON values are created from
+ initializer lists.,basic_json__list_init_t}
+
+ @sa @ref array(std::initializer_list<basic_json>) -- create a JSON array
+ value from an initializer list
+ @sa @ref object(std::initializer_list<basic_json>) -- create a JSON object
+ value from an initializer list
+
+ @since version 1.0.0
+ */
+ basic_json(std::initializer_list<basic_json> init,
+ bool type_deduction = true,
+ value_t manual_type = value_t::array)
+ {
+ // check if each element is an array with two elements whose first
+ // element is a string
+ bool is_an_object = std::all_of(init.begin(), init.end(),
+ [](const basic_json & element)
+ {
+ return element.is_array() and element.size() == 2 and element[0].is_string();
+ });
+
+ // adjust type if type deduction is not wanted
+ if (not type_deduction)
+ {
+ // if array is wanted, do not create an object though possible
+ if (manual_type == value_t::array)
+ {
+ is_an_object = false;
+ }
+
+ // if object is wanted but impossible, throw an exception
+ if (manual_type == value_t::object and not is_an_object)
+ {
+ throw std::domain_error("cannot create object from initializer list");
+ }
+ }
+
+ if (is_an_object)
+ {
+ // the initializer list is a list of pairs -> create object
+ m_type = value_t::object;
+ m_value = value_t::object;
+
+ std::for_each(init.begin(), init.end(), [this](const basic_json & element)
+ {
+ m_value.object->emplace(*(element[0].m_value.string), element[1]);
+ });
+ }
+ else
+ {
+ // the initializer list describes an array -> create array
+ m_type = value_t::array;
+ m_value.array = create<array_t>(init);
+ }
+
+ assert_invariant();
+ }
+
+ /*!
+ @brief explicitly create an array from an initializer list
+
+ Creates a JSON array value from a given initializer list. That is, given a
+ list of values `a, b, c`, creates the JSON value `[a, b, c]`. If the
+ initializer list is empty, the empty array `[]` is created.
+
+ @note This function is only needed to express two edge cases that cannot
+ be realized with the initializer list constructor (@ref
+ basic_json(std::initializer_list<basic_json>, bool, value_t)). These cases
+ are:
+ 1. creating an array whose elements are all pairs whose first element is a
+ string -- in this case, the initializer list constructor would create an
+ object, taking the first elements as keys
+ 2. creating an empty array -- passing the empty initializer list to the
+ initializer list constructor yields an empty object
+
+ @param[in] init initializer list with JSON values to create an array from
+ (optional)
+
+ @return JSON array value
+
+ @complexity Linear in the size of @a init.
+
+ @liveexample{The following code shows an example for the `array`
+ function.,array}
+
+ @sa @ref basic_json(std::initializer_list<basic_json>, bool, value_t) --
+ create a JSON value from an initializer list
+ @sa @ref object(std::initializer_list<basic_json>) -- create a JSON object
+ value from an initializer list
+
+ @since version 1.0.0
+ */
+ static basic_json array(std::initializer_list<basic_json> init =
+ std::initializer_list<basic_json>())
+ {
+ return basic_json(init, false, value_t::array);
+ }
+
+ /*!
+ @brief explicitly create an object from an initializer list
+
+ Creates a JSON object value from a given initializer list. The initializer
+ lists elements must be pairs, and their first elements must be strings. If
+ the initializer list is empty, the empty object `{}` is created.
+
+ @note This function is only added for symmetry reasons. In contrast to the
+ related function @ref array(std::initializer_list<basic_json>), there are
+ no cases which can only be expressed by this function. That is, any
+ initializer list @a init can also be passed to the initializer list
+ constructor @ref basic_json(std::initializer_list<basic_json>, bool,
+ value_t).
+
+ @param[in] init initializer list to create an object from (optional)
+
+ @return JSON object value
+
+ @throw std::domain_error if @a init is not a pair whose first elements are
+ strings; thrown by
+ @ref basic_json(std::initializer_list<basic_json>, bool, value_t)
+
+ @complexity Linear in the size of @a init.
+
+ @liveexample{The following code shows an example for the `object`
+ function.,object}
+
+ @sa @ref basic_json(std::initializer_list<basic_json>, bool, value_t) --
+ create a JSON value from an initializer list
+ @sa @ref array(std::initializer_list<basic_json>) -- create a JSON array
+ value from an initializer list
+
+ @since version 1.0.0
+ */
+ static basic_json object(std::initializer_list<basic_json> init =
+ std::initializer_list<basic_json>())
+ {
+ return basic_json(init, false, value_t::object);
+ }
+
+ /*!
+ @brief construct an array with count copies of given value
+
+ Constructs a JSON array value by creating @a cnt copies of a passed value.
+ In case @a cnt is `0`, an empty array is created. As postcondition,
+ `std::distance(begin(),end()) == cnt` holds.
+
+ @param[in] cnt the number of JSON copies of @a val to create
+ @param[in] val the JSON value to copy
+
+ @complexity Linear in @a cnt.
+
+ @liveexample{The following code shows examples for the @ref
+ basic_json(size_type\, const basic_json&)
+ constructor.,basic_json__size_type_basic_json}
+
+ @since version 1.0.0
+ */
+ basic_json(size_type cnt, const basic_json& val)
+ : m_type(value_t::array)
+ {
+ m_value.array = create<array_t>(cnt, val);
+ assert_invariant();
+ }
+
+ /*!
+ @brief construct a JSON container given an iterator range
+
+ Constructs the JSON value with the contents of the range `[first, last)`.
+ The semantics depends on the different types a JSON value can have:
+ - In case of primitive types (number, boolean, or string), @a first must
+ be `begin()` and @a last must be `end()`. In this case, the value is
+ copied. Otherwise, std::out_of_range is thrown.
+ - In case of structured types (array, object), the constructor behaves as
+ similar versions for `std::vector`.
+ - In case of a null type, std::domain_error is thrown.
+
+ @tparam InputIT an input iterator type (@ref iterator or @ref
+ const_iterator)
+
+ @param[in] first begin of the range to copy from (included)
+ @param[in] last end of the range to copy from (excluded)
+
+ @pre Iterators @a first and @a last must be initialized. **This
+ precondition is enforced with an assertion.**
+
+ @throw std::domain_error if iterators are not compatible; that is, do not
+ belong to the same JSON value; example: `"iterators are not compatible"`
+ @throw std::out_of_range if iterators are for a primitive type (number,
+ boolean, or string) where an out of range error can be detected easily;
+ example: `"iterators out of range"`
+ @throw std::bad_alloc if allocation for object, array, or string fails
+ @throw std::domain_error if called with a null value; example: `"cannot
+ use construct with iterators from null"`
+
+ @complexity Linear in distance between @a first and @a last.
+
+ @liveexample{The example below shows several ways to create JSON values by
+ specifying a subrange with iterators.,basic_json__InputIt_InputIt}
+
+ @since version 1.0.0
+ */
+ template<class InputIT, typename std::enable_if<
+ std::is_same<InputIT, typename basic_json_t::iterator>::value or
+ std::is_same<InputIT, typename basic_json_t::const_iterator>::value, int>::type = 0>
+ basic_json(InputIT first, InputIT last)
+ {
+ assert(first.m_object != nullptr);
+ assert(last.m_object != nullptr);
+
+ // make sure iterator fits the current value
+ if (first.m_object != last.m_object)
+ {
+ throw std::domain_error("iterators are not compatible");
+ }
+
+ // copy type from first iterator
+ m_type = first.m_object->m_type;
+
+ // check if iterator range is complete for primitive values
+ switch (m_type)
+ {
+ case value_t::boolean:
+ case value_t::number_float:
+ case value_t::number_integer:
+ case value_t::number_unsigned:
+ case value_t::string:
+ {
+ if (not first.m_it.primitive_iterator.is_begin() or not last.m_it.primitive_iterator.is_end())
+ {
+ throw std::out_of_range("iterators out of range");
+ }
+ break;
+ }
+
+ default:
+ {
+ break;
+ }
+ }
+
+ switch (m_type)
+ {
+ case value_t::number_integer:
+ {
+ m_value.number_integer = first.m_object->m_value.number_integer;
+ break;
+ }
+
+ case value_t::number_unsigned:
+ {
+ m_value.number_unsigned = first.m_object->m_value.number_unsigned;
+ break;
+ }
+
+ case value_t::number_float:
+ {
+ m_value.number_float = first.m_object->m_value.number_float;
+ break;
+ }
+
+ case value_t::boolean:
+ {
+ m_value.boolean = first.m_object->m_value.boolean;
+ break;
+ }
+
+ case value_t::string:
+ {
+ m_value = *first.m_object->m_value.string;
+ break;
+ }
+
+ case value_t::object:
+ {
+ m_value.object = create<object_t>(first.m_it.object_iterator, last.m_it.object_iterator);
+ break;
+ }
+
+ case value_t::array:
+ {
+ m_value.array = create<array_t>(first.m_it.array_iterator, last.m_it.array_iterator);
+ break;
+ }
+
+ default:
+ {
+ throw std::domain_error("cannot use construct with iterators from " + first.m_object->type_name());
+ }
+ }
+
+ assert_invariant();
+ }
+
+ /*!
+ @brief construct a JSON value given an input stream
+
+ @param[in,out] i stream to read a serialized JSON value from
+ @param[in] cb a parser callback function of type @ref parser_callback_t
+ which is used to control the deserialization by filtering unwanted values
+ (optional)
+
+ @complexity Linear in the length of the input. The parser is a predictive
+ LL(1) parser. The complexity can be higher if the parser callback function
+ @a cb has a super-linear complexity.
+
+ @note A UTF-8 byte order mark is silently ignored.
+
+ @deprecated This constructor is deprecated and will be removed in version
+ 3.0.0 to unify the interface of the library. Deserialization will be
+ done by stream operators or by calling one of the `parse` functions,
+ e.g. @ref parse(std::istream&, const parser_callback_t). That is, calls
+ like `json j(i);` for an input stream @a i need to be replaced by
+ `json j = json::parse(i);`. See the example below.
+
+ @liveexample{The example below demonstrates constructing a JSON value from
+ a `std::stringstream` with and without callback
+ function.,basic_json__istream}
+
+ @since version 2.0.0, deprecated in version 2.0.3, to be removed in
+ version 3.0.0
+ */
+ JSON_DEPRECATED
+ explicit basic_json(std::istream& i, const parser_callback_t cb = nullptr)
+ {
+ *this = parser(i, cb).parse();
+ assert_invariant();
+ }
+
+ ///////////////////////////////////////
+ // other constructors and destructor //
+ ///////////////////////////////////////
+
+ /*!
+ @brief copy constructor
+
+ Creates a copy of a given JSON value.
+
+ @param[in] other the JSON value to copy
+
+ @complexity Linear in the size of @a other.
+
+ @requirement This function helps `basic_json` satisfying the
+ [Container](http://en.cppreference.com/w/cpp/concept/Container)
+ requirements:
+ - The complexity is linear.
+ - As postcondition, it holds: `other == basic_json(other)`.
+
+ @throw std::bad_alloc if allocation for object, array, or string fails.
+
+ @liveexample{The following code shows an example for the copy
+ constructor.,basic_json__basic_json}
+
+ @since version 1.0.0
+ */
+ basic_json(const basic_json& other)
+ : m_type(other.m_type)
+ {
+ // check of passed value is valid
+ other.assert_invariant();
+
+ switch (m_type)
+ {
+ case value_t::object:
+ {
+ m_value = *other.m_value.object;
+ break;
+ }
+
+ case value_t::array:
+ {
+ m_value = *other.m_value.array;
+ break;
+ }
+
+ case value_t::string:
+ {
+ m_value = *other.m_value.string;
+ break;
+ }
+
+ case value_t::boolean:
+ {
+ m_value = other.m_value.boolean;
+ break;
+ }
+
+ case value_t::number_integer:
+ {
+ m_value = other.m_value.number_integer;
+ break;
+ }
+
+ case value_t::number_unsigned:
+ {
+ m_value = other.m_value.number_unsigned;
+ break;
+ }
+
+ case value_t::number_float:
+ {
+ m_value = other.m_value.number_float;
+ break;
+ }
+
+ default:
+ {
+ break;
+ }
+ }
+
+ assert_invariant();
+ }
+
+ /*!
+ @brief move constructor
+
+ Move constructor. Constructs a JSON value with the contents of the given
+ value @a other using move semantics. It "steals" the resources from @a
+ other and leaves it as JSON null value.
+
+ @param[in,out] other value to move to this object
+
+ @post @a other is a JSON null value
+
+ @complexity Constant.
+
+ @liveexample{The code below shows the move constructor explicitly called
+ via std::move.,basic_json__moveconstructor}
+
+ @since version 1.0.0
+ */
+ basic_json(basic_json&& other) noexcept
+ : m_type(std::move(other.m_type)),
+ m_value(std::move(other.m_value))
+ {
+ // check that passed value is valid
+ other.assert_invariant();
+
+ // invalidate payload
+ other.m_type = value_t::null;
+ other.m_value = {};
+
+ assert_invariant();
+ }
+
+ /*!
+ @brief copy assignment
+
+ Copy assignment operator. Copies a JSON value via the "copy and swap"
+ strategy: It is expressed in terms of the copy constructor, destructor,
+ and the swap() member function.
+
+ @param[in] other value to copy from
+
+ @complexity Linear.
+
+ @requirement This function helps `basic_json` satisfying the
+ [Container](http://en.cppreference.com/w/cpp/concept/Container)
+ requirements:
+ - The complexity is linear.
+
+ @liveexample{The code below shows and example for the copy assignment. It
+ creates a copy of value `a` which is then swapped with `b`. Finally\, the
+ copy of `a` (which is the null value after the swap) is
+ destroyed.,basic_json__copyassignment}
+
+ @since version 1.0.0
+ */
+ reference& operator=(basic_json other) noexcept (
+ std::is_nothrow_move_constructible<value_t>::value and
+ std::is_nothrow_move_assignable<value_t>::value and
+ std::is_nothrow_move_constructible<json_value>::value and
+ std::is_nothrow_move_assignable<json_value>::value
+ )
+ {
+ // check that passed value is valid
+ other.assert_invariant();
+
+ using std::swap;
+ swap(m_type, other.m_type);
+ swap(m_value, other.m_value);
+
+ assert_invariant();
+ return *this;
+ }
+
+ /*!
+ @brief destructor
+
+ Destroys the JSON value and frees all allocated memory.
+
+ @complexity Linear.
+
+ @requirement This function helps `basic_json` satisfying the
+ [Container](http://en.cppreference.com/w/cpp/concept/Container)
+ requirements:
+ - The complexity is linear.
+ - All stored elements are destroyed and all memory is freed.
+
+ @since version 1.0.0
+ */
+ ~basic_json()
+ {
+ assert_invariant();
+
+ switch (m_type)
+ {
+ case value_t::object:
+ {
+ AllocatorType<object_t> alloc;
+ alloc.destroy(m_value.object);
+ alloc.deallocate(m_value.object, 1);
+ break;
+ }
+
+ case value_t::array:
+ {
+ AllocatorType<array_t> alloc;
+ alloc.destroy(m_value.array);
+ alloc.deallocate(m_value.array, 1);
+ break;
+ }
+
+ case value_t::string:
+ {
+ AllocatorType<string_t> alloc;
+ alloc.destroy(m_value.string);
+ alloc.deallocate(m_value.string, 1);
+ break;
+ }
+
+ default:
+ {
+ // all other types need no specific destructor
+ break;
+ }
+ }
+ }
+
+ /// @}
+
+ public:
+ ///////////////////////
+ // object inspection //
+ ///////////////////////
+
+ /// @name object inspection
+ /// Functions to inspect the type of a JSON value.
+ /// @{
+
+ /*!
+ @brief serialization
+
+ Serialization function for JSON values. The function tries to mimic
+ Python's `json.dumps()` function, and currently supports its @a indent
+ parameter.
+
+ @param[in] indent If indent is nonnegative, then array elements and object
+ members will be pretty-printed with that indent level. An indent level of
+ `0` will only insert newlines. `-1` (the default) selects the most compact
+ representation.
+
+ @return string containing the serialization of the JSON value
+
+ @complexity Linear.
+
+ @liveexample{The following example shows the effect of different @a indent
+ parameters to the result of the serialization.,dump}
+
+ @see https://docs.python.org/2/library/json.html#json.dump
+
+ @since version 1.0.0
+ */
+ string_t dump(const int indent = -1) const
+ {
+ std::stringstream ss;
+ // fix locale problems
+ const static std::locale loc(std::locale(), new DecimalSeparator);
+ ss.imbue(loc);
+
+ // 6, 15 or 16 digits of precision allows round-trip IEEE 754
+ // string->float->string, string->double->string or string->long
+ // double->string; to be safe, we read this value from
+ // std::numeric_limits<number_float_t>::digits10
+ ss.precision(std::numeric_limits<double>::digits10);
+
+ if (indent >= 0)
+ {
+ dump(ss, true, static_cast<unsigned int>(indent));
+ }
+ else
+ {
+ dump(ss, false, 0);
+ }
+
+ return ss.str();
+ }
+
+ /*!
+ @brief return the type of the JSON value (explicit)
+
+ Return the type of the JSON value as a value from the @ref value_t
+ enumeration.
+
+ @return the type of the JSON value
+
+ @complexity Constant.
+
+ @exceptionsafety No-throw guarantee: this member function never throws
+ exceptions.
+
+ @liveexample{The following code exemplifies `type()` for all JSON
+ types.,type}
+
+ @since version 1.0.0
+ */
+ constexpr value_t type() const noexcept
+ {
+ return m_type;
+ }
+
+ /*!
+ @brief return whether type is primitive
+
+ This function returns true iff the JSON type is primitive (string, number,
+ boolean, or null).
+
+ @return `true` if type is primitive (string, number, boolean, or null),
+ `false` otherwise.
+
+ @complexity Constant.
+
+ @exceptionsafety No-throw guarantee: this member function never throws
+ exceptions.
+
+ @liveexample{The following code exemplifies `is_primitive()` for all JSON
+ types.,is_primitive}
+
+ @sa @ref is_structured() -- returns whether JSON value is structured
+ @sa @ref is_null() -- returns whether JSON value is `null`
+ @sa @ref is_string() -- returns whether JSON value is a string
+ @sa @ref is_boolean() -- returns whether JSON value is a boolean
+ @sa @ref is_number() -- returns whether JSON value is a number
+
+ @since version 1.0.0
+ */
+ constexpr bool is_primitive() const noexcept
+ {
+ return is_null() or is_string() or is_boolean() or is_number();
+ }
+
+ /*!
+ @brief return whether type is structured
+
+ This function returns true iff the JSON type is structured (array or
+ object).
+
+ @return `true` if type is structured (array or object), `false` otherwise.
+
+ @complexity Constant.
+
+ @exceptionsafety No-throw guarantee: this member function never throws
+ exceptions.
+
+ @liveexample{The following code exemplifies `is_structured()` for all JSON
+ types.,is_structured}
+
+ @sa @ref is_primitive() -- returns whether value is primitive
+ @sa @ref is_array() -- returns whether value is an array
+ @sa @ref is_object() -- returns whether value is an object
+
+ @since version 1.0.0
+ */
+ constexpr bool is_structured() const noexcept
+ {
+ return is_array() or is_object();
+ }
+
+ /*!
+ @brief return whether value is null
+
+ This function returns true iff the JSON value is null.
+
+ @return `true` if type is null, `false` otherwise.
+
+ @complexity Constant.
+
+ @exceptionsafety No-throw guarantee: this member function never throws
+ exceptions.
+
+ @liveexample{The following code exemplifies `is_null()` for all JSON
+ types.,is_null}
+
+ @since version 1.0.0
+ */
+ constexpr bool is_null() const noexcept
+ {
+ return m_type == value_t::null;
+ }
+
+ /*!
+ @brief return whether value is a boolean
+
+ This function returns true iff the JSON value is a boolean.
+
+ @return `true` if type is boolean, `false` otherwise.
+
+ @complexity Constant.
+
+ @exceptionsafety No-throw guarantee: this member function never throws
+ exceptions.
+
+ @liveexample{The following code exemplifies `is_boolean()` for all JSON
+ types.,is_boolean}
+
+ @since version 1.0.0
+ */
+ constexpr bool is_boolean() const noexcept
+ {
+ return m_type == value_t::boolean;
+ }
+
+ /*!
+ @brief return whether value is a number
+
+ This function returns true iff the JSON value is a number. This includes
+ both integer and floating-point values.
+
+ @return `true` if type is number (regardless whether integer, unsigned
+ integer or floating-type), `false` otherwise.
+
+ @complexity Constant.
+
+ @exceptionsafety No-throw guarantee: this member function never throws
+ exceptions.
+
+ @liveexample{The following code exemplifies `is_number()` for all JSON
+ types.,is_number}
+
+ @sa @ref is_number_integer() -- check if value is an integer or unsigned
+ integer number
+ @sa @ref is_number_unsigned() -- check if value is an unsigned integer
+ number
+ @sa @ref is_number_float() -- check if value is a floating-point number
+
+ @since version 1.0.0
+ */
+ constexpr bool is_number() const noexcept
+ {
+ return is_number_integer() or is_number_float();
+ }
+
+ /*!
+ @brief return whether value is an integer number
+
+ This function returns true iff the JSON value is an integer or unsigned
+ integer number. This excludes floating-point values.
+
+ @return `true` if type is an integer or unsigned integer number, `false`
+ otherwise.
+
+ @complexity Constant.
+
+ @exceptionsafety No-throw guarantee: this member function never throws
+ exceptions.
+
+ @liveexample{The following code exemplifies `is_number_integer()` for all
+ JSON types.,is_number_integer}
+
+ @sa @ref is_number() -- check if value is a number
+ @sa @ref is_number_unsigned() -- check if value is an unsigned integer
+ number
+ @sa @ref is_number_float() -- check if value is a floating-point number
+
+ @since version 1.0.0
+ */
+ constexpr bool is_number_integer() const noexcept
+ {
+ return m_type == value_t::number_integer or m_type == value_t::number_unsigned;
+ }
+
+ /*!
+ @brief return whether value is an unsigned integer number
+
+ This function returns true iff the JSON value is an unsigned integer
+ number. This excludes floating-point and (signed) integer values.
+
+ @return `true` if type is an unsigned integer number, `false` otherwise.
+
+ @complexity Constant.
+
+ @exceptionsafety No-throw guarantee: this member function never throws
+ exceptions.
+
+ @liveexample{The following code exemplifies `is_number_unsigned()` for all
+ JSON types.,is_number_unsigned}
+
+ @sa @ref is_number() -- check if value is a number
+ @sa @ref is_number_integer() -- check if value is an integer or unsigned
+ integer number
+ @sa @ref is_number_float() -- check if value is a floating-point number
+
+ @since version 2.0.0
+ */
+ constexpr bool is_number_unsigned() const noexcept
+ {
+ return m_type == value_t::number_unsigned;
+ }
+
+ /*!
+ @brief return whether value is a floating-point number
+
+ This function returns true iff the JSON value is a floating-point number.
+ This excludes integer and unsigned integer values.
+
+ @return `true` if type is a floating-point number, `false` otherwise.
+
+ @complexity Constant.
+
+ @exceptionsafety No-throw guarantee: this member function never throws
+ exceptions.
+
+ @liveexample{The following code exemplifies `is_number_float()` for all
+ JSON types.,is_number_float}
+
+ @sa @ref is_number() -- check if value is number
+ @sa @ref is_number_integer() -- check if value is an integer number
+ @sa @ref is_number_unsigned() -- check if value is an unsigned integer
+ number
+
+ @since version 1.0.0
+ */
+ constexpr bool is_number_float() const noexcept
+ {
+ return
<TRUNCATED>