text:
// Copyright (c) 2013-2018 LG Electronics, 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.
//
// SPDX-License-Identifier: Apache-2.0

//->Start of API documentation comment block
/**
@page com_webos_settingsservice com.webos.settingsservice

@brief Service component for Setting. Provides APIs to set/get/manage settings

@{
@}
*/
//->End of API documentation comment block

#include "Logging.h"
#include "PrefsDb8Init.h"
#include "PrefsKeyDescMap.h"
#include "SettingsService.h"
#include "Utils.h"
#include <boost/algorithm/string/replace.hpp>
/* SettingsService initialization sequence
    .
    |
   initKind
    |
   delKind
    |
   regKind
    |
   delKind
    |
    +-- initSubscribers -- ---
    |
   checkingDescKind
    |
   loadingDefaultSettings
    |
   PrefsKeyDescMap::initKeyDescMap
    |
    O
*/
PrefsDb8Init* PrefsDb8Init::s_instance = nullptr;
const static char* APPLICATION_MANAGER = "com.webos.applicationManager";

PrefsDb8Init *PrefsDb8Init::instance()
{
    if (!s_instance) {
        s_instance = new PrefsDb8Init;
    }
    return s_instance;
}

PrefsDb8Init::PrefsDb8Init() :
      m_kindInfo(nullptr)
    , m_serviceHandlePrivate(nullptr)
    , m_dbInitDone(false)
    , m_updateType(UpdateType_eNone)
    , m_tokenForegroundApp(0)
    , m_tokenListApps(0)
{
}

PrefsDb8Init::~PrefsDb8Init()
{
    LSError lsError;
    LSErrorInit(&lsError);

    s_instance = 0;

    releaseKindInfo();

    for (auto& cook : m_serviceCookies ) {
        if( !LSCancelServerStatus(m_serviceHandlePrivate, cook.second, &lsError) ) {
            LSErrorPrint(&lsError, stderr);
            LSErrorFree(&lsError);
        }
    }
}

bool PrefsDb8Init::loadKindInfo(bool delRegFlag) {
    bool result = true;

    if(m_kindInfo) {
        delete(m_kindInfo);
    }

    m_kindInfo = new KindNameInfo;
    if(m_dbInitDone) {
        SSERVICELOG_DEBUG("%s: Init for Volatile kind", __FUNCTION__);
        result = m_kindInfo->loadVolatileKindName();
    }
    else {
        SSERVICELOG_DEBUG("%s: Init for %s kind", __FUNCTION__, m_updateType == UpdateType_eDefault ? "default" : "all");
        if(!delRegFlag) {
            SSERVICELOG_DEBUG("%s: to delKind", __FUNCTION__);
            result = m_kindInfo->loadAllKindNameToDel(m_updateType == UpdateType_eDefault);
        }
        else {
            SSERVICELOG_DEBUG("%s: to regKind", __FUNCTION__);
            result = m_kindInfo->loadAllKindNameToReg(m_updateType == UpdateType_eDefault);
        }
    }

    return result;
}

bool PrefsDb8Init::loadPermissionInfo()
{
    if(m_kindInfo) {
        delete(m_kindInfo);
    }

    m_kindInfo = new KindNameInfo;
    return m_kindInfo->loadPermission();
}

void PrefsDb8Init::getKindInfoNext() {
    if(m_kindInfo) {
        m_kindInfo->getKindInfoNext(m_targetKindName, m_targetKindFilePath);
    }
    else {
        m_targetKindName = "";
        m_targetKindFilePath = "";
    }
    SSERVICELOG_DEBUG("%s: kindfilepath : %s targetkindname : %s", __FUNCTION__,
                      m_targetKindFilePath.c_str(), m_targetKindName.c_str());
}

void PrefsDb8Init::getPermissionInfoNext() {
    if(m_kindInfo) {
        m_kindInfo->getPermissionInfoNext(m_targetPermissionFilePath);
    }
    else {
        m_targetPermissionFilePath = "";
    }
    SSERVICELOG_DEBUG("%s: targetPermissionFilePath : %s", __FUNCTION__, m_targetPermissionFilePath.c_str());
}

void PrefsDb8Init::releaseKindInfo() {
    if(m_kindInfo) {
        delete m_kindInfo;
        m_kindInfo = NULL;
    }
}

bool PrefsDb8Init::cbDelKind(LSHandle * lsHandle, LSMessage * message, void *data)
{
    bool success = false;
    std::string errorText;

    PrefsDb8Init *replyInfo = (PrefsDb8Init *) data;

    const char *payload = LSMessageGetPayload(message);
    do {
        if (!payload) {
            SSERVICELOG_WARNING(MSGID_INIT_PAYLOAD_MISSING, 0, " ");
            errorText = "missing payload";
            break;
        }
        SSERVICELOG_TRACE("%s: %s", __FUNCTION__, payload);

        pbnjson::JValue root = pbnjson::JDomParser::fromString(payload);
        if (root.isNull()) {
            SSERVICELOG_WARNING(MSGID_INIT_PARSE_ERR, 0, "function : %s, payload : %s", __FUNCTION__, payload);
            errorText = std::string("couldn't parse json");
            break;
        }

        pbnjson::JValue label(root["returnValue"]);
        if (label.isBoolean()) {
            success = label.asBool();
            if (!success) {
                pbnjson::JValue label2(root["errorText"]);
                if (label.isString()) {
                    errorText = label.asString();
                    boost::replace_all(errorText, "\"", "'");
                }
                else
                    errorText = "unexpected payload";
            }
        }
    } while (false);

    if(!success) {
        SSERVICELOG_ERROR(MSGID_INIT_DELKIND_ERR, 2, PMLOGKS("kind",replyInfo->m_targetKindName.c_str()),
                             PMLOGKS("Reason",errorText.c_str()), "");
    }

    // for delKind, error is discarded.
    replyInfo->getKindInfoNext();
    if(replyInfo->m_targetKindName.size()) {
        replyInfo->delKind();
    }
    else {
        // start again in kind name list
        if(replyInfo->loadKindInfo(true)) {
            replyInfo->getKindInfoNext();
            if(replyInfo->m_targetKindFilePath.size()) {
                replyInfo->regKind();
            }
            else {
                SSERVICELOG_ERROR(MSGID_INIT_KIND_REG_ERR, 0, "There is no kind info to register");
                replyInfo->releaseKindInfo();   // Don't need KindInfo anymore.
                PrefsFactory::instance()->serviceFailed(__PRETTY_FUNCTION__);
            }
        }
        else {
            SSERVICELOG_ERROR(MSGID_INIT_KIND_LOAD_ERR, 0, " ");
            replyInfo->releaseKindInfo();   // Don't need KindInfo anymore.
            PrefsFactory::instance()->serviceFailed(__PRETTY_FUNCTION__);
        }
    }

    return true;
}

bool PrefsDb8Init::cbRegKind(LSHandle * lsHandle, LSMessage * message, void *data)
{
    bool success = false;
    std::string errorText;

    PrefsDb8Init *replyInfo = (PrefsDb8Init *) data;

    do {
        const char *payload = LSMessageGetPayload(message);
        if (!payload) {
            SSERVICELOG_WARNING(MSGID_INIT_PAYLOAD_MISSING, 0, " ");
            errorText = "missing payload";
            break;
        }

        SSERVICELOG_TRACE("%s: %s", __FUNCTION__, payload);

        pbnjson::JValue root = pbnjson::JDomParser::fromString(payload);
        if (root.isNull()) {
            SSERVICELOG_WARNING(MSGID_INIT_PARSE_ERR, 0, "function : %s, payload : %s", __FUNCTION__, payload);
            errorText = "couldn't parse json";
            break;
        }

        pbnjson::JValue label(root["returnValue"]);
        if (label.isBoolean())
            success = label.asBool();
    } while (false);

    if (success) {
        // If there is another kind fine to register, call regKind again.
        replyInfo->getKindInfoNext();
        if(replyInfo->m_targetKindFilePath.size()) {
            replyInfo->regKind();
        }
        // Otherwise, goto next step.
        else {
            SSERVICELOG_DEBUG("Success to register Kind(s)");
            replyInfo->initSubscribers();
            if(replyInfo->m_dbInitDone) {
                SSERVICELOG_DEBUG("Start to Load Description Kind");
                PrefsKeyDescMap::instance()->initKeyDescMap();
            }
            else {
                // try to register Permissions
                if(replyInfo->loadPermissionInfo()) {
                    replyInfo->getPermissionInfoNext();
                    if(replyInfo->m_targetPermissionFilePath.size()) {
                        replyInfo->regPermission();
                    }
                    else {
                        SSERVICELOG_ERROR(MSGID_INIT_PERM_REG_ERR, 0, "There is no Permission info to register");
                        replyInfo->releaseKindInfo();   // Don't need KindInfo anymore.
                        PrefsFactory::instance()->serviceFailed(__PRETTY_FUNCTION__);
                    }
                }
                else {
                    SSERVICELOG_ERROR(MSGID_INIT_PERM_LOAD_ERR, 0, " ");
                    replyInfo->releaseKindInfo();   // Don't need KindInfo anymore.
                    PrefsFactory::instance()->serviceFailed(__PRETTY_FUNCTION__);
                }
            }
        }
    }
    else {
        SSERVICELOG_ERROR(MSGID_INIT_DB8_CONF_ERR, 1, PMLOGKS("Kind_File",replyInfo->m_targetKindFilePath.c_str()), "");
        replyInfo->releaseKindInfo();
        PrefsFactory::instance()->serviceFailed(__PRETTY_FUNCTION__);
    }

    return true;
}

bool PrefsDb8Init::cbRegPermission(LSHandle * lsHandle, LSMessage * message, void *data)
{
    bool success = false;
    std::string errorText;

    PrefsDb8Init *replyInfo = (PrefsDb8Init *) data;

    do {
        const char *payload = LSMessageGetPayload(message);
        if (!payload) {
            SSERVICELOG_WARNING(MSGID_INIT_PAYLOAD_MISSING, 0, " ");
            errorText = std::string("missing payload");
            break;
        }

        SSERVICELOG_TRACE("%s: %s", __FUNCTION__, payload);

        pbnjson::JValue root = pbnjson::JDomParser::fromString(payload);
        if (root.isNull()) {
            SSERVICELOG_WARNING(MSGID_INIT_PARSE_ERR, 0, "function : %s, payload : %s", __FUNCTION__, payload);
            errorText = std::string("couldn't parse json");
            break;
        }

        pbnjson::JValue label(root["returnValue"]);
        if (label.isBoolean())
            success = label.asBool();
    } while(false);

    if (success) {
        // Initialize a subscriber, all subscribe routines are called here.
        // Before calling this routing, volatile kind must have been iniialized.
        // TODO: It would be good to create appropriate class for subscriber.

        // If there is another permission file to register, call regPermission again.
        replyInfo->getPermissionInfoNext();
        if(replyInfo->m_targetPermissionFilePath.size()) {
            replyInfo->regPermission();
        }
        else {
            SSERVICELOG_DEBUG("Success to register Permission(s)");

            replyInfo->loadDefaultSettings();

            replyInfo->releaseKindInfo();   // Don't need KindInfo anymore.
        }
    }
    else {
        SSERVICELOG_ERROR(MSGID_INIT_DB8_CONF_ERR, 1,
                             PMLOGKS("Permission_File",replyInfo->m_targetPermissionFilePath.c_str()), "");
        replyInfo->releaseKindInfo();
        PrefsFactory::instance()->serviceFailed(__PRETTY_FUNCTION__);
    }

    return true;
}

std::pair<std::string, std::string> PrefsDb8Init::getMajorMinorVersion(const std::string& a_version)
{
    std::string major, minor;

    std::size_t pos = a_version.find(".");
    if (std::string::npos == pos || pos == 0 || (pos+1) == a_version.size() )
    {
        major = a_version;
        minor = "";
    }
    else
    {
        major = a_version.substr(0, pos);
        minor = a_version.substr(pos+1);
    }

    return std::pair<std::string, std::string>(major, minor);
}

void PrefsDb8Init::checkUpdateType(bool a_db_init, const std::string &a_dbVersion, const std::string &a_confVersion)
{
    if (a_db_init == false)
    {
        m_dbInitDone = false;
        m_updateType = UpdateType_eAll;
        return;
    }

    m_updateType = UpdateType_eNone;
    if (a_dbVersion==a_confVersion)
    {
        m_dbInitDone = true;
    }
    else
    {
        std::pair<std::string, std::string> dbVersion;
        std::pair<std::string, std::string> confVersion;

        dbVersion = getMajorMinorVersion(a_dbVersion);
        confVersion = getMajorMinorVersion(a_confVersion);
        m_updateType = UpdateType_eAll;
        if (dbVersion.first != confVersion.first)
        {
            m_updateType = UpdateType_eAll;
        }
        else if (dbVersion.second != confVersion.second)
        {
            m_updateType = UpdateType_eDefault;
        }
        else
        {
            m_dbInitDone = true;
        }

        /* TODO: This is temporary code. We should always keeps user-modified settings.
         *       If MAIN kind schema is changed (m_updateType should be UpdateType_eAll),
         *       we would implement new function to migrate user modified settings. */
        m_updateType = UpdateType_eDefault;
    }
}

