// // Query.cpp // // $Id$ // // Library: JSON // Package: JSON // Module: Query // // Copyright (c) 2012, Applied Informatics Software Engineering GmbH. // and Contributors. // // Permission is hereby granted, free of charge, to any person or organization // obtaining a copy of the software and accompanying documentation covered by // this license (the "Software") to use, reproduce, display, distribute, // execute, and transmit the Software, and to prepare derivative works of the // Software, and to permit third-parties to whom the Software is furnished to // do so, all subject to the following: // // The copyright notices in the Software and this entire statement, including // the above license grant, this restriction and the following disclaimer, // must be included in all copies of the Software, in whole or in part, and // all derivative works of the Software, unless such copies or derivative // works are solely in the form of machine-executable object code generated by // a source language processor. // // 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, TITLE AND NON-INFRINGEMENT. IN NO EVENT // SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE // FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. // #include "Poco/JSON/Query.h" #include "Poco/StringTokenizer.h" #include "Poco/RegularExpression.h" #include "Poco/NumberParser.h" #include using Poco::Dynamic::Var; namespace Poco { namespace JSON { Query::Query(const Var& source): _source(source) { if (!source.isEmpty() && source.type() != typeid(Object) && source.type() != typeid(Object::Ptr) && source.type() != typeid(Array) && source.type() != typeid(Array::Ptr)) throw InvalidArgumentException("Only JSON Object, Array or pointers thereof allowed."); } Query::~Query() { } Object::Ptr Query::findObject(const std::string& path) const { Var result = find(path); if (result.type() == typeid(Object::Ptr)) return result.extract(); else if (result.type() == typeid(Object)) return new Object(result.extract()); return 0; } Object& Query::findObject(const std::string& path, Object& obj) const { obj.clear(); Var result = find(path); if (result.type() == typeid(Object::Ptr)) obj = *result.extract(); else if (result.type() == typeid(Object)) obj = result.extract(); return obj; } Array::Ptr Query::findArray(const std::string& path) const { Var result = find(path); if (result.type() == typeid(Array::Ptr)) return result.extract(); else if (result.type() == typeid(Array)) return new Array(result.extract()); return 0; } Array& Query::findArray(const std::string& path, Array& arr) const { arr.clear(); Var result = find(path); if (result.type() == typeid(Array::Ptr)) arr = *result.extract(); else if (result.type() == typeid(Array)) arr = result.extract(); return arr; } Var Query::find(const std::string& path) const { Var result = _source; StringTokenizer tokenizer(path, "."); for(StringTokenizer::Iterator token = tokenizer.begin(); token != tokenizer.end(); token++) { if (!result.isEmpty()) { std::vector indexes; RegularExpression::MatchVec matches; int firstOffset = -1; int offset = 0; RegularExpression regex("\\[([0-9]+)\\]"); while(regex.match(*token, offset, matches) > 0) { if (firstOffset == -1) { firstOffset = static_cast(matches[0].offset); } std::string num = token->substr(matches[1].offset, matches[1].length); indexes.push_back(NumberParser::parse(num)); offset = static_cast(matches[0].offset + matches[0].length); } std::string name(*token); if (firstOffset != -1) { name = name.substr(0, firstOffset); } if (name.length() > 0) { if (result.type() == typeid(Object::Ptr)) { Object::Ptr o = result.extract(); result = o->get(name); } else if (result.type() == typeid(Object)) { Object o = result.extract(); result = o.get(name); } } if (!result.isEmpty() && !indexes.empty()) { for(std::vector::iterator it = indexes.begin(); it != indexes.end(); ++it) { if (result.type() == typeid(Array::Ptr)) { Array::Ptr array = result.extract(); result = array->get(*it); if (result.isEmpty()) break; } else if (result.type() == typeid(Array)) { Array array = result.extract(); result = array.get(*it); if (result.isEmpty()) break; } } } } } return result; } } } // Namespace Poco::JSON