<commit_before>/*
 *  Licensed to the Apache Software Foundation (ASF) under one or more
 *  contributor license agreements.  See the NOTICE file distributed with
 *  this work for additional information regarding copyright ownership.
 *  The ASF licenses this file to You under the Apache License, Version 2.0
 *  (the "License"); you may not use this file except in compliance with
 *  the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

#include <apr_file_io.h>
#include <apr_file_info.h>
#include <apr_strings.h>
#include "port_dso.h"
#include "port_filepath.h"
#include "port_sysinfo.h"

#define LOG_DOMAIN "init.properties"
#include "cxxlog.h"
#include "properties.h"
#include "vm_properties.h"
#include "init.h"
#include "native_modules.h"

inline char* unquote(char *str)
{
    const char *tokens = " \t\n\r\'\"";
    size_t i = strspn(str, tokens);
    str += i;
    char *p = str + strlen(str) - 1;
    while(strchr(tokens, *p) && p >= str)
        *(p--) = '\0';
    return str;
}

// local memory pool for temporary allocation
static apr_pool_t *prop_pool;

static const char *api_dll_files[] =
{
    "harmonyvm",
    "hythr",
#if !defined(HY_NO_SIG)
    "hysig",
#endif
    "hyprt",
#if defined(HY_LOCAL_ZLIB)
    "z",
#else
    "hyzlib",
#endif
    "hytext",
    "hynio",
    "vmi",
    "hyluni",
    "hyarchive"
};

#define GC_DLL "gc_gen"

/**
 *  Compose a string of file names each of them beginning with path,
 *  names separated by PORT_PATH_SEPARATOR.  If patch is NULL, no path
 *  or separator will be prefixed
 */
static char *compose_full_files_path_names_list(const char *path,
                                                const char **dll_names,
                                                const int names_number,
                                                bool is_dll)
{
    char* full_name = "";
    for (int iii = 0; iii < names_number; iii++)
    {
        const char *tmp = dll_names[iii];
        if (is_dll) {
            tmp = port_dso_name_decorate(tmp, prop_pool);
        }

        /*
         *  if the path is non-null, prefix, otherwise do nothing
         *  to avoid the problem of "/libfoo.so" when we don't want
         *  a path attached
         */

        if (path != NULL) {
            tmp = port_filepath_merge(path, tmp, prop_pool);
        }

        full_name = apr_pstrcat(prop_pool, full_name, tmp,
            (iii + 1 < names_number) ? PORT_PATH_SEPARATOR_STR : "", NULL);
    }

    return full_name;
}

static char* get_module_filename(void* code_ptr)
{
    native_module_t* modules;
    int modules_count;

#ifdef _IPF_
    // On IPF function pointer is not a pointer to a function, it is a pointer
    // to a table with first element of it the address of the funtion
    void **ptr = (void**)code_ptr;
    code_ptr = ptr[0];
#endif
    if (! get_all_native_modules(&modules, &modules_count))
        return NULL;

    native_module_t* module = find_native_module(modules, code_ptr);

    char* filename = NULL;

    if (NULL != module) {
        filename = apr_pstrdup(prop_pool, module->filename);
    }

    clear_native_modules(&modules);

    return filename;
}

static void init_java_properties(Properties & properties)
{
    //java part
    //!!! java.compiler property must be defined by EM

    char *os_name, *os_version, *path;
    const char *tmp;
    char *path_buf = NULL;

    port_OS_name_version(&os_name, &os_version, prop_pool);
    apr_filepath_get(&path, APR_FILEPATH_NATIVE, prop_pool);
    if (APR_SUCCESS != apr_temp_dir_get(&tmp, prop_pool)) {
        tmp = ".";
    }
    properties.set_new("java.version", "1.5.0");
    properties.set_new("java.vendor", "Apache Software Foundation");
    properties.set_new("java.vendor.url", "http://harmony.apache.org");

    // java.home initialization, try to find absolute location of the executable and set
    // java.home to the parent directory.
    char *launcher_dir;
    if (port_executable_name(&launcher_dir, prop_pool) != APR_SUCCESS) {
        LDIE(13, "Failed to find executable location");
    }

    properties.set_new("java.vm.specification.version", "1.0");
    properties.set_new("java.vm.specification.vendor", "Sun Microsystems Inc.");
    properties.set_new("java.vm.specification.name", "Java Virtual Machine Specification");
    properties.set_new("java.vm.version", "11.2.0");
    properties.set_new("java.vm.vendor", "Apache Software Foundation");
    properties.set_new("java.vm.name", "DRLVM");
    properties.set_new("java.runtime.name", "Apache Harmony");
    properties.set_new("java.runtime.version", "1.5.0");
    properties.set_new("java.specification.version", "1.5");
    properties.set_new("java.specification.vendor", "Sun Microsystems Inc.");
    properties.set_new("java.specification.name", "Java Platform API Specification");
    properties.set_new("java.class.version", EXPAND(CLASSFILE_MAJOR_MAX) "."
        EXPAND(CLASSFILE_MINOR_MAX));
    properties.set_new("java.class.path", ".");

    /*
    *  it's possible someone forgot to set this property - set to default of location of vm module
    */
    if (! properties.is_set(O_A_H_VM_VMDIR)) {
        char* vm_dir = get_module_filename((void*) &init_java_properties);

        if (NULL == vm_dir)
            LDIE(43, "ERROR: Can't determine vm module location. Please specify {0} property." << O_A_H_VM_VMDIR);

        char *p = strrchr(vm_dir, PORT_FILE_SEPARATOR);
        if (NULL == p)
            LDIE(43, "ERROR: Can't determine vm module location. Please specify {0} property." << O_A_H_VM_VMDIR);

        *p = '\0';

        properties.set(O_A_H_VM_VMDIR, vm_dir);
    }

    char* vm_dir = properties.get(O_A_H_VM_VMDIR);

    // home directory
    char* home_path = apr_pstrdup(prop_pool, vm_dir);
    char* p = strrchr(home_path, PORT_FILE_SEPARATOR);
    if (NULL == p)
        LDIE(15, "Failed to determine java home directory");
    *p = '\0';

    char* lib_path = apr_pstrcat(prop_pool, vm_dir,
            PORT_PATH_SEPARATOR_STR, home_path, NULL);

    p = strrchr(home_path, PORT_FILE_SEPARATOR);
    if (NULL == p)
        LDIE(15, "Failed to determine java home directory");
    *p = '\0';
    properties.set_new("java.home", home_path);

    properties.destroy(vm_dir);
    vm_dir = NULL;

    /*
     * This property is used by java/lang/Runtime#loadLibrary0 as path to
     * system native libraries.
     * The value is the location of launcher executable and vm binary directory
     */
    properties.set_new("vm.boot.library.path", lib_path);

    // Added for compatibility with the external java JDWP agent
    properties.set_new("sun.boot.library.path", lib_path);

    // java.library.path initialization, the value is the same as for
    // vm.boot.library.path appended with OS library search path
    char *env;
    if (APR_SUCCESS == port_dso_search_path(&env, prop_pool))
    {
        lib_path = apr_pstrcat(prop_pool, lib_path, PORT_PATH_SEPARATOR_STR,
                env, NULL);
    }
    properties.set_new("java.library.path", lib_path);
    //java.ext.dirs initialization.
    char *ext_path = port_filepath_merge(home_path, "lib" PORT_FILE_SEPARATOR_STR "ext", prop_pool);
    properties.set_new("java.ext.dirs", ext_path);
    properties.set_new("os.name", os_name);
    properties.set_new("os.arch", port_CPU_architecture());
    properties.set_new("os.version", os_version);
    properties.set_new("file.separator", PORT_FILE_SEPARATOR_STR);
    properties.set_new("path.separator", PORT_PATH_SEPARATOR_STR);
    properties.set_new("line.separator", APR_EOL_STR);
    // user.name initialization, try to get the name from the system
    char *user_buf;
    apr_status_t status = port_user_name(&user_buf, prop_pool);
    if (APR_SUCCESS != status) {
        LDIE(16, "Failed to get user name from the system. Error code {0}" << status);
    }
    properties.set_new("user.name", user_buf);
    // user.home initialization, try to get home from the system.
    char *user_home;
    status = port_user_home(&user_home, prop_pool);
    if (APR_SUCCESS != status) {
        LDIE(17, "Failed to get user home from the system. Error code {0}" << status);
    }
    properties.set_new("user.home", user_home);
    // java.io.tmpdir initialization.
    const char *tmpdir;
    status = apr_temp_dir_get(&tmpdir, prop_pool);
    if (APR_SUCCESS != status) {
        tmpdir = user_home;
    }
    properties.set_new("java.io.tmpdir", tmpdir);
    properties.set_new("user.dir", path);

    // FIXME??? other (not required by api specification) properties

    properties.set_new("java.vm.info", "no info");
    properties.set_new("java.tmpdir", tmp);

    // FIXME user.timezone initialization, required by java.util.TimeZone implementation
    char *user_tz;
    status = port_user_timezone(&user_tz, prop_pool);
    if (APR_SUCCESS != status) {
        INFO("Failed to get user timezone from the system. Error code " << status);
        user_tz = "GMT";
    }
    properties.set_new("user.timezone", user_tz);

    /*
    *  it's possible someone forgot to set this property - set to default of .
    */
    properties.set_new("java.class.path", ".");
}

//vm part
static void init_vm_properties(Properties & properties)
{
#ifdef _DEBUG
        properties.set_new("vm.assert_dialog", "true");
#else
        properties.set_new("vm.assert_dialog", "false");
#endif
        properties.set_new("vm.crash_handler", "false");
        properties.set_new("vm.finalize", "true");
        properties.set_new("vm.jit_may_inline_sync", "true");
        properties.set_new("vm.use_verifier", "true");
        properties.set_new("vm.jvmti.enabled", "false");
        properties.set_new("vm.jvmti.compiled_method_load.inlined", "false");
        properties.set_new("vm.bootclasspath.appendclasspath", "false");
        properties.set_new("gc.dll", PORT_DSO_NAME(GC_DLL));
        properties.set_new("thread.soft_unreservation", "false");

#ifdef POINTER64
        properties.set_new("vm.compress_references", "true");
#endif

        int n_api_dll_files = sizeof(api_dll_files) / sizeof(char *);
        /*
        *  pass NULL for the pathname as we don't want
        *  any path pre-pended
        */
        char* path_buf = compose_full_files_path_names_list(NULL, api_dll_files, n_api_dll_files, true);
        properties.set_new("vm.other_natives_dlls", path_buf);
}