bool PrefsDb8Init::cbCheckInitKey(LSHandle * lsHandle, LSMessage * message, void *data)
{
    std::string errorText;
    bool db_init_flag = false;
    std::string db_version_str;

    PrefsDb8Init *replyInfo = (PrefsDb8Init *) data;

    do {
          const char *payload = LSMessageGetPayload(message);
          if (!payload) {
              SSERVICELOG_WARNING(MSGID_INIT_PAYLOAD_MISSING, 0, " ");
              errorText = "missing payload";
              break;
          }

          SSERVICELOG_TRACE("%s: %s", __FUNCTION__, payload);

          pbnjson::JValue root = pbnjson::JDomParser::fromString(payload);
          if (root.isNull()) {
              SSERVICELOG_WARNING(MSGID_INIT_PARSE_ERR, 0, "function : %s, payload : %s", __FUNCTION__, payload);
              errorText = "couldn't parse json";
              break;
          }

          pbnjson::JValue label(root["returnValue"]);
          if (!label.isBoolean() || !label.asBool()) {
              SSERVICELOG_WARNING(MSGID_INIT_DB_RETURNS_FAIL, 0, "payload : %s",payload);
              errorText = "DB8 error";
              break;
          }

          pbnjson::JValue resultsArray(root["results"]);
          if (!resultsArray.isArray()) {
              SSERVICELOG_WARNING(MSGID_INIT_JSON_TYPE_ARRAY_ERR, 0, "payload : %s",payload);
              errorText = "Json object error";
              break;
          }

          if(resultsArray.arraySize() != 1) {
              /* if duplicated data object exist */
              SSERVICELOG_WARNING(MSGID_INIT_JSON_TYPE_ARRLEN_ERR, 1, PMLOGKS("Reason","unexpected db8 resultsArray"),
                                  "payload : %s",payload);
              break;
          }

          pbnjson::JValue result_obj(resultsArray[0]);
          /* Simple validation */
          label = result_obj["value"];
          if (label.isNull()) {
              SSERVICELOG_WARNING(MSGID_INIT_NO_VALUE, 1, PMLOGKS("Reason","Category has no keys"),
                                  "payload : %s",payload);
              errorText = "Category has no keys";
              break;
          }

          pbnjson::JValue keyObj = label[SETTINGSSERVICE_DBVER_KEY];
          if (!keyObj.isString()) {
              SSERVICELOG_WARNING(MSGID_INIT_NO_DBVERSION, 0, "payload : %s",payload);
              errorText = "Ver Key is not in DB";
              break;
          }
          db_version_str = keyObj.asString();

          keyObj = label[SETTINGSSERVICE_INIT_KEY];
          if (!keyObj.isBoolean()) {
              SSERVICELOG_WARNING(MSGID_INIT_NO_INITKEY, 1, PMLOGKS("db_version",db_version_str.c_str()), "");
              errorText = "Init Key is not in DB";
              break;
          }
          db_init_flag = keyObj.asBool();
    } while(false);

    if(errorText.size()) {
        SSERVICELOG_DEBUG("%s: errortext : %s", __FUNCTION__, errorText.c_str());
    }

    replyInfo->checkUpdateType(db_init_flag, db_version_str, Settings::settings()->dbVersion);
    if ( UpdateType_eAll == replyInfo->m_updateType )
    {
        // Workaround - just upgrade default kind, not user kind.
        //
        replyInfo->m_updateType = UpdateType_eDefault;
    }

    if(replyInfo->loadKindInfo(false)) {
        replyInfo->getKindInfoNext();
        if(replyInfo->m_targetKindName.size()) {
            replyInfo->delKind();
        }
        else {
            SSERVICELOG_ERROR(MSGID_INIT_DB8_CONF_ERR, 0, "There is no kind info to delete");
            PrefsFactory::instance()->serviceFailed(__PRETTY_FUNCTION__);
        }
    }
    else {
        SSERVICELOG_ERROR(MSGID_ERR_LOADING_KIND_INFO, 0, " ");
        PrefsFactory::instance()->serviceFailed(__PRETTY_FUNCTION__);
    }

    return true;
}

bool PrefsDb8Init::cbLoadDefaultSettingsDB8(LSHandle * lsHandle, LSMessage * message, void *data)
{
    bool success = false;
    std::string errorText;
    pbnjson::JValue label;

    PrefsDb8Init *replyInfo = (PrefsDb8Init *) data;

    const char *payload = LSMessageGetPayload(message);
    do {
        if (!payload) {
            SSERVICELOG_WARNING(MSGID_INIT_PAYLOAD_MISSING, 0, " ");
            errorText = std::string("missing payload");
            break;
        }

        SSERVICELOG_TRACE("%s: %s", __FUNCTION__, payload);

        pbnjson::JValue root = pbnjson::JDomParser::fromString(payload);
        if (root.isNull()) {
            SSERVICELOG_WARNING(MSGID_INIT_PARSE_ERR, 0, "function : %s, payload : %s", __FUNCTION__, payload);
            errorText = std::string("couldn't parse json");
            break;
        }

        label = root["returnValue"];
        if (label.isBoolean())
            success = label.asBool();

        label = root["count"];

    } while(false);

    if (success && label.isNumber()) {
        SSERVICELOG_DEBUG("Loading default values(%d records)", label.asNumber<int>());
        replyInfo->mergeInitKey();
    } else {
        /* TODO: We need to recover this critical error
           SettingsService alwyas return fails for any request in this error */
        SSERVICELOG_ERROR(MSGID_INIT_DB_LOAD_FAIL, 0, "payload : %s",payload);
        PrefsFactory::instance()->serviceFailed(__PRETTY_FUNCTION__);
    }

    return true;
}

bool PrefsDb8Init::loadDefaultSettings()
{
    LSError lsError;
    bool result = false;

    LSErrorInit(&lsError);

    //luna-send -n 1 -a com.palm.configurator luna://com.webos.service.db/load '{"path":"/etc/palm/defaultSettings.json"}'

    result =  DB8_luna_call(m_serviceHandlePrivate,
        "luna://com.webos.service.db/load",
        "{\"path\":\"/etc/palm/defaultSettings.json\"}",
        PrefsDb8Init::cbLoadDefaultSettingsDB8, this, NULL, &lsError);

    if ( !result ) {
        SSERVICELOG_WARNING(MSGID_LSERROR_MSG, 2, PMLOGKS("Function",lsError.func), PMLOGKS("Error",lsError.message), "Load default json");
        LSErrorFree(&lsError);
    }

    return result;
}

bool PrefsDb8Init::checkInitKey()
{
    pbnjson::JValue replyRoot(pbnjson::Object());
    pbnjson::JValue replyRootQuery(pbnjson::Object());
    pbnjson::JValue replyRootWhereArray(pbnjson::Array());
    pbnjson::JValue replyRootItem1(pbnjson::Object());
    LSError lsError;
    LSErrorInit(&lsError);
    bool result = false;

    // add category for where
    replyRootItem1.put("prop", "category");
    replyRootItem1.put("op", "=");
    replyRootItem1.put("val", SETTINGSSERVICE_INIT_CATEGORY);

    // build where
    replyRootWhereArray.append(replyRootItem1);
    replyRootQuery.put("where", replyRootWhereArray);

    // add from
    replyRootQuery.put("from", SETTINGSSERVICE_KIND_DEFAULT);

    // add to root
    replyRoot.put("query", replyRootQuery);

    // add reply root
    result = DB8_luna_call(m_serviceHandlePrivate, "luna://com.webos.service.db/find", replyRoot.stringify().c_str(), PrefsDb8Init::cbCheckInitKey, this, NULL, &lsError);

    if ( !result ) {
        SSERVICELOG_WARNING(MSGID_LSERROR_MSG, 2, PMLOGKS("Function",lsError.func), PMLOGKS("Error",lsError.message), "Check init key");
        LSErrorFree(&lsError);
    }

    return result;
}

bool PrefsDb8Init::delKind()
{
    LSError lsError;
    LSErrorInit(&lsError);
    std::string dbQuery;
    bool result = false;

    if(!m_kindInfo) {
        SSERVICELOG_ERROR(MSGID_INIT_NO_KINDINFO, 0, " error occured during DB initialization for settingsservice");
        PrefsFactory::instance()->serviceFailed(__PRETTY_FUNCTION__);
        return false;
    }

    dbQuery = "{\"id\":\"" + m_targetKindName + "\"}";

    result = DB8_luna_call(m_serviceHandlePrivate, "luna://com.webos.service.db/delKind", dbQuery.c_str(), PrefsDb8Init::cbDelKind, this, NULL, &lsError);

    if ( !result ) {
        SSERVICELOG_WARNING(MSGID_LSERROR_MSG, 2, PMLOGKS("Function",lsError.func), PMLOGKS("Error",lsError.message), "delKind for init");
        LSErrorFree(&lsError);
    }

    return result;
}

bool PrefsDb8Init::regKind()
{
    bool result = false;
    LSError lsError;
    LSErrorInit(&lsError);

    std::string kindData;

    if(Utils::readFile(m_targetKindFilePath, kindData)) {
        result = DB8_luna_call(m_serviceHandlePrivate, "luna://com.webos.service.db/putKind", kindData.c_str(), PrefsDb8Init::cbRegKind, this, NULL, &lsError);

        if ( !result ) {
            SSERVICELOG_WARNING(MSGID_LSERROR_MSG, 2, PMLOGKS("Function",lsError.func), PMLOGKS("Error",lsError.message), "Reg kind");
            LSErrorFree(&lsError);
            PrefsFactory::instance()->serviceFailed(__PRETTY_FUNCTION__);
        }
    }
    else {
        SSERVICELOG_ERROR(MSGID_INIT_READ_DB8_CONF_ERR, 1, PMLOGKS("Kind_file",m_targetKindFilePath.c_str()), "");
        PrefsFactory::instance()->serviceFailed(__PRETTY_FUNCTION__);
    }

    return result;
}

bool PrefsDb8Init::regPermission()
{
    bool result = false;
    std::string permissionData;
    LSError lsError;
    LSErrorInit(&lsError);

    if(Utils::readFile(m_targetPermissionFilePath, permissionData)) {
        pbnjson::JValue dbQuery = pbnjson::Object();
        pbnjson::JValue permissions = pbnjson::JDomParser::fromString(permissionData);
        dbQuery.put("permissions", permissions);
        SSERVICELOG_TRACE("%s: %s", __FUNCTION__, dbQuery.stringify().c_str());
        result = DB8_luna_call(m_serviceHandlePrivate, "luna://com.webos.service.db/putPermissions", dbQuery.stringify().c_str(), PrefsDb8Init::cbRegPermission, this, NULL, &lsError);

        if ( !result ) {
            SSERVICELOG_WARNING(MSGID_LSERROR_MSG, 2, PMLOGKS("Function",lsError.func), PMLOGKS("Error",lsError.message), "Reg permission");
            LSErrorFree(&lsError);
        }
    }
    else {
        SSERVICELOG_ERROR(MSGID_INIT_READ_DB8_CONF_ERR, 1, PMLOGKS("Permissions_File",m_targetPermissionFilePath.c_str()), "");
        PrefsFactory::instance()->serviceFailed(__PRETTY_FUNCTION__);
    }

    return result;
}

bool PrefsDb8Init::initKind()
{
    return checkInitKey();
}

bool PrefsDb8Init::initSubscribers()
{
    return callwithSubscribes();
}

bool PrefsDb8Init::cbCurAppIdSubscribers(LSHandle * sh, LSMessage * message, void *ctx)
{
    std::string curAppId;

    do {
        const char *payload = LSMessageGetPayload(message);
        if (!payload) {
            SSERVICELOG_WARNING(MSGID_INIT_PAYLOAD_MISSING, 0, " ");
            break;
        }

        SSERVICELOG_TRACE("%s: %s", __FUNCTION__, payload);

        /* expected message format
            {"appId":"com.palm.app.enyo2sampler","returnValue":true,"windowId":"","processId":"2198"}
         */

        pbnjson::JValue root = pbnjson::JDomParser::fromString(payload);
        if (root.isNull()) {
            break;
        }
        pbnjson::JValue label = root["returnValue"];
        if (!label.isBoolean() || !label.asBool()) {
            SSERVICELOG_WARNING(MSGID_INIT_SAM_RETURNS_ERR, 1, PMLOGKS("Reason","SAM returns error for forground App ID"),
                                "payload : %s",payload);
            break;
        }

        /* subscribe message doesn't include returnValue */
        label = root["appId"];
        if (!label.isString()) {
            SSERVICELOG_WARNING(MSGID_INIT_NO_APPID, 0, " ");
            break;
        }

        curAppId = label.asString();
        if (!curAppId.empty())
        {
            std::unique_ptr<std::string> appId(new std::string(curAppId));
            if (PrefsFactory::instance()->getTaskManager().pushUserMethod(
                METHODID_CHANGE_APP,
                PrefsFactory::instance()->getServiceHandle(PrefsFactory::COM_WEBOS_SERVICE),
                nullptr,
                appId.get(),
                TASK_PUSH_BACK))
            {
                appId.release();
            }
        }

        SSERVICELOG_DEBUG("%s: currnet app id: %s", __FUNCTION__, curAppId.c_str());
    }while(false);

    return true;
}

