<commit_before>/*
This file is part of the ORK library.
Full copyright and license terms can be found in the LICENSE.txt file.
*/
#pragma once
#include "ork/memory.hpp"
#include "ork/string_utils.hpp"
#include "ork/type_traits.hpp"

#include "glm/fwd.hpp"

#if ORK_USE_JSON
namespace Json {
class Value;
}
#endif

#if ORK_USE_PUGI
namespace pugi {
class xml_document;
class xml_node;
} // namespace pugi
#endif

#if ORK_USE_YAML
namespace YAML {
class Node;
}
#endif

namespace ork {
namespace json {

#if ORK_USE_JSON

class ORK_ORK_API exportable {
public:
    virtual ~exportable() {}

public:
    virtual void export_json(Json::Value& v) const = 0;
};

class ORK_ORK_API serializable {
public:
    virtual ~serializable() {}

public:
    virtual void to_json(Json::Value& v) const = 0;
    virtual void from_json(const Json::Value& v) = 0;
};

ORK_ORK_EXT(void)
export_file(const string& path_to_file, const Json::Value& root);
ORK_ORK_EXT(void)
export_file(const string& path_to_file, const exportable& object);
ORK_ORK_EXT(void) load_and_parse(bi_stream& fin, Json::Value& root);
ORK_ORK_EXT(Json::Value) load_and_parse(bi_stream& fin);

#endif // ORK_USE_JSON

} // namespace json
namespace xml {

#if ORK_USE_PUGI

class ORK_ORK_API exportable {
public:
    virtual ~exportable() {}

public:
    virtual void export_xml(pugi::xml_node& n) const = 0;
};

class ORK_ORK_API serializable {
public:
    virtual ~serializable() {}

public:
    virtual void to_xml(pugi::xml_node& v) const = 0;
    virtual void from_xml(const pugi::xml_node& v) = 0;
};

ORK_ORK_EXT(void)
export_file(const string& path_to_file, const exportable& object, const string& root_node_name);
ORK_ORK_EXT(void)
load_and_parse(i_stream& fin, pugi::xml_document& root); // Just create a file with error checking
ORK_ORK_EXT(void)
load_and_parse_permissive(
    const file::path& path_to_file,
    const bstring& root_tag,
    xml::serializable& obj);

/*
These are permissive interfaces
*/
template<typename T>
void value_to_attribute(pugi::xml_node& node, const bstring& tag, ORK_CPARAM_T value)
{
    try {
        node.append_attribute(tag.c_str()).set_value(to_bstring(value).c_str());
    }
    catch(std::exception& e) {
        ORK_LOG(severity_level::error)
            << ORK("Failed to set attribute ") << ORK_BYTE_2_STR(node.name())
            << ORK(":") << ORK_BYTE_2_STR(tag) << ORK(", ") << e.what();
    }
    catch(...) {
        ORK_LOG(severity_level::error)
            << ORK("Something happened setting attribute ")
            << ORK_BYTE_2_STR(node.name()) << ORK(":") << ORK_BYTE_2_STR(tag);
    }
}
template<typename T>
void value_to_xml(pugi::xml_node& node, const bstring& tag, ORK_CPARAM_T value)
{
    try {
        node.append_child(tag.c_str())
            .append_child(pugi::node_pcdata)
            .set_value(to_bstring(value).c_str());
    }
    catch(std::exception& e) {
        ORK_LOG(severity_level::error)
            << ORK("Failed to set tag ") << ORK_BYTE_2_STR(tag) << ORK(": ")
            << ORK_BYTE_2_STR(e.what());
    }
    catch(...) {
        ORK_LOG(severity_level::error)
            << ORK("Something happened setting tag ") << ORK_BYTE_2_STR(tag);
    }
}
template<typename T>
void value_to_xml(pugi::xml_node& node, ORK_CPARAM_T value)
{
    try {
        node.append_child(pugi::node_pcdata).set_value(to_bstring(value).c_str());
    }
    catch(std::exception& e) {
        ORK_LOG(severity_level::error)
            << ORK("Failed to set tag ") << ORK_BYTE_2_STR(node.name())
            << ORK(": ") << ORK_BYTE_2_STR(e.what());
    }
    catch(...) {
        ORK_LOG(severity_level::error) << ORK("Something happened setting tag ")
                                       << ORK_BYTE_2_STR(node.name());
    }
}

template<typename T>
void value_from_attribute(const pugi::xml_node& node, const bstring& tag, ORK_REF_T value)
{
    try {
        value = from_string<ORK_VAL_T>(node.attribute(tag.c_str()).value());
    }
    catch(std::exception& e) {
        ORK_LOG(severity_level::error)
            << ORK("Failed to read parameter ") << ORK_BYTE_2_STR(tag)
            << ORK(": ") << ORK_BYTE_2_STR(e.what());
    }
    catch(...) {
        ORK_LOG(severity_level::error)
            << ORK("Something happened reading parameter ") << ORK_BYTE_2_STR(tag);
    }
}
template<typename T>
void value_from_xml(const pugi::xml_node& node, const bstring& tag, ORK_REF_T value)
{
    try {
        value = from_string<ORK_VAL_T>(node.child_value(tag.c_str()));
    }
    catch(std::exception& e) {
        ORK_LOG(severity_level::error)
            << ORK("Failed to read tag ") << ORK_BYTE_2_STR(tag) << ORK(": ")
            << ORK_BYTE_2_STR(e.what());
    }
    catch(...) {
        ORK_LOG(severity_level::error)
            << ORK("Something happened reading tag ") << ORK_BYTE_2_STR(tag);
    }
}
template<typename T>
void value_from_xml(const pugi::xml_node& node, ORK_REF_T value)
{
    try {
        value = from_string<ORK_VAL_T>(node.child_value());
    }
    catch(std::exception& e) {
        ORK_LOG(severity_level::error)
            << ORK("Failed to read tag ") << ORK_BYTE_2_STR(node.name())
            << ORK(": ") << ORK_BYTE_2_STR(e.what());
    }
    catch(...) {
        ORK_LOG(severity_level::error) << ORK("Something happened reading tag ")
                                       << ORK_BYTE_2_STR(node.name());
    }
}

// Overloads to eliminate dependency definitions
#    define ORK_XML_SERIALIZE_DECL(TYPE) \
        ORK_EXT(void) \
        to_xml(pugi::xml_node& node, const ork::bstring& tag, ORK_CPARAM(TYPE) value); \
        ORK_EXT(void) \
        from_xml(const pugi::xml_node& node, const ork::bstring& tag, ORK_REF(TYPE) value)

ORK_XML_SERIALIZE_DECL(int);
ORK_XML_SERIALIZE_DECL(unsigned);
ORK_XML_SERIALIZE_DECL(size_t);
ORK_XML_SERIALIZE_DECL(float);
ORK_XML_SERIALIZE_DECL(double);
ORK_XML_SERIALIZE_DECL(bstring);
ORK_XML_SERIALIZE_DECL(wstring);

#    define ORK_XML_SERIALIZE_DEF(TYPE) \
        void to_xml(pugi::xml_node& node, const ork::bstring& tag, ORK_CPARAM(TYPE) value) \
        { \
            value_to_xml<TYPE>(node, tag, value); \
        } \
        void from_xml( \
            const pugi::xml_node& node, const ork::bstring& tag, ORK_REF(TYPE) value) \
        { \
            value_from_xml<TYPE>(node, tag, value); \
        }

#endif // ORK_USE_PUGI

} // namespace xml
namespace yaml {

#if ORK_USE_YAML

class ORK_ORK_API exportable {
public:
    virtual ~exportable() {}

public:
    virtual void export_yaml(YAML::Node& n) const = 0;
};

class ORK_ORK_API serializable {
public:
    virtual ~serializable() {}

public:
    virtual void to_yaml(YAML::Node& v) const = 0;
    virtual void from_yaml(const YAML::Node& v) = 0;
};

ORK_ORK_EXT(void)
export_file(const string& path_to_file, const YAML::Node& root);
ORK_ORK_EXT(void)
export_file(const string& path_to_file, const exportable& object);
ORK_ORK_EXT(void) load_and_parse(bi_stream& fin, YAML::Node& root);
ORK_ORK_EXT(YAML::Node) load_and_parse(bi_stream& fin);

#endif // ORK_USE_YAML

} // namespace yaml
} // namespace ork
<commit_msg>Fixed includes and api for permissive interfaces<commit_after>/*
This file is part of the ORK library.
Full copyright and license terms can be found in the LICENSE.txt file.
*/
#pragma once
#include "ork/memory.hpp"
#include "ork/private/text_includes.hpp"
#include "ork/string_utils.hpp"
#include "ork/type_traits.hpp"

#include "glm/fwd.hpp"

