text:
/**
 *  Copyright (c) 2019 Intel Corporation
 *
 * 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 <daqdb/Types.h>

#include <boost/algorithm/string.hpp>
#include <boost/assign/list_of.hpp>
#include <boost/format.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/property_tree/json_parser.hpp>
#include <boost/property_tree/ptree.hpp>
#include <chrono>
#include <iostream>
#include <map>

#include "config.h"
#include "nodeCli.h"

using namespace std;
using namespace boost::algorithm;
using boost::format;

#define NUM_ELEM_KEY_ATTRS 3
#define GET_CMD_KEY_ATTRS_OFFSET 2
#define PUT_CMD_KEY_ATTRS_OFFSET 3
#define PUT_CMD_VAL_OFFSET 2
#define UPDATE_CMD_KEY_ATTRS_OFFSET 3
#define UPDATE_CMD_VAL_OFFSET 2
#define KEY_ATTRS_OPT_NAME_POS_OFFSET 1
#define KEY_ATTRS_OPT_VAL_POS_OFFSET 2

map<string, string> consoleCmd = boost::assign::map_list_of("help", "")(
    "get", " <key> [-o <long_term> <0|1>]")("aget",
                                            " <key> [-o <long_term> <0|1>]")(
    "put", " <key> <value> [-o <lock|ready|long_term> <0|1>]")(
    "aput", " <key> <value> [-o <lock|ready|long_term> <0|1>]")("status", "")(
    "remove", " <key>")("quit", "")(
    "update", " <key> [value] [-o <lock|ready|long_term> <0|1>]")(
    "aupdate", " <key> [value] [-o <lock|ready|long_term> <0|1>]")("neighbors",
                                                                   "");

/*!
 * Provides completion functionality to dragon shell.
 *
 * @param buf	completion prefix
 * @param lc	callback functions manager
 */
void completion(const char *buf, linenoiseCompletions *lc) {
    if (buf[0] == 'h') {
        linenoiseAddCompletion(lc, "help");
    } else if (buf[0] == 'q') {
        linenoiseAddCompletion(lc, "quit");
    } else if (buf[0] == 'g') {
        linenoiseAddCompletion(lc, "get");
    } else if (buf[0] == 'u') {
        linenoiseAddCompletion(lc, "update");
    } else if (buf[0] == 'p') {
        linenoiseAddCompletion(lc, "put");
    } else if (buf[0] == 's') {
        linenoiseAddCompletion(lc, "status");
    } else if (buf[0] == 'n') {
        linenoiseAddCompletion(lc, "neighbors");
    } else if (buf[0] == 'r') {
        linenoiseAddCompletion(lc, "remove");
    } else if (buf[0] == 'a') {
        if (buf[1] == 'g') {
            linenoiseAddCompletion(lc, "aget");
        } else if (buf[1] == 'p') {
            linenoiseAddCompletion(lc, "aput");
        } else if (buf[1] == 'u') {
            linenoiseAddCompletion(lc, "aupdate");
        }
    }
}

/*!
 * Provides hints for commands to dragon shell.
 *
 * @param buf	command
 * @param color	hint color
 * @param bold	indicate if hint should be bolded
 * @return
 */
char *hints(const char *buf, int *color, int *bold) {
    *color = consoleHintColor;
    char *result = nullptr;

    if (consoleCmd.count(buf)) {
        result = const_cast<char *>(consoleCmd[buf].c_str());
    }

    return result;
}