bool PrefsDb8Init::cbListAppsSubscribers(LSHandle * sh, LSMessage * message, void *ctx)
{
    do {
        const char *payload = LSMessageGetPayload(message);
        if (!payload) {
            SSERVICELOG_WARNING(MSGID_INIT_PAYLOAD_MISSING, 0, " ");
            break;
        }

        SSERVICELOG_TRACE("%s: %s", __FUNCTION__, payload);

        /* expected message format for list apps
         * {
         *    "app": { "id":"youtube.leanback.v2" } <- subscribed reply,
         *    "apps": [ {}, {} ] <- first reply ,
         *    "change": "removed",
         *    "changeReason": "appUninstalled",
         *    "returnValue": true,
         *    "subscribed": true
         * }
         */

        pbnjson::JValue root = pbnjson::JDomParser::fromString(payload);
        if (root.isNull()) {
            break;
        }

        pbnjson::JValue label = root["returnValue"];
        if (label.isNull() || !label.asBool()) {
            SSERVICELOG_WARNING(MSGID_INIT_SAM_RETURNS_ERR, 1, PMLOGKS("Reason","SAM returns error for app list"),
                  "payload : %s",payload);
            break;
        }

        label = root["change"];
        if (!label.isString() || label.asString() != "removed")
        {
            break;
        }

        label = root["changeReason"];
        if (!label.isString() || label.asString() != "appUninstalled")
        {
            break;
        }

        /* Ignore full list of apps which is in first reply */
        label = root["app"];
        if (!label.isObject())
            break;

        label = label["id"];
        if (!label.isString())
            break;

        std::string removedAppId = label.asString();
        SSERVICELOG_DEBUG("%s: removed app id: %s", __FUNCTION__, removedAppId.c_str());
        {
            std::unique_ptr<std::string> appId(new std::string(removedAppId));
            if (PrefsFactory::instance()->getTaskManager().pushUserMethod(
                    METHODID_UNINSTALL_APP,
                    PrefsFactory::instance()->getServiceHandle(PrefsFactory::COM_WEBOS_SERVICE),
                    nullptr,
                    appId.get(),
                    TASK_PUSH_BACK))
            {
                appId.release();
            }
       }

    } while(false);

    return true;
}

void PrefsDb8Init::cancelForegroundApp()
{
    LSError lsError;
    LSErrorInit(&lsError);

    if ( m_tokenForegroundApp ) {
        if ( !LSCallCancel(m_serviceHandlePrivate, m_tokenForegroundApp, &lsError) ) {
            LSErrorPrint(&lsError, stderr);
            LSErrorFree(&lsError);
        }
        m_tokenForegroundApp = 0;
    }
}

void PrefsDb8Init::cancelListApps()
{
    LSError lsError;
    LSErrorInit(&lsError);

    if ( m_tokenListApps ) {
        if ( !LSCallCancel(m_serviceHandlePrivate, m_tokenListApps, &lsError) ) {
            LSErrorPrint(&lsError, stderr);
            LSErrorFree(&lsError);
        }
        m_tokenListApps = 0;
    }
}

bool PrefsDb8Init::subscribeForegroundApp()
{
    LSError lsError;
    LSErrorInit(&lsError);

    bool ret = LSCall(m_serviceHandlePrivate, "luna://com.webos.applicationManager/getForegroundAppInfo", "{\"subscribe\":true}",
            PrefsDb8Init::cbCurAppIdSubscribers, this, &m_tokenForegroundApp, &lsError);

    SSERVICELOG_DEBUG("%s: Db8 call %s %s", __FUNCTION__, "getForegroundAppInfo", "{\"subscribe\":true|");

    if (!ret) {
        SSERVICELOG_WARNING(MSGID_LSCALL_SAM_FAIL, 0, "Failed to call applicationManager to get current app id");
        LSErrorPrint(&lsError, stderr);
        LSErrorFree(&lsError);
        m_tokenForegroundApp = 0;
    }

    return ret;
 }

bool PrefsDb8Init::subscribeListApps()
{
    LSError lsError;
    LSErrorInit(&lsError);

    bool ret = LSCall(m_serviceHandlePrivate, "luna://com.webos.applicationManager/listApps", "{\"subscribe\":true}",
            PrefsDb8Init::cbListAppsSubscribers, this, &(m_tokenListApps), &lsError);

    SSERVICELOG_DEBUG("%s: Db8 call %s %s", __FUNCTION__, "listApps", "{\"subscribe\":true|");

    if (!ret) {
        SSERVICELOG_WARNING(MSGID_LSCALL_SAM_FAIL, 0, "Failed to call applicationManager to get current app id");
        LSErrorPrint(&lsError, stderr);
        LSErrorFree(&lsError);
        m_tokenListApps = 0;
    }

    return ret;
}

bool PrefsDb8Init::_callwithSubscribes(LSHandle *a_handle, const char *a_service, bool a_connected, void *ctx)
{
    LSError lsError;
    LSErrorInit(&lsError);

    if ( !a_handle || !ctx ) {
        SSERVICELOG_WARNING(MSGID_LSCALL_SAM_FAIL, 3,
                PMLOGKS("service", a_service),
                PMLOGKS("connected", a_connected ? "True" : "False"),
                PMLOGKFV("ctx", "\"%p\"", ctx),
                "Unexpected sam status");
        return false;
    }

    PrefsDb8Init* thiz = static_cast<PrefsDb8Init*>(ctx);

    if ( !a_connected ) {
        SSERVICELOG_WARNING(MSGID_LSCALL_SAM_FAIL, 0, "SAM Disconnected");
        thiz->cancelForegroundApp();
        thiz->cancelListApps();
        return true;
    }

    bool subsResultForeApp = thiz->subscribeForegroundApp();
    bool subsResultListApp = thiz->subscribeListApps();

    if ( !subsResultForeApp || !subsResultListApp ) {
        SSERVICELOG_WARNING(MSGID_LSCALL_SAM_FAIL, 0, "SAM Connected, but fail to subscribe");
    }

    return subsResultForeApp && subsResultListApp;
}

bool PrefsDb8Init::callwithSubscribes(void)
{
    LSError lsError;
    LSErrorInit(&lsError);
    void* cookie;

    bool ret = LSRegisterServerStatusEx(m_serviceHandlePrivate,
                        APPLICATION_MANAGER, PrefsDb8Init::_callwithSubscribes,
                        this, &cookie, &lsError);

    if ( !ret || !cookie ) {
        SSERVICELOG_WARNING(MSGID_LSCALL_SAM_FAIL, 0, "Failed to monitor sam status");
        LSErrorPrint(&lsError, stderr);
        LSErrorFree(&lsError);
        return false;
    }

    m_serviceCookies.insert( { APPLICATION_MANAGER, cookie } );

    return true;
}

bool PrefsDb8Init::putInitKey()
{
    LSError lsError;
    LSErrorInit(&lsError);
    bool result;

    pbnjson::JValue valueObj(pbnjson::Object());
    valueObj.put(SETTINGSSERVICE_INIT_KEY, true);
    valueObj.put(SETTINGSSERVICE_DBVER_KEY, Settings::settings()->dbVersion);

    pbnjson::JValue initObj(pbnjson::Object());
    initObj.put("_kind", SETTINGSSERVICE_KIND_DEFAULT);
    initObj.put("app_id", "");
    initObj.put("category", SETTINGSSERVICE_INIT_CATEGORY);
    initObj.put("volatile", false);
    initObj.put("value", valueObj);

    pbnjson::JValue objArray(pbnjson::Array());
    objArray.append(initObj);

    pbnjson::JValue replyRoot(pbnjson::Object());
    replyRoot.put("objects", objArray);

    result = DB8_luna_call(m_serviceHandlePrivate, "luna://com.webos.service.db/put", replyRoot.stringify().c_str(), PrefsDb8Init::cbPutInitKey, this, NULL, &lsError);
    if (!result) {
        SSERVICELOG_WARNING(MSGID_LSCALL_DB_MERGE_FAIL, 2, PMLOGKS("Function",lsError.func), PMLOGKS("Error",lsError.message), "");
        LSErrorPrint(&lsError, stderr);
        LSErrorFree(&lsError);
    }

    return true;
}

bool PrefsDb8Init::mergeInitKey()
{
    LSError lsError;
    LSErrorInit(&lsError);
    bool result;

    pbnjson::JValue whereArray(pbnjson::Array());
    pbnjson::JValue whereItem(pbnjson::Object());
    whereItem.put("prop", "app_id");
    whereItem.put("op", "=");
    whereItem.put("val", "");
    whereArray.append(whereItem);
    whereItem = pbnjson::Object();
    whereItem.put("prop", "category");
    whereItem.put("op", "=");
    whereItem.put("val", SETTINGSSERVICE_INIT_CATEGORY);
    whereArray.append(whereItem);

    pbnjson::JValue queryObj(pbnjson::Object());
    queryObj.put("from", SETTINGSSERVICE_KIND_DEFAULT);
    queryObj.put("where", whereArray);

    pbnjson::JValue dbInitFlagObj(pbnjson::Object());
    dbInitFlagObj.put(SETTINGSSERVICE_INIT_KEY, true);

    pbnjson::JValue propsObj(pbnjson::Object());
    propsObj.put("value", dbInitFlagObj);

    pbnjson::JValue replyRoot(pbnjson::Object());
    replyRoot.put("query", queryObj);
    replyRoot.put("props", propsObj);

    result = DB8_luna_call(m_serviceHandlePrivate, "luna://com.webos.service.db/merge", replyRoot.stringify().c_str(), PrefsDb8Init::cbMergeInitKey, this, NULL, &lsError);
    if (!result) {
        SSERVICELOG_WARNING(MSGID_LSCALL_DB_MERGE_FAIL, 2, PMLOGKS("Function",lsError.func), PMLOGKS("Error",lsError.message), "");
        LSErrorPrint(&lsError, stderr);
        LSErrorFree(&lsError);
    }

    LSErrorInit(&lsError);

    /* create null category in the system KIND
     * to avoid localeInfo object doesn't merge */
    result = DB8_luna_call(m_serviceHandlePrivate, "luna://com.webos.service.db/find",
            "{\"query\":{\"from\":\"com.webos.settings.system:1\", \"where\":[{\"prop\":\"category\",\"op\":\"=\",\"val\":\"\"}]}}",
            PrefsDb8Init::cbFindNullCategory, this, NULL, &lsError);

    if (!result) {
        SSERVICELOG_WARNING(MSGID_LSERROR_MSG, 2, PMLOGKS("Function",lsError.func), PMLOGKS("Error",lsError.message), "create null category");
        LSErrorFree(&lsError);
    }

    return true;
}

bool PrefsDb8Init::cbFindNullCategory(LSHandle * sh, LSMessage * message, void *ctx)
{
    LSError lsError;
    LSErrorInit(&lsError);

    bool success = false;
    PrefsDb8Init *replyInfo = (PrefsDb8Init *)ctx;

    const char *payload = LSMessageGetPayload(message);
    if (!payload) {
        return false;
    }

    pbnjson::JValue root = pbnjson::JDomParser::fromString(payload);
    if (root.isNull()) {
        return false;
    }

    pbnjson::JValue label = root["returnValue"];
    if (label.isBoolean())
        success = label.asBool();
    if (success == false)
        return true;

    pbnjson::JValue null_category = root["results"];

    if (null_category.isArray() && null_category.arraySize() == 0 ) {
        bool result = DB8_luna_call(replyInfo->m_serviceHandlePrivate, "luna://com.webos.service.db/put",
                "{\"objects\":[{\"_kind\":\"com.webos.settings.system:1\", \"value\":{}, \"app_id\":\"\", \"category\":\"\", \"volatile\":false}]}",
                PrefsDb8Init::cbCreateNullCategory, NULL, NULL, &lsError);

        if (!result) {
            SSERVICELOG_WARNING(MSGID_LSERROR_MSG, 2, PMLOGKS("Function",lsError.func), PMLOGKS("Error",lsError.message), "");
            LSErrorFree(&lsError);
        }
    }

    return true;
}

bool PrefsDb8Init::cbCreateNullCategory(LSHandle * sh, LSMessage * message, void *ctx)
{
    /* nothing to do */
    return true;
}

bool PrefsDb8Init::cbMergeInitKey(LSHandle * sh, LSMessage * message, void *ctx)
{
    bool success = false;
    PrefsDb8Init *replyInfo = (PrefsDb8Init *)ctx;

    do {
        const char *payload = LSMessageGetPayload(message);
        if (!payload) {
            SSERVICELOG_WARNING(MSGID_INIT_PAYLOAD_MISSING, 0, " ");
            break;
        }

        SSERVICELOG_TRACE("%s: %s", __FUNCTION__, payload);

        /* expected message format
           { "returnValue": true }
         */

        pbnjson::JValue root = pbnjson::JDomParser::fromString(payload);
        if (root.isNull()) {
            break;
        }

        pbnjson::JValue label = root["returnValue"];
        if (label.isBoolean())
            success = label.asBool();

        label = root["count"];
        if (!label.isNumber() || label.asNumber<int>() == 0 )
            success = false;

    } while(false);

    if (success != true) {
        SSERVICELOG_WARNING(MSGID_INIT_STATUS_UPDATE_FAIL, 0, " ");
        replyInfo->putInitKey();
    }
    else {
        SSERVICELOG_DEBUG("DB init status is set");
        PrefsKeyDescMap::instance()->initKeyDescMap();
    }

    return true;
}