namespace ork {
namespace json {

#if ORK_USE_JSON

class ORK_ORK_API exportable {
public:
    virtual ~exportable() {}

public:
    virtual void export_json(Json::Value& v) const = 0;
};

class ORK_ORK_API serializable {
public:
    virtual ~serializable() {}

public:
    virtual void to_json(Json::Value& v) const = 0;
    virtual void from_json(const Json::Value& v) = 0;
};

ORK_ORK_EXT(void)
export_file(const string& path_to_file, const Json::Value& root);
ORK_ORK_EXT(void)
export_file(const string& path_to_file, const exportable& object);
ORK_ORK_EXT(void) load_and_parse(bi_stream& fin, Json::Value& root);
ORK_ORK_EXT(Json::Value) load_and_parse(bi_stream& fin);

#endif // ORK_USE_JSON

} // namespace json
namespace xml {

#if ORK_USE_PUGI

class ORK_ORK_API exportable {
public:
    virtual ~exportable() {}

public:
    virtual void export_xml(pugi::xml_node& n) const = 0;
};

class ORK_ORK_API serializable {
public:
    virtual ~serializable() {}

public:
    virtual void to_xml(pugi::xml_node& v) const = 0;
    virtual void from_xml(const pugi::xml_node& v) = 0;
};

ORK_ORK_EXT(void)
export_file(const string& path_to_file, const exportable& object, const string& root_node_name);
ORK_ORK_EXT(void)
load_and_parse(i_stream& fin, pugi::xml_document& root); // Just create a file with error checking
ORK_ORK_EXT(void)
load_and_parse_permissive(
    const file::path& path_to_file,
    const bstring& root_tag,
    xml::serializable& obj);

/*
These are permissive interfaces
*/
template<typename T>
void value_to_attribute(pugi::xml_node& node, const bstring& tag, ORK_CPARAM_T value)
{
    try {
        node.append_attribute(tag.c_str()).set_value(to_bstring(value).c_str());
    }
    catch(std::exception& e) {
        ORK_LOG(severity_level::error)
            << ORK("Failed to set attribute ") << ORK_BYTE_2_STR(node.name())
            << ORK(":") << ORK_BYTE_2_STR(tag) << ORK(", ") << e.what();
    }
    catch(...) {
        ORK_LOG(severity_level::error)
            << ORK("Something happened setting attribute ")
            << ORK_BYTE_2_STR(node.name()) << ORK(":") << ORK_BYTE_2_STR(tag);
    }
}
template<typename T>
void value_to_xml(pugi::xml_node& node, const bstring& tag, ORK_CPARAM_T value)
{
    try {
        node.append_child(tag.c_str())
            .append_child(pugi::node_pcdata)
            .set_value(to_bstring(value).c_str());
    }
    catch(std::exception& e) {
        ORK_LOG(severity_level::error)
            << ORK("Failed to set tag ") << ORK_BYTE_2_STR(tag) << ORK(": ")
            << ORK_BYTE_2_STR(e.what());
    }
    catch(...) {
        ORK_LOG(severity_level::error)
            << ORK("Something happened setting tag ") << ORK_BYTE_2_STR(tag);
    }
}
template<typename T>
void value_to_xml(pugi::xml_node& node, ORK_CPARAM_T value)
{
    try {
        node.append_child(pugi::node_pcdata).set_value(to_bstring(value).c_str());
    }
    catch(std::exception& e) {
        ORK_LOG(severity_level::error)
            << ORK("Failed to set tag ") << ORK_BYTE_2_STR(node.name())
            << ORK(": ") << ORK_BYTE_2_STR(e.what());
    }
    catch(...) {
        ORK_LOG(severity_level::error) << ORK("Something happened setting tag ")
                                       << ORK_BYTE_2_STR(node.name());
    }
}

template<typename T>
void value_from_attribute(const pugi::xml_node& node, const bstring& tag, ORK_REF_T value)
{
    try {
        value = from_string<ORK_VAL_T>(node.attribute(tag.c_str()).value());
    }
    catch(std::exception& e) {
        ORK_LOG(severity_level::error)
            << ORK("Failed to read parameter ") << ORK_BYTE_2_STR(tag)
            << ORK(": ") << ORK_BYTE_2_STR(e.what());
    }
    catch(...) {
        ORK_LOG(severity_level::error)
            << ORK("Something happened reading parameter ") << ORK_BYTE_2_STR(tag);
    }
}
template<typename T>
void value_from_xml(const pugi::xml_node& node, const bstring& tag, ORK_REF_T value)
{
    try {
        value = from_string<ORK_VAL_T>(node.child_value(tag.c_str()));
    }
    catch(std::exception& e) {
        ORK_LOG(severity_level::error)
            << ORK("Failed to read tag ") << ORK_BYTE_2_STR(tag) << ORK(": ")
            << ORK_BYTE_2_STR(e.what());
    }
    catch(...) {
        ORK_LOG(severity_level::error)
            << ORK("Something happened reading tag ") << ORK_BYTE_2_STR(tag);
    }
}
template<typename T>
void value_from_xml(const pugi::xml_node& node, ORK_REF_T value)
{
    try {
        value = from_string<ORK_VAL_T>(node.child_value());
    }
    catch(std::exception& e) {
        ORK_LOG(severity_level::error)
            << ORK("Failed to read tag ") << ORK_BYTE_2_STR(node.name())
            << ORK(": ") << ORK_BYTE_2_STR(e.what());
    }
    catch(...) {
        ORK_LOG(severity_level::error) << ORK("Something happened reading tag ")
                                       << ORK_BYTE_2_STR(node.name());
    }
}

// Overloads to eliminate dependency definitions
#    define ORK_XML_SERIALIZE_DECL_(API, TYPE) \
        API(void) \
        to_xml(pugi::xml_node& node, const ork::bstring& tag, ORK_CPARAM(TYPE) value); \
        API(void) \
        from_xml(const pugi::xml_node& node, const ork::bstring& tag, ORK_REF(TYPE) value)

#    define ORK_XML_SERIALIZE_DECL(TYPE) ORK_XML_SERIALIZE_DECL_(ORK_EXT, TYPE)
#    define ORK_ORK_XML_SERIALIZE_DECL(TYPE) \
        ORK_XML_SERIALIZE_DECL_(ORK_ORK_EXT, TYPE)

ORK_ORK_XML_SERIALIZE_DECL(int);
ORK_ORK_XML_SERIALIZE_DECL(unsigned);
ORK_ORK_XML_SERIALIZE_DECL(size_t);
ORK_ORK_XML_SERIALIZE_DECL(float);
ORK_ORK_XML_SERIALIZE_DECL(double);
ORK_ORK_XML_SERIALIZE_DECL(bstring);
ORK_ORK_XML_SERIALIZE_DECL(wstring);

#    define ORK_XML_SERIALIZE_DEF(TYPE) \
        void to_xml(pugi::xml_node& node, const ork::bstring& tag, ORK_CPARAM(TYPE) value) \
        { \
            ork::xml::value_to_xml<TYPE>(node, tag, value); \
        } \
        void from_xml( \
            const pugi::xml_node& node, const ork::bstring& tag, ORK_REF(TYPE) value) \
        { \
            ork::xml::value_from_xml<TYPE>(node, tag, value); \
        }

#endif // ORK_USE_PUGI

} // namespace xml
namespace yaml {

#if ORK_USE_YAML

class ORK_ORK_API exportable {
public:
    virtual ~exportable() {}

public:
    virtual void export_yaml(YAML::Node& n) const = 0;
};

class ORK_ORK_API serializable {
public:
    virtual ~serializable() {}

public:
    virtual void to_yaml(YAML::Node& v) const = 0;
    virtual void from_yaml(const YAML::Node& v) = 0;
};

ORK_ORK_EXT(void)
export_file(const string& path_to_file, const YAML::Node& root);
ORK_ORK_EXT(void)
export_file(const string& path_to_file, const exportable& object);
ORK_ORK_EXT(void) load_and_parse(bi_stream& fin, YAML::Node& root);
ORK_ORK_EXT(YAML::Node) load_and_parse(bi_stream& fin);

#endif // ORK_USE_YAML

} // namespace yaml
} // namespace ork
<|endoftext|>


<commit_before>// Copyright (C) 2014 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <libaddressinput/preload_supplier.h>

#include <libaddressinput/address_data.h>
#include <libaddressinput/address_field.h>
#include <libaddressinput/callback.h>
#include <libaddressinput/supplier.h>

#include <algorithm>
#include <cassert>
#include <cstddef>
#include <functional>
#include <map>
#include <memory>
#include <set>
#include <stack>
#include <string>
#include <vector>

#include "lookup_key.h"
#include "region_data_constants.h"
#include "retriever.h"
#include "rule.h"
#include "util/json.h"
#include "util/size.h"
#include "util/string_compare.h"

namespace i18n {
namespace addressinput {

namespace {

// STL predicate less<> that uses StringCompare to match strings that a human
// reader would consider to be "the same". The default implementation just does
// case insensitive string comparison, but StringCompare can be overridden with
// more sophisticated implementations.
class IndexLess : public std::binary_function<std::string, std::string, bool> {
 public:
  result_type operator()(const first_argument_type& a,
                         const second_argument_type& b) const {
    static const StringCompare kStringCompare;
    return kStringCompare.NaturalLess(a, b);
  }
};

}  // namespace

class IndexMap : public std::map<std::string, const Rule*, IndexLess> {};

namespace {

class Helper {
 public:
  Helper(const Helper&) = delete;
  Helper& operator=(const Helper&) = delete;

  // Does not take ownership of its parameters.
  Helper(const std::string& region_code,
         const std::string& key,
         const PreloadSupplier::Callback& loaded,
         const Retriever& retriever,
         std::set<std::string>* pending,
         IndexMap* rule_index,
         IndexMap* language_rule_index,
         std::vector<const Rule*>* rule_storage,
         std::map<std::string, const Rule*>* region_rules)
      : region_code_(region_code),
        loaded_(loaded),
        pending_(pending),
        rule_index_(rule_index),
        language_rule_index_(language_rule_index),
        rule_storage_(rule_storage),
        region_rules_(region_rules),
        retrieved_(BuildCallback(this, &Helper::OnRetrieved)) {
    assert(pending_ != nullptr);
    assert(rule_index_ != nullptr);
    assert(rule_storage_ != nullptr);
    assert(region_rules_ != nullptr);
    assert(retrieved_ != nullptr);
    pending_->insert(key);
    retriever.Retrieve(key, *retrieved_);
  }

 private:
  ~Helper() = default;

  void OnRetrieved(bool success,
                   const std::string& key,
                   const std::string& data) {
    int rule_count = 0;

    size_t status = pending_->erase(key);
    assert(status == 1);  // There will always be one item erased from the set.
    (void)status;  // Prevent unused variable if assert() is optimized away.

    Json json;
    std::string id;
    std::vector<const Rule*> sub_rules;

    auto last_index_it = rule_index_->end();
    auto last_latin_it = rule_index_->end();
    auto language_index_it = language_rule_index_->end();
    auto last_region_it = region_rules_->end();

    IndexMap::const_iterator hints[size(LookupKey::kHierarchy) - 1];
    std::fill(hints, hints + size(hints), rule_index_->end());

    if (!success) {
      goto callback;
    }

    if (!json.ParseObject(data)) {
      success = false;
      goto callback;
    }

    for (auto ptr : json.GetSubDictionaries()) {
      assert(ptr != nullptr);
      if (!ptr->GetStringValueForKey("id", &id)) {
        success = false;
        goto callback;
      }
      assert(!id.empty());

      size_t depth = std::count(id.begin(), id.end(), '/') - 1;
      assert(depth < size(LookupKey::kHierarchy));
      AddressField field = LookupKey::kHierarchy[depth];

      auto* rule = new Rule;
      if (field == COUNTRY) {
        // All rules on the COUNTRY level inherit from the default rule.
        rule->CopyFrom(Rule::GetDefault());
      }
      rule->ParseJsonRule(*ptr);
      assert(id == rule->GetId());  // Sanity check.

      rule_storage_->push_back(rule);
      if (depth > 0) {
        sub_rules.push_back(rule);
      }

      // Add the ID of this Rule object to the rule index with natural string
      // comparison for keys.
      last_index_it = rule_index_->emplace_hint(last_index_it, id, rule);

      // Add the ID of this Rule object to the region-specific rule index with
      // exact string comparison for keys.
      last_region_it = region_rules_->emplace_hint(last_region_it, id, rule);

      ++rule_count;
    }

    //
    // Normally the address metadata server takes care of mapping from natural
    // language names to metadata IDs (eg. "São Paulo" -> "SP") and from Latin
    // script names to local script names (eg. "Tokushima" -> "徳島県").
    //
    // As the PreloadSupplier doesn't contact the metadata server upon each
    // Supply() request, it instead has an internal lookup table (rule_index_)
    // that contains such mappings.
    //
    // This lookup table is populated by iterating over all sub rules and for
    // each of them construct ID strings using human readable names (eg. "São
    // Paulo") and using Latin script names (eg. "Tokushima").
    //
    for (auto ptr : sub_rules) {
      assert(ptr != nullptr);
      std::stack<const Rule*> hierarchy;
      hierarchy.push(ptr);

      // Push pointers to all parent Rule objects onto the hierarchy stack.
      for (std::string parent_id(ptr->GetId());;) {
        // Strip the last part of parent_id. Break if COUNTRY level is reached.
        std::string::size_type pos = parent_id.rfind('/');
        if (pos == sizeof "data/ZZ" - 1) {
          break;
        }
        parent_id.resize(pos);

        IndexMap::const_iterator* const hint = &hints[hierarchy.size() - 1];
        if (*hint == rule_index_->end() || (*hint)->first != parent_id) {
          *hint = rule_index_->find(parent_id);
        }
        assert(*hint != rule_index_->end());
        hierarchy.push((*hint)->second);
      }

      std::string human_id(ptr->GetId().substr(0, sizeof "data/ZZ" - 1));
      std::string latin_id(human_id);

      // Append the names from all Rule objects on the hierarchy stack.
      for (; !hierarchy.empty(); hierarchy.pop()) {
        const Rule* rule = hierarchy.top();

        human_id.push_back('/');
        if (!rule->GetName().empty()) {
          human_id.append(rule->GetName());
        } else {
          // If the "name" field is empty, the name is the last part of the ID.
          const std::string& id = rule->GetId();
          std::string::size_type pos = id.rfind('/');
          assert(pos != std::string::npos);
          human_id.append(id.substr(pos + 1));
        }

        if (!rule->GetLatinName().empty()) {
          latin_id.push_back('/');
          latin_id.append(rule->GetLatinName());
        }
      }

      // If the ID has a language tag, copy it.
      {
        const std::string& id = ptr->GetId();
        std::string::size_type pos = id.rfind("--");
        if (pos != std::string::npos) {
          language_index_it = language_rule_index_->emplace_hint(
              language_index_it, human_id, ptr);
          human_id.append(id, pos, id.size() - pos);
        }
      }

      last_index_it = rule_index_->emplace_hint(last_index_it, human_id, ptr);

      // Add the Latin script ID, if a Latin script name could be found for
      // every part of the ID.
      if (std::count(human_id.begin(), human_id.end(), '/') ==
          std::count(latin_id.begin(), latin_id.end(), '/')) {
        last_latin_it = rule_index_->emplace_hint(last_latin_it, latin_id, ptr);
      }
    }

  callback:
    loaded_(success, region_code_, rule_count);
    delete this;
  }