namespace DaqDB {

nodeCli::nodeCli(std::shared_ptr<DaqDB::KVStoreBase> &spKVStore)
    : _spKVStore(spKVStore) {
    linenoiseSetCompletionCallback(completion);
    linenoiseSetHintsCallback(hints);
}

nodeCli::~nodeCli() {}

int nodeCli::operator()() {
    auto *inLine = linenoise("daqdb> ");
    auto isEmpty = false;
    if (inLine == nullptr) {
        return false;
    }
    if (inLine[0] == '\0') {
        isEmpty = true;
    }
    std::string strLine(inLine);
    free(inLine);

    try {
        if (isEmpty || starts_with(strLine, "help")) {
            cout << "Following commands supported:" << endl;
            for (auto cmdEntry : consoleCmd) {
                cout << "\t- " << cmdEntry.first << cmdEntry.second << endl;
            }
        } else if (starts_with(strLine, "g")) {
            this->_cmdGet(strLine);
        } else if (starts_with(strLine, "p")) {
            this->_cmdPut(strLine);
        } else if (starts_with(strLine, "u")) {
            this->_cmdUpdate(strLine);
        } else if (starts_with(strLine, "ap")) {
            this->_cmdPutAsync(strLine);
        } else if (starts_with(strLine, "ag")) {
            this->_cmdGetAsync(strLine);
        } else if (starts_with(strLine, "au")) {
            this->_cmdUpdateAsync(strLine);
        } else if (starts_with(strLine, "r")) {
            this->_cmdRemove(strLine);
        } else if (starts_with(strLine, "s")) {
            this->_cmdStatus();
        } else if (starts_with(strLine, "n")) {
            this->_cmdNeighbors();
        } else if (starts_with(strLine, "q")) {
            return false;
        } else {
            cout << format("Unreconized command: %1%\n") % strLine;
        }
    } catch (NotImplementedException &ex) {
        cout << ex.what() << endl;
    }

    return true;
}

void nodeCli::_cmdGet(const std::string &strLine) {
    vector<string> arguments;
    split(arguments, strLine, is_any_of("\t "), boost::token_compress_on);

    if (arguments.size() < 2) {
        cout << "Error: expects at least one argument" << endl;
    } else {
        auto key = arguments[1];
        if (_isInvalidKey(key)) {
            cout << "Error: wrong key size" << endl;
            return;
        }

        DaqDB::Key keyBuff;
        try {
            keyBuff = _strToKey(key);
        } catch (DaqDB::OperationFailedException &e) {
            cout << "Error: cannot allocate key buffer" << endl;
            return;
        }

        auto keyAttrs = _getKeyAttrs(GET_CMD_KEY_ATTRS_OFFSET, arguments);
        DaqDB::GetOptions options(keyAttrs, keyAttrs);

        DaqDB::Value value;
        try {
            value = _spKVStore->Get(keyBuff, std::move(options));
            string valuestr(value.data());
            cout << format("[%1%] = %2%\n") % key % valuestr;
        } catch (DaqDB::OperationFailedException &e) {
            if (e.status()() == DaqDB::KEY_NOT_FOUND) {
                cout << format("[%1%] not found\n") % key;
            } else {
                cout << "Error: cannot get element: " << e.status().to_string()
                     << endl;
            }
        }
        if (value.size() > 0)
            _spKVStore->Free(keyBuff, std::move(value));
        if (keyBuff.size() > 0)
            _spKVStore->Free(std::move(keyBuff));
    }
}

void nodeCli::_cmdGetAsync(const std::string &strLine) {
    vector<string> arguments;
    split(arguments, strLine, is_any_of("\t "), boost::token_compress_on);

    if (arguments.size() < 2) {
        cout << "Error: expects at least one argument" << endl;
    } else {
        auto key = arguments[1];
        if (_isInvalidKey(key)) {
            cout << "Error: wrong key size" << endl;
            return;
        }
        DaqDB::Key keyBuff;
        try {
            keyBuff = _strToKey(key);
        } catch (DaqDB::OperationFailedException &e) {
            cout << "Error: cannot allocate key buffer" << endl;
            return;
        }

        auto keyAttrs = _getKeyAttrs(GET_CMD_KEY_ATTRS_OFFSET, arguments);
        DaqDB::GetOptions options(keyAttrs, keyAttrs);

        try {
            _spKVStore->GetAsync(
                std::move(keyBuff),
                [&](KVStoreBase *kvs, Status status, const char *key,
                    size_t keySize, const char *value, size_t valueSize) {
                    if (!status.ok()) {
                        _statusMsgs.push_back(boost::str(
                            boost::format("Error: cannot get element: %1%") %
                            status.to_string()));
                    } else {
                        _statusMsgs.push_back(boost::str(
                            boost::format("GET[%1%]=%2% : completed") % key %
                            value));
                    }
                },
                std::move(options));
        } catch (DaqDB::OperationFailedException &e) {
            if (e.status()() == StatusCode::OFFLOAD_DISABLED_ERROR) {
                cout << format("Error: Disk offload is disabled") << endl;
            } else {
                cout << "Error: cannot get element: " << e.status().to_string()
                     << endl;
            }
        }
    }
}

DaqDB::Key nodeCli::_strToKey(const std::string &key) {
    if (_isInvalidKey(key)) {
        throw DaqDB::OperationFailedException(BAD_KEY_FORMAT);
    }

    DaqDB::Key keyBuff = _spKVStore->AllocKey(KeyValAttribute::NOT_BUFFERED);
    CliNodeKey *cliKeyPtr = reinterpret_cast<CliNodeKey *>(keyBuff.data());
    memset(cliKeyPtr, 0, sizeof(CliNodeKey));

    memcpy(&(cliKeyPtr->eventId), key.data(), key.size());
    return keyBuff;
}

DaqDB::PrimaryKeyAttribute
nodeCli::_getKeyAttr(unsigned char start,
                     const std::vector<std::string> &cmdAttrs) {
    if ((cmdAttrs.size() < start + NUM_ELEM_KEY_ATTRS) ||
        !(starts_with(cmdAttrs[start], "-o"))) {
        return DaqDB::PrimaryKeyAttribute::EMPTY;
    }

    auto optVal = boost::lexical_cast<bool>(
        cmdAttrs[start + KEY_ATTRS_OPT_VAL_POS_OFFSET]);
    if (optVal) {
        string optName = cmdAttrs[start + KEY_ATTRS_OPT_NAME_POS_OFFSET];
        if (optName == "lock") {
            return DaqDB::PrimaryKeyAttribute::LOCKED;
        } else if (optName == "ready") {
            return DaqDB::PrimaryKeyAttribute::READY;
        } else if (optName == "long_term") {
            return DaqDB::PrimaryKeyAttribute::LONG_TERM;
        }
    }
    return DaqDB::PrimaryKeyAttribute::EMPTY;
}

DaqDB::PrimaryKeyAttribute
nodeCli::_getKeyAttrs(unsigned char start,
                      const std::vector<std::string> &cmdAttrs) {
    if (cmdAttrs.size() < start + NUM_ELEM_KEY_ATTRS) {
        return DaqDB::PrimaryKeyAttribute::EMPTY;
    }
    if ((cmdAttrs.size() - start) % NUM_ELEM_KEY_ATTRS != 0) {
        cout << "Warning: cannot parse key attributes" << endl;
        return DaqDB::PrimaryKeyAttribute::EMPTY;
    }

    unsigned char parsingPositon = start;
    DaqDB::PrimaryKeyAttribute result = DaqDB::PrimaryKeyAttribute::EMPTY;
    while (parsingPositon <= cmdAttrs.size()) {
        result = result | _getKeyAttr(parsingPositon, cmdAttrs);
        parsingPositon += NUM_ELEM_KEY_ATTRS;
    }

    return result;
}

void nodeCli::_cmdPut(const std::string &strLine) {
    vector<string> arguments;
    split(arguments, strLine, is_any_of("\t "), boost::token_compress_on);

    if (arguments.size() < 3) {
        cout << "Error: expects at least two arguments" << endl;
    } else {
        auto key = arguments[1];
        if (_isInvalidKey(key)) {
            cout << "Error: wrong key size" << endl;
            return;
        }

        DaqDB::Key keyBuff;
        try {
            keyBuff = _strToKey(key);
        } catch (...) {
            cout << "Error: cannot allocate key buffer" << endl;
            return;
        }
        DaqDB::Value valBuff;
        try {
            valBuff = _allocValue(keyBuff, arguments[PUT_CMD_VAL_OFFSET]);
        } catch (...) {
            cout << "Error: cannot allocate value buffer" << endl;
            _spKVStore->Free(std::move(keyBuff));
            return;
        }

        auto keyAttrs = _getKeyAttrs(PUT_CMD_KEY_ATTRS_OFFSET, arguments);
        DaqDB::PutOptions options(keyAttrs);

        try {
            _spKVStore->Put(std::move(keyBuff), std::move(valBuff),
                            std::move(options));
            cout << format("Put: [%1%] = %2% (Opts:%3%)\n") % key %
                        arguments[PUT_CMD_VAL_OFFSET] % options.attr;
        } catch (DaqDB::OperationFailedException &e) {
            cout << "Error: cannot put element: " << e.status().to_string()
                 << endl;

            // @TODO jschmieg: free value
            //_spKVStore->Free(std::move(valBuff));
        }
    }
}

DaqDB::Value nodeCli::_strToValue(const std::string &valStr) {
    Value result;
    if (!starts_with(valStr, "-o")) {
        auto buffer = new char[valStr.size() + 1];
        result = Value(buffer, valStr.size() + 1);
        std::memcpy(result.data(), valStr.c_str(), valStr.size());
        result.data()[result.size() - 1] = '\0';
    }
    return result;
}

DaqDB::Value nodeCli::_allocValue(const DaqDB::Key &key,
                                  const std::string &valStr) {
    DaqDB::Value result = _spKVStore->Alloc(key, valStr.size() + 1);
    std::memcpy(result.data(), valStr.c_str(), valStr.size());
    result.data()[result.size() - 1] = '\0';
    return result;
}

void nodeCli::_cmdUpdate(const std::string &strLine) {
    vector<string> arguments;
    split(arguments, strLine, is_any_of("\t "), boost::token_compress_on);

    if (arguments.size() < 2) {
        cout << "Error: expects at least one argument" << endl;
    } else {
        auto key = arguments[1];
        if (_isInvalidKey(key)) {
            cout << "Error: wrong key size" << endl;
            return;
        }
        DaqDB::Key keyBuff;
        try {
            keyBuff = _strToKey(key);
        } catch (...) {
            cout << "Error: cannot allocate key buffer" << endl;
            return;
        }

        DaqDB::Value valBuff;
        unsigned short optionStartPos = UPDATE_CMD_KEY_ATTRS_OFFSET;
        if ((arguments.size() > UPDATE_CMD_VAL_OFFSET) &&
            (!starts_with(arguments[UPDATE_CMD_VAL_OFFSET], "-o"))) {
            valBuff = _strToValue(arguments[UPDATE_CMD_VAL_OFFSET]);
        } else {
            optionStartPos = UPDATE_CMD_VAL_OFFSET;
        }

        auto keyAttrs = _getKeyAttrs(optionStartPos, arguments);
        DaqDB::UpdateOptions options(keyAttrs);

        try {
            if (valBuff.size() > 0) {
                _spKVStore->Update(std::move(keyBuff), std::move(valBuff),
                                   std::move(options));
            } else {
                _spKVStore->Update(std::move(keyBuff), std::move(options));
            }
        } catch (DaqDB::OperationFailedException &e) {
            cout << "Error: cannot update element: " << e.status().to_string()
                 << endl;
        }
    }
}

void nodeCli::_cmdUpdateAsync(const std::string &strLine) {
    vector<string> arguments;
    split(arguments, strLine, is_any_of("\t "), boost::token_compress_on);

    if (arguments.size() < 2) {
        cout << "Error: expects at least one argument" << endl;
    } else {
        auto key = arguments[1];
        if (_isInvalidKey(key)) {
            cout << "Error: wrong key size" << endl;
            return;
        }
        DaqDB::Key keyBuff;
        try {
            keyBuff = _strToKey(key);
        } catch (...) {
            cout << "Error: cannot allocate key buffer" << endl;
            return;
        }

        DaqDB::Value valBuff;
        unsigned short optionStartPos = UPDATE_CMD_KEY_ATTRS_OFFSET;
        if ((arguments.size() > UPDATE_CMD_VAL_OFFSET) &&
            (!starts_with(arguments[UPDATE_CMD_VAL_OFFSET], "-o"))) {
            valBuff = _strToValue(arguments[UPDATE_CMD_VAL_OFFSET]);
        } else {
            optionStartPos = UPDATE_CMD_VAL_OFFSET;
        }

        auto keyAttrs = _getKeyAttrs(optionStartPos, arguments);
        DaqDB::UpdateOptions options(keyAttrs);

        try {
            if (valBuff.size() > 0) {
                _spKVStore->UpdateAsync(
                    std::move(keyBuff), std::move(valBuff),
                    [&](DaqDB::KVStoreBase *kvs, DaqDB::Status status,
                        const char *key, const size_t keySize,
                        const char *value, const size_t valueSize) {
                        if (!status.ok()) {
                            _statusMsgs.push_back(boost::str(
                                boost::format(
                                    "Error: cannot update element: %1%") %
                                status.to_string()));
                        } else {
                            _statusMsgs.push_back(boost::str(
                                boost::format(
                                    "UPDATE[%1%]=%2% (Opts:%3%) : completed") %
                                key % value % options.attr));
                        }
                        if (keyBuff.size() > 0)
                            _spKVStore->Free(std::move(keyBuff));
                    },
                    std::move(options));
            } else {
                _spKVStore->UpdateAsync(
                    std::move(keyBuff), std::move(options),
                    [&](DaqDB::KVStoreBase *kvs, DaqDB::Status status,
                        const char *key, const size_t keySize,
                        const char *value, const size_t valueSize) {
                        if (!status.ok()) {
                            _statusMsgs.push_back(boost::str(
                                boost::format(
                                    "Error: cannot update element: %1%") %
                                status.to_string()));
                        } else {
                            _statusMsgs.push_back(boost::str(
                                boost::format("UPDATE[%1%] (Opts:%2%) "
                                              ": completed") %
                                key % options.attr));
                        }
                        if (keyBuff.size() > 0)
                            _spKVStore->Free(std::move(keyBuff));
                    });
            }
        } catch (DaqDB::OperationFailedException &e) {
            if (e.status()() == StatusCode::OFFLOAD_DISABLED_ERROR) {
                cout << format("Error: Disk offload is disabled\n") << endl;
            } else {
                cout << "Error: cannot update element: "
                     << e.status().to_string() << endl;
            }
        }
    }
}

void nodeCli::_cmdPutAsync(const std::string &strLine) {
    vector<string> arguments;
    split(arguments, strLine, is_any_of("\t "), boost::token_compress_on);

    if (arguments.size() < 3) {
        cout << "Error: expects at least two arguments" << endl;
    } else {
        auto key = arguments[1];
        if (_isInvalidKey(key)) {
            cout << "Error: wrong key size" << endl;
            return;
        }

        DaqDB::Key keyBuff;
        try {
            keyBuff = _strToKey(key);
        } catch (...) {
            cout << "Error: cannot allocate key buffer" << endl;
            return;
        }

        DaqDB::Value valBuff;
        try {
            valBuff = _allocValue(keyBuff, arguments[PUT_CMD_VAL_OFFSET]);
        } catch (...) {
            cout << "Error: cannot allocate value buffer" << endl;
            _spKVStore->Free(std::move(keyBuff));
            return;
        }

        auto keyAttrs = _getKeyAttrs(PUT_CMD_KEY_ATTRS_OFFSET, arguments);
        DaqDB::PutOptions options(keyAttrs);

        try {
            _spKVStore->PutAsync(
                std::move(keyBuff), std::move(valBuff),
                [&](DaqDB::KVStoreBase *kvs, DaqDB::Status status,
                    const char *key, const size_t keySize, const char *value,
                    const size_t valueSize) {
                    if (!status.ok()) {
                        _statusMsgs.push_back(boost::str(
                            boost::format("Error: cannot put element: %1%") %
                            status.to_string()));
                    } else {
                        _statusMsgs.push_back(boost::str(
                            boost::format(
                                "PUT[%1%]=%2% (Opts:%3%) : completed") %
                            key % value % options.attr));
                    }
                    if (keyBuff.size() > 0)
                        _spKVStore->Free(std::move(keyBuff));
                },
                std::move(options));
        } catch (DaqDB::OperationFailedException &e) {
            cout << "Error: cannot put element: " << e.status().to_string()
                 << endl;

            // @TODO jschmieg: free value
            // _spKVStore->Free(std::move(valBuff));
        }
    }
}

void nodeCli::_cmdRemove(const std::string &strLine) {
    vector<string> arguments;
    split(arguments, strLine, is_any_of("\t "), boost::token_compress_on);

    if (arguments.size() != 2) {
        cout << "Error: expects one argument" << endl;
    } else {

        auto key = arguments[1];
        if (_isInvalidKey(key)) {
            cout << "Error: wrong key size" << endl;
            return;
        }

        DaqDB::Key keyBuff;
        try {
            keyBuff = _strToKey(key);
        } catch (...) {
            cout << "Error: cannot allocate key buffer" << endl;
            return;
        }

        try {
            _spKVStore->Remove(keyBuff);
            cout << format("Remove: [%1%]\n") % key;
        } catch (DaqDB::OperationFailedException &e) {
            if (e.status()() == DaqDB::KEY_NOT_FOUND) {
                cout << format("[%1%] not found\n") % key;
            } else {
                cout << "Error: cannot remove element" << endl;
            }
        }
    }
}

void nodeCli::_cmdStatus() {
    chrono::time_point<chrono::system_clock> timestamp;
    auto currentTime = chrono::system_clock::to_time_t(timestamp);
    cout << format("DHT ID = %1%\nDHT ip:port = localhost:%2%\n") %
                _spKVStore->getProperty("daqdb.dht.id") %
                _spKVStore->getProperty("daqdb.dht.port")
         << flush;
    cout << format("%1%") % _spKVStore->getProperty("daqdb.dht.status")
         << flush;
    if (_statusMsgs.size() > 0) {
        cout << endl << "Async operations:" << endl;
        for (std::string message : _statusMsgs) {
            cout << "\t- " << message << endl;
        }
        _statusMsgs.clear();
    }
}

void nodeCli::_cmdNeighbors() {
    cout << format("Neighbors:\n%1%") %
                _spKVStore->getProperty("daqdb.dht.neighbours")
         << endl;
}

} // namespace DaqDB