jint initialize_properties(Global_Env * p_env)
{
    jint status = JNI_OK;

    if (!prop_pool) {
        apr_pool_create(&prop_pool, 0);
    }
/*
 * 1. Process command line options.
 * Java properties are set as -Dkey[=value];
 * VM properties are set with the following syntax ("fully compatible" with RI):
 * - options are set with -XX:<option>=<string>
 * - Boolean options may be turned on with -XX:+<option> and turned off with -XX:-<option>
 * - Numeric options are set with -XX:<option>=<number>.
 *   Numbers can include 'm' or 'M' for megabytes, 'k' or 'K' for kilobytes, and 'g' or
 *   'G' for gigabytes (for example, 32k is the same as 32768).
 */
    char *src, *tok;
    for (int arg_num = 0; arg_num < p_env->vm_arguments.nOptions; arg_num++)
    {
        char *option = p_env->vm_arguments.options[arg_num].optionString;
        if (strncmp(option, "-D", 2) == 0)
        {
            TRACE("setting property " << option + 2);
            src = strdup(option + 2);
            tok = strchr(src, '=');
            if(tok)
            {
                *tok = '\0';
                p_env->JavaProperties()->set(unquote(src), unquote(tok + 1));
            }
            else
            {
                p_env->JavaProperties()->set(unquote(src), "");
            }
            STD_FREE(src);
        }
        else if (strncmp(option, "-XD", 3) == 0)
        {
            WARN("Deprecated syntax to set internal property, use -XX:key=value instead: " << option);
            TRACE("setting internal property " << option + 3);
            src = strdup(option + 3);
            tok = strchr(src, '=');
            if(tok)
            {
                *tok = '\0';
                p_env->VmProperties()->set(unquote(src), unquote(tok + 1));
            }
            else
            {
                p_env->VmProperties()->set(unquote(src), "");
            }

            STD_FREE(src);
        }
        else if (strncmp(option, "-XX:", 4) == 0)
        {
            TRACE("setting internal property " << option + 4);
            src = strdup(option + 4);
            char* name = unquote(src);
            char* value = strchr(src, '=');
            if(value)
            {
                *value = '\0';
                ++value;
            }
            else
            {
                if (name[0] == '-' ) {
                    value = "off";
                    ++name;
                } else if (src[0] == '+') {
                    value = "on";
                    ++name;
                } else {
                    value = "";
                    LECHO(28, "Wrong option format {0}" << option);
                    status = JNI_ERR;
                }
            }

            TRACE("parsed internal property " << name << " = " << value << ";");
            p_env->VmProperties()->set(name, value);

            STD_FREE(src);

            if (status != JNI_OK) break;
        }
    }

/*
 * 2. Set predefined values to properties not defined via vm options.
 */
    if (status == JNI_OK)
    {
        init_java_properties(*p_env->JavaProperties());
        init_vm_properties(*p_env->VmProperties());
    }
    apr_pool_clear(prop_pool);
    return status;
}
<commit_msg>Removed hytext from preloads since it is no longer exists after revision 588195<commit_after>/*
 *  Licensed to the Apache Software Foundation (ASF) under one or more
 *  contributor license agreements.  See the NOTICE file distributed with
 *  this work for additional information regarding copyright ownership.
 *  The ASF licenses this file to You under the Apache License, Version 2.0
 *  (the "License"); you may not use this file except in compliance with
 *  the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

#include <apr_file_io.h>
#include <apr_file_info.h>
#include <apr_strings.h>
#include "port_dso.h"
#include "port_filepath.h"
#include "port_sysinfo.h"

#define LOG_DOMAIN "init.properties"
#include "cxxlog.h"
#include "properties.h"
#include "vm_properties.h"
#include "init.h"
#include "native_modules.h"

inline char* unquote(char *str)
{
    const char *tokens = " \t\n\r\'\"";
    size_t i = strspn(str, tokens);
    str += i;
    char *p = str + strlen(str) - 1;
    while(strchr(tokens, *p) && p >= str)
        *(p--) = '\0';
    return str;
}

// local memory pool for temporary allocation
static apr_pool_t *prop_pool;

static const char *api_dll_files[] =
{
    "harmonyvm",
    "hythr",
#if !defined(HY_NO_SIG)
    "hysig",
#endif
    "hyprt",
#if defined(HY_LOCAL_ZLIB)
    "z",
#else
    "hyzlib",
#endif
    "hynio",
    "vmi",
    "hyluni",
    "hyarchive"
};

#define GC_DLL "gc_gen"

/**
 *  Compose a string of file names each of them beginning with path,
 *  names separated by PORT_PATH_SEPARATOR.  If patch is NULL, no path
 *  or separator will be prefixed
 */
static char *compose_full_files_path_names_list(const char *path,
                                                const char **dll_names,
                                                const int names_number,
                                                bool is_dll)
{
    char* full_name = "";
    for (int iii = 0; iii < names_number; iii++)
    {
        const char *tmp = dll_names[iii];
        if (is_dll) {
            tmp = port_dso_name_decorate(tmp, prop_pool);
        }

        /*
         *  if the path is non-null, prefix, otherwise do nothing
         *  to avoid the problem of "/libfoo.so" when we don't want
         *  a path attached
         */

        if (path != NULL) {
            tmp = port_filepath_merge(path, tmp, prop_pool);
        }

        full_name = apr_pstrcat(prop_pool, full_name, tmp,
            (iii + 1 < names_number) ? PORT_PATH_SEPARATOR_STR : "", NULL);
    }

    return full_name;
}

static char* get_module_filename(void* code_ptr)
{
    native_module_t* modules;
    int modules_count;

#ifdef _IPF_
    // On IPF function pointer is not a pointer to a function, it is a pointer
    // to a table with first element of it the address of the funtion
    void **ptr = (void**)code_ptr;
    code_ptr = ptr[0];
#endif
    if (! get_all_native_modules(&modules, &modules_count))
        return NULL;

    native_module_t* module = find_native_module(modules, code_ptr);

    char* filename = NULL;

    if (NULL != module) {
        filename = apr_pstrdup(prop_pool, module->filename);
    }

    clear_native_modules(&modules);

    return filename;
}

static void init_java_properties(Properties & properties)
{
    //java part
    //!!! java.compiler property must be defined by EM

    char *os_name, *os_version, *path;
    const char *tmp;
    char *path_buf = NULL;

    port_OS_name_version(&os_name, &os_version, prop_pool);
    apr_filepath_get(&path, APR_FILEPATH_NATIVE, prop_pool);
    if (APR_SUCCESS != apr_temp_dir_get(&tmp, prop_pool)) {
        tmp = ".";
    }
    properties.set_new("java.version", "1.5.0");
    properties.set_new("java.vendor", "Apache Software Foundation");
    properties.set_new("java.vendor.url", "http://harmony.apache.org");

    // java.home initialization, try to find absolute location of the executable and set
    // java.home to the parent directory.
    char *launcher_dir;
    if (port_executable_name(&launcher_dir, prop_pool) != APR_SUCCESS) {
        LDIE(13, "Failed to find executable location");
    }

    properties.set_new("java.vm.specification.version", "1.0");
    properties.set_new("java.vm.specification.vendor", "Sun Microsystems Inc.");
    properties.set_new("java.vm.specification.name", "Java Virtual Machine Specification");
    properties.set_new("java.vm.version", "11.2.0");
    properties.set_new("java.vm.vendor", "Apache Software Foundation");
    properties.set_new("java.vm.name", "DRLVM");
    properties.set_new("java.runtime.name", "Apache Harmony");
    properties.set_new("java.runtime.version", "1.5.0");
    properties.set_new("java.specification.version", "1.5");
    properties.set_new("java.specification.vendor", "Sun Microsystems Inc.");
    properties.set_new("java.specification.name", "Java Platform API Specification");
    properties.set_new("java.class.version", EXPAND(CLASSFILE_MAJOR_MAX) "."
        EXPAND(CLASSFILE_MINOR_MAX));
    properties.set_new("java.class.path", ".");

    /*
    *  it's possible someone forgot to set this property - set to default of location of vm module
    */
    if (! properties.is_set(O_A_H_VM_VMDIR)) {
        char* vm_dir = get_module_filename((void*) &init_java_properties);

        if (NULL == vm_dir)
            LDIE(43, "ERROR: Can't determine vm module location. Please specify {0} property." << O_A_H_VM_VMDIR);

        char *p = strrchr(vm_dir, PORT_FILE_SEPARATOR);
        if (NULL == p)
            LDIE(43, "ERROR: Can't determine vm module location. Please specify {0} property." << O_A_H_VM_VMDIR);

        *p = '\0';

        properties.set(O_A_H_VM_VMDIR, vm_dir);
    }

    char* vm_dir = properties.get(O_A_H_VM_VMDIR);

    // home directory
    char* home_path = apr_pstrdup(prop_pool, vm_dir);
    char* p = strrchr(home_path, PORT_FILE_SEPARATOR);
    if (NULL == p)
        LDIE(15, "Failed to determine java home directory");
    *p = '\0';

    char* lib_path = apr_pstrcat(prop_pool, vm_dir,
            PORT_PATH_SEPARATOR_STR, home_path, NULL);

    p = strrchr(home_path, PORT_FILE_SEPARATOR);
    if (NULL == p)
        LDIE(15, "Failed to determine java home directory");
    *p = '\0';
    properties.set_new("java.home", home_path);

    properties.destroy(vm_dir);
    vm_dir = NULL;

    /*
     * This property is used by java/lang/Runtime#loadLibrary0 as path to
     * system native libraries.
     * The value is the location of launcher executable and vm binary directory
     */
    properties.set_new("vm.boot.library.path", lib_path);

    // Added for compatibility with the external java JDWP agent
    properties.set_new("sun.boot.library.path", lib_path);

    // java.library.path initialization, the value is the same as for
    // vm.boot.library.path appended with OS library search path
    char *env;
    if (APR_SUCCESS == port_dso_search_path(&env, prop_pool))
    {
        lib_path = apr_pstrcat(prop_pool, lib_path, PORT_PATH_SEPARATOR_STR,
                env, NULL);
    }
    properties.set_new("java.library.path", lib_path);
    //java.ext.dirs initialization.
    char *ext_path = port_filepath_merge(home_path, "lib" PORT_FILE_SEPARATOR_STR "ext", prop_pool);
    properties.set_new("java.ext.dirs", ext_path);
    properties.set_new("os.name", os_name);
    properties.set_new("os.arch", port_CPU_architecture());
    properties.set_new("os.version", os_version);
    properties.set_new("file.separator", PORT_FILE_SEPARATOR_STR);
    properties.set_new("path.separator", PORT_PATH_SEPARATOR_STR);
    properties.set_new("line.separator", APR_EOL_STR);
    // user.name initialization, try to get the name from the system
    char *user_buf;
    apr_status_t status = port_user_name(&user_buf, prop_pool);
    if (APR_SUCCESS != status) {
        LDIE(16, "Failed to get user name from the system. Error code {0}" << status);
    }
    properties.set_new("user.name", user_buf);
    // user.home initialization, try to get home from the system.
    char *user_home;
    status = port_user_home(&user_home, prop_pool);
    if (APR_SUCCESS != status) {
        LDIE(17, "Failed to get user home from the system. Error code {0}" << status);
    }
    properties.set_new("user.home", user_home);
    // java.io.tmpdir initialization.
    const char *tmpdir;
    status = apr_temp_dir_get(&tmpdir, prop_pool);
    if (APR_SUCCESS != status) {
        tmpdir = user_home;
    }
    properties.set_new("java.io.tmpdir", tmpdir);
    properties.set_new("user.dir", path);

    // FIXME??? other (not required by api specification) properties

    properties.set_new("java.vm.info", "no info");
    properties.set_new("java.tmpdir", tmp);

    // FIXME user.timezone initialization, required by java.util.TimeZone implementation
    char *user_tz;
    status = port_user_timezone(&user_tz, prop_pool);
    if (APR_SUCCESS != status) {
        INFO("Failed to get user timezone from the system. Error code " << status);
        user_tz = "GMT";
    }
    properties.set_new("user.timezone", user_tz);

    /*
    *  it's possible someone forgot to set this property - set to default of .
    */
    properties.set_new("java.class.path", ".");
}