  const std::string region_code_;
  const PreloadSupplier::Callback& loaded_;
  std::set<std::string>* const pending_;
  IndexMap* const rule_index_;
  IndexMap* const language_rule_index_;
  std::vector<const Rule*>* const rule_storage_;
  std::map<std::string, const Rule*>* const region_rules_;
  const std::unique_ptr<const Retriever::Callback> retrieved_;
};

std::string KeyFromRegionCode(const std::string& region_code) {
  AddressData address;
  address.region_code = region_code;
  LookupKey lookup_key;
  lookup_key.FromAddress(address);
  return lookup_key.ToKeyString(0);  // Zero depth = COUNTRY level.
}

}  // namespace

PreloadSupplier::PreloadSupplier(const Source* source, Storage* storage)
    : retriever_(new Retriever(source, storage)),
      pending_(),
      rule_index_(new IndexMap),
      language_rule_index_(new IndexMap),
      rule_storage_(),
      region_rules_() {}

PreloadSupplier::~PreloadSupplier() {
  for (auto ptr : rule_storage_) {
    delete ptr;
  }
}

void PreloadSupplier::Supply(const LookupKey& lookup_key,
                             const Supplier::Callback& supplied) {
  Supplier::RuleHierarchy hierarchy;
  bool success = GetRuleHierarchy(lookup_key, &hierarchy, false);
  supplied(success, lookup_key, hierarchy);
}

void PreloadSupplier::SupplyGlobally(const LookupKey& lookup_key,
                                     const Supplier::Callback& supplied) {
  Supplier::RuleHierarchy hierarchy;
  bool success = GetRuleHierarchy(lookup_key, &hierarchy, true);
  supplied(success, lookup_key, hierarchy);
}

const Rule* PreloadSupplier::GetRule(const LookupKey& lookup_key) const {
  assert(IsLoaded(lookup_key.GetRegionCode()));
  Supplier::RuleHierarchy hierarchy;
  if (!GetRuleHierarchy(lookup_key, &hierarchy, false)) {
    return nullptr;
  }
  return hierarchy.rule[lookup_key.GetDepth()];
}

void PreloadSupplier::LoadRules(const std::string& region_code,
                                const Callback& loaded) {
  const std::string& key = KeyFromRegionCode(region_code);

  if (IsLoadedKey(key)) {
    loaded(true, region_code, 0);
    return;
  }

  if (IsPendingKey(key)) {
    return;
  }

  new Helper(
      region_code,
      key,
      loaded,
      *retriever_,
      &pending_,
      rule_index_.get(),
      language_rule_index_.get(),
      &rule_storage_,
      &region_rules_[region_code]);
}

const std::map<std::string, const Rule*>& PreloadSupplier::GetRulesForRegion(
    const std::string& region_code) const {
  assert(IsLoaded(region_code));
  return region_rules_.find(region_code)->second;
}

bool PreloadSupplier::IsLoaded(const std::string& region_code) const {
  return IsLoadedKey(KeyFromRegionCode(region_code));
}

bool PreloadSupplier::IsPending(const std::string& region_code) const {
  return IsPendingKey(KeyFromRegionCode(region_code));
}

bool PreloadSupplier::GetRuleHierarchy(const LookupKey& lookup_key,
                                       RuleHierarchy* hierarchy,
                                       const bool search_globally) const {
  assert(hierarchy != nullptr);

  if (RegionDataConstants::IsSupported(lookup_key.GetRegionCode())) {
    size_t max_depth = std::min(
        lookup_key.GetDepth(),
        RegionDataConstants::GetMaxLookupKeyDepth(lookup_key.GetRegionCode()));

    for (size_t depth = 0; depth <= max_depth; ++depth) {
      const std::string& key = lookup_key.ToKeyString(depth);
      const Rule* rule = nullptr;
      auto it = rule_index_->find(key);
      if (it != rule_index_->end()) {
        rule = it->second;
      } else if (search_globally && depth > 0 &&
                 !hierarchy->rule[0]->GetLanguages().empty()) {
        it = language_rule_index_->find(key);
        if (it != language_rule_index_->end()) {
          rule = it->second;
        }
      }
      if (rule == nullptr) {
        return depth > 0;  // No data on COUNTRY level is failure.
      }
      hierarchy->rule[depth] = rule;
    }
  }

  return true;
}

size_t PreloadSupplier::GetLoadedRuleDepth(
    const std::string& region_code) const {
  // The country codes are always two char long.
  std::string full_code = region_code.substr(0, strlen("data/ZZ"));
  size_t depth = 0;
  auto it = rule_index_->find(full_code);
  while (it != rule_index_->end()) {
    const Rule* rule = it->second;
    depth++;
    if (rule->GetSubKeys().empty())
      return depth;
    full_code += "/" + rule->GetSubKeys()[0];
    it = rule_index_->find(full_code);
  }
  return depth;
}

bool PreloadSupplier::IsLoadedKey(const std::string& key) const {
  return rule_index_->find(key) != rule_index_->end();
}

bool PreloadSupplier::IsPendingKey(const std::string& key) const {
  return pending_.find(key) != pending_.end();
}

}  // namespace addressinput
}  // namespace i18n
<commit_msg>(AUTOMATIC) opensource update<commit_after>// Copyright (C) 2014 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <libaddressinput/preload_supplier.h>

#include <libaddressinput/address_data.h>
#include <libaddressinput/address_field.h>
#include <libaddressinput/callback.h>
#include <libaddressinput/supplier.h>

#include <algorithm>
#include <cassert>
#include <cstddef>
#include <functional>
#include <map>
#include <memory>
#include <set>
#include <stack>
#include <string>
#include <vector>

#include "lookup_key.h"
#include "region_data_constants.h"
#include "retriever.h"
#include "rule.h"
#include "util/json.h"
#include "util/size.h"
#include "util/string_compare.h"

namespace i18n {
namespace addressinput {

namespace {

// STL predicate less<> that uses StringCompare to match strings that a human
// reader would consider to be "the same". The default implementation just does
// case insensitive string comparison, but StringCompare can be overridden with
// more sophisticated implementations.
class IndexLess : public std::binary_function<std::string, std::string, bool> {
 public:
  result_type operator()(const first_argument_type& a,
                         const second_argument_type& b) const {
    static const StringCompare kStringCompare;
    return kStringCompare.NaturalLess(a, b);
  }
};

}  // namespace

class IndexMap : public std::map<std::string, const Rule*, IndexLess> {};

namespace {

class Helper {
 public:
  Helper(const Helper&) = delete;
  Helper& operator=(const Helper&) = delete;

  // Does not take ownership of its parameters.
  Helper(const std::string& region_code, const std::string& key,
         const PreloadSupplier::Callback& loaded, const Retriever& retriever,
         std::set<std::string>* pending, IndexMap* rule_index,
         IndexMap* language_rule_index, std::vector<const Rule*>* rule_storage,
         std::map<std::string, const Rule*>* region_rules)
      : region_code_(region_code),
        loaded_(loaded),
        pending_(pending),
        rule_index_(rule_index),
        language_rule_index_(language_rule_index),
        rule_storage_(rule_storage),
        region_rules_(region_rules),
        retrieved_(BuildCallback(this, &Helper::OnRetrieved)) {
    assert(pending_ != nullptr);
    assert(rule_index_ != nullptr);
    assert(rule_storage_ != nullptr);
    assert(region_rules_ != nullptr);
    assert(retrieved_ != nullptr);
    pending_->insert(key);
    retriever.Retrieve(key, *retrieved_);
  }

 private:
  ~Helper() = default;

  void OnRetrieved(bool success, const std::string& key,
                   const std::string& data) {
    int rule_count = 0;

    size_t status = pending_->erase(key);
    assert(status == 1);  // There will always be one item erased from the set.
    (void)status;  // Prevent unused variable if assert() is optimized away.

    Json json;
    std::string id;
    std::vector<const Rule*> sub_rules;

    auto last_index_it = rule_index_->end();
    auto last_latin_it = rule_index_->end();
    auto language_index_it = language_rule_index_->end();
    auto last_region_it = region_rules_->end();

    IndexMap::const_iterator hints[size(LookupKey::kHierarchy) - 1];
    std::fill(hints, hints + size(hints), rule_index_->end());

    if (!success) {
      goto callback;
    }

    if (!json.ParseObject(data)) {
      success = false;
      goto callback;
    }

    for (auto ptr : json.GetSubDictionaries()) {
      assert(ptr != nullptr);
      if (!ptr->GetStringValueForKey("id", &id)) {
        success = false;
        goto callback;
      }
      assert(!id.empty());

      size_t depth = std::count(id.begin(), id.end(), '/') - 1;
      assert(depth < size(LookupKey::kHierarchy));
      AddressField field = LookupKey::kHierarchy[depth];

      auto* rule = new Rule;
      if (field == COUNTRY) {
        // All rules on the COUNTRY level inherit from the default rule.
        rule->CopyFrom(Rule::GetDefault());
      }
      rule->ParseJsonRule(*ptr);
      assert(id == rule->GetId());  // Sanity check.

      rule_storage_->push_back(rule);
      if (depth > 0) {
        sub_rules.push_back(rule);
      }

      // Add the ID of this Rule object to the rule index with natural string
      // comparison for keys.
      last_index_it = rule_index_->emplace_hint(last_index_it, id, rule);

      // Add the ID of this Rule object to the region-specific rule index with
      // exact string comparison for keys.
      last_region_it = region_rules_->emplace_hint(last_region_it, id, rule);

      ++rule_count;
    }

    //
    // Normally the address metadata server takes care of mapping from natural
    // language names to metadata IDs (eg. "São Paulo" -> "SP") and from Latin
    // script names to local script names (eg. "Tokushima" -> "徳島県").
    //
    // As the PreloadSupplier doesn't contact the metadata server upon each
    // Supply() request, it instead has an internal lookup table (rule_index_)
    // that contains such mappings.
    //
    // This lookup table is populated by iterating over all sub rules and for
    // each of them construct ID strings using human readable names (eg. "São
    // Paulo") and using Latin script names (eg. "Tokushima").
    //
    for (auto ptr : sub_rules) {
      assert(ptr != nullptr);
      std::stack<const Rule*> hierarchy;
      hierarchy.push(ptr);

      // Push pointers to all parent Rule objects onto the hierarchy stack.
      for (std::string parent_id(ptr->GetId());;) {
        // Strip the last part of parent_id. Break if COUNTRY level is reached.
        std::string::size_type pos = parent_id.rfind('/');
        if (pos == sizeof "data/ZZ" - 1) {
          break;
        }
        parent_id.resize(pos);

        IndexMap::const_iterator* const hint = &hints[hierarchy.size() - 1];
        if (*hint == rule_index_->end() || (*hint)->first != parent_id) {
          *hint = rule_index_->find(parent_id);
        }
        assert(*hint != rule_index_->end());
        hierarchy.push((*hint)->second);
      }

      std::string human_id(ptr->GetId().substr(0, sizeof "data/ZZ" - 1));
      std::string latin_id(human_id);

      // Append the names from all Rule objects on the hierarchy stack.
      for (; !hierarchy.empty(); hierarchy.pop()) {
        const Rule* rule = hierarchy.top();

        human_id.push_back('/');
        if (!rule->GetName().empty()) {
          human_id.append(rule->GetName());
        } else {
          // If the "name" field is empty, the name is the last part of the ID.
          const std::string& id = rule->GetId();
          std::string::size_type pos = id.rfind('/');
          assert(pos != std::string::npos);
          human_id.append(id.substr(pos + 1));
        }

        if (!rule->GetLatinName().empty()) {
          latin_id.push_back('/');
          latin_id.append(rule->GetLatinName());
        }
      }

      // If the ID has a language tag, copy it.
      {
        const std::string& id = ptr->GetId();
        std::string::size_type pos = id.rfind("--");
        if (pos != std::string::npos) {
          language_index_it = language_rule_index_->emplace_hint(
              language_index_it, human_id, ptr);
          human_id.append(id, pos, id.size() - pos);
        }
      }

      last_index_it = rule_index_->emplace_hint(last_index_it, human_id, ptr);

      // Add the Latin script ID, if a Latin script name could be found for
      // every part of the ID.
      if (std::count(human_id.begin(), human_id.end(), '/') ==
          std::count(latin_id.begin(), latin_id.end(), '/')) {
        last_latin_it = rule_index_->emplace_hint(last_latin_it, latin_id, ptr);
      }
    }

  callback:
    loaded_(success, region_code_, rule_count);
    delete this;
  }