max_stars_repo_name: gjerecze/daqdb

max_issues_repo_name: gjerecze/daqdb

max_forks_repo_name: gjerecze/daqdb


text:
#ifndef MANIFOLDS_FUNCTIONS_SIMPLIFY_HH
#define MANIFOLDS_FUNCTIONS_SIMPLIFY_HH

#include "streaming.hh"
#include <boost/type_traits/is_same.hpp>
#include <iostream>
#include <unordered_map>
#include <typeinfo>
#include <boost/any.hpp>
#include <boost/filesystem/convenience.hpp>
#include <tuple>

namespace manifolds {

static const int num_simplification_levels = 5;

#ifdef PRINT_SIMPLIFIES
template <class Tuple> class OutputHolder {
  Tuple t;

public:
  OutputHolder(const Tuple &t) : t(t) {}
  template <class C>
  auto operator<<(C c) -> OutputHolder<decltype(push_back(t, c))> {
    return { push_back(t, c) };
  }
  void Flush() const {
    std::cout << std::get<0>(t);
    OutputHolder<decltype(remove_element<0>(t))>(remove_element<0>(t)).Flush();
  }
};
template <> class OutputHolder<std::tuple<> > {
public:
  OutputHolder(std::tuple<>) {}
  template <class C> auto operator<<(C c) {
    return OutputHolder<std::tuple<C> >(std::make_tuple(c));
  }
  void Flush() const {}
};

#define SIMPLIFY_INFO(msg)                                                     \
  (OutputHolder<std::tuple<> >(std::tuple<>())                                 \
   << boost::filesystem::basename(__FILE__) << ":" << __LINE__ << " "          \
   << msg).Flush()
#else
#define SIMPLIFY_INFO(msg)
#endif

template <class A, int level, class ForEnableIf = void> struct Simplification {
  typedef A type;
  static type Combine(A a) {
    SIMPLIFY_INFO("No simplification found\n");
    return a;
  }
};

template <class> struct SimplificationLevel;

template <class A, int level, class B>
struct SimplificationLevel<Simplification<A, level, B> > : int_<level> {};

template <int iter> struct SimplificationWrapper {
  template <class F, int level> static auto Simplify(F f, F, int_<level>) {
    SIMPLIFY_INFO("Done level " << level << ", "
                                << "moving to level " << level + 1 << '\n');
    return SimplificationWrapper<iter + 1>::Simplify(f, int_<level + 1>());
  }

  template <class F, class G, int level>
  static auto Simplify(F f, G, int_<level>) {
    SIMPLIFY_INFO("Got " << f << ", starting back at level 0\n");
    return SimplificationWrapper<iter + 1>::Simplify(f, int_<0>());
  }

  template <class F, int level> static auto Simplify(F f, int_<level>) {
    return Simplify(Simplification<F, level>::Combine(f), f, int_<level>());
  }

  template <class F>
  static auto Simplify(F f, int_<num_simplification_levels>) {
    SIMPLIFY_INFO("Done: " << f << "\n\n");
    return f;
  }
};

template <class T>
using SimplifiedType =
    decltype(SimplificationWrapper<0>::Simplify(std::declval<T>(), int_<0>()));

template <class F> auto Simplify(F f, std::false_type) {
  return SimplificationWrapper<0>::Simplify(f, int_<0>());
}

template <class F> auto Simplify(F f, std::true_type) {
  static auto hasher = [](const auto &a) {
    return std::hash<const char *>()(a.type().name());
  };
  static auto equaler = [](const auto &a,
                           const auto &b) { return a.type() == b.type(); };
  static std::unordered_map<boost::any, boost::any, decltype(hasher),
                            decltype(equaler)> already_done(30, hasher,
                                                            equaler);
  auto i = already_done.find(f);
  if (i == already_done.end()) {
    auto r = Simplify(f, std::false_type());
    already_done[f] = r;
    return r;
  }
  typedef SimplifiedType<F> RType;
  SIMPLIFY_INFO("Already done, skipping to result "
                << boost::any_cast<RType>(i->second) << '\n');
  return boost::any_cast<RType>(i->second);
}

template <class F> auto Simplify(F f) {
  SIMPLIFY_INFO("Simplifying: " << f << "\n");
#ifdef PRINT_SIMPLIFIES
  return Simplify(f, bool_<F::stateless>());
#else
  return SimplificationWrapper<0>::Simplify(f, int_<0>());
#endif
}

template <class T>
using Simplifies = bool_<!std::is_same<SimplifiedType<T>, T>::value>;
}