bool PrefsDb8Init::cbPutInitKey(LSHandle * sh, LSMessage * message, void *ctx)
{
    bool success = false;

    do {
        const char *payload = LSMessageGetPayload(message);
        if (!payload) {
            SSERVICELOG_WARNING(MSGID_INIT_PAYLOAD_MISSING, 0, " ");
            break;
        }

        SSERVICELOG_TRACE("%s: %s", __FUNCTION__, payload);

        /* expected message format
           { "returnValue": true }
         */

        pbnjson::JValue root = pbnjson::JDomParser::fromString(payload);
        if (root.isNull()) {
            break;
        }

        pbnjson::JValue label = root["returnValue"];
        if (label.isBoolean())
            success = label.asBool();
    } while(false);

    if (success != true) {
        SSERVICELOG_WARNING(MSGID_INIT_STATUS_UPDATE_FAIL, 0, " ");
        PrefsFactory::instance()->serviceFailed(__PRETTY_FUNCTION__);
    }
    else {
        SSERVICELOG_DEBUG("DB init status is set");
        PrefsKeyDescMap::instance()->initKeyDescMap();
    }

    return true;
}

// TODO: loading file lists from /etc/palm/db/kinds
bool PrefsDb8Init::KindNameInfo::loadAllKindNameToDel(bool a_defaultOnly)
{
    kindNameList.clear();

    if (a_defaultOnly)
    {
        kindNameList.push_back(SETTINGSSERVICE_KIND_MAIN_VOLATILE);
        kindNameList.push_back(SETTINGSSERVICE_KIND_COUNTRY);           // FIXME: delete this?
        kindNameList.push_back(SETTINGSSERVICE_KIND_DEFAULT);
        kindNameList.push_back(SETTINGSSERVICE_KIND_DFLT_CTRY_DESC);    // FIXME: delete this?
        kindNameList.push_back(SETTINGSSERVICE_KIND_OVER_CTRY_DESC);
        kindNameList.push_back(SETTINGSSERVICE_KIND_DFLT_DESC);
        kindNameList.push_back(SETTINGSSERVICE_KIND_OVER_DESC);
    }
    else
    {
        kindNameList.push_back(SETTINGSSERVICE_KIND_MAIN_VOLATILE);
        kindNameList.push_back(SETTINGSSERVICE_KIND_MAIN);
        kindNameList.push_back(SETTINGSSERVICE_KIND_COUNTRY);           // For backward compatibility.
        kindNameList.push_back(SETTINGSSERVICE_KIND_DEFAULT);
        kindNameList.push_back(SETTINGSSERVICE_KIND_DFLT_CTRY_DESC);
        kindNameList.push_back(SETTINGSSERVICE_KIND_OVER_CTRY_DESC);
        kindNameList.push_back(SETTINGSSERVICE_KIND_DFLT_DESC);
        kindNameList.push_back(SETTINGSSERVICE_KIND_OVER_DESC);
        kindNameList.push_back(SETTINGSSERVICE_KIND_MAIN_DESC);
        kindNameList.push_back(SETTINGSSERVICE_KIND_DESC);
        kindNameList.push_back(SETTINGSSERVICE_KIND);
    }

    itemN = kindNameList.size();
    itCurKindName = kindNameList.end();

    return true;
}

bool PrefsDb8Init::KindNameInfo::loadAllKindNameToReg(bool a_defaultOnly)
{
    kindNameList.clear();

    /* There are any side effects even
     * settingsservice try to create already existed kind */

    kindNameList.push_back(SETTINGSSERVICE_KIND);
    kindNameList.push_back(SETTINGSSERVICE_KIND_DESC);
    kindNameList.push_back(SETTINGSSERVICE_KIND_MAIN_DESC);
    kindNameList.push_back(SETTINGSSERVICE_KIND_DFLT_DESC);
//    kindNameList.push_back(SETTINGSSERVICE_KIND_DFLT_CTRY_DESC);
    kindNameList.push_back(SETTINGSSERVICE_KIND_DEFAULT);
//    kindNameList.push_back(SETTINGSSERVICE_KIND_COUNTRY);
    kindNameList.push_back(SETTINGSSERVICE_KIND_MAIN);
    kindNameList.push_back(SETTINGSSERVICE_KIND_MAIN_VOLATILE);

    itemN = kindNameList.size();
    itCurKindName = kindNameList.end();

    return true;
}

bool PrefsDb8Init::KindNameInfo::loadVolatileKindName() {
    kindNameList.push_back(SETTINGSSERVICE_KIND_MAIN_VOLATILE);

    itemN = kindNameList.size();

    return true;
}

bool PrefsDb8Init::KindNameInfo::loadPermission() {
    kindNameList.clear();

    kindNameList.push_back(SETTINGSSERVICE_KIND_PERMISSION_MAIN);
    kindNameList.push_back(SETTINGSSERVICE_KIND_PERMISSION_DESC);

    itemN = kindNameList.size();
    itCurKindName = kindNameList.end();

    return true;
}

void PrefsDb8Init::KindNameInfo::getPermissionInfoNext(std::string& permissionPath) {

    if(itCurKindName == kindNameList.end()) {
        itCurKindName = kindNameList.begin();
    }
    else {
        itCurKindName++;
    }

    if(itCurKindName != kindNameList.end()) {
        permissionPath = PERMISSION_FILEPATH_BASE;
        permissionPath += *itCurKindName;
    }
    else {
        permissionPath = "";
    }
}

void PrefsDb8Init::KindNameInfo::getKindInfoNext(std::string& kindName, std::string& kindPath) {

    if(itCurKindName == kindNameList.end()) {
        itCurKindName = kindNameList.begin();
    }
    else {
        itCurKindName++;
    }

    if(itCurKindName != kindNameList.end()) {
        unsigned int pos;
        kindName = *itCurKindName;
        pos = kindName.find(":");
        kindPath = KINDFILEPATH_BASE;
        kindPath += kindName.substr(0,pos);
    }
    else {
        kindName = "";
        kindPath = "";
    }
}

max_stars_repo_name: webOS-ports/settingsservice

max_issues_repo_name: webOS-ports/settingsservice

max_forks_repo_name: webOS-ports/settingsservice


text:
#include <iostream>
#include <algorithm>
#include <future>
#include <stdlib.h>
#define BOOST_SPIRIT_THREADSAFE
#include <boost/regex.hpp>
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/json_parser.hpp>
#include <curl/curl.h>
#include "Simple-Web-Server/server_http.hpp"
#include "inotify-cxx/inotify-cxx.cpp"

using namespace std;
typedef SimpleWeb::Server<SimpleWeb::HTTP> HttpServer;

unsigned char from_hex(unsigned char ch)
{
  if (ch <= '9' && ch >= '0')
  ch -= '0';
  else if (ch <= 'f' && ch >= 'a')
  ch -= 'a' - 10;
  else if (ch <= 'F' && ch >= 'A')
  ch -= 'A' - 10;
  else
  ch = 0;
  return ch;
}

string urldecode(const string& str)
{
  string result;
  string::size_type i;
  for (i = 0; i < str.size(); ++i)
  {
    if (str[i] == '+')
    {
      result += ' ';
    }
    else if (str[i] == '%' && str.size() > i+2)
    {
      const unsigned char ch1 = from_hex(str[i+1]);
      const unsigned char ch2 = from_hex(str[i+2]);
      const unsigned char ch = (ch1 << 4) | ch2;
      result += ch;
      i += 2;
    }
    else
    {
      result += str[i];
    }
  }
  return result;
}

map<string, string> parse_url(std::string word)
{
  string::size_type pos;
  map<string, string> queries;

  for (pos = 0; pos < word.size(); ++pos)
  {
    if (word[pos] == '&')
    word[pos] = ' ';
  }

  istringstream sin(word);
  sin >> word;
  while (sin)
  {
    pos = word.find_first_of("=");
    if (pos != std::string::npos)
    {
      string key = urldecode(word.substr(0,pos));
      string value = urldecode(word.substr(pos+1));

      queries[key] = value;
    }
    sin >> word;
  }
  return queries;
}

string sendMsgToMinecraft(string request, string outToken, string service, string mm2m)
{
  auto params  = parse_url(request);

  auto team_id      = params["team_id"];
  auto team_domain  = params["team_domain"];

  auto channel_id   = params["channel_id"];
  auto channel_name = params["channel_name"];

  auto user_id      = params["user_id"];
  auto user_name    = params["user_name"];

  auto trigger_word = params["trigger_word"];
  auto text         = params["text"];

  auto timestamp    = params["timestamp"];
  auto token        = params["token"];

  boost::regex re1("\"");
  boost::regex re2("'");
  text = boost::regex_replace(text, re1, "\\\\u0022");
  text = boost::regex_replace(text, re2, "\\\\u0027");

  auto command = "service "+service+" command 'tellraw @a {\"text\":\"<"+mm2m+":"+user_name+"> "+text+"\"}'";
  system(command.c_str());

  cout << command << endl;

  return "HTTP/1.1 200 OK\r\nContent-Length: 0 \r\n\r\n";
}

void sendMsgToMattermost(string logMsg, string webhook, string m2mm, string iconUrl)
{
  boost::smatch what;
  boost::regex expression("^\\[[0-9]{2}:[0-9]{2}:[0-9]{2}\\] \\[Server thread\\/INFO\\]: <([^>]+)> (.+)$");
  if(boost::regex_match(logMsg, what, expression))
  {
    string username = what[1];
    string message = what[2];

    boost::regex re("\"");
    message = boost::regex_replace(message, re, "\\\\u0022");

    string payload = "payload={\"username\":\""+m2mm+":"+username+"\",\"icon_url\": \""+iconUrl+"\",\"text\":\""+message+"\"}";

    CURL *curl;
    CURLcode res;

    res = curl_global_init(CURL_GLOBAL_DEFAULT);
    curl = curl_easy_init();
    curl_easy_setopt(curl, CURLOPT_URL, webhook.c_str());
    curl_easy_setopt(curl, CURLOPT_POST, 1L);
    curl_easy_setopt(curl, CURLOPT_POSTFIELDS, payload.c_str());
    res = curl_easy_perform(curl);
    curl_easy_cleanup(curl);
    curl_global_cleanup();

    cout << payload << endl;
  }
}

int main()
{
  boost::property_tree::ptree config;
  int port, threads;
  string outToken, webhook, mc_log, service, m2mm, mm2m, iconUrl;
  try
  {
    boost::property_tree::read_json("config.json", config);

    port    = config.get<int>("port");
    threads = config.get<int>("threads");

    outToken= config.get<string>("token");
    service = config.get<string>("minecraft_service");
    mm2m    = config.get<string>("mattermost_to_minecraft_prefix");

    webhook = config.get<string>("webhook");
    mc_log  = config.get<string>("minecraft_log");
    m2mm    = config.get<string>("minecraft_to_mattermost_prefix");
    iconUrl = config.get<string>("icon_url");
  }
  catch(exception& e)
  {
    cout << "Error parsing config.json: " << e.what() << endl;
    return 1;
  }

  HttpServer server(port, threads);
  server.default_resource["POST"] = server.default_resource["GET"] = [outToken,service,mm2m](HttpServer::Response& response, shared_ptr<HttpServer::Request> request)
  {
    try
    {
      response << sendMsgToMinecraft(request->content.string(),outToken,service,mm2m);
    }
    catch(exception& e)
    {
      response << "HTTP/1.1 400 Bad Request\r\nContent-Length: " << strlen(e.what()) << "\r\n\r\n" << e.what();
    }
  };

  auto future = async(launch::async, [&server](){ server.start(); });

  condition_variable cv;
  atomic<bool> readLog(false);
  atomic<bool> running(true);
  Inotify notify;
  InotifyWatch watch(mc_log, IN_MODIFY);
  notify.Add(watch);

  thread worker([&cv,&running,&readLog,mc_log,webhook,m2mm,iconUrl]()
  {
    mutex mtx;
    std::unique_lock<std::mutex> lck(mtx);
    ifstream initLog(mc_log);
    string line;
    while (initLog >> ws && getline(initLog, line)); //get the last line
    initLog.seekg(0, initLog.end);
    auto oldPosition = initLog.tellg();
    initLog.close();

    while(running)
    {
        cv.wait(lck,[&readLog](){return readLog.load();});
        readLog.store(false);

        ifstream logFile(mc_log);
        logFile.seekg(0, logFile.end);
        auto newPosition = logFile.tellg();
        logFile.seekg(0, logFile.beg);
        if(oldPosition <= newPosition) logFile.seekg(oldPosition);

        do {
          getline(logFile, line);
          logFile >> ws;
          sendMsgToMattermost(line, webhook, m2mm, iconUrl);
        } while(logFile.good());

        oldPosition = newPosition;
        logFile.close();
    }
  });

  for (auto status = future.wait_for(chrono::milliseconds(0)); status != future_status::ready; status = future.wait_for(chrono::milliseconds(0))) {
    notify.WaitForEvents();
    readLog.store(true);
    cv.notify_one();
  }

  return 0;
}

ext: cpp


text:
#ifndef HPP_PIECE_NODE
#define HPP_PIECE_NODE

#include <boost/serialization/access.hpp>

#include <vector>
#include <limits>
#include <utility>

#include "piece.hpp"

class piece_node {
    enum direction {
        LEFT, RIGHT
    };

    size_t             d_point;
    piece_node*        d_left;
    piece_node*        d_right;
    std::vector<piece> d_pieces;

public:
    explicit piece_node(const std::vector<piece>& pieces)
        : d_point(0)
        , d_left(nullptr)
        , d_right(nullptr)
        , d_pieces()
    {
        d_point = median(pieces);
        std::vector<piece> to_left, to_right;

        for (const auto& p : pieces) {
            if (p.end() < d_point) {
                to_left.push_back(p);
            }
            else if (p.start() > d_point) {
                to_right.push_back(p);
            }
            else {
                d_pieces.push_back(p);
            }
        }

        if (to_left.size() > 0) {
            d_left = new piece_node(to_left);
        }
        if (to_right.size() > 0) {
            d_right = new piece_node(to_right);
        }
    }