//vm part
static void init_vm_properties(Properties & properties)
{
#ifdef _DEBUG
        properties.set_new("vm.assert_dialog", "true");
#else
        properties.set_new("vm.assert_dialog", "false");
#endif
        properties.set_new("vm.crash_handler", "false");
        properties.set_new("vm.finalize", "true");
        properties.set_new("vm.jit_may_inline_sync", "true");
        properties.set_new("vm.use_verifier", "true");
        properties.set_new("vm.jvmti.enabled", "false");
        properties.set_new("vm.jvmti.compiled_method_load.inlined", "false");
        properties.set_new("vm.bootclasspath.appendclasspath", "false");
        properties.set_new("gc.dll", PORT_DSO_NAME(GC_DLL));
        properties.set_new("thread.soft_unreservation", "false");

#ifdef POINTER64
        properties.set_new("vm.compress_references", "true");
#endif

        int n_api_dll_files = sizeof(api_dll_files) / sizeof(char *);
        /*
        *  pass NULL for the pathname as we don't want
        *  any path pre-pended
        */
        char* path_buf = compose_full_files_path_names_list(NULL, api_dll_files, n_api_dll_files, true);
        properties.set_new("vm.other_natives_dlls", path_buf);
}

jint initialize_properties(Global_Env * p_env)
{
    jint status = JNI_OK;

    if (!prop_pool) {
        apr_pool_create(&prop_pool, 0);
    }
/*
 * 1. Process command line options.
 * Java properties are set as -Dkey[=value];
 * VM properties are set with the following syntax ("fully compatible" with RI):
 * - options are set with -XX:<option>=<string>
 * - Boolean options may be turned on with -XX:+<option> and turned off with -XX:-<option>
 * - Numeric options are set with -XX:<option>=<number>.
 *   Numbers can include 'm' or 'M' for megabytes, 'k' or 'K' for kilobytes, and 'g' or
 *   'G' for gigabytes (for example, 32k is the same as 32768).
 */
    char *src, *tok;
    for (int arg_num = 0; arg_num < p_env->vm_arguments.nOptions; arg_num++)
    {
        char *option = p_env->vm_arguments.options[arg_num].optionString;
        if (strncmp(option, "-D", 2) == 0)
        {
            TRACE("setting property " << option + 2);
            src = strdup(option + 2);
            tok = strchr(src, '=');
            if(tok)
            {
                *tok = '\0';
                p_env->JavaProperties()->set(unquote(src), unquote(tok + 1));
            }
            else
            {
                p_env->JavaProperties()->set(unquote(src), "");
            }
            STD_FREE(src);
        }
        else if (strncmp(option, "-XD", 3) == 0)
        {
            WARN("Deprecated syntax to set internal property, use -XX:key=value instead: " << option);
            TRACE("setting internal property " << option + 3);
            src = strdup(option + 3);
            tok = strchr(src, '=');
            if(tok)
            {
                *tok = '\0';
                p_env->VmProperties()->set(unquote(src), unquote(tok + 1));
            }
            else
            {
                p_env->VmProperties()->set(unquote(src), "");
            }

            STD_FREE(src);
        }
        else if (strncmp(option, "-XX:", 4) == 0)
        {
            TRACE("setting internal property " << option + 4);
            src = strdup(option + 4);
            char* name = unquote(src);
            char* value = strchr(src, '=');
            if(value)
            {
                *value = '\0';
                ++value;
            }
            else
            {
                if (name[0] == '-' ) {
                    value = "off";
                    ++name;
                } else if (src[0] == '+') {
                    value = "on";
                    ++name;
                } else {
                    value = "";
                    LECHO(28, "Wrong option format {0}" << option);
                    status = JNI_ERR;
                }
            }

            TRACE("parsed internal property " << name << " = " << value << ";");
            p_env->VmProperties()->set(name, value);

            STD_FREE(src);

            if (status != JNI_OK) break;
        }
    }

/*
 * 2. Set predefined values to properties not defined via vm options.
 */
    if (status == JNI_OK)
    {
        init_java_properties(*p_env->JavaProperties());
        init_vm_properties(*p_env->VmProperties());
    }
    apr_pool_clear(prop_pool);
    return status;
}
<|endoftext|>


<commit_before>// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.

#include "sparse_tensor_match.h"

namespace vespalib {
namespace tensor {

namespace {

enum class AddressOp
{
    REMOVE,
    PAD,
    COPY
};

void
buildTransformOps(std::vector<AddressOp> &ops,
                  const eval::ValueType &lhs,
                  const eval::ValueType &rhs)
{
    auto rhsItr = rhs.dimensions().cbegin();
    auto rhsItrEnd = rhs.dimensions().cend();
    for (auto &lhsDim : lhs.dimensions()) {
        while (rhsItr != rhsItrEnd && rhsItr->name < lhsDim.name) {
            ops.push_back(AddressOp::PAD);
            ++rhsItr;
        }
        if (rhsItr != rhsItrEnd && rhsItr->name == lhsDim.name) {
            ops.push_back(AddressOp::COPY);
            ++rhsItr;
        } else {
            ops.push_back(AddressOp::REMOVE);
        }
    }
    while (rhsItr != rhsItrEnd) {
        ops.push_back(AddressOp::PAD);
        ++rhsItr;
    }
}

bool
transformAddress(SparseTensorAddressBuilder &builder,
                 SparseTensorAddressRef ref,
                 const std::vector<AddressOp> &ops)
{
    builder.clear();
    SparseTensorAddressDecoder addr(ref);
    for (auto op : ops) {
        switch (op) {
        case AddressOp::REMOVE:
        {
            auto label = addr.decodeLabel();
            if (label.size() != 0u) {
                return false;
            }
        }
        break;
        case AddressOp::PAD:
            builder.addUndefined();
            break;
        case AddressOp::COPY:
            builder.add(addr.decodeLabel());
        }
    }
    assert(!addr.valid());
    return true;
}

}

void
SparseTensorMatch::fastMatch(const TensorImplType &lhs,
                                const TensorImplType &rhs)
{
    for (const auto &lhsCell : lhs.cells()) {
        auto rhsItr = rhs.cells().find(lhsCell.first);
        if (rhsItr != rhs.cells().end()) {
            _builder.insertCell(lhsCell.first, lhsCell.second * rhsItr->second);
        }
    }
}

void
SparseTensorMatch::slowMatch(const TensorImplType &lhs,
                                const TensorImplType &rhs)
{
    std::vector<AddressOp> ops;
    SparseTensorAddressBuilder addressBuilder;
    SparseTensorAddressPadder addressPadder(_builder.fast_type(),
                                            lhs.fast_type());
    buildTransformOps(ops, lhs.fast_type(), rhs.fast_type());
    for (const auto &lhsCell : lhs.cells()) {
        if (!transformAddress(addressBuilder, lhsCell.first, ops)) {
            continue;
        }
        SparseTensorAddressRef ref(addressBuilder.getAddressRef());
        auto rhsItr = rhs.cells().find(ref);
        if (rhsItr != rhs.cells().end()) {
            addressPadder.padAddress(lhsCell.first);
            _builder.insertCell(addressPadder, lhsCell.second * rhsItr->second);
        }
    }
}

SparseTensorMatch::SparseTensorMatch(const TensorImplType &lhs,
                                           const TensorImplType &rhs)
    : Parent(lhs.combineDimensionsWith(rhs))
{
    if ((lhs.fast_type().dimensions().size() == rhs.fast_type().dimensions().size()) &&
        (lhs.fast_type().dimensions().size() == _builder.fast_type().dimensions().size())) {
        // Ensure that first tensor to fastMatch has fewest cells.
        if (lhs.cells().size() <= rhs.cells().size()) {
            fastMatch(lhs, rhs);
        } else {
            fastMatch(rhs, lhs);
        }
    } else {
        slowMatch(lhs, rhs);
    }
}

} // namespace vespalib::tensor
} // namespace vespalib
<commit_msg>Reserve space up front.<commit_after>// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.

#include "sparse_tensor_match.h"

namespace vespalib::tensor {

namespace {

enum class AddressOp
{
    REMOVE,
    PAD,
    COPY
};

void
buildTransformOps(std::vector<AddressOp> &ops,
                  const eval::ValueType &lhs,
                  const eval::ValueType &rhs)
{
    auto rhsItr = rhs.dimensions().cbegin();
    auto rhsItrEnd = rhs.dimensions().cend();
    for (auto &lhsDim : lhs.dimensions()) {
        while (rhsItr != rhsItrEnd && rhsItr->name < lhsDim.name) {
            ops.push_back(AddressOp::PAD);
            ++rhsItr;
        }
        if (rhsItr != rhsItrEnd && rhsItr->name == lhsDim.name) {
            ops.push_back(AddressOp::COPY);
            ++rhsItr;
        } else {
            ops.push_back(AddressOp::REMOVE);
        }
    }
    while (rhsItr != rhsItrEnd) {
        ops.push_back(AddressOp::PAD);
        ++rhsItr;
    }
}

bool
transformAddress(SparseTensorAddressBuilder &builder,
                 SparseTensorAddressRef ref,
                 const std::vector<AddressOp> &ops)
{
    builder.clear();
    SparseTensorAddressDecoder addr(ref);
    for (auto op : ops) {
        switch (op) {
        case AddressOp::REMOVE:
        {
            auto label = addr.decodeLabel();
            if (label.size() != 0u) {
                return false;
            }
        }
        break;
        case AddressOp::PAD:
            builder.addUndefined();
            break;
        case AddressOp::COPY:
            builder.add(addr.decodeLabel());
        }
    }
    assert(!addr.valid());
    return true;
}

}

void
SparseTensorMatch::fastMatch(const TensorImplType &lhs, const TensorImplType &rhs)
{
    _builder.reserve(lhs.cells().size());
    for (const auto &lhsCell : lhs.cells()) {
        auto rhsItr = rhs.cells().find(lhsCell.first);
        if (rhsItr != rhs.cells().end()) {
            _builder.insertCell(lhsCell.first, lhsCell.second * rhsItr->second);
        }
    }
}

void
SparseTensorMatch::slowMatch(const TensorImplType &lhs, const TensorImplType &rhs)
{
    std::vector<AddressOp> ops;
    SparseTensorAddressBuilder addressBuilder;
    SparseTensorAddressPadder addressPadder(_builder.fast_type(), lhs.fast_type());
    buildTransformOps(ops, lhs.fast_type(), rhs.fast_type());
    for (const auto &lhsCell : lhs.cells()) {
        if (!transformAddress(addressBuilder, lhsCell.first, ops)) {
            continue;
        }
        SparseTensorAddressRef ref(addressBuilder.getAddressRef());
        auto rhsItr = rhs.cells().find(ref);
        if (rhsItr != rhs.cells().end()) {
            addressPadder.padAddress(lhsCell.first);
            _builder.insertCell(addressPadder, lhsCell.second * rhsItr->second);
        }
    }
}

SparseTensorMatch::SparseTensorMatch(const TensorImplType &lhs, const TensorImplType &rhs)
    : Parent(lhs.combineDimensionsWith(rhs))
{
    if ((lhs.fast_type().dimensions().size() == rhs.fast_type().dimensions().size()) &&
        (lhs.fast_type().dimensions().size() == _builder.fast_type().dimensions().size())) {
        // Ensure that first tensor to fastMatch has fewest cells.
        if (lhs.cells().size() <= rhs.cells().size()) {
            fastMatch(lhs, rhs);
        } else {
            fastMatch(rhs, lhs);
        }
    } else {
        slowMatch(lhs, rhs);
    }
}

}
<|endoftext|>


<commit_before>/* The Next Great Finite Element Library. */
/* Copyright (C) 2003  Benjamin S. Kirk */

/* This library is free software; you can redistribute it and/or */
/* modify it under the terms of the GNU Lesser General Public */
/* License as published by the Free Software Foundation; either */
/* version 2.1 of the License, or (at your option) any later version. */

/* This library 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 */
/* Lesser General Public License for more details. */