#endif

ext: hh

max_stars_repo_name: GuylainGreer/manifolds

max_issues_repo_name: GuylainGreer/manifolds

max_forks_repo_name: GuylainGreer/manifolds


text:
/**
 * Copyright (c) 2020 libnuls developers (see AUTHORS)
 *
 * This file is part of libnuls.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
#include <boost/test/test_tools.hpp>
#include <boost/test/unit_test_suite.hpp>

#include <nuls/system.hpp>

using namespace nuls::system;

BOOST_AUTO_TEST_SUITE(property_tree_tests)

BOOST_AUTO_TEST_CASE(property_tree__property_tree__value__expected_json)
{
    const std::string json
    {
        "{\"sequence\":\"101\",\"command\":\"query fetch-tx\",\"arguments\":\"4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b\"}"
    };
    boost::property_tree::ptree tree;
    const auto result = property_tree(tree, json);
    BOOST_REQUIRE_EQUAL(result, true);
    BOOST_REQUIRE_EQUAL(tree.get<uint32_t>("sequence"), 101u);
    BOOST_REQUIRE_EQUAL(tree.get<std::string>("command"), std::string("query fetch-tx"));
    BOOST_REQUIRE_EQUAL(tree.get<std::string>("arguments"), std::string("4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b"));
}

BOOST_AUTO_TEST_CASE(property_tree__property_tree__value__expected_empty)
{
    const std::string invalid_json
    {
        "{\"sequence\":\"101\" \"arguments\";\"test\"}"
    };
    boost::property_tree::ptree tree;
    const auto result = property_tree(tree, invalid_json);
    BOOST_REQUIRE_EQUAL(result, false);
}

BOOST_AUTO_TEST_SUITE_END()

ext: cpp

max_issues_repo_name: CCC-NULS/nuls-cplusplus-sdk

max_forks_repo_name: CCC-NULS/nuls-cplusplus-sdk


text:
// All content Copyright (C) 2018 Genomics plc
#include <iostream>
#include <fstream>
#include <boost/algorithm/string/predicate.hpp>
#include <boost/regex.hpp>
#include <utils/exceptions.hpp>
#include <boost/algorithm/string.hpp>
#include <boost/filesystem/operations.hpp>
#include <variant/type/variant.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/filesystem/operations.hpp>
#include <boost/iostreams/filtering_streambuf.hpp>
#include <boost/iostreams/copy.hpp>
#include <boost/iostreams/filter/gzip.hpp>

#include "io/tabixVCFFile.hpp"
#include "vcf/reader.hpp"
#include "vcf/filterDescription.hpp"

namespace wecall
{
namespace io
{

    TabixVCFFile::TabixVCFFile( std::string filename, std::string indexFilename )
        : m_tabixFile( filename, indexFilename )
    {
        this->readHeader( filename );
    }

    TabixVCFFile::~TabixVCFFile() {}

    void TabixVCFFile::readHeader( std::string filename )
    {
        WECALL_LOG( DEBUG, "Reading vcf file header" );

        const auto headerLines = m_tabixFile.header();

        if ( headerLines.empty() )
        {
            throw utils::wecall_exception( "Malformed VCF: missing header." );
        }
        else if ( not boost::starts_with( headerLines.back(), "#CHROM" ) )
        {
            throw utils::wecall_exception( "Malformed VCF: did not find #CHROM at start of final header line." );
        }

        for ( const auto & line : headerLines )
        {
            if ( boost::starts_with( line, "##FILTER" ) )
            {
                WECALL_LOG( DEBUG, "Found filter " << line );
                auto filterDesc = parseFilterHeaderLine( line );
                if ( containsFilterId( m_filterDescs, filterDesc.id ) )
                {
                    throw utils::wecall_exception( "The header contains repeated filter " + filterDesc.id + "." );
                }
                m_filterDescs.insert( filterDesc );
            }
            else if ( boost::starts_with( line, "##INFO" ) )
            {
                WECALL_LOG( DEBUG, "VCF 'INFO' fields are not yet parsed. Skipping: " << line );
            }
            else if ( boost::starts_with( line, "##FORMAT" ) )
            {
                WECALL_LOG( DEBUG, "VCF 'FORMAT' fields are not yet parsed. Skipping: " << line );
            }
            else if ( boost::starts_with( line, "##" ) )
            {
                auto metadata = parseMetaInfoLine( line );
                m_metaInformation.insert( metadata );
            }
            else if ( boost::starts_with( line, "#CHROM" ) )
            {
                // actual data on subsequent lines, the header has been parsed,
                // any additional header lines should be ignored as if they are comments.
                break;
            }
        }
    }

    std::vector< vcf::Record > TabixVCFFile::fetch( const caller::Region & region ) const
    {
        std::vector< vcf::Record > records;
        for ( const auto & line : m_tabixFile.fetch( region ) )
        {
            std::vector< std::string > cols;
            std::vector< std::string > alts;
            std::set< std::string > filterIds;

            boost::split( cols, line, boost::is_any_of( "\t" ) );

            if ( cols.size() < 8 )
            {
                throw utils::wecall_exception( "Record line should have at least 7 columns: " + line );
            }

            const std::string chrom = cols.at( 0 );
            const std::size_t one_based_pos = boost::lexical_cast< size_t >( cols.at( 1 ) );
            const auto stringIDs = cols.at( 2 );
            const std::string ref = cols.at( 3 );
            boost::split( alts, cols.at( 4 ), boost::is_any_of( "," ) );
            const double qual =
                cols.at( 5 ) == constants::vcfUnknownValue ? -1 : boost::lexical_cast< double >( cols.at( 5 ) );

            boost::split( filterIds, cols.at( 6 ), boost::is_any_of( ";" ) );

            const vcf::Info info = vcf::parseVCFInfo( cols.at( 7 ) );

            std::set< std::string > ids;
            if ( stringIDs != constants::vcfUnknownValue )
            {
                boost::split( ids, stringIDs, boost::is_any_of( ";" ) );
            }

            for ( const auto & filterId : filterIds )
            {
                if ( not containsFilterId( m_filterDescs, filterId ) and filterId != "PASS" )
                {
                    WECALL_LOG( DEBUG, "Filter ID \"" + filterId + "\" was not supplied in the header." );
                }
            }

            vcf::SampleInfo emptySampleInfo;

            records.emplace_back( chrom, one_based_pos, ids, ref, alts, qual, filterIds, info, emptySampleInfo );
        }

        return records;
    }

    bool TabixVCFFile::containsFilterId( const std::set< vcf::FilterDesc > & filterDescs, const std::string & filterId )
    {
        // Try searching the set see if any filterDescs object contain the id
        auto it = std::find_if( filterDescs.begin(), filterDescs.end(), [&filterId]( const vcf::FilterDesc & desc )
                                {
                                    return desc.id == filterId;
                                } );
        return it != filterDescs.end();
    }

    std::pair< std::string, std::string > TabixVCFFile::parseMetaInfoLine( const std::string line )
    {
        boost::regex re( "^##(.+)=(.+)$" );
        boost::cmatch matches;
        if ( boost::regex_match( line.c_str(), matches, re ) )
        {
            const std::string key( matches[1].first, matches[1].second );
            const std::string value( matches[2].first, matches[2].second );
            return std::make_pair( key, value );
        }
        else
        {
            throw utils::wecall_exception( "Failed to match meta information header line: " + line );
        }
    }

    vcf::FilterDesc TabixVCFFile::parseFilterHeaderLine( const std::string & line )
    {
        boost::regex re( "^##FILTER=<ID=([^,]+),\\s*Description=\\\"(.*)\\\">\\s*$" );
        boost::cmatch matches;

        if ( boost::regex_match( line.c_str(), matches, re ) )
        {
            const std::string id( matches[1].first, matches[1].second );
            const std::string desc( matches[2].first, matches[2].second );
            return vcf::FilterDesc( id, desc );
        }
        else
        {
            throw utils::wecall_exception( "Failed to match filter header line: " + line );
        }
    }
}
}

max_stars_repo_name: dylex/wecall

max_issues_repo_name: dylex/wecall

max_forks_repo_name: dylex/wecall


text:
#include "OcTreeMapper.hpp"

#include <boost/format.hpp>
#include <boost/thread.hpp>

#include <pcl/common/transforms.h>

using namespace slam3d;

octomap::OcTree* initOcTree(const OctoMapConfiguration &conf)
{
	octomap::OcTree* tree = new octomap::OcTree(conf.resolution);
	tree->setOccupancyThres(conf.occupancyThres);
	tree->setProbHit(conf.probHit);
	tree->setProbMiss(conf.probMiss);
	tree->setClampingThresMin(conf.clampingThresMin);
	tree->setClampingThresMax(conf.clampingThresMax);
	return tree;
}

OcTreeMapper::OcTreeMapper(std::string const& name)
    : OcTreeMapperBase(name)
{
}

OcTreeMapper::OcTreeMapper(std::string const& name, RTT::ExecutionEngine* engine)
    : OcTreeMapperBase(name, engine)
{
}

OcTreeMapper::~OcTreeMapper()
{
}

void OcTreeMapper::addScanToMap(PointCloudMeasurement::Ptr scan, const Transform& pose)
{
	PointCloud::Ptr tempCloud(new PointCloud);
	Transform sensor = pose * scan->getSensorPose();
	pcl::transformPointCloud(*(scan->getPointCloud()), *tempCloud, sensor.matrix());

	octomap::Pointcloud octoCloud;
	for(PointCloud::iterator it = tempCloud->begin(); it < tempCloud->end(); ++it)
	{
		octoCloud.push_back(octomap::point3d(it->x, it->y,it->z));
	}
	Eigen::Vector3d origin = sensor.translation();
	mOcTree->insertPointCloud(octoCloud, octomap::point3d(origin(0), origin(1), origin(2)), mOctreeConf.rangeMax, true, true);
}

void OcTreeMapper::clearMap()
{
	// Reset OctoMap (OcTree::clear is currently not working)
	delete mOcTree;
	mOcTree = initOcTree(mOctreeConf);
}

void OcTreeMapper::buildMLS()
{
	mLogger->message(WARNING, "Generating MLS from OcTree is not implemented.");
/*
	mLogger->message(DEBUG, "Generating MLS from OcTree.");
	mMultiLayerMap->clear();
	for(octomap::OcTree::leaf_iterator leaf = mOcTree->begin_leafs() ; leaf != mOcTree->end_leafs(); ++leaf)
	{
		if(!mOcTree->isNodeOccupied(*leaf))
		{
			continue;
		}
		double half_size = leaf.getSize() / 2.0;
		double half_res = mGridConf.resolution / 2.0;
		double x_min = leaf.getX() - half_size + half_res;
		double y_min = leaf.getY() - half_size + half_res;
		double x_max = leaf.getX() + half_size;
		double y_max = leaf.getY() + half_size;

		for(double y = y_min; y < y_max; y += mGridConf.resolution)
		{
			for(double x = x_min; x < x_max; x += mGridConf.resolution)
			{
				double z_low  = std::max(mGridConf.min_z, leaf.getZ() - half_size);
				double z_high = std::min(mGridConf.max_z, leaf.getZ() + half_size);
				if(z_high > z_low)
				{
					envire::SurfacePatch patch(z_high, 0, z_high - z_low, envire::SurfacePatch::VERTICAL);
					mMultiLayerMap->update(Eigen::Vector2d(x, y) , patch);
				}
			}
		}
	}
*/
}