  const std::string region_code_;
  const PreloadSupplier::Callback& loaded_;
  std::set<std::string>* const pending_;
  IndexMap* const rule_index_;
  IndexMap* const language_rule_index_;
  std::vector<const Rule*>* const rule_storage_;
  std::map<std::string, const Rule*>* const region_rules_;
  const std::unique_ptr<const Retriever::Callback> retrieved_;
};

std::string KeyFromRegionCode(const std::string& region_code) {
  AddressData address;
  address.region_code = region_code;
  LookupKey lookup_key;
  lookup_key.FromAddress(address);
  return lookup_key.ToKeyString(0);  // Zero depth = COUNTRY level.
}

}  // namespace

PreloadSupplier::PreloadSupplier(const Source* source, Storage* storage)
    : retriever_(new Retriever(source, storage)),
      pending_(),
      rule_index_(new IndexMap),
      language_rule_index_(new IndexMap),
      rule_storage_(),
      region_rules_() {}

PreloadSupplier::~PreloadSupplier() {
  for (auto ptr : rule_storage_) {
    delete ptr;
  }
}

void PreloadSupplier::Supply(const LookupKey& lookup_key,
                             const Supplier::Callback& supplied) {
  Supplier::RuleHierarchy hierarchy;
  bool success = GetRuleHierarchy(lookup_key, &hierarchy, false);
  supplied(success, lookup_key, hierarchy);
}

void PreloadSupplier::SupplyGlobally(const LookupKey& lookup_key,
                                     const Supplier::Callback& supplied) {
  Supplier::RuleHierarchy hierarchy;
  bool success = GetRuleHierarchy(lookup_key, &hierarchy, true);
  supplied(success, lookup_key, hierarchy);
}

const Rule* PreloadSupplier::GetRule(const LookupKey& lookup_key) const {
  assert(IsLoaded(lookup_key.GetRegionCode()));
  Supplier::RuleHierarchy hierarchy;
  if (!GetRuleHierarchy(lookup_key, &hierarchy, false)) {
    return nullptr;
  }
  return hierarchy.rule[lookup_key.GetDepth()];
}

void PreloadSupplier::LoadRules(const std::string& region_code,
                                const Callback& loaded) {
  const std::string& key = KeyFromRegionCode(region_code);

  if (IsLoadedKey(key)) {
    loaded(true, region_code, 0);
    return;
  }

  if (IsPendingKey(key)) {
    return;
  }

  new Helper(region_code, key, loaded, *retriever_, &pending_,
             rule_index_.get(), language_rule_index_.get(), &rule_storage_,
             &region_rules_[region_code]);
}

const std::map<std::string, const Rule*>& PreloadSupplier::GetRulesForRegion(
    const std::string& region_code) const {
  assert(IsLoaded(region_code));
  return region_rules_.find(region_code)->second;
}

bool PreloadSupplier::IsLoaded(const std::string& region_code) const {
  return IsLoadedKey(KeyFromRegionCode(region_code));
}

bool PreloadSupplier::IsPending(const std::string& region_code) const {
  return IsPendingKey(KeyFromRegionCode(region_code));
}

bool PreloadSupplier::GetRuleHierarchy(const LookupKey& lookup_key,
                                       RuleHierarchy* hierarchy,
                                       const bool search_globally) const {
  assert(hierarchy != nullptr);

  if (RegionDataConstants::IsSupported(lookup_key.GetRegionCode())) {
    size_t max_depth = std::min(
        lookup_key.GetDepth(),
        RegionDataConstants::GetMaxLookupKeyDepth(lookup_key.GetRegionCode()));

    for (size_t depth = 0; depth <= max_depth; ++depth) {
      const std::string& key = lookup_key.ToKeyString(depth);
      const Rule* rule = nullptr;
      auto it = rule_index_->find(key);
      if (it != rule_index_->end()) {
        rule = it->second;
      } else if (search_globally && depth > 0 &&
                 !hierarchy->rule[0]->GetLanguages().empty()) {
        it = language_rule_index_->find(key);
        if (it != language_rule_index_->end()) {
          rule = it->second;
        }
      }
      if (rule == nullptr) {
        return depth > 0;  // No data on COUNTRY level is failure.
      }
      hierarchy->rule[depth] = rule;
    }
  }

  return true;
}

size_t PreloadSupplier::GetLoadedRuleDepth(
    const std::string& region_code) const {
  // We care for the code which has the format of "data/ZZ". Ignore what comes
  // after, such as language code.
  const size_t code_size = 7;
  std::string full_code = region_code.substr(0, code_size);
  size_t depth = 0;
  auto it = rule_index_->find(full_code);
  while (it != rule_index_->end()) {
    const Rule* rule = it->second;
    depth++;
    if (rule->GetSubKeys().empty()) return depth;
    full_code += "/" + rule->GetSubKeys()[0];
    it = rule_index_->find(full_code);
  }
  return depth;
}

bool PreloadSupplier::IsLoadedKey(const std::string& key) const {
  return rule_index_->find(key) != rule_index_->end();
}

bool PreloadSupplier::IsPendingKey(const std::string& key) const {
  return pending_.find(key) != pending_.end();
}

}  // namespace addressinput
}  // namespace i18n
<|endoftext|>


<commit_before>// Copyright 2014, Max Planck Institute for Intelligent Systems.
// Distributed under the BSD 3-Clause license.
// (See accompanying file LICENSE.txt or copy at
// http://opensource.org/licenses/BSD-3-Clause)

//!@file
//! Mex wrapper file for robust PCA

#include "mex.h"

#include <boost/numeric/ublas/storage.hpp>

#include <include/robust_pca.hpp>
#include <include/private/boost_ublas_matlab_helper.hpp>
#include <include/private/boost_ublas_matrix_helper.hpp>

//! Implements allocate and free.
template <class T>
struct matlab_matrix_allocation;

template <>
struct matlab_matrix_allocation<double>
{
  static mxArray * allocate(size_t s)
  {
    return mxCreateDoubleMatrix(s, 1, mxREAL);
  }

  static void free(mxArray *mat)
  {
    mxDestroyArray(mat);
  }
};

//! An helper class that implements the storage concept of boost::ublas
//! and performs the allocation on matlab side. It is also possible
//! to provide a matlab array.
template <class T>
class matlab_matrix_storage
{
  typedef T& reference;

  //! Default constructible
  matlab_matrix_storage() : pData(0)
  {
  }

  //! Size constructible
  matlab_matrix_storage(size_t s) : pData(0)
  {
    mxArray *v = matlab_matrix_allocation<T>::allocate(s);

  }

  //! Random access container
  reference operator[](size_t i)
  {
    return pData[i];
  }

private:
  T* pData;
};

#if 0

//! A simple vector used with two pointers.
//! The vector is read-only
template <class T>
struct pointer_vector_t
{
  typedef typename boost::add_reference<T>::type reference;
  //! @param length_ length of the vector (number of elements)
  pointer_vector_t(T * initial_position_, size_t const length_) :
    initial_position(initial_position_)
    length(length_)
  {}

  reference operator[](size_t const index)
  {
    return
  }

private:
  T* initial_position;
  size_t length;
};
#endif

void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
  namespace ub = boost::numeric::ublas;
  using namespace robust_pca;
  using namespace robust_pca::ublas_adaptor;
  using namespace robust_pca::ublas_matlab_helper;

  // arguments checking
  if (nrhs < 1 || nrhs > 2)
  {
	  mexErrMsgTxt("One or two input arguments required. ");
  }

  const mxArray* const X = prhs[0];
  assert(X);

  // checking the format of the data
  if (!mxIsDouble(X) && !mxIsSingle(X))
  {
	  mexErrMsgTxt("Unsupported input format");
  }

  if(mxIsComplex(X))
  {
    mexErrMsgTxt("Unsupported format (should be scalar)");
  }

  // Check the dimensions of inputs
  const size_t rows = mxGetM(X);
  const size_t columns = mxGetN(X);
  size_t dimension = columns;
  size_t max_dimension = dimension;
  if (nrhs == 2)
  {
    const mxArray* const maxDimArray = prhs[1];
    if(!mxIsNumeric(maxDimArray))
    {
      mexErrMsgTxt("Erroneous argument for the maximal dimension specification (non numeric argument)");
    }

    if(mxGetNumberOfElements(maxDimArray) > 1)
    {
      mexErrMsgTxt("Erroneous argument for the maximal dimension specification (non scalar)");
    }

    mxClassID classId = mxGetClassID(maxDimArray);
    if(classId == mxDOUBLE_CLASS || classId == mxSINGLE_CLASS)
    {
      mexErrMsgTxt("Erroneous argument for the maximal dimension specification (floating point type)");
    }

  }

  if(mxIsDouble(X))
  {
    typedef external_storage_adaptor<double> storage_t;
    typedef ub::matrix<double, ub::column_major, storage_t> matrix_t;

    // input data matrix, external storage.
    storage_t storage(rows*columns, mxGetPr(X));
    matrix_t mat_data(rows, columns, storage);

    // this is the form of the data extracted from the storage
    typedef ub::vector<double> data_t;
    typedef robust_pca_impl< data_t > robust_pca_t;

    // TODO put the dimension
    // for the library to work, we need to allocate some temporary storage
    // we also allocate the output if given
    plhs[0] = mxCreateDoubleMatrix(dimension, max_dimension, mxREAL);
    mxArray *outputMatrix = plhs[0];
    assert(outputMatrix);

    storage_t storageOutput(dimension * max_dimension, mxGetPr(outputMatrix));
    matrix_t mat_eigen_vectors(dimension, max_dimension, storageOutput);

    typedef row_iter<matrix_t> const_row_iter_t;

    // should be matlab style
    std::vector<data_t> temporary_data(rows);

    robust_pca_t instance;
    instance.batch_process(
      100,
      max_dimension,
      const_row_iter_t(mat_data, 0),
      const_row_iter_t(mat_data, mat_data.size1()),
      temporary_data.begin(),
      const_row_iter_t(mat_eigen_vectors, 0));

  }

  //typedef robust_pca::robust_pca_impl< boost::numeric::ublas::vector<double> > robust_pca_t;

  //robust_pca_t instance;

}<commit_msg>RP-34 Some cleanups<commit_after>// Copyright 2014, Max Planck Institute for Intelligent Systems.
// Distributed under the BSD 3-Clause license.
// (See accompanying file LICENSE.txt or copy at
// http://opensource.org/licenses/BSD-3-Clause)

//!@file
//! Mex wrapper file for robust PCA

#include "mex.h"

#include <boost/numeric/ublas/storage.hpp>

#include <include/robust_pca.hpp>
#include <include/private/boost_ublas_matlab_helper.hpp>
#include <include/private/boost_ublas_matrix_helper.hpp>

//! Implements allocate and free.
template <class T>
struct matlab_matrix_allocation;

template <>
struct matlab_matrix_allocation<double>
{
  static mxArray * allocate(size_t s)
  {
    return mxCreateDoubleMatrix(s, 1, mxREAL);
  }

  static void free(mxArray *mat)
  {
    mxDestroyArray(mat);
  }
};

//! An helper class that implements the storage concept of boost::ublas
//! and performs the allocation on matlab side. It is also possible
//! to provide a matlab array.
template <class T>
class matlab_matrix_storage
{
  typedef T& reference;

  //! Default constructible
  matlab_matrix_storage() : pData(0)
  {
  }

  //! Size constructible
  matlab_matrix_storage(size_t s) : pData(0)
  {
    mxArray *v = matlab_matrix_allocation<T>::allocate(s);

  }

  //! Random access container
  reference operator[](size_t i)
  {
    return pData[i];
  }

private:
  T* pData;
};