/* You should have received a copy of the GNU Lesser General Public */
/* License along with this library; if not, write to the Free Software */
/* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */

 //
Introduction Example 1 - Creation of a Mesh Object

 //
 // This is the first example program.  It simply demonstrates
 // how to create a mesh object.  A mesh is read from file,
 // information is printed to the screen, and the mesh is then
 // written.

 // C++ include files that we need
#include <iostream>
// Functions to initialize the library.
#include "libmesh.h"
// Basic include files needed for the mesh functionality.
#include "mesh.h"

// Bring in everything from the libMesh namespace
using namespace libMesh;

int main (int argc, char** argv)
{
  // Initialize the library.  This is necessary because the library
  // may depend on a number of other libraries (i.e. MPI and PETSc)
  // that require initialization before use.  When the LibMeshInit
  // object goes out of scope, other libraries and resources are
  // finalized.
  LibMeshInit init (argc, argv);

  // Check for proper usage. The program is designed to be run
  // as follows:
  // ./ex1 -d DIM input_mesh_name [-o output_mesh_name]
  // where [output_mesh_name] is an optional parameter giving
  // a filename to write the mesh into.
  if (argc < 4)
    {
      if (libMesh::processor_id() == 0)
        std::cerr << "Usage: " << argv[0] << " -d 2 in.mesh [-o out.mesh]"
                  << std::endl;

      // This handy function will print the file name, line number,
      // and then abort.  Currently the library does not use C++
      // exception handling.
      libmesh_error();
    }

  // Get the dimensionality of the mesh from argv[2]
  const unsigned int dim = std::atoi(argv[2]);

  // Skip higher-dimensional examples on a lower-dimensional libMesh build
  libmesh_example_assert(dim <= LIBMESH_DIM, "2D/3D support");

  // Create a mesh
  Mesh mesh;

  // Read the input mesh.
  mesh.read (argv[3]);

  mesh.find_neighbors();

  // Print information about the mesh to the screen.
  mesh.print_info();

  // Write the output mesh if the user specified an
  // output file name.
  if (argc >= 6 && std::string("-o") == argv[4])
    mesh.write (argv[5]);

  // All done.  libMesh objects are destroyed here.  Because the
  // LibMeshInit object was created first, its destruction occurs
  // last, and it's destructor finalizes any external libraries and
  // checks for leaked memory.
  return 0;
}
<commit_msg>Remove redundant find_neighbors() call<commit_after>/* The Next Great Finite Element Library. */
/* Copyright (C) 2003  Benjamin S. Kirk */

/* This library is free software; you can redistribute it and/or */
/* modify it under the terms of the GNU Lesser General Public */
/* License as published by the Free Software Foundation; either */
/* version 2.1 of the License, or (at your option) any later version. */

/* This library 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 */
/* Lesser General Public License for more details. */

/* You should have received a copy of the GNU Lesser General Public */
/* License along with this library; if not, write to the Free Software */
/* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */

 //
Introduction Example 1 - Creation of a Mesh Object

 //
 // This is the first example program.  It simply demonstrates
 // how to create a mesh object.  A mesh is read from file,
 // information is printed to the screen, and the mesh is then
 // written.

 // C++ include files that we need
#include <iostream>
// Functions to initialize the library.
#include "libmesh.h"
// Basic include files needed for the mesh functionality.
#include "mesh.h"

// Bring in everything from the libMesh namespace
using namespace libMesh;

int main (int argc, char** argv)
{
  // Initialize the library.  This is necessary because the library
  // may depend on a number of other libraries (i.e. MPI and PETSc)
  // that require initialization before use.  When the LibMeshInit
  // object goes out of scope, other libraries and resources are
  // finalized.
  LibMeshInit init (argc, argv);

  // Check for proper usage. The program is designed to be run
  // as follows:
  // ./ex1 -d DIM input_mesh_name [-o output_mesh_name]
  // where [output_mesh_name] is an optional parameter giving
  // a filename to write the mesh into.
  if (argc < 4)
    {
      if (libMesh::processor_id() == 0)
        std::cerr << "Usage: " << argv[0] << " -d 2 in.mesh [-o out.mesh]"
                  << std::endl;

      // This handy function will print the file name, line number,
      // and then abort.  Currently the library does not use C++
      // exception handling.
      libmesh_error();
    }

  // Get the dimensionality of the mesh from argv[2]
  const unsigned int dim = std::atoi(argv[2]);

  // Skip higher-dimensional examples on a lower-dimensional libMesh build
  libmesh_example_assert(dim <= LIBMESH_DIM, "2D/3D support");

  // Create a mesh
  Mesh mesh;

  // Read the input mesh.
  mesh.read (argv[3]);

  // Print information about the mesh to the screen.
  mesh.print_info();

  // Write the output mesh if the user specified an
  // output file name.
  if (argc >= 6 && std::string("-o") == argv[4])
    mesh.write (argv[5]);

  // All done.  libMesh objects are destroyed here.  Because the
  // LibMeshInit object was created first, its destruction occurs
  // last, and it's destructor finalizes any external libraries and
  // checks for leaked memory.
  return 0;
}
<|endoftext|>