    size_t median(const std::vector<piece>& pieces) const {
        auto start = std::numeric_limits<size_t>::max();
        auto end   = std::numeric_limits<size_t>::max();

        for (const auto& p : pieces) {
            auto cur_start = p.start();
            auto cur_end = p.end();

            if (start == std::numeric_limits<size_t>::max() || cur_start < start) {
                start = cur_start;
            }
            if (end == std::numeric_limits<size_t>::max() || cur_end > end) {
                end = cur_end;
            }
        }

        return (start + end) / 2;
    }

    std::vector<piece> overlaps(const piece& p) {
        std::vector<piece> overlaps;

        if (d_point < p.start()) {
            add_overlaps(p, overlaps, find_node_overlaps(d_right, p));
            add_overlaps(p, overlaps, overlaps_right(p));
        }
        else if (d_point > p.end()) {
            add_overlaps(p, overlaps, find_node_overlaps(d_left, p));
            add_overlaps(p, overlaps, overlaps_left(p));
        }
        else {
            add_overlaps(p, overlaps, d_pieces);
            add_overlaps(p, overlaps, find_node_overlaps(d_left, p));
            add_overlaps(p, overlaps, find_node_overlaps(d_right, p));
        }

        return std::vector<piece>(overlaps);
    }

protected:
    void add_overlaps(const piece& p, std::vector<piece>& overlaps, std::vector<piece> new_overlaps) const {
        for (const auto& cur : new_overlaps) {
            if (cur != p) {
                overlaps.push_back(cur);
            }
        }
    }

    std::vector<piece> overlaps_left(const piece& p) const {
        return std::vector<piece>(overlaps_direction(p, LEFT));
    }

    std::vector<piece> overlaps_right(const piece& p) const {
        return std::vector<piece>(overlaps_direction(p, RIGHT));
    }

    std::vector<piece> overlaps_direction(const piece& p, direction d) const {
        std::vector<piece> overlaps;

        for (const auto& cur : d_pieces) {
            switch (d) {
                case LEFT:
                    if (cur.start() <= p.end()) {
                        overlaps.push_back(cur);
                    }
                    break;

                case RIGHT:
                    if (cur.end() >= p.start()) {
                        overlaps.push_back(cur);
                    }
                    break;
            }
        }

        return std::vector<piece>(overlaps);
    }

    std::vector<piece> find_node_overlaps(piece_node* piece_node, const piece& p) const {
        if (piece_node) {
            return std::vector<piece>(piece_node->overlaps(p));
        }

        return std::vector<piece>();
    }

private:
    friend class boost::serialization::access;

    template <typename Archive>
    void serialize(Archive &ar, const unsigned int version) {
        ar & d_point;
        ar & d_left;
        ar & d_right;
        ar & d_pieces;
    }
};

#endif

ext: hpp


text:
//#include "convexdecomp.hpp"
#include <pcl/point_types.h>
#include <Eigen/Core>
#include <set>
#include <map>
#include <queue>
#include <boost/foreach.hpp>
#include <pcl/kdtree/kdtree_flann.h>
#include "sphere_sampling.hpp"
#include <iostream>
#include "utils/stl_to_string.hpp"
#include "convexdecomp.hpp"
using namespace pcl;
using namespace Eigen;
using namespace std;
using namespace util;

typedef Matrix<bool, Dynamic, Dynamic> MatrixXb;
typedef Matrix<bool, Dynamic, 1> VectorXb;
typedef vector<int> IntVec;
typedef set<int> IntSet;
typedef vector<float> FloatVec;
typedef map<int, int> Int2Int; // ass to ass
typedef map<int, IntSet> Int2IntSet;

//#define DEBUG_PRINT(...) printf(__VA_ARGS__)
#define DEBUG_PRINT(...)

namespace {

struct SupInfo {
  IntVec inds;
  FloatVec sups;
  float best;
};

vector<int> getNeighbors(const pcl::KdTreeFLANN<PointXYZ>& tree, int i_pt, int k_neighbs, float maxdist) {
  k_neighbs += 1;
  IntVec neighb_inds(k_neighbs, -666);
  FloatVec sqdists(k_neighbs, -666);
//  int n_neighbs = tree.nearestKSearch(i_pt, k_neighbs, neighb_inds, sqdists);
  int n_neighbs = tree.radiusSearch(i_pt, maxdist, neighb_inds, sqdists, k_neighbs);
  return vector<int>(neighb_inds.begin()+1, neighb_inds.begin() + n_neighbs);
}

}

namespace cloudproc {

void ConvexDecomp1(const pcl::PointCloud<pcl::PointXYZ>::ConstPtr& cloud, float thresh,
    /*optional outputs: */ std::vector<IntVec>* indices, std::vector< IntVec >* hull_indices) {
  MatrixXf dirs = getSpherePoints(1);
  ConvexDecomp(cloud, dirs, thresh, indices, hull_indices);
}

void ConvexDecomp(const pcl::PointCloud<pcl::PointXYZ>::ConstPtr& cloud, const Eigen::MatrixXf& dirs, float thresh,
    /*optional outputs: */ std::vector<IntVec>* indices, std::vector< IntVec >* hull_indices) {

  int k_neighbs = 5;
  pcl::KdTreeFLANN<pcl::PointXYZ>::Ptr tree (new pcl::KdTreeFLANN<pcl::PointXYZ>(true));
  tree->setEpsilon(0);
  tree->setInputCloud (cloud);
  int n_pts = cloud->size();
  int n_dirs = dirs.rows();

  DEBUG_PRINT("npts, ndirs %i %i\n", n_pts, n_dirs);

  MatrixXf dirs4(n_dirs, 4);
  dirs4.leftCols(3) = dirs;
  dirs4.col(3).setZero();
  MatrixXf pt2supports = Map< const Matrix<float, Dynamic, Dynamic,RowMajor > >(reinterpret_cast<const float*>(cloud->points.data()), n_pts, 4) * dirs4.transpose();

  const int UNLABELED = -1;
  IntVec pt2label(n_pts, UNLABELED);

  IntSet alldirs;
  for (int i=0; i < n_dirs; ++i) alldirs.insert(i);

  int i_seed=0;
  int i_label = 0;

  // each loop cycle, add a new cluster
  while (true) {

    // find first unlabeled point
    while (true) {
      if (i_seed == n_pts) return;
      if (pt2label[i_seed] == UNLABELED) break;
      ++i_seed;
    }

    pt2label[i_seed] = i_label;
    map<int, IntSet> pt2dirs;
    pt2dirs[i_seed] = alldirs;
    vector<SupInfo> dir2supinfo(n_dirs);
    for (int i_dir=0; i_dir < n_dirs; ++i_dir) {
      float seedsup = pt2supports(i_seed, i_dir);
      dir2supinfo[i_dir].inds.push_back(i_seed);
      dir2supinfo[i_dir].sups.push_back(seedsup);
      dir2supinfo[i_dir].best = seedsup;

    }

    DEBUG_PRINT("seed: %i\n", i_seed);

    IntSet exclude_frontier;
    exclude_frontier.insert(i_seed);
    queue<int> frontier;

    BOOST_FOREACH(const int& i_nb,  getNeighbors(*tree, i_seed, k_neighbs, 2*thresh)) {
      if (pt2label[i_nb]==UNLABELED && exclude_frontier.find(i_nb) == exclude_frontier.end()) {
        DEBUG_PRINT("adding %i to frontier\n", i_nb);
        frontier.push(i_nb);
        exclude_frontier.insert(i_nb);
      }
    }

    while (!frontier.empty()) {

#if 0 // for serious debugging
      vector<int> clu;
      BOOST_FOREACH(Int2IntSet::value_type& pt_dir, pt2dirs) {
        clu.push_back(pt_dir.first);
      }
      MatrixXd sup_pd(clu.size(), n_dirs);
      for (int i=0; i < clu.size(); ++i) {
        for (int i_dir = 0; i_dir < n_dirs; ++i_dir) {
          sup_pd(i,i_dir) = pt2supports(clu[i], i_dir);
        }
      }
      for (int i_dir=0; i_dir < n_dirs; ++i_dir) {
        IntSet nearext;
        for (int i=0; i < clu.size(); ++i) {
          if (sup_pd.col(i_dir).maxCoeff() - sup_pd(i,i_dir) < thresh) {
            nearext.insert(clu[i]);
          }
        }
        assert( toSet(dir2supinfo[i_dir].inds) == nearext );
      }
      printf("ok!\n");
#endif

      int i_cur = frontier.front();
      frontier.pop();
//      printf("cur: %i\n", i_cur);
      DEBUG_PRINT("pt2dirs %s", Str(pt2dirs).c_str());

      bool reject = false;

      Int2Int pt2decrement;
      for (int i_dir = 0; i_dir < n_dirs; ++i_dir) {
        float cursup = pt2supports(i_cur, i_dir);
        SupInfo& si = dir2supinfo[i_dir];
        if (cursup > si.best) {
          for (int i=0; i < si.inds.size(); ++i) {
            float sup = si.sups[i];
            int i_pt = si.inds[i];
            if (cursup - sup > thresh) {
              pt2decrement[i_pt] = pt2decrement[i_pt] + 1;
              DEBUG_PRINT("decrementing %i (dir %i)\n", i_pt, i_dir);
            }
          }
        }
      }

      DEBUG_PRINT("pt2dec: %s", Str(pt2decrement).c_str());

      BOOST_FOREACH(const Int2Int::value_type& pt_dec, pt2decrement) {
        if (pt_dec.second == pt2dirs[pt_dec.first].size()) {
          reject = true;
          break;
        }
      }

      DEBUG_PRINT("reject? %i\n", reject);
      if (!reject) {
        pt2label[i_cur] = i_label;
        pt2dirs[i_cur] = IntSet();
        for (int i_dir = 0; i_dir < n_dirs; ++i_dir) {
          float cursup = pt2supports(i_cur, i_dir);
          if (cursup > dir2supinfo[i_dir].best - thresh) pt2dirs[i_cur].insert(i_dir);
        }

        for (int i_dir = 0; i_dir < n_dirs; ++i_dir) {
          float cursup = pt2supports(i_cur, i_dir);
          SupInfo& si = dir2supinfo[i_dir];
          if (cursup > si.best) {

            IntVec filtinds;
            FloatVec filtsups;
            for (int i = 0; i < si.inds.size(); ++i) {
              float sup = si.sups[i];
              int i_pt = si.inds[i];
              if (cursup - sup > thresh) {
                pt2dirs[i_pt].erase(i_dir);
              }
              else {
                filtinds.push_back(i_pt);
                filtsups.push_back(sup);
              }
            }
            si.inds = filtinds;
            si.sups = filtsups;
            si.inds.push_back(i_cur);
            si.sups.push_back(cursup);
            si.best = cursup;
          }
          else if (cursup > si.best - thresh) {
            si.inds.push_back(i_cur);
            si.sups.push_back(cursup);
          }
        }
        BOOST_FOREACH(const int& i_nb,  getNeighbors(*tree, i_cur, k_neighbs, 2*thresh)) {
          if (pt2label[i_nb]==UNLABELED && exclude_frontier.find(i_nb) == exclude_frontier.end()) {
            DEBUG_PRINT("adding %i to frontier\n", i_nb);
            frontier.push(i_nb);
            exclude_frontier.insert(i_nb);
          }
        }

      } // if !reject
      else {
      }

    } // while frontier nonempty

    if (indices != NULL) {
      indices->push_back(IntVec());
      BOOST_FOREACH(Int2IntSet::value_type& pt_dir, pt2dirs) {
        indices->back().push_back(pt_dir.first);
      }
    }
    if (hull_indices != NULL) {
      hull_indices->push_back(IntVec());
      BOOST_FOREACH(Int2IntSet::value_type& pt_dirs, pt2dirs) {
        BOOST_FOREACH(const int& dir, pt_dirs.second) {
          if (pt2supports(pt_dirs.first, dir) == dir2supinfo[dir].best) {
            hull_indices->back().push_back(pt_dirs.first);
            break;
          }
        }
      }
      DEBUG_PRINT("hull size: %i/%i\n", hull_indices->back().size(), pt2dirs.size());
    }

    ++i_label;
  }

}

}

max_stars_repo_name: HARPLab/trajopt

max_issues_repo_name: HARPLab/trajopt

max_forks_repo_name: HARPLab/trajopt


text:
/**
 * Mapping Human Poses
 *
 * azure_kinect_bt_data_collect.cpp
 * @author Reid Sutherland
 * @date 09/20/19
 *
 * */

#include "azure_kinect_bt_data_collect.h"

#include <csignal>
#include <cstdlib>
#include <iostream>
#include <fstream>
#include <string.h>
#include <boost/program_options.hpp>

#define TIMEOUT_IN_MS 20;

using namespace std;
namespace po = boost::program_options;

// Device Capture Resources
k4a_device_t device = NULL;
extern k4a_device_configuration_t device_config = K4A_DEVICE_CONFIG_INIT_DISABLE_ALL;
//volatile extern k4a_capture_t device_capture = NULL;
extern k4a_capture_t device_capture = NULL;

// Body Tracking Resources
k4a_calibration_t sensor_calibration;
k4abt_tracker_t tracker = NULL;
extern k4abt_tracker_configuration_t tracker_config = K4ABT_TRACKER_CONFIG_DEFAULT;
//volatile extern k4abt_frame_t body_frame = NULL;
extern k4abt_frame_t body_frame = NULL;