template <class output_type, class input_type>
output_type get_matlab_array_value_dispatch(mxArray const* array_, size_t index_row, size_t index_column)
{
  input_type* p_array = static_cast<input_type*>(mxGetData(array_));
  if(p_array == 0)
  {
    throw std::runtime_error("Unable to retrieve a pointer to the typed array");
  }

  // column major
  return p_array[index_row + mxGetN(array_) * index_column];
}

template <class output_type>
output_type get_matlab_array_value(mxArray const* array_, size_t index_row, size_t index_column)
{
  assert(index_row < mxGetM(array_));
  assert(index_column < mxGetN(array_));

  mxClassID classId = mxGetClassID(array_);
  switch(classId)
  {
  case mxDOUBLE_CLASS:
    return get_matlab_array_value_dispatch<output_type, double>(array_, index_row, index_column);
  case mxSINGLE_CLASS:
    return get_matlab_array_value_dispatch<output_type, float>(array_, index_row, index_column);
  default:
    throw std::runtime_error("Unable to dispatch to the correct type");
  }
}

template <class input_array_type>
bool robust_pca_dispatch(mxArray const* X, size_t rows, size_t columns, size_t max_dimension, int max_iterations, mxArray *outputMatrix)
{
  namespace ub = boost::numeric::ublas;

  using namespace robust_pca;
  using namespace robust_pca::ublas_adaptor;
  using namespace robust_pca::ublas_matlab_helper;

  typedef external_storage_adaptor<input_array_type> input_storage_t;
  typedef ub::matrix<input_array_type, ub::column_major, input_storage_t> input_matrix_t;

  typedef external_storage_adaptor<double> output_storage_t;
  typedef ub::matrix<double, ub::column_major, output_storage_t> output_matrix_t;

  const size_t dimension = columns;

  // input data matrix, external storage.
  input_storage_t input_storage(rows*columns, mxGetPr(X));
  input_matrix_t input_data(rows, columns, input_storage);

  // output data matrix, also external storage for uBlas
  output_storage_t storageOutput(dimension * max_dimension, mxGetPr(outputMatrix));
  output_matrix_t output_eigen_vectors(dimension, max_dimension, storageOutput);

  // this is the form of the data extracted from the storage
  typedef ub::vector<double> data_t;
  typedef robust_pca_impl< data_t > robust_pca_t;

  typedef row_iter<input_matrix_t> const_input_row_iter_t;
  typedef row_iter<output_matrix_t> output_row_iter_t;

  // should be matlab style
  std::vector<data_t> temporary_data(rows);

  robust_pca_t instance;
  return instance.batch_process(
    max_iterations,
    max_dimension,
    const_input_row_iter_t(input_data, 0),
    const_input_row_iter_t(input_data, input_data.size1()),
    temporary_data.begin(),
    output_row_iter_t(output_eigen_vectors, 0));

}

void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{

  // arguments checking
  if (nrhs < 1 || nrhs > 2)
  {
	  mexErrMsgTxt("One or two input arguments required. ");
  }

  const mxArray* const X = prhs[0];
  assert(X);

  // checking the format of the data
  if (!mxIsDouble(X) && !mxIsSingle(X))
  {
	  mexErrMsgTxt("Unsupported input format");
  }

  if(mxIsComplex(X))
  {
    mexErrMsgTxt("Unsupported format (should be scalar)");
  }

  // Check the dimensions of inputs
  const size_t rows = mxGetM(X);
  const size_t columns = mxGetN(X);
  size_t dimension = columns;
  size_t max_dimension = dimension;
  if (nrhs == 2)
  {
    const mxArray* const maxDimArray = prhs[1];
    if(!mxIsNumeric(maxDimArray))
    {
      mexErrMsgTxt("Erroneous argument for the maximal dimension specification (non numeric argument)");
    }

    if(mxIsEmpty(maxDimArray))
    {
      mexErrMsgTxt("Erroneous argument for the maximal dimension specification (empty value)");
    }

    if(mxGetNumberOfElements(maxDimArray) > 1)
    {
      mexErrMsgTxt("Erroneous argument for the maximal dimension specification (non scalar)");
    }

    mxClassID classId = mxGetClassID(maxDimArray);
    if(classId == mxDOUBLE_CLASS || classId == mxSINGLE_CLASS)
    {
      //mexErrMsgTxt("Erroneous argument for the maximal dimension specification (floating point type)");
    }
    max_dimension = static_cast<size_t>(mxGetScalar(maxDimArray) + 0.5);

    if(max_dimension >= dimension)
    {
      mexErrMsgTxt("Erroneous argument for the maximal dimension specification (exceeds the dimension of the data)");
    }
  }

  // TODO put the dimension
  // for the library to work, we need to allocate some temporary storage
  // we also allocate the output if given
  plhs[0] = mxCreateDoubleMatrix(dimension, max_dimension, mxREAL);
  mxArray *outputMatrix = plhs[0];
  assert(outputMatrix);

  bool result = false;
  switch(mxGetClassID(X))
  {
  case mxDOUBLE_CLASS:
    result = robust_pca_dispatch<double>(X, rows, columns, max_dimension, 1000, outputMatrix);
    break;
  default:
    break;
  }

  if(!result)
  {
    mexErrMsgTxt("Robust PCA: an error occurred in the call of the function.");
  }

}<|endoftext|>


<commit_before><commit_msg>commented an assertion line in json.cpp which was prohibiting ct.rb for restarting tilestacktool when it could not read a json file due to shared filesystem latency over a network<commit_after><|endoftext|>


<commit_before>#include "GUI.h"

using namespace sf;
using namespace Chess;

namespace GUI {
	GUI::GUI(int width, int height, Board& board) : board(board) {
		this->width = width;
		this->height = height;

		window = new RenderWindow(VideoMode(width, height), "Ninja Chess");
		window->setVerticalSyncEnabled(true);

		font.loadFromFile("Resources/stchess.ttf");

		text.setFont(font);
		text.setCharacterSize(height / 8);
		text.setColor(Color::Black);

		notationMap['P'] = "A";
		notationMap['p'] = "a";
		notationMap['R'] = "D";
		notationMap['r'] = "d";
		notationMap['N'] = "B";
		notationMap['n'] = "b";
		notationMap['B'] = "C";
		notationMap['b'] = "c";
		notationMap['Q'] = "E";
		notationMap['q'] = "e";
		notationMap['K'] = "F";
		notationMap['k'] = "f";
	}

	GUI::~GUI() {
		delete window;
	}

	bool GUI::isOpen() const {
		return window->isOpen();
	}

	void GUI::update() {
		Event event;
		while (window->pollEvent(event)) {
			if (event.type == Event::Closed)
				window->close();
		}
	}

	void GUI::render() {
		window->clear();

		drawBoard();
		drawPieces();

		window->display();
	}

	void GUI::drawBoard() {
		Color brightSquare(224, 217, 190);
		Color darkSquare(152, 145, 135);

		RectangleShape square(Vector2f(width / 8.f, height / 8.f));
		for (int x = 0; x < 8; x++) {
			for (int y = 0; y < 8; y++) {
				square.setPosition(x * width / 8.f, y * height / 8.f);

				if ((x + y) % 2 == 0)
					square.setFillColor(brightSquare);
				else
					square.setFillColor(darkSquare);

				window->draw(square);
			}
		}
	}

	void GUI::drawPieces() {
		for (int x = 0; x < 8; x++) {
			for (int y = 0; y < 8; y++) {
				Piece* piece = board.getPiece(Position(x, 7-y));
				if (piece != nullptr) {
					text.setPosition(Vector2f(x * width / 8.f, y * width / 8.f));
					text.setString(notationMap[piece->notation()]);
					window->draw(text);
				}
			}
		}
	}
}<commit_msg>Offset so pieces are drawn inside square<commit_after>#include "GUI.h"

using namespace sf;
using namespace Chess;

namespace GUI {
	GUI::GUI(int width, int height, Board& board) : board(board) {
		this->width = width;
		this->height = height;

		window = new RenderWindow(VideoMode(width, height), "Ninja Chess");
		window->setVerticalSyncEnabled(true);

		font.loadFromFile("Resources/stchess.ttf");

		text.setFont(font);
		text.setCharacterSize(height / 8);
		text.setColor(Color::Black);

		notationMap['P'] = "A";
		notationMap['p'] = "a";
		notationMap['R'] = "D";
		notationMap['r'] = "d";
		notationMap['N'] = "B";
		notationMap['n'] = "b";
		notationMap['B'] = "C";
		notationMap['b'] = "c";
		notationMap['Q'] = "E";
		notationMap['q'] = "e";
		notationMap['K'] = "F";
		notationMap['k'] = "f";
	}

	GUI::~GUI() {
		delete window;
	}

	bool GUI::isOpen() const {
		return window->isOpen();
	}

	void GUI::update() {
		Event event;
		while (window->pollEvent(event)) {
			if (event.type == Event::Closed)
				window->close();
		}
	}

	void GUI::render() {
		window->clear();

		drawBoard();
		drawPieces();

		window->display();
	}

	void GUI::drawBoard() {
		Color brightSquare(224, 217, 190);
		Color darkSquare(152, 145, 135);

		RectangleShape square(Vector2f(width / 8.f, height / 8.f));
		for (int x = 0; x < 8; x++) {
			for (int y = 0; y < 8; y++) {
				square.setPosition(x * width / 8.f, y * height / 8.f);

				if ((x + y) % 2 == 0)
					square.setFillColor(brightSquare);
				else
					square.setFillColor(darkSquare);

				window->draw(square);
			}
		}
	}

	void GUI::drawPieces() {
		for (int x = 0; x < 8; x++) {
			for (int y = 0; y < 8; y++) {
				Piece* piece = board.getPiece(Position(x, 7-y));
				if (piece != nullptr) {
					text.setPosition(Vector2f(x * width / 8.f, (y - 0.2f) * width / 8.f));
					text.setString(notationMap[piece->notation()]);
					window->draw(text);
				}
			}
		}
	}
}<|endoftext|>


<commit_before>#include "GUI.h"

using namespace sf;
using namespace Chess;

namespace GUI {
	GUI::GUI(int width, int height, Board& board) : board(board) {
		this->width = width;
		this->height = height;

		window = new RenderWindow(VideoMode(width, height), "Ninja Chess");
		window->setVerticalSyncEnabled(true);

		font.loadFromFile("Resources/stchess.ttf");

		text.setFont(font);
		text.setCharacterSize(height / 8);
		text.setColor(Color::Black);

		notationMap['P'] = "A";
		notationMap['p'] = "a";
		notationMap['R'] = "D";
		notationMap['r'] = "d";
		notationMap['N'] = "B";
		notationMap['n'] = "b";
		notationMap['B'] = "C";
		notationMap['b'] = "c";
		notationMap['Q'] = "E";
		notationMap['q'] = "e";
		notationMap['K'] = "F";
		notationMap['k'] = "f";
	}

	GUI::~GUI() {
		delete window;
	}

	bool GUI::isOpen() const {
		return window->isOpen();
	}

	void GUI::update() {
		if (showPromoteWindow == true)
			updatePromote();
		else
			updateGame();
	}

	void GUI::updateGame(){
		Event event;
		while (window->pollEvent(event)) {
			if (event.type == Event::Closed)
				window->close();
		}

		bool pressed = Mouse::isButtonPressed(Mouse::Left);
		if (pressed && !mousePressed) {
			Vector2i mousePos = Mouse::getPosition(*window);
			Position tempPos(mousePos.x * 8 / width, mousePos.y * 8 / height);
			tempPos.y = 7 - tempPos.y;
			if (tempPos.valid()) {
				Piece* tempPiece = board.getPiece(tempPos);
				if (selected) {
					Piece* selectedPiece = board.getPiece(selection);
					if (selectedPiece->isLegal(board, tempPos)) {
						board.move(selection, tempPos);
						selected = false;
					}
					else if (tempPiece != nullptr) {
						if (tempPiece->isWhite() && (board.getState() == GameState::BLACKPLAYS))
							return;
						else if (!tempPiece->isWhite() && (board.getState() == GameState::WHITEPLAYS))
							return;
						selection = tempPos;
						selected = true;
						highlights = tempPiece->legalMoves(board);
					}
				}
				else if (tempPiece != nullptr) {
					if (tempPiece->isWhite() && (board.getState() == GameState::BLACKPLAYS))
						return;
					else if (!tempPiece->isWhite() && (board.getState() == GameState::WHITEPLAYS))
						return;
					selection = tempPos;
					selected = true;
					highlights = tempPiece->legalMoves(board);
				}
			}
		}

		mousePressed = pressed;
	}