void OcTreeMapper::sendMap()
{
	// Build and publish the MLS-Map
	mOcTree->updateInnerOccupancy();
	mOcTree->writeBinaryConst("slam3d_octomap.bt");
	buildMLS();
	mMultiLayerMap.setTime(mCurrentTime);
	_mls.write(mMultiLayerMap.asSpatioTemporal());
}

bool OcTreeMapper::remove_dynamic_objects()
{
	mLogger->message(INFO, "Requested dynamic object removal.");
	timeval start = mClock->now();
	VertexObjectList vertices = mGraph->getVerticesFromSensor(mPclSensor->getName());
	unsigned deleted = 0;

	boost::unique_lock<boost::shared_mutex> guard(mGraphMutex);
	for(VertexObjectList::iterator v = vertices.begin(); v != vertices.end(); ++v)
	{
		// Cast to PointCloudMeasurement
		PointCloudMeasurement::Ptr m = boost::dynamic_pointer_cast<PointCloudMeasurement>(v->measurement);
		if(!m)
		{
			mLogger->message(WARNING, "Vertex given to remove_dynamic_objects is not a Pointcloud!");
			continue;
		}

		// Check each point, if it is in free OctoMap voxel
		PointCloud::Ptr cloud = m->getPointCloud();
		for(PointCloud::iterator p = cloud->begin(); p != cloud->end();)
		{
			base::Vector3d p_tf;
			p_tf[0] = p->x;
			p_tf[1] = p->y;
			p_tf[2] = p->z;
			p_tf = v->corrected_pose * m->getSensorPose() * p_tf;
			octomap::OcTreeNode* node = mOcTree->search(p_tf[0], p_tf[1], p_tf[2]);
			if(node && !mOcTree->isNodeOccupied(node))
			{
				deleted++;
				p = cloud->erase(p);
			}else
			{
				p++;
			}
		}
	}
	int duration = mClock->now().tv_sec - start.tv_sec;
	mLogger->message(INFO, (boost::format("Removed %1% dynamic points in %2% seconds.") % deleted % duration).str());
	return true;
}