<commit_before>/*
 * The Biomechanical ToolKit
 * Copyright (c) 2009-2013, Arnaud Barré
 * 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(s) of the copyright holders 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 "btkForcePlatform.h"

namespace btk
{
  /**
   * @class ForcePlatform btkForcePlatform.h
   * @brief Base class for all type of force platform.
   *
   * This class is generic and doesn't know its type, nor the number of analog channels used.
   * To use predefined force platform as proposed in the documentation of the C3D file format, check the following classes:
   *  - btk::ForcePlatformType1: 6 channels (FX, FY, FZ, PX, PY, MZ);
   *  - btk::ForcePlatformType2: 6 channels (FX, FY, FZ, MX, MY, MZ);
   *  - btk::ForcePlatformType3: 8 channels (FZ1, FZ2, FZ3, FZ4, FX12, FX34, FY14, FY23);
   *  - btk::ForcePlatformType4: Same as Type-2 + calibration matrix 6 (columns) by 6 (rows);
   *  - btk::ForcePlatformType5: Same as Type-3 + calibration matrix 6 (columns) by 8 (rows);
   *  - btk::ForcePlatformType6: 12 channels (FX[1,2,3,4], FY[1,2,3,4], FZ[1,2,3,4] + calibration matrix 12 by 12).
   *
   * @ingroup BTKCommon
   */
  /**
   * @var ForcePlatform::m_Type
   * Type of the force platform. Used to determine necessary data for a particular force platform model.
   */
  /**
   * @var ForcePlatform::m_Channels
   * Channels of the force platform.
   */
  /**
   * @var ForcePlatform::m_CalMatrix
   * Calibrage matrix which could be used to correct cross talk between channels.
   */

  /**
   * @typedef ForcePlatform::Corners
   * Type which represents the coordinates of the four corners of the force platform.
   */

  /**
   * @typedef ForcePlatform::Corner
   * Type which represents the coordinates of one corner.
   */

  /**
   * @typedef ForcePlatform::Origin
   * Type which represents the origin of the force platform.
   */

  /**
   * @typedef ForcePlatform::CalMatrix
   * Type which represents a possible calibration matrix used with the force platform.
   */

  /**
   * @typedef ForcePlatform::Pointer
   * Smart pointer associated with a ForcePlatform object.
   */

  /**
   * @typedef ForcePlatform::ConstPointer
   * Smart pointer associated with a const ForcePlatform object.
   */

  /**
   * @typedef ForcePlatform::Iterator
   * Iterator for channels contained in the force platform object.
   */

  /**
   * @typedef ForcePlatform::ConstIterator
   * Const iterator for channels contained in the force platform object.
   */

  /**
   * @fn ForcePlatform::~ForcePlatform()
   * Empty destructor.
   */

  /**
   * @fn Iterator ForcePlatform::Begin()
   * Returns an iterator to the beginning of the list of items.
   */

  /**
   * @fn ConstIterator ForcePlatform::Begin() const
   * Returns a const iterator to the beginning of the list of items.
   */

  /**
   * @fn Iterator ForcePlatform::End()
   * Returns an iterator just past the last item.
   */

  /**
   * @fn ConstIterator ForcePlatform::End() const
   * Returns a const iterator just past the last item.
   */

  /**
   * @fn int ForcePlatform::GetChannelNumber() const
   * Returns the number of channels.
   */

  /**
   * @fn Analog::Pointer ForcePlatform::GetChannel(int idx) const
   * Returns the channel at the index @a idx.
   */

  /**
   * Sets the channel at the index @a idx by the object @a c.
   */
  void ForcePlatform::SetChannel(int idx, Analog::Pointer c)
  {
    if (this->m_Channels->SetItem(idx, c))
      this->Modified();
  }

  /**
   * @fn AnalogCollection::Pointer ForcePlatform::GetChannels() const
   * Returns force platform's channels.
   */

  /**
   * @fn Origin& ForcePlatform::GetOrigin()
   * Returns the origin of the force platform.
   *
   * @warning If you modify the object's content with this function, don't forget to call the Modified() method.
   */

  /**
   * @fn const Origin& ForcePlatform::GetOrigin() const
   * Returns the origin of the force platform.
   */

  /**
   * Sets the origin.
   */
  void ForcePlatform::SetOrigin(double x, double y, double z)
  {
    if ((this->m_Origin.x() == x)
        && (this->m_Origin.y() == y)
        && (this->m_Origin.z() == z))
      return;
    this->m_Origin.x() = x;
    this->m_Origin.y() = y;
    this->m_Origin.z() = z;
    this->Modified();
  };

  /**
   * Sets the origin.
   */
  void ForcePlatform::SetOrigin(const Origin& o)
  {
    if (this->m_Origin.isApprox(o))
      return;
    this->m_Origin = o;
    this->Modified();
  };

  /**
   * Returns the corner at index @a idx.
   */
  const ForcePlatform::Corner ForcePlatform::GetCorner(int idx) const
  {
    if (idx >= 4)
      throw OutOfRangeException("ForcePlatform::GetCorner");
    return this->m_Corners.col(idx);
  };

  /**
   * Sets the coordinate at position @a row and @a col with the value @a v.
   */
  void ForcePlatform::SetCorner(int row, int col, double v)
  {
    if ((row > 3) || (col > 4))
      throw OutOfRangeException("ForcePlatform::SetCorner");
    this->m_Corners.coeffRef(row, col) = v;
  };

  /**
   * Set the coordinates of the corner @a idx.
   */
  void ForcePlatform::SetCorner(int idx, double x, double y, double z)
  {
    if (idx >= 4)
      throw OutOfRangeException("ForcePlatform::SetCorner");
    Corner c = this->m_Corners.col(idx);
    if ((c.x() == x)
        && (c.y() == y)
        && (c.z() == z))
      return;
    this->m_Corners.coeffRef(0, idx) = x;
    this->m_Corners.coeffRef(1, idx) = y;
    this->m_Corners.coeffRef(2, idx) = z;
    this->Modified();
  };

  /**
   * Set the corner @a idx by @a c.
   */
  void ForcePlatform::SetCorner(int idx, const Corner& c)
  {
    if (idx >= 4)
      throw OutOfRangeException("ForcePlatform::SetCorner");
    if (this->m_Corners.col(idx).isApprox(c))
      return;
    this->m_Corners.col(idx) = c;
    this->Modified();
  };

  /**
   * @fn Corners& ForcePlatform::GetCorners()
   * Returns corners.
   *
   * @warning If you modify the object's content with this function, don't forget to call the Modified() method.
   */

  /**
   * @fn const Corners& ForcePlatform::GetCorners() const
   * Returns corners.
   */

  /**
   * Set corners by @a c.
   */
  void ForcePlatform::SetCorners(const Corners& c)
  {
    if (this->m_Corners.isApprox(c))
      return;
    this->m_Corners = c;
    this->Modified();
  };

  /**
   * @fn CalMatrix& ForcePlatform::GetCalMatrix()
   * Returns calibration marix.
   *
   * @warning If you modify the object's content with this function, don't forget to call the Modified() method.
   */

  /**
   * @fn const CalMatrix& ForcePlatform::GetCalMatrix() const
   * Returns the calibration matrix.
   */

  /**
   * Set the calibration matrix
   */
  void ForcePlatform::SetCalMatrix(const CalMatrix& cal)
  {
    if (this->m_CalMatrix.isApprox(cal))
      return;
    this->m_CalMatrix = cal;
    this->Modified();
  };

  /**
   * @fn int ForcePlatform::GetType() const
   * Returns the type of the force platform.
   */

  /**
   * @fn Pointer ForcePlatform::Clone() const
   * Clones the object and return it as new smart pointer.
   */

  /**
   * Constructor.
   */
  ForcePlatform::ForcePlatform()
  : DataObject(), m_Channels(), m_CalMatrix()
  {
    this->m_Origin << 0.0, 0.0, 0.0;
    // By default the force platform is square with a side length of 500mm.
    this->m_Corners << 1.0, 1.0, 0.0,
                      -1.0, 1.0, 0.0,
                      -1.0,-1.0, 0.0,
                       1.0,-1.0, 0.0;
    this->m_Corners *= 250;
    this->m_Channels = AnalogCollection::New();
    this->m_Type = 0;
  };

  ForcePlatform::ForcePlatform(const ForcePlatform& toCopy)
  : DataObject(toCopy), m_CalMatrix(toCopy.m_CalMatrix), m_Origin(toCopy.m_Origin), m_Corners(toCopy.m_Corners)
  {
    this->m_Channels = toCopy.m_Channels->Clone();
    this->m_Type = toCopy.m_Type;
  };
};<commit_msg>[FIX] Wrong initialization for the coordinates of the force plate corners.<commit_after>/*
 * The Biomechanical ToolKit
 * Copyright (c) 2009-2013, Arnaud Barré
 * 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(s) of the copyright holders 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 "btkForcePlatform.h"

namespace btk
{
  /**
   * @class ForcePlatform btkForcePlatform.h
   * @brief Base class for all type of force platform.
   *
   * This class is generic and doesn't know its type, nor the number of analog channels used.
   * To use predefined force platform as proposed in the documentation of the C3D file format, check the following classes:
   *  - btk::ForcePlatformType1: 6 channels (FX, FY, FZ, PX, PY, MZ);
   *  - btk::ForcePlatformType2: 6 channels (FX, FY, FZ, MX, MY, MZ);
   *  - btk::ForcePlatformType3: 8 channels (FZ1, FZ2, FZ3, FZ4, FX12, FX34, FY14, FY23);
   *  - btk::ForcePlatformType4: Same as Type-2 + calibration matrix 6 (columns) by 6 (rows);
   *  - btk::ForcePlatformType5: Same as Type-3 + calibration matrix 6 (columns) by 8 (rows);
   *  - btk::ForcePlatformType6: 12 channels (FX[1,2,3,4], FY[1,2,3,4], FZ[1,2,3,4] + calibration matrix 12 by 12).
   *
   * @ingroup BTKCommon
   */
  /**
   * @var ForcePlatform::m_Type
   * Type of the force platform. Used to determine necessary data for a particular force platform model.
   */
  /**
   * @var ForcePlatform::m_Channels
   * Channels of the force platform.
   */
  /**
   * @var ForcePlatform::m_CalMatrix
   * Calibrage matrix which could be used to correct cross talk between channels.
   */

  /**
   * @typedef ForcePlatform::Corners
   * Type which represents the coordinates of the four corners of the force platform.
   */

  /**
   * @typedef ForcePlatform::Corner
   * Type which represents the coordinates of one corner.
   */

  /**
   * @typedef ForcePlatform::Origin
   * Type which represents the origin of the force platform.
   */

  /**
   * @typedef ForcePlatform::CalMatrix
   * Type which represents a possible calibration matrix used with the force platform.
   */

  /**
   * @typedef ForcePlatform::Pointer
   * Smart pointer associated with a ForcePlatform object.
   */

  /**
   * @typedef ForcePlatform::ConstPointer
   * Smart pointer associated with a const ForcePlatform object.
   */

  /**
   * @typedef ForcePlatform::Iterator
   * Iterator for channels contained in the force platform object.
   */

  /**
   * @typedef ForcePlatform::ConstIterator
   * Const iterator for channels contained in the force platform object.
   */

  /**
   * @fn ForcePlatform::~ForcePlatform()
   * Empty destructor.
   */

  /**
   * @fn Iterator ForcePlatform::Begin()
   * Returns an iterator to the beginning of the list of items.
   */

  /**
   * @fn ConstIterator ForcePlatform::Begin() const
   * Returns a const iterator to the beginning of the list of items.
   */

  /**
   * @fn Iterator ForcePlatform::End()
   * Returns an iterator just past the last item.
   */

  /**
   * @fn ConstIterator ForcePlatform::End() const
   * Returns a const iterator just past the last item.
   */

  /**
   * @fn int ForcePlatform::GetChannelNumber() const
   * Returns the number of channels.
   */

  /**
   * @fn Analog::Pointer ForcePlatform::GetChannel(int idx) const
   * Returns the channel at the index @a idx.
   */

  /**
   * Sets the channel at the index @a idx by the object @a c.
   */
  void ForcePlatform::SetChannel(int idx, Analog::Pointer c)
  {
    if (this->m_Channels->SetItem(idx, c))
      this->Modified();
  }

  /**
   * @fn AnalogCollection::Pointer ForcePlatform::GetChannels() const
   * Returns force platform's channels.
   */

  /**
   * @fn Origin& ForcePlatform::GetOrigin()
   * Returns the origin of the force platform.
   *
   * @warning If you modify the object's content with this function, don't forget to call the Modified() method.
   */

  /**
   * @fn const Origin& ForcePlatform::GetOrigin() const
   * Returns the origin of the force platform.
   */

  /**
   * Sets the origin.
   */
  void ForcePlatform::SetOrigin(double x, double y, double z)
  {
    if ((this->m_Origin.x() == x)
        && (this->m_Origin.y() == y)
        && (this->m_Origin.z() == z))
      return;
    this->m_Origin.x() = x;
    this->m_Origin.y() = y;
    this->m_Origin.z() = z;
    this->Modified();
  };

  /**
   * Sets the origin.
   */
  void ForcePlatform::SetOrigin(const Origin& o)
  {
    if (this->m_Origin.isApprox(o))
      return;
    this->m_Origin = o;
    this->Modified();
  };

  /**
   * Returns the corner at index @a idx.
   */
  const ForcePlatform::Corner ForcePlatform::GetCorner(int idx) const
  {
    if (idx >= 4)
      throw OutOfRangeException("ForcePlatform::GetCorner");
    return this->m_Corners.col(idx);
  };

  /**
   * Sets the coordinate at position @a row and @a col with the value @a v.
   */
  void ForcePlatform::SetCorner(int row, int col, double v)
  {
    if ((row > 3) || (col > 4))
      throw OutOfRangeException("ForcePlatform::SetCorner");
    this->m_Corners.coeffRef(row, col) = v;
  };

  /**
   * Set the coordinates of the corner @a idx.
   */
  void ForcePlatform::SetCorner(int idx, double x, double y, double z)
  {
    if (idx >= 4)
      throw OutOfRangeException("ForcePlatform::SetCorner");
    Corner c = this->m_Corners.col(idx);
    if ((c.x() == x)
        && (c.y() == y)
        && (c.z() == z))
      return;
    this->m_Corners.coeffRef(0, idx) = x;
    this->m_Corners.coeffRef(1, idx) = y;
    this->m_Corners.coeffRef(2, idx) = z;
    this->Modified();
  };

  /**
   * Set the corner @a idx by @a c.
   */
  void ForcePlatform::SetCorner(int idx, const Corner& c)
  {
    if (idx >= 4)
      throw OutOfRangeException("ForcePlatform::SetCorner");
    if (this->m_Corners.col(idx).isApprox(c))
      return;
    this->m_Corners.col(idx) = c;
    this->Modified();
  };

  /**
   * @fn Corners& ForcePlatform::GetCorners()
   * Returns corners.
   *
   * @warning If you modify the object's content with this function, don't forget to call the Modified() method.
   */

  /**
   * @fn const Corners& ForcePlatform::GetCorners() const
   * Returns corners.
   */

  /**
   * Set corners by @a c.
   */
  void ForcePlatform::SetCorners(const Corners& c)
  {
    if (this->m_Corners.isApprox(c))
      return;
    this->m_Corners = c;
    this->Modified();
  };

  /**
   * @fn CalMatrix& ForcePlatform::GetCalMatrix()
   * Returns calibration marix.
   *
   * @warning If you modify the object's content with this function, don't forget to call the Modified() method.
   */

  /**
   * @fn const CalMatrix& ForcePlatform::GetCalMatrix() const
   * Returns the calibration matrix.
   */

  /**
   * Set the calibration matrix
   */
  void ForcePlatform::SetCalMatrix(const CalMatrix& cal)
  {
    if (this->m_CalMatrix.isApprox(cal))
      return;
    this->m_CalMatrix = cal;
    this->Modified();
  };

  /**
   * @fn int ForcePlatform::GetType() const
   * Returns the type of the force platform.
   */

  /**
   * @fn Pointer ForcePlatform::Clone() const
   * Clones the object and return it as new smart pointer.
   */

  /**
   * Constructor.
   */
  ForcePlatform::ForcePlatform()
  : DataObject(), m_Channels(), m_CalMatrix()
  {
    this->m_Origin << 0.0, 0.0, 0.0;
    // By default the force platform is square with a side length of 500mm.
    this->m_Corners << 1.0, -1.0, -1.0,  1.0,
                       1.0,  1.0, -1.0, -1.0,
                       0.0,  0.0,  0.0,  0.0;
    this->m_Corners *= 250;
    this->m_Channels = AnalogCollection::New();
    this->m_Type = 0;
  };

  ForcePlatform::ForcePlatform(const ForcePlatform& toCopy)
  : DataObject(toCopy), m_CalMatrix(toCopy.m_CalMatrix), m_Origin(toCopy.m_Origin), m_Corners(toCopy.m_Corners)
  {
    this->m_Channels = toCopy.m_Channels->Clone();
    this->m_Type = toCopy.m_Type;
  };
};<|endoftext|>


<commit_before><commit_msg>change level-0 file sort strategy<commit_after><|endoftext|>


<commit_before>// Copyright (c)2008-2012, Preferred Infrastructure 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 Preferred Infrastructure nor the names of other
//       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 "parser.h"

#include <iostream>
#include <new>
#include <stack>
#include <cerrno>
#include <climits>
#include <cmath>
#include <cstring>
#include <cstdio>
#include <cstdlib>

#include "../../lang/exception.h"

namespace pfi {
namespace text {
namespace json {

class json_builder : public json_parser::callback {
public:
  const json& get() const {
    if (stk.size() != 1)
      throw pfi::lang::parse_error();
    return stk[0];
  }

  void null() {
    stk.push_back(new json_null());
  }

  void boolean(bool val) {
    stk.push_back(new json_bool(val));
  }