// Configurations
int VERBOSE = 0;
int CONTINUOUS = 0;
int DURRATION = 10;
int DO_OUTPUT = 0;

std::ofstream TXT_FILE_OUT;

/*
*/
void sigHandler(int signal) {
	cout << "Intteruption Signal Detected. Closing and Releasing Resources" << endl << endl;

	if (TXT_FILE_OUT.is_open()) {
		TXT_FILE_OUT.close();
	}

	clean_up();

	exit(EXIT_FAILURE);

}

/*
*/
void _error_(void) {

	cout << "An error occured: Releasing resources: Exiting" << endl;
	clean_up();

	exit(EXIT_FAILURE);
}

/*
	*	init_device()
	*
	*	Initilizes Connected Device at DeviceIndex = 0
	*
	*	Returns 0
	*
*/
int init_device(void) {

	printf("Opening Azure Kinect Device for Capture\n");

	VERIFY(k4a_device_open(0, &device), "Opening of K4A Device Failed...");

	printf("Starting Camera with Depth Sensor Enabled\n");

	device_config.depth_mode = K4A_DEPTH_MODE_NFOV_UNBINNED;
	device_config.color_resolution = K4A_COLOR_RESOLUTION_OFF;

	VERIFY(k4a_device_start_cameras(device, &device_config), "Start K4A Device Cameras Failed...");

	return 0;

}

/*
	*	init_bt)
	*
	*	Initilizes Body Tracking Engine for Specific Device Parameters
	*
	*	Returns 0
	*
*/
int init_bt(void) {

	VERIFY(k4a_device_get_calibration(device, device_config.depth_mode, device_config.color_resolution, &sensor_calibration), "Get Depth Camera Calibration Failed...");

	VERIFY(k4abt_tracker_create(&sensor_calibration, tracker_config, &tracker), "Body Tracker Initialization Failed...");

	return 0;

}

/*
	*	clean_up()
	*
	*	Closes and Releases Resources
	*
	*
*/
void clean_up() {

	k4abt_tracker_shutdown(tracker);
	k4abt_tracker_destroy(tracker);
	k4a_device_stop_cameras(device);
	k4a_device_close(device);
}

/*
	*	get_device_bt_capture()
	*
	*	Captures One Frame from the Connected Device
	*	Passes Frame into Body Tracking Engine
	*		to Detect Body Skeletons
	*	Data is Placed in body_skel
	*
	*	@param  unsigned long* frame_number
	*				Pointer to Current Frame Number Counter
	*
	*	@param  k4abt_skeleton_t* body_skel
	*				Pointer to Body Skeleton Data
	*
	*	@onerror return -1
	*
	*	Returns 0
	*
*/
int get_device_bt_capture(unsigned long* frame_number, k4abt_skeleton_t* body_skel) {

	// Capture Wait Result
	k4a_wait_result_t capture_result = K4A_WAIT_RESULT_SUCCEEDED;
	k4a_wait_result_t q_capture_result = K4A_WAIT_RESULT_SUCCEEDED;
	k4a_wait_result_t pop_frame_result = K4A_WAIT_RESULT_SUCCEEDED;

	// Fet Sensor Capture from Device
	capture_result = k4a_device_get_capture(device, &device_capture, K4A_WAIT_INFINITE);

	if (q_capture_result == K4A_WAIT_RESULT_SUCCEEDED) {

		frame_number++;

		// Enque Sensor Capture Result tor Tracking
		q_capture_result = k4abt_tracker_enqueue_capture(tracker, device_capture, K4A_WAIT_INFINITE);

		// Relsease Sensor Capture after Use
		k4a_capture_release(device_capture);

		// Check Q Capture Result
		if (q_capture_result == K4A_WAIT_RESULT_TIMEOUT)
		{
			// It should never hit timeout when K4A_WAIT_INFINITE is set.
			printf("Error! Add capture to tracker process queue timeout!\n");
			return -1;
		}
		else if (q_capture_result == K4A_WAIT_RESULT_FAILED)
		{
			printf("Error! Add capture to tracker process queue failed!\n");
			return -1;
		}

		// Pop Body Tracking Result from Processed Queue
		pop_frame_result = k4abt_tracker_pop_result(tracker, &body_frame, K4A_WAIT_INFINITE);

		// Check Pop Frame Result
		if (pop_frame_result == K4A_WAIT_RESULT_SUCCEEDED)
		{
			// Successfully popped the body tracking result.

			size_t num_bodies = k4abt_frame_get_num_bodies(body_frame);
			printf("%zu bodies are detected!\n", num_bodies);

			k4abt_frame_get_body_skeleton(body_frame, 0, body_skel);

			k4abt_frame_release(body_frame); // Remember to release the body frame once you finish using it
		}
		else if (pop_frame_result == K4A_WAIT_RESULT_TIMEOUT)
		{
			//  It should never hit timeout when K4A_WAIT_INFINITE is set.
			printf("Error! Pop body frame result timeout!\n");
			return -1;
		}
		else
		{
			printf("Pop body frame result failed!\n");
			return -1;
		}

	}
	else if (capture_result == K4A_WAIT_RESULT_TIMEOUT)
	{
		// It should never hit time out when K4A_WAIT_INFINITE is set.
		printf("Error! Get depth frame time out!\n");
		return -1;
	}
	else
	{
		printf("Get depth capture returned error: %d\n", capture_result);
		return -1;
	}

	return 0;

}

/*
	*	print_body_skeleton()
	*
	*	Prints Body Skeleton Data to Output Console
	*
	*	@param  unsigned long seq_number
	*				Current Sequence Number Counter
	*
	*	@param  unsigned long frame_number
	*				Current Frame Number Counter
	*
	*	@param  k4abt_skeleton_t body_skel
	*				Body Skeleton Data
	*
	*	@onerror return -1
	*
	*	Returns 0
	*
*/
int print_body_skeleton(unsigned long seq_number, unsigned long frame_number, k4abt_skeleton_t body_skel) {

	printf("Body Skeliton Joint:\n");

	for (int i = 0; i < 25; i++) {

		cout << "\tJoint Position XYZ [mm]: " << endl;
		cout << "\t\tX: " << body_skel.joints[i].position.xyz.x << endl;
		cout << "\t\tY: " << body_skel.joints[i].position.xyz.y << endl;
		cout << "\t\tZ: " << body_skel.joints[i].position.xyz.z << endl;

		cout << "\tJoint Orrientation WXYZ: " << endl;
		cout << "\t\tW: " << body_skel.joints[i].orientation.wxyz.w << endl;
		cout << "\t\tX: " << body_skel.joints[i].orientation.wxyz.x << endl;
		cout << "\t\tY: " << body_skel.joints[i].orientation.wxyz.y << endl;
		cout << "\t\tZ: " << body_skel.joints[i].orientation.wxyz.z << endl;

		cout << "\tJoint Confidence: " << endl;

		switch(body_skel.joints[i].confidence_level){
			case K4ABT_JOINT_CONFIDENCE_NONE:
				cout << "\t\tK4ABT_JOINT_CONFIDENCE_NONE" << endl;
				break;
			case K4ABT_JOINT_CONFIDENCE_LOW:
				cout << "\t\tK4ABT_JOINT_CONFIDENCE_LOW" << endl;
				break;
			case K4ABT_JOINT_CONFIDENCE_MEDIUM:
				cout << "\t\tK4ABT_JOINT_CONFIDENCE_MEDIUM" << endl;
				break;
			case K4ABT_JOINT_CONFIDENCE_HIGH:
				cout << "\t\tK4ABT_JOINT_CONFIDENCE_HIGH" << endl;
				break;
			default:
				cout << "\t\tJoint Confidence Unknown:Error" << endl;
				break;
		}

		cout << "\n\n\n" << endl;

	}

	return 0;

}

/*
	*	parse_skeleton_to_txt()
	*
	*	Outputs Body Skeleton Data to Costom Format Text File
	*
	*	@param  unsigned long seq_number
	*				Current Sequence Number Counter
	*
	*	@param  unsigned long frame_number
	*				Current Frame Number Counter
	*
	*	@param  k4abt_skeleton_t body_skel
	*				Body Skeleton Data
	*
	*	@param  FILE* output_file
	*				FILE Pointer for Output File
	*
	*	@onerror return -1
	*
	*	Returns 0
	*
*/
int parse_skeleton_to_txt(unsigned long seq_number, unsigned long frame_number, k4abt_skeleton_t body_skel, std::ofstream& fileStream){

	char output_data[2048] = {'\0'};
	k4a_float3_t joint_pos;
	k4a_quaternion_t joint_orr;
	int joint_conf = K4ABT_JOINT_CONFIDENCE_NONE;

	if (!(fileStream.is_open())){
		cout << "Invalid call of parse_skeleton_to_txt(): File Not Specified" << endl << endl;
		return -1;
	}

	sprintf_s(output_data, sizeof(output_data), "%lu %lu : ", seq_number, frame_number);

	fileStream << output_data;

	//output_data = {'\0'};  Not sure of purpose

	for (int i = 0; i < 25; i++) {

		joint_pos = body_skel.joints[i].position;
		joint_orr = body_skel.joints[i].orientation;

		switch(body_skel.joints[i].confidence_level){
			case K4ABT_JOINT_CONFIDENCE_NONE:
				joint_conf = int(K4ABT_JOINT_CONFIDENCE_NONE);
				break;
			case K4ABT_JOINT_CONFIDENCE_LOW:
				joint_conf = int(K4ABT_JOINT_CONFIDENCE_LOW);
				break;
			case K4ABT_JOINT_CONFIDENCE_MEDIUM:
				joint_conf = int(K4ABT_JOINT_CONFIDENCE_MEDIUM);
				break;
			case K4ABT_JOINT_CONFIDENCE_HIGH:
				joint_conf = int(K4ABT_JOINT_CONFIDENCE_HIGH);
				break;
			default:
				joint_conf = int(K4ABT_JOINT_CONFIDENCE_NONE);
				break;
		}

		sprintf_s(output_data, sizeof(output_data), "%d %f %f %f %f %f %f %f %d : ", i, joint_pos.xyz.x, joint_pos.xyz.y, joint_pos.xyz.z, joint_orr.wxyz.w, joint_orr.wxyz.x, joint_orr.wxyz.y, joint_orr.wxyz.z, joint_conf);

		fileStream << output_data;

	}
	fileStream << endl;
	fileStream.flush();

	return 0;

}

/*
	*	parse_txt_to_skeleton()
	*
	*	Outputs Body Skeleton Data to Costom Format Text File
	*
	*	@param  unsigned long* seq_number
	*				Pointer to Current Sequence Number Counter
	*
	*	@param  unsigned long* frame_number
	*				Pointer to Current Frame Number Counter
	*
	*	@param  k4abt_skeleton_t* body_skel
	*				Pointer to Body Skeleton Data Structure
	*
	*	@param  char* input_data
	*				One Line of the Body Skeleton Data File
	*
	*	@onerror return -1
	*
	*	Returns 0
	*
*/
int parse_txt_to_skeleton(unsigned long* seq_number, unsigned long* frame_number, k4abt_skeleton_t* body_skel, char* input_data){

	k4a_float3_t joint_pos ;
	k4a_quaternion_t joint_orr;
	int joint_conf = K4ABT_JOINT_CONFIDENCE_NONE;
	char* parameter = NULL;
	char* next_parameter = NULL;

	float xyz_x = 0;
	float xyz_y = 0;
	float xyz_z = 0;
	float wxyz_w = 0;
	float wxyz_x = 0;
	float wxyz_y = 0;
	float wxyz_z = 0;
	int confidence = 0;

	if (input_data[0] == '\n'){
		cout << "End of Input Data File Reached" << endl << endl;
		return 1;
	}

	parameter = strtok_s(input_data, ":", &next_parameter);

	while(parameter != NULL){

		sscanf_s(parameter, "%lu %lu", seq_number, frame_number);

		for (int i = 0; i < 25; i++) {
			parameter = strtok_s(NULL, ":", &next_parameter);

			sscanf_s(parameter, "%*d %f %f %f %f %f %f %f %d",
				&xyz_x, &xyz_y, &xyz_z,
				&wxyz_w, &wxyz_x, &wxyz_y, &wxyz_z,
				&confidence
			);

			body_skel->joints[i].position.xyz.x = xyz_x;
			body_skel->joints[i].position.xyz.y = xyz_y;
			body_skel->joints[i].position.xyz.z = xyz_z;

			body_skel->joints[i].orientation.wxyz.w = wxyz_w;
			body_skel->joints[i].orientation.wxyz.x = wxyz_x;
			body_skel->joints[i].orientation.wxyz.y = wxyz_y;
			body_skel->joints[i].orientation.wxyz.z = wxyz_z;

			body_skel->joints[i].confidence_level = (k4abt_joint_confidence_level_t)confidence;
		}

	}

	return 0;

}

/*
	*	do_one()
	*
	*	Testing and Example for Capturing One
	*		Collection of Body Skeleton Data
	*
	*	Returns 0
	*
*/
int do_one() {

	k4abt_skeleton_t body_skel;
	unsigned long frame_number = 0;
	unsigned long seq_number = 0;

	if (-1 == get_device_bt_capture(&frame_number, &body_skel)) {
		cout << "An Error Occured Capturing a Body Skel" << endl << endl;
	}

	if (VERBOSE){
		print_body_skeleton(seq_number, frame_number, body_skel);
	}

	if (DO_OUTPUT) {
		parse_skeleton_to_txt(seq_number, frame_number, body_skel, TXT_FILE_OUT);
	}

	return 0;
}