	void GUI::updatePromote()
	{
		Event event;
		while (window->pollEvent(event)) {
			if (event.type == Event::Closed)
				window->close();
		}
		bool pressed = Mouse::isButtonPressed(Mouse::Left);
		if (pressed && !mousePressed){
			Vector2i mousePos = Mouse::getPosition(*window);
			if ((mousePos.x < width / 2.f) && (mousePos.y < height)){
				text.setCharacterSize(height / 8);
				showPromoteWindow = false;
			}
			else if ((mousePos.x > width / 2.f) && (mousePos.y < height)){
				text.setCharacterSize(height / 8);
				showPromoteWindow = false;
			}
			else if ((mousePos.x < width / 2.f) && (mousePos.y > height)){
				text.setCharacterSize(height / 8);
				showPromoteWindow = false;
			}
			else if ((mousePos.x < width / 2.f) && (mousePos.y > height)){
				text.setCharacterSize(height / 8);
				showPromoteWindow = false;
			}
		}
	}

	void GUI::render() {
		window->clear();
		if (showPromoteWindow == false)
		{
			drawBoard();
			drawPieces();
		}
		else
		{
			drawPromote();
		}
		window->display();
	}

	void GUI::drawPromote()
	{
		Color brightSquare(224, 217, 190);
		Color darkSquare(152, 145, 135);
		RectangleShape square(Vector2f(width / 2.f, width / 2.f));
		for (int x = 0; x < 2; x++) {
			for (int y = 0; y < 2; y++) {
				square.setPosition(x * width / 2.f, y * height / 2.f);

				if (selected && selection == Position(x, 1 - y))
					square.setFillColor(Color::Yellow);
				else if (selected && highlighted(Position(x, 1 - y)))
					square.setFillColor(Color::Green);
				else if ((x + y) % 2 == 0)
					square.setFillColor(brightSquare);
				else
					square.setFillColor(darkSquare);

				window->draw(square);
			}
		}
		char tempPromotes[4] = { 'q', 'R', 'B', 'n' };
		int i = 0;
		for (int x = 0; x < 2; x++) {
			for (int y = 0; y < 2; y++) {
				text.setCharacterSize(height / 2);
				text.setPosition(Vector2f(x * width / 2.f, (y - 0.2f) * width / 2.f));
				text.setString(notationMap[tempPromotes[i]]);
				i++;
				window->draw(text);
			}
		}
	}

	void GUI::drawBoard() {
		Color brightSquare(224, 217, 190);
		Color darkSquare(152, 145, 135);

		RectangleShape square(Vector2f(width / 8.f, height / 8.f));
		for (int x = 0; x < 8; x++) {
			for (int y = 0; y < 8; y++) {
				square.setPosition(x * width / 8.f, y * height / 8.f);

				if (selected && selection == Position(x, 7 - y))
					square.setFillColor(Color::Yellow);
				else if (selected && highlighted(Position(x, 7 - y)))
					square.setFillColor(Color::Green);
				else if ((x + y) % 2 == 0)
					square.setFillColor(brightSquare);
				else
					square.setFillColor(darkSquare);

				window->draw(square);
			}
		}
	}

	void GUI::drawPieces() {
		for (int x = 0; x < 8; x++) {
			for (int y = 0; y < 8; y++) {
				Piece* piece = board.getPiece(Position(x, 7-y));
				if (piece != nullptr) {
					text.setPosition(Vector2f(x * width / 8.f, (y - 0.2f) * width / 8.f));
					text.setString(notationMap[piece->notation()]);
					window->draw(text);
				}
			}
		}
	}

	bool GUI::highlighted(const Position& position) {
		for (Position move : highlights) {
			if (move == position)
				return true;
		}

		return false;
	}
}<commit_msg>height bug fixed<commit_after>#include "GUI.h"

using namespace sf;
using namespace Chess;

namespace GUI {
	GUI::GUI(int width, int height, Board& board) : board(board) {
		this->width = width;
		this->height = height;

		window = new RenderWindow(VideoMode(width, height), "Ninja Chess");
		window->setVerticalSyncEnabled(true);

		font.loadFromFile("Resources/stchess.ttf");

		text.setFont(font);
		text.setCharacterSize(height / 8);
		text.setColor(Color::Black);

		notationMap['P'] = "A";
		notationMap['p'] = "a";
		notationMap['R'] = "D";
		notationMap['r'] = "d";
		notationMap['N'] = "B";
		notationMap['n'] = "b";
		notationMap['B'] = "C";
		notationMap['b'] = "c";
		notationMap['Q'] = "E";
		notationMap['q'] = "e";
		notationMap['K'] = "F";
		notationMap['k'] = "f";
	}

	GUI::~GUI() {
		delete window;
	}

	bool GUI::isOpen() const {
		return window->isOpen();
	}

	void GUI::update() {
		if (showPromoteWindow == true)
			updatePromote();
		else
			updateGame();
	}

	void GUI::updateGame(){
		Event event;
		while (window->pollEvent(event)) {
			if (event.type == Event::Closed)
				window->close();
		}

		bool pressed = Mouse::isButtonPressed(Mouse::Left);
		if (pressed && !mousePressed) {
			Vector2i mousePos = Mouse::getPosition(*window);
			Position tempPos(mousePos.x * 8 / width, mousePos.y * 8 / height);
			tempPos.y = 7 - tempPos.y;
			if (tempPos.valid()) {
				Piece* tempPiece = board.getPiece(tempPos);
				if (selected) {
					Piece* selectedPiece = board.getPiece(selection);
					if (selectedPiece->isLegal(board, tempPos)) {
						board.move(selection, tempPos);
						selected = false;
					}
					else if (tempPiece != nullptr) {
						if (tempPiece->isWhite() && (board.getState() == GameState::BLACKPLAYS))
							return;
						else if (!tempPiece->isWhite() && (board.getState() == GameState::WHITEPLAYS))
							return;
						selection = tempPos;
						selected = true;
						highlights = tempPiece->legalMoves(board);
					}
				}
				else if (tempPiece != nullptr) {
					if (tempPiece->isWhite() && (board.getState() == GameState::BLACKPLAYS))
						return;
					else if (!tempPiece->isWhite() && (board.getState() == GameState::WHITEPLAYS))
						return;
					selection = tempPos;
					selected = true;
					highlights = tempPiece->legalMoves(board);
				}
			}
		}

		mousePressed = pressed;
	}

	void GUI::updatePromote()
	{
		Event event;
		while (window->pollEvent(event)) {
			if (event.type == Event::Closed)
				window->close();
		}
		bool pressed = Mouse::isButtonPressed(Mouse::Left);
		if (pressed && !mousePressed){
			Vector2i mousePos = Mouse::getPosition(*window);
			if ((mousePos.x < width / 2.f) && (mousePos.y < height / 2.f)){
				text.setCharacterSize(height / 8);
				showPromoteWindow = false;
			}
			else if ((mousePos.x > width / 2.f) && (mousePos.y < height / 2.f)){
				text.setCharacterSize(height / 8);
				showPromoteWindow = false;
			}
			else if ((mousePos.x < width / 2.f) && (mousePos.y > height / 2.f)){
				text.setCharacterSize(height / 8);
				showPromoteWindow = false;
			}
			else if ((mousePos.x > width / 2.f) && (mousePos.y > height / 2.f)){
				text.setCharacterSize(height / 8);
				showPromoteWindow = false;
			}
		}
	}

	void GUI::render() {
		window->clear();
		if (showPromoteWindow == false)
		{
			drawBoard();
			drawPieces();
		}
		else
		{
			drawPromote();
		}
		window->display();
	}

	void GUI::drawPromote()
	{
		Color brightSquare(224, 217, 190);
		Color darkSquare(152, 145, 135);
		RectangleShape square(Vector2f(width / 2.f, width / 2.f));
		for (int x = 0; x < 2; x++) {
			for (int y = 0; y < 2; y++) {
				square.setPosition(x * width / 2.f, y * height / 2.f);

				if (selected && selection == Position(x, 1 - y))
					square.setFillColor(Color::Yellow);
				else if (selected && highlighted(Position(x, 1 - y)))
					square.setFillColor(Color::Green);
				else if ((x + y) % 2 == 0)
					square.setFillColor(brightSquare);
				else
					square.setFillColor(darkSquare);

				window->draw(square);
			}
		}
		char tempPromotes[4] = { 'q', 'R', 'B', 'n' };
		int i = 0;
		for (int x = 0; x < 2; x++) {
			for (int y = 0; y < 2; y++) {
				text.setCharacterSize(height / 2);
				text.setPosition(Vector2f(x * width / 2.f, (y - 0.2f) * width / 2.f));
				text.setString(notationMap[tempPromotes[i]]);
				i++;
				window->draw(text);
			}
		}
	}

	void GUI::drawBoard() {
		Color brightSquare(224, 217, 190);
		Color darkSquare(152, 145, 135);

		RectangleShape square(Vector2f(width / 8.f, height / 8.f));
		for (int x = 0; x < 8; x++) {
			for (int y = 0; y < 8; y++) {
				square.setPosition(x * width / 8.f, y * height / 8.f);

				if (selected && selection == Position(x, 7 - y))
					square.setFillColor(Color::Yellow);
				else if (selected && highlighted(Position(x, 7 - y)))
					square.setFillColor(Color::Green);
				else if ((x + y) % 2 == 0)
					square.setFillColor(brightSquare);
				else
					square.setFillColor(darkSquare);

				window->draw(square);
			}
		}
	}

	void GUI::drawPieces() {
		for (int x = 0; x < 8; x++) {
			for (int y = 0; y < 8; y++) {
				Piece* piece = board.getPiece(Position(x, 7-y));
				if (piece != nullptr) {
					text.setPosition(Vector2f(x * width / 8.f, (y - 0.2f) * width / 8.f));
					text.setString(notationMap[piece->notation()]);
					window->draw(text);
				}
			}
		}
	}

	bool GUI::highlighted(const Position& position) {
		for (Position move : highlights) {
			if (move == position)
				return true;
		}

		return false;
	}
}<|endoftext|>


<commit_before>#include "osrm_router.hpp"
#include "route.hpp"
#include "vehicle_model.hpp"

#include "../geometry/distance.hpp"

#include "../indexer/mercator.hpp"
#include "../indexer/index.hpp"

#include "../platform/platform.hpp"

#include "../base/logging.hpp"

#include "../3party/osrm/osrm-backend/DataStructures/SearchEngineData.h"
#include "../3party/osrm/osrm-backend/Descriptors/DescriptionFactory.h"
#include "../3party/osrm/osrm-backend/RoutingAlgorithms/ShortestPathRouting.h"

namespace routing
{

namespace
{

class Point2PhantomNode
{
  m2::PointD m_point;
  OsrmFtSegMapping const & m_mapping;

  struct Candidate
  {
    double m_dist;
    uint32_t m_segIdx;
    FeatureID m_fID;
    m2::PointD m_point;

    Candidate() : m_dist(numeric_limits<double>::max()) {}
  };

  buffer_vector<Candidate, 128> m_candidates;

public:
  Point2PhantomNode(m2::PointD const & pt, OsrmFtSegMapping const & mapping)
    : m_point(pt), m_mapping(mapping)
  {
  }