  void integer(int64_t val) {
    stk.push_back(new json_integer(val));
  }

  void number(double val) {
    stk.push_back(new json_float(val));
  }

  void string(const char* val, size_t len) {
    stk.push_back(new json_string(std::string(val, val+len)));
  }

  void start_object() {
    ixs.push(stk.size());
  }
  void object_key(const char* val, size_t len) {
    key.push_back(std::string(val, val+len));
  }
  void end_object() {
    json obj(new json_object());
    int ix = ixs.top();
    int jx = stk.size();
    int sz = jx - ix;
    for (int i = 0; i < sz; i++)
      obj.add(key[key.size() - sz + i], stk[ix + i]);
    stk.push_back(obj);
    stk.erase(stk.end() - sz - 1, stk.end() - 1);
    key.erase(key.end() - sz, key.end());
    ixs.pop();
  }

  void start_array() {
    ixs.push(stk.size());
  }
  void end_array() {
    json obj(new json_array());
    int ix = ixs.top();
    int jx = stk.size();
    int sz = jx - ix;
    for (int i = 0; i < sz; i++)
      obj.add(stk[ix + i]);
    stk.push_back(obj);
    stk.erase(stk.end() - sz - 1, stk.end() - 1);
    ixs.pop();
  }

  std::vector<json> stk;
  std::vector<std::string> key;

  std::stack<int> ixs;
};

json_parser::json_parser(std::istream& is)
  : is(is), it(is), end(), lineno(1), charno(1), cbuf(-1)
{
  buf_len = 256;
  if ((buf = static_cast<char*>(malloc(buf_len))) == 0)
    throw std::bad_alloc();
}

json_parser::~json_parser()
{
  free(buf);
}

json json_parser::parse()
{
  json_builder jb;
  parse_stream(jb);
  return jb.get();
}

void json_parser::parse_stream(callback& cb)
{
  ss();
  if (it == end)
    throw lang::end_of_data("json_parser reached end of data");
  return parse_impl(cb);
}

void json_parser::parse_impl(callback& cb)
{
  ss();
  switch(peek()) {
  case '{':
    parse_object(cb);
    return;

  case '[':
    parse_array(cb);
    return;

  case '0': case '1': case '2': case '3': case '4':
  case '5': case '6': case '7': case '8': case '9':
  case '-':
    parse_number(cb);
    return;

  case '\"':
    parse_string(cb);
    return;

  case 'f':
    parse_false(cb);
    return;
  case 'n':
    parse_null(cb);
    return;
  case 't':
    parse_true(cb);
    return;

  default: {
    char err_msg[64];
    snprintf(err_msg, sizeof(err_msg),
             "invalid char: \'%s\' (U+%04X)",
             pfi::data::string::uchar_to_string(peek()).c_str(), peek());
    error(err_msg);
  }

  }
  return; // dmy for supressing warning
}

void json_parser::parse_object(callback& cb)
{
  cb.start_object();

  smatch('{');

  for (int i = 0; ; i++) {
    if (speek() == '}')
      break;
    if (i > 0)
      smatch(',');

    ss();
    int len = 0;
    parse_string_prim(buf, buf_len, len);
    cb.object_key(buf, len);
    smatch(':');
    parse_impl(cb);
  }

  smatch('}');

  cb.end_object();
}

void json_parser::parse_array(callback& cb)
{
  cb.start_array();

  smatch('[');

  for (int i = 0; ; i++) {
    if (speek() == ']')
      break;
    if (i > 0)
      smatch(',');

    parse_impl(cb);
  }

  smatch(']');

  cb.end_array();
}

void json_parser::parse_number(callback& cb)
{
  std::string src;
  bool is_frac = false;

  if (it != end && peek() == '-') {
    src += '-';
    incr();
  }

  while (it != end && safe_isdigit(peek())) {
    src += peek();
    incr();
  }

  if (it != end && peek() == '.') {
    is_frac = true;
    src += '.';
    incr();
    while (it != end && safe_isdigit(peek())) {
      src += peek();
      incr();
    }
  }

  if (it != end && (peek() == 'e' || peek() == 'E')) {
    is_frac = true;
    src += peek();
    incr();

    if (it == end)
      error("after exp, digit required.");

    if (peek() == '+' || peek() == '-') {
      src += peek();
      incr();
    }
  }

  while (it != end && safe_isdigit(peek())) {
    src += peek();
    incr();
  }

  const char *srcptr = src.c_str();
  char *endptr;

  if (is_frac) {
    errno = 0;
    double num = strtod(srcptr, &endptr);
    if (errno == ERANGE) {
      if (num == HUGE_VALF || num == HUGE_VALL)
        error("strtod overflow range over. Too huge value for double.");
      else if (num == 0.0)
        error("strtod underflow range over.");
      error("strtod range over.");
    }
    cb.number(num);
  } else {
    errno = 0;
    int64_t num = strtoll(srcptr, &endptr, 10);
    if (errno == ERANGE) {
      if (num == LLONG_MAX || num == LLONG_MIN)
        error("strtoll overflow range over. Too huge value for int64_t.");
      else if (num == 0)
        error("strtoll underflow range over.");
      error("strtoll range over.");
    }
    cb.integer(num);
  }
}

void json_parser::parse_string(callback& cb)
{
  int len = 0;
  parse_string_prim(buf, buf_len, len);
  cb.string(buf, len);
}

void json_parser::parse_string_prim(char*& buf, int& buf_len, int& str_len)
{
  char* p = buf;

  match('\"');

  for (;;) {
    if (p+8 >= buf+buf_len) {
      size_t adv = p - buf;
      if (char* newbuf = static_cast<char*>(realloc(buf, 2*buf_len)))
        buf = newbuf;
      else
        throw std::bad_alloc();
      buf_len *= 2;
      p = buf + adv;
    }

    if (peek() == '\"')
      break;

    if (peek() == '\\') {
      incr();

      int c = incr();

      switch (c) {
      case '\"': *p++ = '\"'; break;
      case '\\': *p++ = '\\'; break;
      case '/':  *p++ = '/';  break;
      case 'b':  *p++ = '\b'; break;
      case 'f':  *p++ = '\f'; break;
      case 'n':  *p++ = '\n'; break;
      case 'r':  *p++ = '\r'; break;
      case 't':  *p++ = '\t'; break;

      case 'u': {
        int a = parse_hex();
        int b = parse_hex();
        int c = parse_hex();
        int d = parse_hex();
        pfi::data::string::uchar_to_chars((a<<12)|(b<<8)|(c<<4)|d, p);
        break;
      }

      default: {
        char err_msg[64];
        snprintf(err_msg, sizeof(err_msg),
                 "unexpected unescaped char: \'%s\' (U+%04X)",
                 pfi::data::string::uchar_to_string(c).c_str(), c);
        error(err_msg);
      }

      }
    }
    else {
      int c = incr();

      if ((c>=0x20 && c<=0x21) ||
          (c>=0x23 && c<=0x5B) ||
          (c>=0x5D && c<=0x10FFFF))
        pfi::data::string::uchar_to_chars(c, p);
      else {
        char err_msg[64];
        snprintf(err_msg, sizeof(err_msg),
                 "unexpected unescaped char: \'%s\' (U+%04X)",
                 pfi::data::string::uchar_to_string(c).c_str(), c);
        error(err_msg);
      }
    }
  }

  match('\"');

  str_len = p - buf;
}

void json_parser::parse_false(callback& cb)
{
  match('f');
  match('a');
  match('l');
  match('s');
  match('e');
  cb.boolean(false);
}

void json_parser::parse_null(callback& cb)
{
  match('n');
  match('u');
  match('l');
  match('l');
  cb.null();
}

void json_parser::parse_true(callback& cb)
{
  match('t');
  match('r');
  match('u');
  match('e');
  cb.boolean(true);
}

void json_parser::error(const std::string& msg)
{
  std::string filename="<istream>";

  throw pfi::lang::parse_error(filename, lineno, charno, msg);
}

} // json
} // text
} // pfi
<commit_msg>Reformat json_parser::parser_number<commit_after>// Copyright (c)2008-2012, Preferred Infrastructure 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 Preferred Infrastructure nor the names of other
//       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 "parser.h"

#include <iostream>
#include <new>
#include <stack>
#include <cerrno>
#include <climits>
#include <cmath>
#include <cstring>
#include <cstdio>
#include <cstdlib>

#include "../../lang/exception.h"

namespace pfi {
namespace text {
namespace json {

class json_builder : public json_parser::callback {
public:
  const json& get() const {
    if (stk.size() != 1)
      throw pfi::lang::parse_error();
    return stk[0];
  }

  void null() {
    stk.push_back(new json_null());
  }

  void boolean(bool val) {
    stk.push_back(new json_bool(val));
  }

  void integer(int64_t val) {
    stk.push_back(new json_integer(val));
  }

  void number(double val) {
    stk.push_back(new json_float(val));
  }

  void string(const char* val, size_t len) {
    stk.push_back(new json_string(std::string(val, val+len)));
  }

  void start_object() {
    ixs.push(stk.size());
  }
  void object_key(const char* val, size_t len) {
    key.push_back(std::string(val, val+len));
  }
  void end_object() {
    json obj(new json_object());
    int ix = ixs.top();
    int jx = stk.size();
    int sz = jx - ix;
    for (int i = 0; i < sz; i++)
      obj.add(key[key.size() - sz + i], stk[ix + i]);
    stk.push_back(obj);
    stk.erase(stk.end() - sz - 1, stk.end() - 1);
    key.erase(key.end() - sz, key.end());
    ixs.pop();
  }

  void start_array() {
    ixs.push(stk.size());
  }
  void end_array() {
    json obj(new json_array());
    int ix = ixs.top();
    int jx = stk.size();
    int sz = jx - ix;
    for (int i = 0; i < sz; i++)
      obj.add(stk[ix + i]);
    stk.push_back(obj);
    stk.erase(stk.end() - sz - 1, stk.end() - 1);
    ixs.pop();
  }

  std::vector<json> stk;
  std::vector<std::string> key;