/*
	*	do_continuous()
	*
	*	Testing and Example for Capturing Multiple
	*		Collection of Body Skeleton Data
	*
	*	@param  unsigned long seq_len
	*				Approxamate Durration of Continuous Capturing
	*
	*	Returns 0
	*
*/
int do_continuous(unsigned long seq_len) {

	k4abt_skeleton_t body_skel;
	unsigned long frame_number = 0;
	unsigned long seq_number = 0;
	unsigned long total_frames = 0;

	unsigned long num_frames_seq = device_config.camera_fps * seq_len;

	do {
		if (-1 == get_device_bt_capture(&frame_number, &body_skel)) {
			cout << "An Error Occured Capturing a Body Skel" << endl << endl;
		}

		if (VERBOSE){
			print_body_skeleton(seq_number, frame_number, body_skel);
		}

		if (DO_OUTPUT) {
			parse_skeleton_to_txt(seq_number, frame_number, body_skel, TXT_FILE_OUT);
		}

		//Sleep(1000);

		if (frame_number == num_frames_seq) {

			frame_number = 0;
			seq_number++;

		}
		else {
			frame_number += 1;
		}

		total_frames++;

	} while (seq_number < num_frames_seq);

	if (TXT_FILE_OUT.is_open()) {
		TXT_FILE_OUT.close();
	}

	return 0;
}

/*
	*	parse_user_input()
	*
	*	Parses User Input for Configuration Parameters
	*
	*	@param  int argc
	*				User Input Argument Count
	*	@param  char* argv
	*				User Input Arguments
	*
	*	Returns 0
	*
*/
void parse_user_input(po::variables_map vm){

	// File Specifier
	if (vm.count("-f")) {

		DO_OUTPUT = 1;
		TXT_FILE_OUT.open(vm["-f"].as<string>(), ostream::out | ostream::trunc);

	}

	// Verbose Mode
	if (vm.count("-v")) {

		VERBOSE = 1;

	}

	// Continuous Mode
	if (vm.count("-c")) {

		CONTINUOUS = 1;

	}

	// Durration Specifier
	if (vm.count("-d")) {

		DURRATION = vm["-d"].as<int>();

	}

}

/*
	*	print_usage()
	*
	*	Prints Usage Message
	*
	*
*/
void print_usage(void){

	cout << "USAGE: ./azure_kinect_bt_data_collect [-f <text file path> : Specifies the output file for skeleton data] [-c : Capture Continuously] [-v : Verbose Output] [-d <durration in seconds> : DURRATION, for continuous mode]" << endl << endl;

}

/*
	*	main()
	*
	*	Demo Operation of Data Collection Functionality
	*
	*
*/
int main(int argc, char* argv[]) {

	signal(SIGINT, sigHandler);

	// Setup User Input Parameters
	po::options_description desc("Allowed options");
	desc.add_options()
		("-f", po::value<string>(), "Output File Path")
		("-v", "Verbose Mode")
		("-c", "Continuous Mode")
		("-d", po::value<int>()->default_value(10), "Durration of Capture in Seconds")
		;

	po::variables_map vm;
	po::store(po::parse_command_line(argc, argv, desc), vm);
	po::notify(vm);

	// Parse User Input
	parse_user_input(vm);

	// Initialise Connected Device
	init_device();

	// Initialise Body Tracking Engine
	init_bt();

	// Run Operation Mode
	if (CONTINUOUS) {

		// Continuous Capture Mode
		do_continuous(DURRATION);

	}
	else {

		do_one();

	}

	printf("Finished Body Tracking Processing\n");

	// Close and Release Resources
	clean_up();

}


text:
#include "test.h"

#include <iostream>
#include <string>
#include <vector>

#include "baldr/graphreader.h"
#include "baldr/rapidjson_utils.h"
#include "baldr/tilehierarchy.h"
#include "midgard/encoded.h"
#include "midgard/util.h"
#include <boost/property_tree/ptree.hpp>

using namespace valhalla;
using namespace valhalla::baldr;
using namespace valhalla::midgard;

namespace std {
std::string to_string(const midgard::PointLL& p) {
  return "[" + to_string(p.first) + "," + to_string(p.second) + "]";
}
} // namespace std
namespace {

boost::property_tree::ptree get_conf() {
  std::stringstream ss;
  ss << R"({
      "mjolnir":{"tile_dir":"test/data/utrecht_tiles", "concurrency": 1},
      "loki":{
        "actions":["route"],
        "logging":{"long_request": 100},
        "service_defaults":{"minimum_reachability": 50,"radius": 0,"search_cutoff": 35000, "node_snap_tolerance": 5, "street_side_tolerance": 5, "heading_tolerance": 60}
      },
      "thor":{"logging":{"long_request": 100}},
      "odin":{"logging":{"long_request": 100}},
      "skadi":{"actons":["height"],"logging":{"long_request": 5}},
      "meili":{"customizable": ["turn_penalty_factor","max_route_distance_factor","max_route_time_factor","search_radius"],
              "mode":"auto","grid":{"cache_size":100240,"size":500},
              "default":{"beta":3,"breakage_distance":2000,"geometry":false,"gps_accuracy":5.0,"interpolation_distance":10,
              "max_route_distance_factor":5,"max_route_time_factor":5,"max_search_radius":200,"route":true,
              "search_radius":15.0,"sigma_z":4.07,"turn_penalty_factor":200}},
      "service_limits": {
        "auto": {"max_distance": 5000000.0, "max_locations": 20,"max_matrix_distance": 400000.0,"max_matrix_locations": 50},
        "auto_shorter": {"max_distance": 5000000.0,"max_locations": 20,"max_matrix_distance": 400000.0,"max_matrix_locations": 50},
        "bicycle": {"max_distance": 500000.0,"max_locations": 50,"max_matrix_distance": 200000.0,"max_matrix_locations": 50},
        "bus": {"max_distance": 5000000.0,"max_locations": 50,"max_matrix_distance": 400000.0,"max_matrix_locations": 50},
        "hov": {"max_distance": 5000000.0,"max_locations": 20,"max_matrix_distance": 400000.0,"max_matrix_locations": 50},
        "isochrone": {"max_contours": 4,"max_distance": 25000.0,"max_locations": 1,"max_time": 120},
        "max_avoid_locations": 50,"max_radius": 200,"max_reachability": 100,"max_alternates":2,
        "multimodal": {"max_distance": 500000.0,"max_locations": 50,"max_matrix_distance": 0.0,"max_matrix_locations": 0},
        "pedestrian": {"max_distance": 250000.0,"max_locations": 50,"max_matrix_distance": 200000.0,"max_matrix_locations": 50,"max_transit_walking_distance": 10000,"min_transit_walking_distance": 1},
        "skadi": {"max_shape": 750000,"min_resample": 10.0},
        "trace": {"max_distance": 200000.0,"max_gps_accuracy": 100.0,"max_search_radius": 100,"max_shape": 16000,"max_best_paths":4,"max_best_paths_shape":100},
        "transit": {"max_distance": 500000.0,"max_locations": 50,"max_matrix_distance": 200000.0,"max_matrix_locations": 50},
        "truck": {"max_distance": 5000000.0,"max_locations": 20,"max_matrix_distance": 400000.0,"max_matrix_locations": 50}
      }
    })";
  boost::property_tree::ptree conf;
  rapidjson::read_json(ss, conf);
  return conf;
}

void test_recover_shortcut_edges() {
  auto conf = get_conf();
  GraphReader graphreader(conf.get_child("mjolnir"));

  size_t total = 0;
  size_t bad = 0;

  // for each tile set per level
  for (const auto& level : TileHierarchy::levels()) {
    // we dont get shortcuts on level 2 and up
    if (level.first > 1)
      continue;

    // for each tile in the tile set
    auto tileset = graphreader.GetTileSet(level.first);
    for (const auto tileid : tileset) {
      printf("bad: %zu, total: %zu\n", bad, total);
      if (graphreader.OverCommitted())
        graphreader.Trim();

      // for each edge in the tile
      const auto* tile = graphreader.GetGraphTile(tileid);
      for (size_t j = 0; j < tile->header()->directededgecount(); ++j) {
        // skip it if its not a shortcut or the shortcut is one we will never traverse
        const auto* edge = tile->directededge(j);
        if (!edge->is_shortcut() || !(edge->forwardaccess() & kAutoAccess))
          continue;

        // we'll have the shape to compare to
        auto shortcut_shape = tile->edgeinfo(edge->edgeinfo_offset()).shape();
        if (!edge->forward())
          std::reverse(shortcut_shape.begin(), shortcut_shape.end());

        // make a graph id out of the shortcut to send to recover
        auto shortcutid = tileid;
        shortcutid.set_id(j);
        auto edgeids = graphreader.RecoverShortcut(shortcutid);

        // if it gave us back the shortcut we failed
        if (edgeids.front() == shortcutid) {
          /*throw std::logic_error("We couldnt recover the shortcut\nShortcut was: " +
                                 midgard::encode(shortcut_shape));*/
          ++bad;
          ++total;
          continue;
        }

        // accumulate the shape along the edges that we recovered
        std::vector<PointLL> recovered_shape;
        for (auto edgeid : edgeids) {
          const auto* tile = graphreader.GetGraphTile(edgeid);
          const auto* de = tile->directededge(edgeid);
          auto de_shape = tile->edgeinfo(de->edgeinfo_offset()).shape();
          if (!de->forward()) {
            std::reverse(de_shape.begin(), de_shape.end());
          }
          recovered_shape.insert(recovered_shape.end(),
                                 (de_shape.begin() + (recovered_shape.size() == 0 ? 0 : 1)),
                                 de_shape.end());
        }

        // check the number of coords match
        if (shortcut_shape.size() != recovered_shape.size()) {
          /*throw std::logic_error(
              "shape lengths do not match: " + std::to_string(shortcut_shape.size()) +
              " != " + std::to_string(recovered_shape.size()) +
              "\nShortcut was: " + midgard::encode(shortcut_shape) +
              "\nRecovered was: " + midgard::encode(recovered_shape));*/
          ++bad;
          ++total;
          continue;
        }

        // check if the shape matches approximatly
        for (size_t k = 0; k < shortcut_shape.size(); ++k) {
          if (!shortcut_shape[k].ApproximatelyEqual(recovered_shape[k])) {
            /*throw std::logic_error(
                "edge shape points are not equal: " + std::to_string(shortcut_shape[k]) +
                " != " + std::to_string(recovered_shape[k]) +
                "\nShortcut was: " + midgard::encode(shortcut_shape) +
                "\nRecovered was: " + midgard::encode(recovered_shape));*/
            ++bad;
            break;
          }
        }
        ++total;
      }
    }
  }
  printf("bad: %zu, total: %zu\n", bad, total);
  if (double(bad) / double(total) > .001)
    throw std::logic_error("More than 0.1% is too much");
}

} // namespace

int main(int argc, char* argv[]) {
  test::suite suite("recover_shortcut");

  // valhalla::midgard::logging::Configure({{"type", ""}});

  suite.test(TEST_CASE(test_recover_shortcut_edges));

  return suite.tear_down();
}

ext: cc

max_stars_repo_name: elsa-pato/valhalla

max_issues_repo_name: elsa-pato/valhalla

max_forks_repo_name: elsa-pato/valhalla


text:
/****************************************************************************
 *  Copyright (C) 2019 RoboMaster.
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU 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 General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program. If not, see <http://www.gnu.org/licenses/>.
 ***************************************************************************/
/*********************************************************************
 *
 * Software License Agreement (BSD License)
 *
 *  Copyright (c) 2008, 2013, Willow Garage, Inc.
 *  All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions
 *  are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *   * Redistributions in binary form must reproduce the above
 *     copyright notice, this list of conditions and the following
 *     disclaimer in the documentation and/or other materials provided
 *     with the distribution.
 *   * Neither the name of Willow Garage, Inc. nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 *  POSSIBILITY OF SUCH DAMAGE.
 *
 *********************************************************************/
#include <boost/algorithm/string.hpp>
#include <geometry_msgs/Point32.h>
#include "costmap_math.h"
#include "footprint.h"