  void operator() (FeatureType const & ft)
  {
    static CarModel const carModel;
    if (ft.GetFeatureType() != feature::GEOM_LINE || !carModel.IsRoad(ft))
      return;

    Candidate res;

    ft.ParseGeometry(FeatureType::BEST_GEOMETRY);

    size_t const count = ft.GetPointsCount();
    ASSERT_GREATER(count, 1, ());
    for (size_t i = 1; i < count; ++i)
    {
      /// @todo Probably, we need to get exact projection distance in meters.
      m2::ProjectionToSection<m2::PointD> segProj;
      segProj.SetBounds(ft.GetPoint(i - 1), ft.GetPoint(i));

      m2::PointD const pt = segProj(m_point);
      double const d = m_point.SquareLength(pt);
      if (d < res.m_dist)
      {
        res.m_dist = d;
        res.m_fID = ft.GetID();
        res.m_segIdx = i - 1;
        res.m_point = pt;
      }
    }

    if (res.m_fID.IsValid())
      m_candidates.push_back(res);
  }

  bool MakeResult(PhantomNode & resultNode, uint32_t & mwmId, OsrmFtSegMapping::FtSeg & seg, m2::PointD & pt)
  {
    resultNode.forward_node_id = resultNode.reverse_node_id = -1;

    sort(m_candidates.begin(), m_candidates.end(), [] (Candidate const & r1, Candidate const & r2)
    {
      return (r1.m_dist < r2.m_dist);
    });

    for (auto const & c : m_candidates)
    {
      seg.m_fid = c.m_fID.m_offset;
      seg.m_pointStart = c.m_segIdx;
      seg.m_pointEnd = c.m_segIdx + 1;
      pt = c.m_point;
      m_mapping.GetOsrmNode(seg, resultNode.forward_node_id, resultNode.reverse_node_id);

      mwmId = c.m_fID.m_mwm;

      if (resultNode.forward_node_id != -1 || resultNode.reverse_node_id != -1)
        return true;
    }

    if (m_candidates.empty())
      LOG(LDEBUG, ("No candidates for point:", m_point));
    else
      LOG(LINFO, ("Can't find osrm node for feature:", m_candidates[0].m_fID));

    return false;
  }
};

} // namespace

OsrmRouter::OsrmRouter(Index const * index, CountryFileFnT const & fn)
  : m_countryFn(fn), m_pIndex(index)
{
}

string OsrmRouter::GetName() const
{
  return "mapsme";
}

void OsrmRouter::SetFinalPoint(m2::PointD const & finalPt)
{
  m_finalPt = finalPt;
}

namespace
{

class MakeResultGuard
{
  IRouter::ReadyCallback const & m_callback;
  Route m_route;
  string m_errorMsg;

public:
  MakeResultGuard(IRouter::ReadyCallback const & callback, string const & name)
    : m_callback(callback), m_route(name)
  {
  }

  ~MakeResultGuard()
  {
    if (!m_errorMsg.empty())
      LOG(LINFO, ("Failed calculate route", m_errorMsg));
    m_callback(m_route);
  }

  void SetErrorMsg(char const * msg) { m_errorMsg = msg; }

  void SetGeometry(vector<m2::PointD> const & vec)
  {
    m_route.SetGeometry(vec.begin(), vec.end());
    m_errorMsg.clear();
  }
};

}

void OsrmRouter::CalculateRoute(m2::PointD const & startingPt, ReadyCallback const & callback)
{
  MakeResultGuard resGuard(callback, GetName());

  string const fName = m_countryFn(startingPt);
  if (fName != m_countryFn(m_finalPt))
  {
    resGuard.SetErrorMsg("Points are in different MWMs");
    return;
  }

  string const fPath = GetPlatform().WritablePathForFile(fName + DATA_FILE_EXTENSION + ROUTING_FILE_EXTENSION);
  if (NeedReload(fPath))
  {
    LOG(LDEBUG, ("Load routing index for file:", fPath));

    try
    {
      // Clear data while m_container is valid.
      m_dataFacade.Clear();
      m_mapping.Clear();

      m_container.Open(fPath);

      m_dataFacade.Load(m_container);
      m_mapping.Load(m_container);
    }
    catch (Reader::Exception const & e)
    {
      LOG(LERROR, ("Error while loading routing index:", fPath, e.Msg()));
      resGuard.SetErrorMsg("Routing index absent or incorrect.");
      return;
    }
  }

  SearchEngineData engineData;
  ShortestPathRouting<DataFacadeT> pathFinder(&m_dataFacade, engineData);
  RawRouteData rawRoute;

  PhantomNodes nodes;

  OsrmFtSegMapping::FtSeg segBegin;
  m2::PointD segPointStart;
  uint32_t mwmIdStart = -1;
  if (!FindPhantomNode(startingPt, nodes.source_phantom, mwmIdStart, segBegin, segPointStart))
  {
    resGuard.SetErrorMsg("Can't find start point node");
    return;
  }

  uint32_t mwmIdEnd = -1;
  OsrmFtSegMapping::FtSeg segEnd;
  m2::PointD segPointEnd;
  if (!FindPhantomNode(m_finalPt, nodes.target_phantom, mwmIdEnd, segEnd, segPointEnd))
  {
    resGuard.SetErrorMsg("Can't find end point node");
    return;
  }

  if (mwmIdEnd != mwmIdStart || mwmIdEnd == -1 || mwmIdStart == -1)
  {
    resGuard.SetErrorMsg("Found features are in different MWMs");
    return;
  }

  rawRoute.segment_end_coordinates.push_back(nodes);

  pathFinder({nodes}, {}, rawRoute);

  if (INVALID_EDGE_WEIGHT == rawRoute.shortest_path_length
      || rawRoute.segment_end_coordinates.empty()
      || rawRoute.source_traversed_in_reverse.empty())
  {
    resGuard.SetErrorMsg("Route not found");
    return;
  }

  // restore route
  vector<m2::PointD> points;
  for (auto i : osrm::irange<std::size_t>(0, rawRoute.unpacked_path_segments.size()))
  {
    // Get all the coordinates for the computed route
    size_t const n = rawRoute.unpacked_path_segments[i].size();
    for (size_t j = 0; j < n; ++j)
    {
      PathData const & path_data = rawRoute.unpacked_path_segments[i][j];

      typedef OsrmFtSegMapping::FtSeg SegT;
      buffer_vector<SegT, 8> buffer;
      m_mapping.ForEachFtSeg(path_data.node, MakeBackInsertFunctor(buffer));

      auto correctFn = [&buffer] (SegT const & seg, size_t & ind)
      {
        auto const it = find_if(buffer.begin(), buffer.end(), [&seg] (OsrmFtSegMapping::FtSeg const & s)
        {
          return s.IsIntersect(seg);
        });

        ASSERT(it != buffer.end(), ());
        ind = distance(buffer.begin(), it);
      };

      //m_mapping.DumpSegmentByNode(path_data.node);

      size_t startK = 0, endK = buffer.size();
      if (j == 0)
        correctFn(segBegin, startK);
      else if (j == n - 1)
      {
        correctFn(segEnd, endK);
        ++endK;
      }

      for (size_t k = startK; k < endK; ++k)
      {
        SegT const & seg = buffer[k];

        FeatureType ft;
        Index::FeaturesLoaderGuard loader(*m_pIndex, mwmIdStart);
        loader.GetFeature(seg.m_fid, ft);
        ft.ParseGeometry(FeatureType::BEST_GEOMETRY);

        auto startIdx = seg.m_pointStart;
        auto endIdx = seg.m_pointEnd;

        if (j == 0 && k == startK)
          startIdx = (seg.m_pointEnd > seg.m_pointStart) ? segBegin.m_pointStart : segBegin.m_pointEnd;
        else if (j == n - 1 && k == endK - 1)
          endIdx = (seg.m_pointEnd > seg.m_pointStart) ? segEnd.m_pointEnd : segEnd.m_pointStart;

        if (seg.m_pointEnd > seg.m_pointStart)
        {
          for (auto idx = startIdx; idx <= endIdx; ++idx)
            points.push_back(ft.GetPoint(idx));
        }
        else
        {
          for (auto idx = startIdx; idx > endIdx; --idx)
            points.push_back(ft.GetPoint(idx));
          points.push_back(ft.GetPoint(endIdx));
        }
      }
    }
  }

  points.front() = segPointStart;
  points.back() = segPointEnd;

  resGuard.SetGeometry(points);
}

bool OsrmRouter::FindPhantomNode(m2::PointD const & pt, PhantomNode & resultNode,
                                 uint32_t & mwmId, OsrmFtSegMapping::FtSeg & seg, m2::PointD & segPt)
{
  Point2PhantomNode getter(pt, m_mapping);

  /// @todo Review radius of rect and read index scale.
  m_pIndex->ForEachInRect(getter, MercatorBounds::RectByCenterXYAndSizeInMeters(pt, 1000.0), 17);

  return getter.MakeResult(resultNode, mwmId, seg, segPt);
}

bool OsrmRouter::NeedReload(string const & fPath) const
{
  return (m_container.GetName() != fPath);
}

}
<commit_msg>[routing] Efficient usage of virtual memory<commit_after>#include "osrm_router.hpp"
#include "route.hpp"
#include "vehicle_model.hpp"

#include "../geometry/distance.hpp"

#include "../indexer/mercator.hpp"
#include "../indexer/index.hpp"

#include "../platform/platform.hpp"

#include "../base/logging.hpp"

#include "../3party/osrm/osrm-backend/DataStructures/SearchEngineData.h"
#include "../3party/osrm/osrm-backend/Descriptors/DescriptionFactory.h"
#include "../3party/osrm/osrm-backend/RoutingAlgorithms/ShortestPathRouting.h"

namespace routing
{

namespace
{

class Point2PhantomNode
{
  m2::PointD m_point;
  OsrmFtSegMapping const & m_mapping;

  struct Candidate
  {
    double m_dist;
    uint32_t m_segIdx;
    FeatureID m_fID;
    m2::PointD m_point;

    Candidate() : m_dist(numeric_limits<double>::max()) {}
  };

  buffer_vector<Candidate, 128> m_candidates;

public:
  Point2PhantomNode(m2::PointD const & pt, OsrmFtSegMapping const & mapping)
    : m_point(pt), m_mapping(mapping)
  {
  }

  void operator() (FeatureType const & ft)
  {
    static CarModel const carModel;
    if (ft.GetFeatureType() != feature::GEOM_LINE || !carModel.IsRoad(ft))
      return;

    Candidate res;

    ft.ParseGeometry(FeatureType::BEST_GEOMETRY);

    size_t const count = ft.GetPointsCount();
    ASSERT_GREATER(count, 1, ());
    for (size_t i = 1; i < count; ++i)
    {
      /// @todo Probably, we need to get exact projection distance in meters.
      m2::ProjectionToSection<m2::PointD> segProj;
      segProj.SetBounds(ft.GetPoint(i - 1), ft.GetPoint(i));

      m2::PointD const pt = segProj(m_point);
      double const d = m_point.SquareLength(pt);
      if (d < res.m_dist)
      {
        res.m_dist = d;
        res.m_fID = ft.GetID();
        res.m_segIdx = i - 1;
        res.m_point = pt;
      }
    }

    if (res.m_fID.IsValid())
      m_candidates.push_back(res);
  }

  bool MakeResult(PhantomNode & resultNode, uint32_t & mwmId, OsrmFtSegMapping::FtSeg & seg, m2::PointD & pt)
  {
    resultNode.forward_node_id = resultNode.reverse_node_id = -1;

    sort(m_candidates.begin(), m_candidates.end(), [] (Candidate const & r1, Candidate const & r2)
    {
      return (r1.m_dist < r2.m_dist);
    });

    for (auto const & c : m_candidates)
    {
      seg.m_fid = c.m_fID.m_offset;
      seg.m_pointStart = c.m_segIdx;
      seg.m_pointEnd = c.m_segIdx + 1;
      pt = c.m_point;
      m_mapping.GetOsrmNode(seg, resultNode.forward_node_id, resultNode.reverse_node_id);

      mwmId = c.m_fID.m_mwm;

      if (resultNode.forward_node_id != -1 || resultNode.reverse_node_id != -1)
        return true;
    }

    if (m_candidates.empty())
      LOG(LDEBUG, ("No candidates for point:", m_point));
    else
      LOG(LINFO, ("Can't find osrm node for feature:", m_candidates[0].m_fID));

    return false;
  }
};

} // namespace

OsrmRouter::OsrmRouter(Index const * index, CountryFileFnT const & fn)
  : m_countryFn(fn), m_pIndex(index)
{
}

string OsrmRouter::GetName() const
{
  return "mapsme";
}

void OsrmRouter::SetFinalPoint(m2::PointD const & finalPt)
{
  m_finalPt = finalPt;
}

namespace
{

class MakeResultGuard
{
  IRouter::ReadyCallback const & m_callback;
  Route m_route;
  string m_errorMsg;

public:
  MakeResultGuard(IRouter::ReadyCallback const & callback, string const & name)
    : m_callback(callback), m_route(name)
  {
  }