  std::stack<int> ixs;
};

json_parser::json_parser(std::istream& is)
  : is(is), it(is), end(), lineno(1), charno(1), cbuf(-1)
{
  buf_len = 256;
  if ((buf = static_cast<char*>(malloc(buf_len))) == 0)
    throw std::bad_alloc();
}

json_parser::~json_parser()
{
  free(buf);
}

json json_parser::parse()
{
  json_builder jb;
  parse_stream(jb);
  return jb.get();
}

void json_parser::parse_stream(callback& cb)
{
  ss();
  if (it == end)
    throw lang::end_of_data("json_parser reached end of data");
  return parse_impl(cb);
}

void json_parser::parse_impl(callback& cb)
{
  ss();
  switch(peek()) {
  case '{':
    parse_object(cb);
    return;

  case '[':
    parse_array(cb);
    return;

  case '0': case '1': case '2': case '3': case '4':
  case '5': case '6': case '7': case '8': case '9':
  case '-':
    parse_number(cb);
    return;

  case '\"':
    parse_string(cb);
    return;

  case 'f':
    parse_false(cb);
    return;
  case 'n':
    parse_null(cb);
    return;
  case 't':
    parse_true(cb);
    return;

  default: {
    char err_msg[64];
    snprintf(err_msg, sizeof(err_msg),
             "invalid char: \'%s\' (U+%04X)",
             pfi::data::string::uchar_to_string(peek()).c_str(), peek());
    error(err_msg);
  }

  }
  return; // dmy for supressing warning
}

void json_parser::parse_object(callback& cb)
{
  cb.start_object();

  smatch('{');

  for (int i = 0; ; i++) {
    if (speek() == '}')
      break;
    if (i > 0)
      smatch(',');

    ss();
    int len = 0;
    parse_string_prim(buf, buf_len, len);
    cb.object_key(buf, len);
    smatch(':');
    parse_impl(cb);
  }

  smatch('}');

  cb.end_object();
}

void json_parser::parse_array(callback& cb)
{
  cb.start_array();

  smatch('[');

  for (int i = 0; ; i++) {
    if (speek() == ']')
      break;
    if (i > 0)
      smatch(',');

    parse_impl(cb);
  }

  smatch(']');

  cb.end_array();
}

void json_parser::parse_number(callback& cb)
{
  std::string src;
  bool is_frac = false;

  if (it != end && peek() == '-') {
    src += '-';
    incr();
  }

  while (it != end && safe_isdigit(peek())) {
    src += peek();
    incr();
  }

  if (it != end && peek() == '.') {
    is_frac = true;
    src += '.';
    incr();
    while (it != end && safe_isdigit(peek())) {
      src += peek();
      incr();
    }
  }

  if (it != end && (peek() == 'e' || peek() == 'E')) {
    is_frac = true;
    src += peek();
    incr();

    if (it == end)
      error("after exp, digit required.");

    if (peek() == '+' || peek() == '-') {
      src += peek();
      incr();
    }
  }

  while (it != end && safe_isdigit(peek())) {
    src += peek();
    incr();
  }

  const char* srcptr = src.c_str();
  char* endptr;

  if (is_frac) {
    errno = 0;
    double num = strtod(srcptr, &endptr);
    if (errno == ERANGE) {
      if (num == HUGE_VALF || num == HUGE_VALL)
        error("strtod overflow range over. Too huge value for double.");
      else if (num == 0.0)
        error("strtod underflow range over.");
      error("strtod range over.");
    }
    cb.number(num);
  } else {
    errno = 0;
    int64_t num = strtoll(srcptr, &endptr, 10);
    if (errno == ERANGE) {
      if (num == LLONG_MAX || num == LLONG_MIN)
        error("strtoll overflow range over. Too huge value for int64_t.");
      else if (num == 0)
        error("strtoll underflow range over.");
      error("strtoll range over.");
    }
    cb.integer(num);
  }
}

void json_parser::parse_string(callback& cb)
{
  int len = 0;
  parse_string_prim(buf, buf_len, len);
  cb.string(buf, len);
}

void json_parser::parse_string_prim(char*& buf, int& buf_len, int& str_len)
{
  char* p = buf;

  match('\"');

  for (;;) {
    if (p+8 >= buf+buf_len) {
      size_t adv = p - buf;
      if (char* newbuf = static_cast<char*>(realloc(buf, 2*buf_len)))
        buf = newbuf;
      else
        throw std::bad_alloc();
      buf_len *= 2;
      p = buf + adv;
    }

    if (peek() == '\"')
      break;

    if (peek() == '\\') {
      incr();

      int c = incr();

      switch (c) {
      case '\"': *p++ = '\"'; break;
      case '\\': *p++ = '\\'; break;
      case '/':  *p++ = '/';  break;
      case 'b':  *p++ = '\b'; break;
      case 'f':  *p++ = '\f'; break;
      case 'n':  *p++ = '\n'; break;
      case 'r':  *p++ = '\r'; break;
      case 't':  *p++ = '\t'; break;

      case 'u': {
        int a = parse_hex();
        int b = parse_hex();
        int c = parse_hex();
        int d = parse_hex();
        pfi::data::string::uchar_to_chars((a<<12)|(b<<8)|(c<<4)|d, p);
        break;
      }

      default: {
        char err_msg[64];
        snprintf(err_msg, sizeof(err_msg),
                 "unexpected unescaped char: \'%s\' (U+%04X)",
                 pfi::data::string::uchar_to_string(c).c_str(), c);
        error(err_msg);
      }

      }
    }
    else {
      int c = incr();

      if ((c>=0x20 && c<=0x21) ||
          (c>=0x23 && c<=0x5B) ||
          (c>=0x5D && c<=0x10FFFF))
        pfi::data::string::uchar_to_chars(c, p);
      else {
        char err_msg[64];
        snprintf(err_msg, sizeof(err_msg),
                 "unexpected unescaped char: \'%s\' (U+%04X)",
                 pfi::data::string::uchar_to_string(c).c_str(), c);
        error(err_msg);
      }
    }
  }

  match('\"');

  str_len = p - buf;
}

void json_parser::parse_false(callback& cb)
{
  match('f');
  match('a');
  match('l');
  match('s');
  match('e');
  cb.boolean(false);
}

void json_parser::parse_null(callback& cb)
{
  match('n');
  match('u');
  match('l');
  match('l');
  cb.null();
}

void json_parser::parse_true(callback& cb)
{
  match('t');
  match('r');
  match('u');
  match('e');
  cb.boolean(true);
}

void json_parser::error(const std::string& msg)
{
  std::string filename="<istream>";

  throw pfi::lang::parse_error(filename, lineno, charno, msg);
}

} // json
} // text
} // pfi
<|endoftext|>


<commit_before>#include "scraper.hpp"

#include <queue>
#include <jsoncpp/json/json.h>
#include <boost/algorithm/string.hpp>

#include <supermarx/util/stubborn.hpp>

namespace supermarx
{

Json::Value parse_json(std::string const& src)
{
	Json::Value root;
	Json::Reader reader;

	if(!reader.parse(src, root, false))
		throw std::runtime_error("Could not parse json feed");

	return root;
}

scraper::scraper(callback_t _callback, unsigned int _ratelimit, bool _cache, bool)
	: callback(_callback)
	, dl("supermarx vladimir/0.1", _ratelimit, _cache ? boost::optional<std::string>("./cache") : boost::none)
{}

void scraper::get_rootmenu(cat_callback_t const& f)
{
	Json::Value root(parse_json(
		stubborn::attempt<std::string>([&]{
			return dl.fetch("https://api-01.cooponline.nl/shopapi/webshopCategory/getMenu").body;
		})
	));

	for(auto const& cat : root["rootWebshopCategories"])
	{
		category c({cat["id"].asUInt64(), cat["name"].asString(), cat["hasChildren"].asBool()});
		f(c);
	}
}

void scraper::get_submenu(category const& c_parent, cat_callback_t const& f)
{
	std::string uri("https://api-01.cooponline.nl/shopapi/webshopCategory/getMenu?categoryId=");
	uri += boost::lexical_cast<std::string>(c_parent.id);

	Json::Value root(parse_json(
		stubborn::attempt<std::string>([&]{
			return dl.fetch(uri).body;
		})
	));

	for(auto const& cat : root["childrenWebshopCategories"])
	{
		category c({cat["id"].asUInt64(), cat["name"].asString(), cat["hasChildren"].asBool()});
		f(c);
	}
}

void report_problem_understanding(std::string const& field, std::string const& value, scraper::problems_t& problems)
{
	std::stringstream sstr;
	sstr << "Unclear '" << field << "'' with value '" << value << "'";

	problems.emplace_back(sstr.str());
}

void scraper::process_products(category const& c)
{
	std::vector<std::string> problems;

	std::string uri("https://api-01.cooponline.nl/shopapi/article/list?offset=0&size=10000&webshopCategoryId=");
	uri += boost::lexical_cast<std::string>(c.id);

	Json::Value root(parse_json(
		stubborn::attempt<std::string>([&]{
			return dl.fetch(uri).body;
		})
	));

	for(auto const& j : root["articles"])
	{
		message::product_base p;
		confidence conf = confidence::NEUTRAL;
		datetime retrieved_on = datetime_now();

		p.identifier = j["articleNumber"].asString();

		std::string brand = j["brand"]["name"].asString();
		if(brand == "-------")
			brand = "coop";

		p.name = brand + " " + j["name"].asString();

		// Coop gives names as uppercase strings, which is undesireable.
		boost::algorithm::to_lower(p.name, std::locale("en_US.utf8")); // TODO fix UTF8-handling with ICU or similar.

		p.valid_on = retrieved_on;
		p.discount_amount = 1;

		p.price = j["salePrice"].asFloat()*100.0;
		if(!j["originalPrice"].isNull())
			p.orig_price = j["originalPrice"].asFloat()*100.0;
		else
			p.orig_price = p.price;

		if(j["mixMatched"].asBool())
		{
			std::string type = j["mixMatchButtonType"].asString();
			if(type == "FIXED_PRICE")
			{
				p.price = j["mixMatchDiscount"].asFloat()*100.0;
			}
			else if(type == "QUANTITY_FIXED_PRICE")
			{
				p.discount_amount = j["mixMatchItemQuantity"].asInt();
				p.price = j["mixMatchDiscount"].asFloat()*100.0 / p.discount_amount;
			}
			else if(type == "PERCENT")
			{
				p.discount_amount = j["mixMatchItemQuantity"].asInt();
				p.price *= j["mixMatchDiscount"].asFloat()/100.0;
			}
			else if(type == "TWO_BUY_ONE_PAY")
			{
				p.discount_amount = j["mixMatchItemQuantity"].asInt();
				p.price *= j["mixMatchDiscount"].asFloat()/100.0;
			}
			else if(type == "" && j["mixMatchDiscount"].isInt() && j["mixMatchDiscount"].asInt() == 100)
			{
				// Not actually a discount, bug in Coop's system
			}
			else
			{
				report_problem_understanding("mixMatchButtonType", type, problems);
				conf = confidence::LOW;
			}
		}

		const static std::map<std::string, std::pair<uint64_t, measure>> measure_map({
			{"DOZIJN", {12, measure::UNITS}},
			{"GROS", {144, measure::UNITS}},
			{"MILIGRAM", {1, measure::MILLIGRAMS}},
			{"GRAM", {1000, measure::MILLIGRAMS}},
			{"HECTOGRM", {100000, measure::MILLIGRAMS}},
			{"KILOGRAM", {1000000, measure::MILLIGRAMS}},
			{"TON", {1000000000, measure::MILLIGRAMS}},
			{"POND", {500000, measure::MILLIGRAMS}},
			{"ONS", {100000, measure::MILLIGRAMS}},
			{"MILIMETR", {1, measure::MILLIMETERS}},
			{"CENTIMTR", {10, measure::MILLIMETERS}},
			{"DECIMETR", {100, measure::MILLIMETERS}},
			{"METER", {1000, measure::MILLIMETERS}},
			{"KILOMETR", {1000000, measure::MILLIMETERS}},
			{"MILILITR", {1, measure::MILLILITERS}},
			{"CENTILTR", {10, measure::MILLILITERS}},
			{"DECILITR", {100, measure::MILLILITERS}},
			{"LITER", {1000, measure::MILLILITERS}},
			{"DECALITR", {10000, measure::MILLILITERS}},
			{"HECTOLTR", {100000, measure::MILLILITERS}},
			{"STUK", {1, measure::UNITS}},
			{"Diversen", {1, measure::UNITS}},
			{"PLAK", {1, measure::UNITS}},
			{"PUNT(EN)", {1, measure::UNITS}},
			{"ROL(LEN)", {1, measure::UNITS}}
		});

		p.volume = 1;
		p.volume_measure = measure::UNITS;

		std::string volume_str = j["volume"].asString();
		std::string measure_str = j["volumeMeasure"]["name"].asString();

		auto measure_it = measure_map.find(measure_str);
		if(measure_it != measure_map.end())
		{
			try
			{
				p.volume = boost::lexical_cast<uint64_t>(volume_str) * measure_it->second.first;
				p.volume_measure = measure_it->second.second;
			} catch(boost::bad_lexical_cast e)
			{
				report_problem_understanding("volume", volume_str, problems);
				conf = confidence::LOW;
			}
		}
		else
		{
			report_problem_understanding("volumeMeasure", volume_str, problems);
			conf = confidence::LOW;
		}

		boost::optional<std::string> image_uri;
		if(j["imageId"].isInt())
			image_uri = "https://api-01.cooponline.nl/shopapi/image/A/N/" + boost::lexical_cast<std::string>(j["imageId"].asUInt());

		callback(uri, image_uri, p, {}, retrieved_on, conf, problems);
	}
}

void scraper::scrape()
{
	std::vector<category> todo;

	cat_callback_t cat_f = [&](category const& c) {
		todo.push_back(c);
	};

	get_rootmenu(cat_f);

	while(!todo.empty())
	{
		category c(todo.back());
		todo.pop_back();

		if(c.has_children)
			get_submenu(c, cat_f);

		process_products(c);
	}
}

raw scraper::download_image(const std::string& uri)
{
	std::string buf(dl.fetch(uri).body);
	return raw(buf.data(), buf.length());
}

}
<commit_msg>Fixed reporting of problems<commit_after>#include "scraper.hpp"