bool OcTreeMapper::configureHook()
{
	if (! OcTreeMapperBase::configureHook())
		return false;

	mOctreeConf  = _octo_map_config.get();
	mOcTree = initOcTree(mOctreeConf);

	mLogger->message(INFO, " = OctoMap - Parameters =");
	mLogger->message(INFO, (boost::format("resolution:       %1%") % mOctreeConf.resolution).str());
	mLogger->message(INFO, (boost::format("occupancyThres:   %1%") % mOctreeConf.occupancyThres).str());
	mLogger->message(INFO, (boost::format("probHit:          %1%") % mOctreeConf.probHit).str());
	mLogger->message(INFO, (boost::format("probMiss:         %1%") % mOctreeConf.probMiss).str());
	mLogger->message(INFO, (boost::format("clampingThresMin: %1%") % mOctreeConf.clampingThresMin).str());
	mLogger->message(INFO, (boost::format("clampingThresMax: %1%") % mOctreeConf.clampingThresMax).str());
	mLogger->message(INFO, (boost::format("rangeMax:         %1%") % mOctreeConf.rangeMax).str());

	return true;
}

bool OcTreeMapper::startHook()
{
	if (! OcTreeMapperBase::startHook())
		return false;
	return true;
}

void OcTreeMapper::updateHook()
{
	OcTreeMapperBase::updateHook();
}

void OcTreeMapper::errorHook()
{
	OcTreeMapperBase::errorHook();
}

void OcTreeMapper::stopHook()
{
	OcTreeMapperBase::stopHook();
}

void OcTreeMapper::cleanupHook()
{
	OcTreeMapperBase::cleanupHook();
	delete mOcTree;
}


text:
//
// Copyright RIME Developers
// Distributed under the BSD License
//
// 2012-02-18 GONG Chen <chen.sst@gmail.com>
//
#include <utility>
#include <boost/algorithm/string.hpp>
#include <boost/filesystem.hpp>
#include <rime/config.h>
#include <rime/deployer.h>
#include <rime/lever/switcher_settings.h>

namespace fs = boost::filesystem;

namespace rime {

SwitcherSettings::SwitcherSettings(Deployer* deployer)
    : CustomSettings(deployer, "default", "Rime::SwitcherSettings") {
}

bool SwitcherSettings::Load() {
  if (!CustomSettings::Load())
    return false;
  available_.clear();
  selection_.clear();
  hotkeys_.clear();
  GetAvailableSchemasFromDirectory(deployer_->shared_data_dir);
  GetAvailableSchemasFromDirectory(deployer_->user_data_dir);
  GetSelectedSchemasFromConfig();
  GetHotkeysFromConfig();
  return true;
}

bool SwitcherSettings::Select(Selection selection) {
  selection_ = std::move(selection);
  auto schema_list = New<ConfigList>();
  for (const string& schema_id : selection_) {
    auto item = New<ConfigMap>();
    item->Set("schema", New<ConfigValue>(schema_id));
    schema_list->Append(item);
  }
  return Customize("schema_list", schema_list);
}

bool SwitcherSettings::SetHotkeys(const string& hotkeys) {
  // TODO: not implemented; validation required
  return false;
}

void SwitcherSettings::GetAvailableSchemasFromDirectory(const fs::path& dir) {
  if (!fs::exists(dir) || !fs::is_directory(dir)) {
    LOG(INFO) << "directory '" << dir.string() << "' does not exist.";
    return;
  }
  for (fs::directory_iterator it(dir), end;
       it != end; ++it) {
    string file_path(it->path().string());
    if (boost::ends_with(file_path, ".schema.yaml")) {
      Config config;
      if (config.LoadFromFile(file_path)) {
        SchemaInfo info;
        // required properties
        if (!config.GetString("schema/schema_id", &info.schema_id))
          continue;
        if (!config.GetString("schema/name", &info.name))
          continue;
		if (!config.GetBool("schema/hide_in_ui", &info.hide_in_ui))
			LOG(INFO) << "no hide_in_ui property found";

        // check for duplicates
        bool duplicated = false;
        for (const SchemaInfo& other : available_) {
          if (other.schema_id == info.schema_id) {
            duplicated = true;
            break;
          }
        }
        if (duplicated)
          continue;
        // details
        config.GetString("schema/version", &info.version);
        if (auto authors = config.GetList("schema/author")) {
          for (size_t i = 0; i < authors->size(); ++i) {
            auto author = authors->GetValueAt(i);
            if (author && !author->str().empty()) {
              if (!info.author.empty())
                info.author += "\n";
              info.author += author->str();
            }
          }
        }
        config.GetString("schema/description", &info.description);
        info.file_path = file_path;
        available_.push_back(info);
      }
    }
  }
}

void SwitcherSettings::GetSelectedSchemasFromConfig() {
  auto schema_list = config_.GetList("schema_list");
  if (!schema_list) {
    LOG(WARNING) << "schema list not defined.";
    return;
  }
  for (auto it = schema_list->begin(); it != schema_list->end(); ++it) {
    auto item = As<ConfigMap>(*it);
    if (!item)
      continue;
    auto schema_property = item->GetValue("schema");
    if (!schema_property)
      continue;
    const string& schema_id(schema_property->str());
    selection_.push_back(schema_id);
  }
}

void SwitcherSettings::GetHotkeysFromConfig() {
  auto hotkeys = config_.GetList("switcher/hotkeys");
  if (!hotkeys) {
    LOG(WARNING) << "hotkeys not defined.";
    return;
  }
  for (auto it = hotkeys->begin(); it != hotkeys->end(); ++it) {
    auto item = As<ConfigValue>(*it);
    if (!item)
      continue;
    const string& hotkey(item->str());
    if (hotkey.empty())
      continue;
    if (!hotkeys_.empty())
      hotkeys_ += ", ";
    hotkeys_ += hotkey;
  }
}

}  // namespace rime

ext: cc

max_stars_repo_name: kanskinson/librime

max_issues_repo_name: kanskinson/librime

max_forks_repo_name: kanskinson/librime


text:
/*=============================================================================
    Copyright (c) 2001-2007 Joel de Guzman
    Copyright (c) 2001-2008 Hartmut Kaiser

    Distributed under the Boost Software License, Version 1.0. (See accompanying
    file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
=============================================================================*/
#if !defined(SPIRIT_ALTERNATIVE_FEB_05_2007_1153AM)
#define SPIRIT_ALTERNATIVE_FEB_05_2007_1153AM

#include <boost/spirit/home/qi/detail/alternative_function.hpp>
#include <boost/spirit/home/support/attribute_transform.hpp>
#include <boost/spirit/home/support/detail/what_function.hpp>
#include <boost/spirit/home/support/unused.hpp>
#include <boost/spirit/home/support/as_variant.hpp>
#include <boost/fusion/include/any.hpp>
#include <boost/fusion/include/vector.hpp>
#include <boost/fusion/include/mpl.hpp>
#include <boost/fusion/include/for_each.hpp>
#include <boost/fusion/include/push_front.hpp>
#include <boost/variant.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/mpl/end.hpp>
#include <boost/mpl/find_if.hpp>
#include <boost/mpl/eval_if.hpp>
#include <boost/mpl/identity.hpp>

namespace boost { namespace spirit { namespace qi
{
    struct alternative
    {
        template <typename T>
        struct transform_child : mpl::identity<T> {};