namespace roborts_costmap {

void CalculateMinAndMaxDistances(const std::vector<geometry_msgs::Point> &footprint,
                                 double &min_dist,
                                 double &max_dist) {
  min_dist = std::numeric_limits<double>::max();
  max_dist = 0.0;

  if (footprint.size() <= 2) {
    return;
  }

  for (unsigned int i = 0; i < footprint.size() - 1; ++i) {
    // check the distance from the robot center point to the first vertex
    double vertex_dist = distance(0.0, 0.0, footprint[i].x, footprint[i].y);
    double edge_dist = Distance2Line(0.0, 0.0, footprint[i].x, footprint[i].y,
                                     footprint[i + 1].x, footprint[i + 1].y);
    min_dist = std::min(min_dist, std::min(vertex_dist, edge_dist));
    max_dist = std::max(max_dist, std::max(vertex_dist, edge_dist));
  }

  // we also need to do the last vertex and the first vertex
  double vertex_dist = distance(0.0, 0.0, footprint.back().x, footprint.back().y);
  double edge_dist = Distance2Line(0.0, 0.0, footprint.back().x, footprint.back().y,
                                   footprint.front().x, footprint.front().y);
  min_dist = std::min(min_dist, std::min(vertex_dist, edge_dist));
  max_dist = std::max(max_dist, std::max(vertex_dist, edge_dist));
}

geometry_msgs::Point32 ToPoint32(geometry_msgs::Point pt) {
  geometry_msgs::Point32 point32;
  point32.x = pt.x;
  point32.y = pt.y;
  point32.z = pt.z;
  return point32;
}

geometry_msgs::Point ToPoint(geometry_msgs::Point32 pt) {
  geometry_msgs::Point point;
  point.x = pt.x;
  point.y = pt.y;
  point.z = pt.z;
  return point;
}

geometry_msgs::Polygon ToPolygon(std::vector<geometry_msgs::Point> pts) {
  geometry_msgs::Polygon polygon;
  for (int i = 0; i < pts.size(); i++) {
    polygon.points.push_back(ToPoint32(pts[i]));
  }
  return polygon;
}

std::vector<geometry_msgs::Point> ToPointVector(geometry_msgs::Polygon polygon) {
  std::vector<geometry_msgs::Point> pts;
  for (int i = 0; i < polygon.points.size(); i++) {
    pts.push_back(ToPoint(polygon.points[i]));
  }
  return pts;
}

void TransformFootprint(double x, double y, double theta, const std::vector<geometry_msgs::Point> &footprint_spec,
                        std::vector<geometry_msgs::Point> &oriented_footprint) {
  // build the oriented footprint at a given location
  oriented_footprint.clear();
  double cos_th = cos(theta);
  double sin_th = sin(theta);
  for (unsigned int i = 0; i < footprint_spec.size(); ++i) {
    geometry_msgs::Point new_pt;
    new_pt.x = x + (footprint_spec[i].x * cos_th - footprint_spec[i].y * sin_th);
    new_pt.y = y + (footprint_spec[i].x * sin_th + footprint_spec[i].y * cos_th);
    oriented_footprint.push_back(new_pt);
  }
}

void TransformFootprint(double x, double y, double theta, const std::vector<geometry_msgs::Point> &footprint_spec,
                        geometry_msgs::PolygonStamped &oriented_footprint) {
  // build the oriented footprint at a given location
  oriented_footprint.polygon.points.clear();
  double cos_th = cos(theta);
  double sin_th = sin(theta);
  for (unsigned int i = 0; i < footprint_spec.size(); ++i) {
    geometry_msgs::Point32 new_pt;
    new_pt.x = x + (footprint_spec[i].x * cos_th - footprint_spec[i].y * sin_th);
    new_pt.y = y + (footprint_spec[i].x * sin_th + footprint_spec[i].y * cos_th);
    oriented_footprint.polygon.points.push_back(new_pt);
  }
}

void PadFootprint(std::vector<geometry_msgs::Point> &footprint, double padding) {
  // pad footprint in place
  for (unsigned int i = 0; i < footprint.size(); i++) {
    geometry_msgs::Point &pt = footprint[i];
    pt.x += sign0(pt.x) * padding;
    pt.y += sign0(pt.y) * padding;
  }
}

} //namespace roborts_costmap


text:
#pragma once
#include <mutex>

#include <boost/config.hpp>
#include <boost/signals2.hpp>

#include <ext/library_logger/logger.hpp>
#include <ext/net/subscription_controller.hpp>

namespace ext {
namespace net
{
	/// Abstract subscription_controller implementation: state_machine, futures.
	/// Actual pause/resume/close is delegated to derived class.
	/// On creation has opened state.
	///
	/// state protocol:
	///   * controller initializes connect request with do_connect_request,
	///     when connection is done - derived class notifies abstract_connection_controller via notify_connected.
	///   * controller initializes disconnect request do_disconnect_request,
	///     when disconnection is done - derived class notifies abstract_connection_controller via notify_disconnected notify_disconnected.
	///   * if connection is lost at any moment - derived class notifies abstract_connection_controller via notify_disconnected notify_disconnected.
	///   Cause of disconnection is stored in derived class(it's nature is implementation-specific).
	///
	/// NOTE: subscription_controller is an interface in fact.
	///       To support parallel hierarchies of interfaces and implementation - virtual inheritance must be used.
	class abstract_subscription_controller : public virtual subscription_controller
	{
	protected:
		typedef std::mutex mutex_type;
		typedef std::unique_lock<mutex_type> unique_lock;
		typedef boost::signals2::signal<event_slot::signature_type> signal_type;

	protected:
		mutable mutex_type m_mutex;
		state_type m_state = opened;
		delayed_state_type m_delayed_state = normal;
		signal_type m_event_signal;

		ext::intrusive_ptr<ext::shared_state<void>> m_close_future;
		ext::intrusive_ptr<ext::shared_state<bool>> m_pause_future, m_resume_future;

	protected:
		/// optional logger support, this method always will be called under m_mutex lock
		virtual ext::library_logger::logger * get_logger() const { return nullptr; }

	public:
		/// name of this object, used mainly for logging purposes
		virtual std::string_view name() const { return "<anonymous>"; }

	protected:
		/// BadTransactionRequest handler (see connection_controller description), throws std::logic_error
		/*virtual*/ void BOOST_NORETURN on_bad_transaction();
		/// unexpected handler currently does nothing
		/*virtual*/ void on_unexpected(state_type ev);

		/// Emits signal sig with state, default implementation just calls sig(state).
		/// Can be overridden to customize signal emission, for example, serialize and signal calls via GUI thread queue
		virtual void emit_signal(signal_type & sig, state_type state);

		/// close request implementation, state-machine lock is passed.
		/// call is done after state is changed.
		/// implementation can manipulate lock is it pleases,
		/// caller has no more need in lock - passed by value.
		virtual void do_close_request(unique_lock lk) = 0;
		/// pause request implementation, state-machine lock is passed.
		/// call is done after state is changed.
		/// implementation can manipulate lock is it pleases,
		/// caller has no more need in lock - passed by value.
		virtual void do_pause_request(unique_lock lk) = 0;
		/// resume request implementation, state-machine lock is passed.
		/// call is done after state is changed.
		/// implementation can manipulate lock is it pleases,
		/// caller has no more need in lock - passed by value.
		virtual void do_resume_request(unique_lock lk) = 0;

		/// Derived class notifies about successful close request. thread safe.
		/// On call takes lock (lk.owns_lock() == true)
		/// lock is unlocked in process before emitting signals.
		/// You should avoid calling this method with eptr != nullptr.
		virtual void notify_closed(unique_lock lk, std::exception_ptr eptr = nullptr);
		/// Derived class notifies about execution of pause request. thread safe.
		/// * if success == true request future is set with true
		/// * if success == false and eptr != null, request future is set with set_exception(eptr)
		/// * otherwise request future is set with false
		///
		/// On call takes lock (lk.owns_lock() == true)
		/// lock is unlocked in process before emitting signals.
		virtual void notify_paused(unique_lock lk, bool success = true, std::exception_ptr eptr = nullptr);
		/// Derived class notifies about execution of resume request. thread safe.
		/// * if success == true request future is set with true
		/// * if success == false and eptr != null, request future is set with set_exception(eptr)
		/// * otherwise request future is set with false
		///
		/// On call takes lock (lk.owns_lock() == true)
		/// lock is unlocked in process before emitting signals.
		virtual void notify_resumed(unique_lock lk, bool success = true, std::exception_ptr eptr = nullptr);

		/// close state-machine event implementation.
		/// assert(lk.owns_lock() == true)
		ext::shared_future<void> do_close(unique_lock lk);
		/// pause state-machine event implementation.
		/// assert(lk.owns_lock() == true)
		ext::shared_future<bool> do_pause(unique_lock lk);
		/// resume state-machine event implementation.
		/// assert(lk.owns_lock() == true)
		ext::shared_future<bool> do_resume(unique_lock lk);

		/// returns current state-machine state
		/// assert(lk.owns_lock() == true)
		state_type get_state(unique_lock & lk) { return  m_state; }

	public:
		/// current state of connection,
		/// actually it can be changed immediately after call.
		state_type get_state() override;
		/// Makes close request.
		/// Returns future<void> - result of connection
		ext::shared_future<void> close() override;
		/// Makes pause request.
		/// Returns future<bool> - result of connection
		/// @Throws std::logic_error, see class decription
		ext::shared_future<bool> pause() override;
		/// Makes resume request.
		/// Returns future<bool> - result of connection
		/// @Throws std::logic_error, see class decription
		ext::shared_future<bool> resume() override;
		/// event signal, event is identified with state_type
		boost::signals2::connection on_event(const event_slot & slot) override
		{ return m_event_signal.connect(slot); }

	public:
		abstract_subscription_controller();
		~abstract_subscription_controller() noexcept;
	};
}}

max_stars_repo_name: dmlys/netlib

max_issues_repo_name: dmlys/netlib

max_forks_repo_name: dmlys/netlib


text:
//---------------------------------------------------------------------------//
// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@gmail.com>
//
// 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
//
// See http://kylelutz.github.com/compute for more information.
//---------------------------------------------------------------------------//

#ifndef BOOST_COMPUTE_CONTAINER_VALARRAY_HPP
#define BOOST_COMPUTE_CONTAINER_VALARRAY_HPP

#include <cstddef>
#include <valarray>

#include <boost/compute/buffer.hpp>
#include <boost/compute/functional.hpp>
#include <boost/compute/algorithm/copy.hpp>
#include <boost/compute/algorithm/fill.hpp>
#include <boost/compute/algorithm/max_element.hpp>
#include <boost/compute/algorithm/min_element.hpp>
#include <boost/compute/algorithm/transform.hpp>
#include <boost/compute/algorithm/accumulate.hpp>
#include <boost/compute/detail/buffer_value.hpp>
#include <boost/compute/iterator/buffer_iterator.hpp>

namespace boost {
namespace compute {

template<class T>
class valarray
{
public:
    explicit valarray(const context &context = system::default_context())
        : m_buffer(context, 0)
    {
    }

    explicit valarray(size_t size,
                      const context &context = system::default_context())
        : m_buffer(context, size * sizeof(T))
    {
    }

    valarray(const T &value,
             size_t size,
             const context &context = system::default_context())
        : m_buffer(context, size * sizeof(T))
    {
        fill(begin(), end(), value);
    }

    valarray(const T *values,
             size_t size,
             const context &context = system::default_context())
        : m_buffer(context, size * sizeof(T))
    {
        copy(values, values + size, begin());
    }

    valarray(const valarray<T> &other)
        : m_buffer(other.m_buffer.get_context(), other.size() * sizeof(T))
    {
    }

    valarray(const std::valarray<T> &valarray,
             const context &context = system::default_context())
        : m_buffer(context, valarray.size() * sizeof(T))
    {
        copy(&valarray[0], &valarray[valarray.size()], begin());
    }

    valarray<T>& operator=(const valarray<T> &other)
    {
        if(this != &other){
            resize(other.size());
            copy(other.begin(), other.end(), begin());
        }

        return *this;
    }

    valarray<T>& operator=(const std::valarray<T> &valarray)
    {
        resize(valarray.size());
        copy(&valarray[0], &valarray[valarray.size()], begin());
    }

    ~valarray()
    {
    }

    size_t size() const
    {
        return m_buffer.size() / sizeof(T);
    }

    void resize(size_t size, T value = T())
    {
        m_buffer = buffer(m_buffer.get_context(), size * sizeof(T));
        fill(begin(), end(), value);
    }

    detail::buffer_value<T> operator[](size_t index)
    {
        return *(begin() + static_cast<ptrdiff_t>(index));
    }

    const detail::buffer_value<T> operator[](size_t index) const
    {
        return *(begin() + static_cast<ptrdiff_t>(index));
    }

    T (min)() const
    {
        return *(boost::compute::min_element(begin(), end()));
    }

    T (max)() const
    {
        return *(boost::compute::max_element(begin(), end()));
    }

    T sum() const
    {
        return boost::compute::accumulate(begin(), end(), T(0));
    }

    template<class UnaryFunction>
    valarray<T> apply(UnaryFunction function) const
    {
        valarray<T> result(size());
        transform(begin(), end(), result.begin(), function);
        return result;
    }

    const buffer& get_buffer() const
    {
        return m_buffer;
    }

private:
    buffer_iterator<T> begin() const
    {
        return buffer_iterator<T>(m_buffer, 0);
    }

    buffer_iterator<T> end() const
    {
        return buffer_iterator<T>(m_buffer, size());
    }

private:
    buffer m_buffer;
};

} // end compute namespace
} // end boost namespace

#endif // BOOST_COMPUTE_CONTAINER_VALARRAY_HPP

max_stars_repo_name: bastiankoe/compute

max_issues_repo_name: bastiankoe/compute

max_forks_repo_name: bastiankoe/compute


text:
//
// Copyright 2021 Autodesk
//
// 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 <mayaUsd/fileio/utils/shadingUtil.h>

#include <boost/python/class.hpp>
#include <boost/python/def.hpp>

PXR_NAMESPACE_USING_DIRECTIVE

class ShadingUtil
{
};

//----------------------------------------------------------------------------------------------------------------------
void wrapShadingUtil()
{
    boost::python::class_<ShadingUtil, boost::noncopyable>("ShadingUtil", boost::python::no_init)
        .def("GetStandardAttrName", &UsdMayaShadingUtil::GetStandardAttrName)
        .staticmethod("GetStandardAttrName");
}

max_stars_repo_name: sun-frog/maya-usd

max_issues_repo_name: sun-frog/maya-usd

max_forks_repo_name: sun-frog/maya-usd