#include <queue>
#include <jsoncpp/json/json.h>
#include <boost/algorithm/string.hpp>

#include <supermarx/util/stubborn.hpp>

namespace supermarx
{

Json::Value parse_json(std::string const& src)
{
	Json::Value root;
	Json::Reader reader;

	if(!reader.parse(src, root, false))
		throw std::runtime_error("Could not parse json feed");

	return root;
}

scraper::scraper(callback_t _callback, unsigned int _ratelimit, bool _cache, bool)
	: callback(_callback)
	, dl("supermarx vladimir/0.1", _ratelimit, _cache ? boost::optional<std::string>("./cache") : boost::none)
{}

void scraper::get_rootmenu(cat_callback_t const& f)
{
	Json::Value root(parse_json(
		stubborn::attempt<std::string>([&]{
			return dl.fetch("https://api-01.cooponline.nl/shopapi/webshopCategory/getMenu").body;
		})
	));

	for(auto const& cat : root["rootWebshopCategories"])
	{
		category c({cat["id"].asUInt64(), cat["name"].asString(), cat["hasChildren"].asBool()});
		f(c);
	}
}

void scraper::get_submenu(category const& c_parent, cat_callback_t const& f)
{
	std::string uri("https://api-01.cooponline.nl/shopapi/webshopCategory/getMenu?categoryId=");
	uri += boost::lexical_cast<std::string>(c_parent.id);

	Json::Value root(parse_json(
		stubborn::attempt<std::string>([&]{
			return dl.fetch(uri).body;
		})
	));

	for(auto const& cat : root["childrenWebshopCategories"])
	{
		category c({cat["id"].asUInt64(), cat["name"].asString(), cat["hasChildren"].asBool()});
		f(c);
	}
}

void report_problem_understanding(std::string const& field, std::string const& value, scraper::problems_t& problems)
{
	std::stringstream sstr;
	sstr << "Unclear '" << field << "' with value '" << value << "'";

	problems.emplace_back(sstr.str());
}

void scraper::process_products(category const& c)
{
	std::string uri("https://api-01.cooponline.nl/shopapi/article/list?offset=0&size=10000&webshopCategoryId=");
	uri += boost::lexical_cast<std::string>(c.id);

	Json::Value root(parse_json(
		stubborn::attempt<std::string>([&]{
			return dl.fetch(uri).body;
		})
	));

	for(auto const& j : root["articles"])
	{
		std::vector<std::string> problems;

		message::product_base p;
		confidence conf = confidence::NEUTRAL;
		datetime retrieved_on = datetime_now();

		p.identifier = j["articleNumber"].asString();

		std::string brand = j["brand"]["name"].asString();
		if(brand == "-------")
			brand = "coop";

		p.name = brand + " " + j["name"].asString();

		// Coop gives names as uppercase strings, which is undesireable.
		boost::algorithm::to_lower(p.name, std::locale("en_US.utf8")); // TODO fix UTF8-handling with ICU or similar.

		p.valid_on = retrieved_on;
		p.discount_amount = 1;

		p.price = j["salePrice"].asFloat()*100.0;
		if(!j["originalPrice"].isNull())
			p.orig_price = j["originalPrice"].asFloat()*100.0;
		else
			p.orig_price = p.price;

		if(j["mixMatched"].asBool())
		{
			std::string type = j["mixMatchButtonType"].asString();
			if(type == "FIXED_PRICE")
			{
				p.price = j["mixMatchDiscount"].asFloat()*100.0;
			}
			else if(type == "QUANTITY_FIXED_PRICE")
			{
				p.discount_amount = j["mixMatchItemQuantity"].asInt();
				p.price = j["mixMatchDiscount"].asFloat()*100.0 / p.discount_amount;
			}
			else if(type == "PERCENT")
			{
				p.discount_amount = j["mixMatchItemQuantity"].asInt();
				p.price *= j["mixMatchDiscount"].asFloat()/100.0;
			}
			else if(type == "TWO_BUY_ONE_PAY")
			{
				p.discount_amount = j["mixMatchItemQuantity"].asInt();
				p.price *= j["mixMatchDiscount"].asFloat()/100.0;
			}
			else if(type == "" && j["mixMatchDiscount"].isInt() && j["mixMatchDiscount"].asInt() == 100)
			{
				// Not actually a discount, bug in Coop's system
			}
			else
			{
				report_problem_understanding("mixMatchButtonType", type, problems);
				conf = confidence::LOW;
			}
		}

		const static std::map<std::string, std::pair<uint64_t, measure>> measure_map({
			{"DOZIJN", {12, measure::UNITS}},
			{"GROS", {144, measure::UNITS}},
			{"MILIGRAM", {1, measure::MILLIGRAMS}},
			{"GRAM", {1000, measure::MILLIGRAMS}},
			{"HECTOGRM", {100000, measure::MILLIGRAMS}},
			{"KILOGRAM", {1000000, measure::MILLIGRAMS}},
			{"TON", {1000000000, measure::MILLIGRAMS}},
			{"POND", {500000, measure::MILLIGRAMS}},
			{"ONS", {100000, measure::MILLIGRAMS}},
			{"MILIMETR", {1, measure::MILLIMETERS}},
			{"CENTIMTR", {10, measure::MILLIMETERS}},
			{"DECIMETR", {100, measure::MILLIMETERS}},
			{"METER", {1000, measure::MILLIMETERS}},
			{"KILOMETR", {1000000, measure::MILLIMETERS}},
			{"MILILITR", {1, measure::MILLILITERS}},
			{"CENTILTR", {10, measure::MILLILITERS}},
			{"DECILITR", {100, measure::MILLILITERS}},
			{"LITER", {1000, measure::MILLILITERS}},
			{"DECALITR", {10000, measure::MILLILITERS}},
			{"HECTOLTR", {100000, measure::MILLILITERS}},
			{"STUK", {1, measure::UNITS}},
			{"Diversen", {1, measure::UNITS}},
			{"PLAK", {1, measure::UNITS}},
			{"PUNT(EN)", {1, measure::UNITS}},
			{"ROL(LEN)", {1, measure::UNITS}}
		});

		p.volume = 1;
		p.volume_measure = measure::UNITS;

		std::string volume_str = j["volume"].asString();
		std::string measure_str = j["volumeMeasure"]["name"].asString();

		auto measure_it = measure_map.find(measure_str);
		if(measure_it != measure_map.end())
		{
			try
			{
				p.volume = boost::lexical_cast<uint64_t>(volume_str) * measure_it->second.first;
				p.volume_measure = measure_it->second.second;
			} catch(boost::bad_lexical_cast e)
			{
				report_problem_understanding("volume", volume_str, problems);
				conf = confidence::LOW;
			}
		}
		else
		{
			report_problem_understanding("volumeMeasure", volume_str, problems);
			conf = confidence::LOW;
		}

		boost::optional<std::string> image_uri;
		if(j["imageId"].isInt())
			image_uri = "https://api-01.cooponline.nl/shopapi/image/A/N/" + boost::lexical_cast<std::string>(j["imageId"].asUInt());

		callback(uri, image_uri, p, {}, retrieved_on, conf, problems);
	}
}

void scraper::scrape()
{
	std::vector<category> todo;

	cat_callback_t cat_f = [&](category const& c) {
		todo.push_back(c);
	};

	get_rootmenu(cat_f);

	while(!todo.empty())
	{
		category c(todo.back());
		todo.pop_back();

		if(c.has_children)
			get_submenu(c, cat_f);

		process_products(c);
	}
}

raw scraper::download_image(const std::string& uri)
{
	std::string buf(dl.fetch(uri).body);
	return raw(buf.data(), buf.length());
}

}
<|endoftext|>


<commit_before>#include "daemon.h"
#include <QtCore/QTimer>
#include <QtDBus/QtDBus>
#include <iostream>

void Daemon::processTransaction(QString card_number, QString amount, const QDBusMessage &msg)
{
	//TODO: Lookup username from card_number.

	//TODO: Load authkey from file.

	//TODO: Do real calls against backend API.

	//TODO: Get result from transaction. Build feedback reply.

	//prepare dummy reply: nickname, balance, transaction status
	QList<QVariant> return_values;
	return_values << QVariant("tjata");
	return_values << QVariant(QString::number(-600));
	return_values << QVariant(2);
	QDBusMessage reply = msg.createReply(return_values);
	QDBusConnection::systemBus().send(reply);
}

Daemon::Daemon(QObject *parent) : QObject(parent)
{
	//check for dbus errors
	if (!QDBusConnection::systemBus().isConnected()) {
		fprintf(stderr, "Cannot connect to the D-Bus system bus.\n");
		exit(1);
	}

	if (!QDBusConnection::systemBus().registerService(DBUS_SERVICE_NAME)) {
		fprintf(stderr, "%s\n",	qPrintable(QDBusConnection::systemBus().lastError().message()));
		exit(1);
	}

	//set up dbus connection across system bus
	QDBusConnection::systemBus().registerObject("/", this, QDBusConnection::ExportScriptableSlots);
}

<commit_msg>Remove superflouous space.<commit_after>#include "daemon.h"
#include <QtCore/QTimer>
#include <QtDBus/QtDBus>
#include <iostream>

void Daemon::processTransaction(QString card_number, QString amount, const QDBusMessage &msg)
{
	//TODO: Lookup username from card_number.

	//TODO: Load authkey from file.

	//TODO: Do real calls against backend API.

	//TODO: Get result from transaction. Build feedback reply.

	//prepare dummy reply: nickname, balance, transaction status
	QList<QVariant> return_values;
	return_values << QVariant("tjata");
	return_values << QVariant(QString::number(-600));
	return_values << QVariant(2);
	QDBusMessage reply = msg.createReply(return_values);
	QDBusConnection::systemBus().send(reply);
}

Daemon::Daemon(QObject *parent) : QObject(parent)
{
	//check for dbus errors
	if (!QDBusConnection::systemBus().isConnected()) {
		fprintf(stderr, "Cannot connect to the D-Bus system bus.\n");
		exit(1);
	}

	if (!QDBusConnection::systemBus().registerService(DBUS_SERVICE_NAME)) {
		fprintf(stderr, "%s\n",	qPrintable(QDBusConnection::systemBus().lastError().message()));
		exit(1);
	}

	//set up dbus connection across system bus
	QDBusConnection::systemBus().registerObject("/", this, QDBusConnection::ExportScriptableSlots);
}

<|endoftext|>