        template <typename All, typename Filtered>
        struct build_container
        {
            // if the original attribute list does not contain any unused
            // attributes it is used, otherwise a single unused_type is
            // pushed to the front the list. This is to make sure that if
            // there is an unused in the list it is the first one.
            typedef typename
                mpl::find_if<All, is_same<mpl::_, unused_type> >::type
            unused_;

            typedef typename
                mpl::eval_if<
                    is_same<unused_, typename mpl::end<All>::type>,
                    mpl::identity<All>,
                    fusion::result_of::push_front<Filtered, unused_type>
                >::type
            attribute_sequence;

            // Ok, now make a variant over the attribute_sequence. It's
            // a pity that make_variant_over does not support forward MPL
            // sequences. We use our own conversion metaprogram (as_variant).
            typedef typename
                as_variant<attribute_sequence>::type
            type;
        };

        template <typename Component, typename Context, typename Iterator>
        struct attribute :
            build_fusion_sequence<alternative, Component, Iterator, Context>
        {
        };

        template <
            typename Component
          , typename Iterator, typename Context
          , typename Skipper, typename Attribute>
        static bool parse(
            Component const& component
          , Iterator& first, Iterator const& last
          , Context& context, Skipper const& skipper
          , Attribute& attr)
        {
            detail::alternative_function<Iterator, Context, Skipper, Attribute>
                f(first, last, context, skipper, attr);

            // return true if *any* of the parsers succeed
            return fusion::any(component.elements, f);
        }

        template <typename Component, typename Context>
        static std::string what(Component const& component, Context const& ctx)
        {
            std::string result = "alternatives[";
            fusion::for_each(component.elements,
                spirit::detail::what_function<Context>(result, ctx));
            result += "]";
            return result;
        }
    };
}}}

#endif

ext: hpp

max_stars_repo_name: jaredhoberock/gotham

max_issues_repo_name: jaredhoberock/gotham

max_forks_repo_name: jaredhoberock/gotham


text:
/**
*          Copyright Springbeats Sarl 2013.
* Distributed under the Boost Software License, Version 1.0.
*    (See accompanying file ../LICENSE_1_0.txt or copy at
*          http://www.boost.org/LICENSE_1_0.txt)
*/
#include "BaseRpcChannel.hpp"
#include "RpcController.hpp"
#include "MethodCallIDGenerator.hpp"
#include "RpcMessage.hpp"
#include "Timer.hpp"
#include "Queue.hpp"
#include "ThreadSafeMap.hpp"
#include "Util.hpp"
#include <sstream>
#include <boost/bind.hpp>

using std::istringstream;

namespace pbrpcpp {

	BaseRpcChannel::BaseRpcChannel( )
		:timeoutMillis_( 0 ),
		timer_( new Timer<string>() ),
		responses_( new Queue<string>() ),
		waitingResponses_( new ThreadSafeMap< string, shared_ptr<ResponseParam> >() )
	{
		//create a thread to process all the responses
		responseProcThreads_.create_thread( boost::bind( &BaseRpcChannel::takeAndProcessResponse, this ));
	}

	BaseRpcChannel::~BaseRpcChannel() {
		responseProcThreads_.interrupt_all();
		responseProcThreads_.join_all();
	}

	void BaseRpcChannel::CallMethod(const MethodDescriptor* method,
		google::protobuf::RpcController* controller,
		const Message* request,
		Message* response,
		Closure* done) {
			//each call will allocate a unique callId for parallel processing reason
			string callId = MethodCallIDGenerator::generateID();

			if( controller ) {
				RpcController* pRpcController = dynamic_cast<RpcController*>( controller );
				if( pRpcController ) {
					pRpcController->setStartCancelCallback( boost::bind(&BaseRpcChannel::startCancel, this, callId ) );
				}
			}

			bool completed = false;
			shared_ptr<ResponseParam> respParam( new ResponseParam( controller, response, done, (done == 0)?(&completed):0 ) );

			(*waitingResponses_)[ callId ] = respParam ;

			//serialize the message
			ostringstream out;

			RpcMessage::serializeRequest( callId, *method, *request, out );

			//start a timer if timeout is enabled
			if( timeoutMillis_ > 0 ) {
				timer_->add( callId, timeoutMillis_, boost::bind( &BaseRpcChannel::handleRequestTimeout, this, callId ) );
			}

			//send the serialized message to server
			sendMessage( out.str(), boost::bind( &BaseRpcChannel::messageSent, this, _1, _2, callId ) );

			// if sync call, waiting for complete
			if( done == 0 ) {
				boost::unique_lock<boost::mutex> lock(mMutex);
 				while(!completed)
 				{
 					mCondVariable.wait(lock);
 				}

			}
	}

	void BaseRpcChannel::messageSent( bool success, const string& reason, string callId) {
		//if fail to send message to the server
		if( ! success ) {
			shared_ptr<ResponseParam> respParam = waitingResponses_->erase( callId );
			if( respParam ) {
				timer_->cancel( callId );
				RpcController* pController = dynamic_cast<RpcController*>( respParam->controller );
				if( pController ) {
					pController->SetFailed( reason );
				}

				if( respParam->completed ) {
					{
						boost::lock_guard<boost::mutex> lock(mMutex);
						*(respParam->completed) = true;
					}
					mCondVariable.notify_all();

				}

				if (respParam->done) {
					respParam->done->Run();
				}

				if( pController ) {
					pController->complete();
				}
			}
		}
	}

	void BaseRpcChannel::startCancel( string callId ) {

		//if the request is still on-going, send cancel request to server
		if( waitingResponses_->contains( callId ) ) {
			ostringstream out;

			RpcMessage::serializeCancel( callId, out );

			sendMessage( out.str(), boost::bind( &BaseRpcChannel::messageSent, this, _1, _2, callId )  );
		}
	}

	void BaseRpcChannel::responseReceived( const string& responseMsg ) {
		responses_->add( responseMsg );
	}

	void BaseRpcChannel::takeAndProcessResponse() {
		for( ; ; ) {
			try {
				string resp = responses_->take();

				if( !resp.empty() ) {
					processResponse( resp );
				}
			}catch( const boost::thread_interrupted& ex ) {
				//                GOOGLE_LOG( INFO ) << "thread interrupted";
				break;
			}catch( ... ) {

			}
		}
	}
	void BaseRpcChannel::processResponse( const string& responseMsg ) {
		try {
			istringstream in( responseMsg );
			int msgType = Util::readInt( in );

			switch( msgType ) {
			case RpcMessage::RESPONSE_MSG:
				{
					string callId;
					RpcController controller;
					shared_ptr<Message> response;
					//parse the response
					RpcMessage::parseResponseFrom( in, callId, controller, response );
					GOOGLE_LOG( INFO ) << "received a response message, callId:" << callId;
					//if the response is still not timeout
					shared_ptr<ResponseParam> respParam = waitingResponses_->erase( callId );
					if( respParam ) {
						timer_->cancel( callId );
						RpcController* pController = dynamic_cast<RpcController*>( respParam->controller );
						if( pController ) {
							copyController( *pController, controller );
						}
						if( respParam->response && response ) {
							copyMessage( *(respParam->response), *response );
						}

						if( respParam->completed ) {

							{
								boost::lock_guard<boost::mutex> lock(mMutex);
								*(respParam->completed) = true;
							}
							mCondVariable.notify_all();
						}

						if( respParam->done ) {
							respParam->done->Run();
						}

						if( pController ) {
							pController->complete();
						}

					}
				}
				break;
			}

		}catch( const std::exception& ex) {
			GOOGLE_LOG( ERROR ) << "catch exception:" << ex.what() ;
		} catch( ... ) {
			GOOGLE_LOG( ERROR ) << "catch unknown exception";
		}
	}

	void BaseRpcChannel::copyController( RpcController& dest, const RpcController& src ) {
		if( src.failed_ ) {
			dest.SetFailed ( src.ErrorText() );
		}
		dest.canceled_ = src.canceled_;
	}