  ~MakeResultGuard()
  {
    if (!m_errorMsg.empty())
      LOG(LINFO, ("Failed calculate route", m_errorMsg));
    m_callback(m_route);
  }

  void SetErrorMsg(char const * msg) { m_errorMsg = msg; }

  void SetGeometry(vector<m2::PointD> const & vec)
  {
    m_route.SetGeometry(vec.begin(), vec.end());
    m_errorMsg.clear();
  }
};

}

void OsrmRouter::CalculateRoute(m2::PointD const & startingPt, ReadyCallback const & callback)
{
  MakeResultGuard resGuard(callback, GetName());

  string const fName = m_countryFn(startingPt);
  if (fName != m_countryFn(m_finalPt))
  {
    resGuard.SetErrorMsg("Points are in different MWMs");
    return;
  }

  string const fPath = GetPlatform().WritablePathForFile(fName + DATA_FILE_EXTENSION + ROUTING_FILE_EXTENSION);
  if (NeedReload(fPath))
  {
    LOG(LDEBUG, ("Load routing index for file:", fPath));

    try
    {
      // Clear data while m_container is valid.
      m_dataFacade.Clear();
      m_mapping.Clear();

      m_container.Open(fPath);

      m_mapping.Load(m_container);
    }
    catch (Reader::Exception const & e)
    {
      LOG(LERROR, ("Error while loading routing index:", fPath, e.Msg()));
      resGuard.SetErrorMsg("Routing index absent or incorrect.");
      return;
    }
  }

  SearchEngineData engineData;
  ShortestPathRouting<DataFacadeT> pathFinder(&m_dataFacade, engineData);
  RawRouteData rawRoute;

  PhantomNodes nodes;

  OsrmFtSegMapping::FtSeg segBegin;
  m2::PointD segPointStart;
  uint32_t mwmIdStart = -1;
  if (!FindPhantomNode(startingPt, nodes.source_phantom, mwmIdStart, segBegin, segPointStart))
  {
    resGuard.SetErrorMsg("Can't find start point node");
    return;
  }

  uint32_t mwmIdEnd = -1;
  OsrmFtSegMapping::FtSeg segEnd;
  m2::PointD segPointEnd;
  if (!FindPhantomNode(m_finalPt, nodes.target_phantom, mwmIdEnd, segEnd, segPointEnd))
  {
    resGuard.SetErrorMsg("Can't find end point node");
    return;
  }

  if (mwmIdEnd != mwmIdStart || mwmIdEnd == -1 || mwmIdStart == -1)
  {
    resGuard.SetErrorMsg("Found features are in different MWMs");
    return;
  }

  try
  {
    m_mapping.Clear();
    m_dataFacade.Load(m_container);
  }
  catch(Reader::Exception const & e)
  {
    LOG(LERROR, ("Error while loading routing data:", fPath, e.Msg()));
    resGuard.SetErrorMsg("Routing data absent or incorrect.");
    return;
  }

  rawRoute.segment_end_coordinates.push_back(nodes);

  pathFinder({nodes}, {}, rawRoute);

  // unmap routing data
  m_dataFacade.Clear();

  if (INVALID_EDGE_WEIGHT == rawRoute.shortest_path_length
      || rawRoute.segment_end_coordinates.empty()
      || rawRoute.source_traversed_in_reverse.empty())
  {
    resGuard.SetErrorMsg("Route not found");
    return;
  }

  try
  {
    m_mapping.Load(m_container);
  }
  catch(Reader::Exception const & e)
  {
    LOG(LERROR, ("Error while loading routing index:", fPath, e.Msg()));
    resGuard.SetErrorMsg("Routing index absent or incorrect.");
    return;
  }

  // restore route
  vector<m2::PointD> points;
  for (auto i : osrm::irange<std::size_t>(0, rawRoute.unpacked_path_segments.size()))
  {
    // Get all the coordinates for the computed route
    size_t const n = rawRoute.unpacked_path_segments[i].size();
    for (size_t j = 0; j < n; ++j)
    {
      PathData const & path_data = rawRoute.unpacked_path_segments[i][j];

      typedef OsrmFtSegMapping::FtSeg SegT;
      buffer_vector<SegT, 8> buffer;
      m_mapping.ForEachFtSeg(path_data.node, MakeBackInsertFunctor(buffer));

      auto correctFn = [&buffer] (SegT const & seg, size_t & ind)
      {
        auto const it = find_if(buffer.begin(), buffer.end(), [&seg] (OsrmFtSegMapping::FtSeg const & s)
        {
          return s.IsIntersect(seg);
        });

        ASSERT(it != buffer.end(), ());
        ind = distance(buffer.begin(), it);
      };

      //m_mapping.DumpSegmentByNode(path_data.node);

      size_t startK = 0, endK = buffer.size();
      if (j == 0)
        correctFn(segBegin, startK);
      else if (j == n - 1)
      {
        correctFn(segEnd, endK);
        ++endK;
      }

      for (size_t k = startK; k < endK; ++k)
      {
        SegT const & seg = buffer[k];

        FeatureType ft;
        Index::FeaturesLoaderGuard loader(*m_pIndex, mwmIdStart);
        loader.GetFeature(seg.m_fid, ft);
        ft.ParseGeometry(FeatureType::BEST_GEOMETRY);

        auto startIdx = seg.m_pointStart;
        auto endIdx = seg.m_pointEnd;

        if (j == 0 && k == startK)
          startIdx = (seg.m_pointEnd > seg.m_pointStart) ? segBegin.m_pointStart : segBegin.m_pointEnd;
        else if (j == n - 1 && k == endK - 1)
          endIdx = (seg.m_pointEnd > seg.m_pointStart) ? segEnd.m_pointEnd : segEnd.m_pointStart;

        if (seg.m_pointEnd > seg.m_pointStart)
        {
          for (auto idx = startIdx; idx <= endIdx; ++idx)
            points.push_back(ft.GetPoint(idx));
        }
        else
        {
          for (auto idx = startIdx; idx > endIdx; --idx)
            points.push_back(ft.GetPoint(idx));
          points.push_back(ft.GetPoint(endIdx));
        }
      }
    }
  }

  points.front() = segPointStart;
  points.back() = segPointEnd;

  resGuard.SetGeometry(points);
}

bool OsrmRouter::FindPhantomNode(m2::PointD const & pt, PhantomNode & resultNode,
                                 uint32_t & mwmId, OsrmFtSegMapping::FtSeg & seg, m2::PointD & segPt)
{
  Point2PhantomNode getter(pt, m_mapping);

  /// @todo Review radius of rect and read index scale.
  m_pIndex->ForEachInRect(getter, MercatorBounds::RectByCenterXYAndSizeInMeters(pt, 1000.0), 17);

  return getter.MakeResult(resultNode, mwmId, seg, segPt);
}

bool OsrmRouter::NeedReload(string const & fPath) const
{
  return (m_container.GetName() != fPath);
}

}
<|endoftext|>


<commit_before>#include <string>
#include <iostream>
#include <array>
#include <vector>
#include <bitset>

using namespace std;

bitset<4> encode_nt(char nt) {
	bitset<4> encoding;// = {0,0,0,0};
	switch(nt) {
		case 'A': encoding[0] = 1; break;
		case 'C': encoding[1] = 1; break;
		case 'G': encoding[2] = 1; break;
		case 'T': encoding[3] = 1; break;
		default: cerr << "nucleotide unaccepted in sequence " << nt << endl;
	}
	return encoding;
}

vector<bool> dct(vector<bool> signal) {
	vector<bool> output;
	for(int i=0; i<signal.size(); i++) {

	}
	return signal;
}

array<float, 4> extract(string s) {
	int last_pos[] = {0,0,0,0};
	int count[] = {0,0,0,0};
	array<float, 4> freq;
	for(int i=0; i < s.length(); i++) {
		switch(s.at(i)) {
			case 'A': count[0]++; break;
			case 'C': count[1]++; break;
			case 'G': count[2]++; break;
			case 'T': count[3]++; break;
			default: cerr << "nucleotide unaccepted in sequence " << s << endl;
		}
	}
	for(int i=0; i<4; i++) {
		freq[i] = 1.0 * count[i] / s.length();
	}
	return freq;
}

array<vector<bool>, 4> decompose(string sequence) {
	array<vector<bool>, 4> channels;
	for(auto it=sequence.begin(); it!=sequence.end(); ++it) {
		auto signal = encode_nt(*it);
		for(int i=0; i<4; i++) {
			channels[i].push_back(signal[i]);
		}
	}
	return channels;
}

int main(const int argc, const char* argv[]) {
	auto channels = decompose(string(argv[1]));
	auto frequencies = extract(string(argv[1]));
	for(int i=0; i<4; i++) {
		cerr << "FREQ=" << frequencies[i] << " BINARY_SIGNAL=";
		for(auto s : channels[i]) {
			cerr << s;
		}
		cerr << endl;
	}
	return 0;
}
<commit_msg>added simple DCT algorithm to ntprofile<commit_after>#include <string>
#include <iostream>
#include <array>
#include <vector>
#include <bitset>
#include <cmath>

//const double M_PI = 3.14159265358979323846;

using namespace std;

/// encode capital nucleotide character as bitset
bitset<4> encode_nt(char nt) {
	bitset<4> encoding;// = {0,0,0,0};
	switch(nt) {
		case 'A': encoding[0] = 1; break;
		case 'C': encoding[1] = 1; break;
		case 'G': encoding[2] = 1; break;
		case 'T': encoding[3] = 1; break;
		default: cerr << "nucleotide unaccepted in sequence " << nt << endl;
	}
	return encoding;
}

/// Discrete Cosine Transformation of binary signal. Returns only N coefficients (default=5)
vector<double> dct(vector<bool> x, int N = 5) {
	vector<double> output;
	if(N < 1 || N > x.size()) {
		N = x.size();
	}
	for(int k=0; k<N; k++) {
		double y;
		for(int n=0; n<x.size(); n++) {
			y += x[n] * cos((M_PI/N) * (n+0.5) * k);
		}
		output.push_back(sqrt(2)/x.size()*y);
	}
	return output;
}

/// average nucleotide frequency
array<float, 4> extract(string s) {
	int last_pos[] = {0,0,0,0};
	int count[] = {0,0,0,0};
	array<float, 4> freq;
	for(int i=0; i < s.length(); i++) {
		switch(s.at(i)) {
			case 'A': count[0]++; break;
			case 'C': count[1]++; break;
			case 'G': count[2]++; break;
			case 'T': count[3]++; break;
			default: cerr << "nucleotide unaccepted in sequence " << s << endl;
		}
	}
	for(int i=0; i<4; i++) {
		freq[i] = 1.0 * count[i] / s.length();
	}
	return freq;
}

/// decompose a nucleotide sequence into binary channels
array<vector<bool>, 4> decompose(string sequence) {
	array<vector<bool>, 4> channels;
	for(auto it=sequence.begin(); it!=sequence.end(); ++it) {
		auto signal = encode_nt(*it);
		for(int i=0; i<4; i++) {
			channels[i].push_back(signal[i]);
		}
	}
	return channels;
}

int main(const int argc, const char* argv[]) {
	auto channels = decompose(string(argv[1]));
	auto frequencies = extract(string(argv[1]));
	for(int i=0; i<4; i++) {
		cerr << "FREQ=" << frequencies[i] << " BINARY_SIGNAL= c(";
		for(auto s : channels[i]) {
			cerr << s << ",";
		}
		cerr << ")" << endl << "dct = c(";
		for(auto s : dct(channels[i])) {
			cerr << s << ",";
		}
		cerr << ")" << endl;
	}
	return 0;
}
<|endoftext|>