	void BaseRpcChannel::copyMessage( Message& dest, const Message& src ) {
		if( dest.GetDescriptor() == src.GetDescriptor() ) {
			dest.CopyFrom( src );
		}
	}

	bool BaseRpcChannel::isCallCompleted( const string& callId )  {
		return !waitingResponses_->contains( callId );
	}

	void BaseRpcChannel::handleRequestTimeout( string callId ) {
		shared_ptr<ResponseParam> respParam = waitingResponses_->erase( callId );
		if( respParam ) {
			RpcController* pController = dynamic_cast<RpcController*> (respParam->controller);
			if (pController) {
				pController->SetFailed("request timeout");
			}

			if (respParam->completed) {
				{
					boost::lock_guard<boost::mutex> lock(mMutex);
					*(respParam->completed) = true;
				}
				mCondVariable.notify_all();
			}

			if (respParam->done) {
				respParam->done->Run();
			}

			if( pController ) {
				pController->complete();
			}
		}
	}

}//end name space pbrpcpp

max_stars_repo_name: adanselm/pbRPCpp

max_issues_repo_name: adanselm/pbRPCpp

max_forks_repo_name: adanselm/pbRPCpp


text:
/*
// Licensed to DynamoBI Corporation (DynamoBI) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  DynamoBI licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at

//   http://www.apache.org/licenses/LICENSE-2.0

// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.  See the License for the
// specific language governing permissions and limitations
// under the License.
*/

#include "fennel/common/CommonPreamble.h"
#include "fennel/common/ResourceBundle.h"

#include <algorithm>
#include <cstdlib>
#include <fstream>
#include <map>
#include <set>
#include <string>
#include <sstream>

#include <boost/lexical_cast.hpp>

FENNEL_BEGIN_CPPFILE("$Id$");

using namespace std;
using namespace boost;

static string globalResourceLocation("");

RecursiveMutex ResourceBundle::mutex;

RecursiveMutex &ResourceBundle::getMutex()
{
    return mutex;
}

void ResourceBundle::setGlobalResourceFileLocation(const string &location)
{
    globalResourceLocation = location;
}

ResourceBundle::ResourceBundle(
    const string &baseName,
    const Locale &locale,
    const string &location)
    : _baseName(baseName),
      _locale(locale),
      _location(location),
      _parent(NULL)
{
    loadMessages();
}

ResourceBundle::~ResourceBundle()
{
}

void ResourceBundle::setParent(ResourceBundle *bundle)
{
    _parent = bundle;
}

const set<string> ResourceBundle::getKeys() const
{
    set<string> keys;

    map<string, string>::const_iterator iter = _messages.begin(),
        end = _messages.end();

    while (iter != end) {
        keys.insert((*iter).first);
        iter++;
    }

    if (_parent) {
        set<string> parentKeys = _parent->getKeys();

        keys.insert(parentKeys.begin(), parentKeys.end());
    }

    return keys;
}

static string MISSING_KEY("[[unknown key]]");

const string &ResourceBundle::getMessage(const string &key) const
{
    map<string, string>::const_iterator iter;
    iter = _messages.find(key);
    if (iter == _messages.end()) {
        if (_parent) {
            return _parent->getMessage(key);
        }

        return MISSING_KEY;
    }

    return (*iter).second;
}

bool ResourceBundle::hasMessage(const string &key) const
{
    return
        _messages.find(key) != _messages.end()
        || (_parent && _parent->hasMessage(key));
}

const Locale &ResourceBundle::getLocale() const
{
    return _locale;
}

const string &ResourceBundle::getBaseName() const
{
    return _baseName;
}

static const char APOS = '\'';
static const char LEFT_BRACE = '{';
static const char RIGHT_BRACE = '}';
static const char COMMA = ',';

static string convertPropertyToBoost(string &message)
{
    stringstream ss;

    bool quoted = false;
    char ch;
    char nextCh;

    for (int i = 0, n = message.length(); i < n; i++) {
        ch = message[i];
        nextCh = (i + 1 < n) ? message[i + 1] : 0;

        if (ch == APOS) {
            if (nextCh != APOS) {
                // Bare apostrophes signal start/end of QuotedString in the BNF
                quoted = !quoted;
                continue;
            }

            // Quoted or not, the next character is an apostrophe, so we
            // output an apostrophe.
            ss << APOS;
            i++; // skip nextCh
            continue;
        }

        if (quoted || ch != LEFT_BRACE) {
            ss << ch;
            continue;
        }

        // Handle an argument
        string::size_type commaPos = message.find(COMMA, i);
        string::size_type bracketPos = message.find(RIGHT_BRACE, i);
        if (bracketPos == string::npos) {
            // Bad format -- give up
            return message;
        }

        int argEndIndex = (commaPos == string::npos
                           ? bracketPos
                           : min(commaPos, bracketPos));

        int argIndex = boost::lexical_cast<int>(
            message.substr(i + 1, argEndIndex - (i + 1)));

        // Boost args are 1-based
        ss << '%' << (argIndex + 1) << '%';

        // Find the end of the argument tag
        bool quotedPattern = false;
        int bracketDepth = 0;
        i = argEndIndex;

        bool done = false;
        while (!done && i < n) {
            ch = message[i];

            switch (ch) {
            default:
                i++;
                break;

            case APOS:
                quotedPattern = !quotedPattern;
                i++;
                break;

            case LEFT_BRACE:
                if (!quotedPattern) {
                    bracketDepth++;
                }
                i++;
                break;

            case RIGHT_BRACE:
                if (!quotedPattern) {
                    if (bracketDepth > 0) {
                        bracketDepth--;
                    } else {
                        // end of pattern!
                        done = true;
                        break;
                    }
                }
                i++;
                break;
            }
        }

        if (i == n) {
            // couldn't find end of pattern -- give up
            return message;
        }
    }

    return ss.str();
}

// NOTE jvs 18-Feb-2004:  The conversion from Java resource format
// to Boost format could be done just once as part of the build, instead
// of each time on startup.  However, keeping everything in Java format
// simplifies the packaging/translation/distribution process.  And the
// performance hit should be minuscule unless the number of
// messages is huge.

void ResourceBundle::loadMessages()
{
    fstream in;

    // e.g. GeneratedResourceBundle_en_US.resources
    string fileName;

    if (_locale == Locale("")) {
        fileName.assign(
            _baseName + ".properties");
    } else {
        fileName.assign(
            _baseName + "_" + _locale.getDisplayName() + ".properties");
    }

    // look in _location first
    bool tryGlobalLocation = true;
    if (!_location.empty()) {
        string path = _location + "/" + fileName;
        in.open(path.c_str(), ios::in);
        if (in.good()) {
            tryGlobalLocation = false;
        }
    }

    // failing that, try the gobal location, if any
    if (tryGlobalLocation) {
        bool tryEnvVar = true;

        // TODO jvs 18-Feb-2004: once Fennel starts using Boost's
        // platform-independent filesystem library, use it here too.
        if (!globalResourceLocation.empty()) {
            string path = globalResourceLocation + "/" + fileName;
            in.open(path.c_str(), ios::in);
            if (in.good()) {
                tryEnvVar = false;
            }
        }

        if (tryEnvVar) {
            const char *fennelHome = getenv("FENNEL_HOME");
            if (fennelHome == NULL) {
                return; // give up
            }

            string path = string(fennelHome) + "/common/" + fileName;
            in.open(path.c_str(), ios::in);
            if (!in.good()) {
                return; // give up
            }
        }
    }

    string line, key, message;
    while (in.good()) {
        getline(in, line);

        if (line.length() == 0 || line[0] == '#') {
            // ignore blank lines and comments
            continue;
        }

        string::size_type pos = line.find('=');
        if (pos == string::npos) {
            // bad message format?
            continue;
        }

        key = line.substr(0, pos);
        message = line.substr(pos + 1);

        _messages[key] = convertPropertyToBoost(message);
    }

    in.close();
}

FENNEL_END_CPPFILE("$Id$");

// End ResourceBundle.cpp