<commit_before>/*
 postmortem.c - output of debug info on sketch crash
 Copyright (c) 2015 Ivan Grokhotkov. All rights reserved.
 This file is part of the esp8266 core for Arduino environment.

 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdarg.h>
#include "debug.h"
#include "ets_sys.h"
#include "user_interface.h"
#include "esp8266_peri.h"
#include "cont.h"
#include "pgmspace.h"
#include "gdb_hooks.h"
#include "StackThunk.h"

extern "C" {

extern void __real_system_restart_local();

// These will be pointers to PROGMEM const strings
static const char* s_panic_file = 0;
static int s_panic_line = 0;
static const char* s_panic_func = 0;
static const char* s_panic_what = 0;

static bool s_abort_called = false;
static const char* s_unhandled_exception = NULL;

void abort() __attribute__((noreturn));
static void uart_write_char_d(char c);
static void uart0_write_char_d(char c);
static void uart1_write_char_d(char c);
static void print_stack(uint32_t start, uint32_t end);

// using numbers different from "REASON_" in user_interface.h (=0..6)
enum rst_reason_sw
{
    REASON_USER_SWEXCEPTION_RST = 254
};
static int s_user_reset_reason = REASON_DEFAULT_RST;

// From UMM, the last caller of a malloc/realloc/calloc which failed:
extern void *umm_last_fail_alloc_addr;
extern int umm_last_fail_alloc_size;
#if defined(DEBUG_ESP_OOM)
extern const char *umm_last_fail_alloc_file;
extern int umm_last_fail_alloc_line;
#endif

static void raise_exception() __attribute__((noreturn));

extern void __custom_crash_callback( struct rst_info * rst_info, uint32_t stack, uint32_t stack_end ) {
    (void) rst_info;
    (void) stack;
    (void) stack_end;
}

extern void custom_crash_callback( struct rst_info * rst_info, uint32_t stack, uint32_t stack_end ) __attribute__ ((weak, alias("__custom_crash_callback")));

// Prints need to use our library function to allow for file and function
// to be safely accessed from flash. This function encapsulates snprintf()
// [which by definition will 0-terminate] and dumping to the UART
static void ets_printf_P(const char *str, ...) {
    char destStr[160];
    char *c = destStr;
    va_list argPtr;
    va_start(argPtr, str);
    vsnprintf(destStr, sizeof(destStr), str, argPtr);
    va_end(argPtr);
    while (*c) {
        ets_putc(*(c++));
    }
}

void __wrap_system_restart_local() {
    register uint32_t sp asm("a1");
    uint32_t sp_dump = sp;

    struct rst_info rst_info;
    memset(&rst_info, 0, sizeof(rst_info));
    if (s_user_reset_reason == REASON_DEFAULT_RST)
    {
        system_rtc_mem_read(0, &rst_info, sizeof(rst_info));
        if (rst_info.reason != REASON_SOFT_WDT_RST &&
            rst_info.reason != REASON_EXCEPTION_RST &&
            rst_info.reason != REASON_WDT_RST)
        {
            rst_info.reason = REASON_DEFAULT_RST;
        }
    }
    else
        rst_info.reason = s_user_reset_reason;

    ets_install_putc1(&uart_write_char_d);

    if (s_panic_line) {
        ets_printf_P(PSTR("\nPanic %S:%d %S"), s_panic_file, s_panic_line, s_panic_func);
        if (s_panic_what) {
            ets_printf_P(PSTR(": Assertion '%S' failed."), s_panic_what);
        }
        ets_putc('\n');
    }
    else if (s_unhandled_exception) {
        ets_printf_P(PSTR("\nUnhandled C++ exception: %S\n"), s_unhandled_exception);
    }
    else if (s_abort_called) {
        ets_printf_P(PSTR("\nAbort called\n"));
    }
    else if (rst_info.reason == REASON_EXCEPTION_RST) {
        ets_printf_P(PSTR("\nException (%d):\nepc1=0x%08x epc2=0x%08x epc3=0x%08x excvaddr=0x%08x depc=0x%08x\n"),
            rst_info.exccause, rst_info.epc1, rst_info.epc2, rst_info.epc3, rst_info.excvaddr, rst_info.depc);
    }
    else if (rst_info.reason == REASON_SOFT_WDT_RST) {
        ets_printf_P(PSTR("\nSoft WDT reset\n"));
    }
    else {
        ets_printf_P(PSTR("\nGeneric Reset\n"));
    }

    uint32_t cont_stack_start = (uint32_t) &(g_pcont->stack);
    uint32_t cont_stack_end = (uint32_t) g_pcont->stack_end;
    uint32_t stack_end;

    // amount of stack taken by interrupt or exception handler
    // and everything up to __wrap_system_restart_local
    // (determined empirically, might break)
    uint32_t offset = 0;
    if (rst_info.reason == REASON_SOFT_WDT_RST) {
        offset = 0x1b0;
    }
    else if (rst_info.reason == REASON_EXCEPTION_RST) {
        offset = 0x1a0;
    }
    else if (rst_info.reason == REASON_WDT_RST) {
        offset = 0x10;
    }

    ets_printf_P(PSTR("\n>>>stack>>>\n"));

    if (sp_dump > stack_thunk_get_stack_bot() && sp_dump <= stack_thunk_get_stack_top()) {
        // BearSSL we dump the BSSL second stack and then reset SP back to the main cont stack
        ets_printf_P(PSTR("\nctx: bearssl\nsp: %08x end: %08x offset: %04x\n"), sp_dump, stack_thunk_get_stack_top(), offset);
        print_stack(sp_dump + offset, stack_thunk_get_stack_top());
        offset = 0; // No offset needed anymore, the exception info was stored in the bssl stack
        sp_dump = stack_thunk_get_cont_sp();
    }

    if (sp_dump > cont_stack_start && sp_dump < cont_stack_end) {
        ets_printf_P(PSTR("\nctx: cont\n"));
        stack_end = cont_stack_end;
    }
    else {
        ets_printf_P(PSTR("\nctx: sys\n"));
        stack_end = 0x3fffffb0;
        // it's actually 0x3ffffff0, but the stuff below ets_run
        // is likely not really relevant to the crash
    }

    ets_printf_P(PSTR("sp: %08x end: %08x offset: %04x\n"), sp_dump, stack_end, offset);

    print_stack(sp_dump + offset, stack_end);

    ets_printf_P(PSTR("<<<stack<<<\n"));

    // Use cap-X formatting to ensure the standard EspExceptionDecoder doesn't match the address
    if (umm_last_fail_alloc_addr) {
#if defined(DEBUG_ESP_OOM)
        ets_printf_P(PSTR("\nlast failed alloc call: %08X(%d)@%S:%d\n"),
            (uint32_t)umm_last_fail_alloc_addr, umm_last_fail_alloc_size,
            umm_last_fail_alloc_file, umm_last_fail_alloc_line);
#else
        ets_printf_P(PSTR("\nlast failed alloc call: %08X(%d)\n"), (uint32_t)umm_last_fail_alloc_addr, umm_last_fail_alloc_size);
#endif
    }

    custom_crash_callback( &rst_info, sp_dump + offset, stack_end );

    ets_delay_us(10000);
    __real_system_restart_local();
}

static void print_stack(uint32_t start, uint32_t end) {
    for (uint32_t pos = start; pos < end; pos += 0x10) {
        uint32_t* values = (uint32_t*)(pos);

        // rough indicator: stack frames usually have SP saved as the second word
        bool looksLikeStackFrame = (values[2] == pos + 0x10);

        ets_printf_P(PSTR("%08x:  %08x %08x %08x %08x %c\n"),
            pos, values[0], values[1], values[2], values[3], (looksLikeStackFrame)?'<':' ');
    }
}

static void uart_write_char_d(char c) {
    uart0_write_char_d(c);
    uart1_write_char_d(c);
}

static void uart0_write_char_d(char c) {
    while (((USS(0) >> USTXC) & 0xff)) { }

    if (c == '\n') {
        USF(0) = '\r';
    }
    USF(0) = c;
}

static void uart1_write_char_d(char c) {
    while (((USS(1) >> USTXC) & 0xff) >= 0x7e) { }

    if (c == '\n') {
        USF(1) = '\r';
    }
    USF(1) = c;
}

static void raise_exception() {
    if (gdb_present())
        __asm__ __volatile__ ("syscall"); // triggers GDB when enabled

    s_user_reset_reason = REASON_USER_SWEXCEPTION_RST;
    ets_printf_P(PSTR("\nUser exception (panic/abort/assert)"));
    __wrap_system_restart_local();

    while (1); // never reached, needed to satisfy "noreturn" attribute
}

void abort() {
    s_abort_called = true;
    raise_exception();
}

void __unhandled_exception(const char *str) {
    s_unhandled_exception = str;
    raise_exception();
}

void __assert_func(const char *file, int line, const char *func, const char *what) {
    s_panic_file = file;
    s_panic_line = line;
    s_panic_func = func;
    s_panic_what = what;
    gdb_do_break();     /* if GDB is not present, this is a no-op */
    raise_exception();
}

void __panic_func(const char* file, int line, const char* func) {
    s_panic_file = file;
    s_panic_line = line;
    s_panic_func = func;
    s_panic_what = 0;
    gdb_do_break();     /* if GDB is not present, this is a no-op */
    raise_exception();
}

};
<commit_msg>Updated stack offsets for postmortem stack dump. Changed ets_putc to ets_uart_putc1 to better newline handling.<commit_after>/*
 postmortem.c - output of debug info on sketch crash
 Copyright (c) 2015 Ivan Grokhotkov. All rights reserved.
 This file is part of the esp8266 core for Arduino environment.

 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdarg.h>
#include "debug.h"
#include "ets_sys.h"
#include "user_interface.h"
#include "esp8266_peri.h"
#include "cont.h"
#include "pgmspace.h"
#include "gdb_hooks.h"
#include "StackThunk.h"

extern "C" {

extern void __real_system_restart_local();

// These will be pointers to PROGMEM const strings
static const char* s_panic_file = 0;
static int s_panic_line = 0;
static const char* s_panic_func = 0;
static const char* s_panic_what = 0;

static bool s_abort_called = false;
static const char* s_unhandled_exception = NULL;

void abort() __attribute__((noreturn));
static void uart_write_char_d(char c);
static void uart0_write_char_d(char c);
static void uart1_write_char_d(char c);
static void print_stack(uint32_t start, uint32_t end);

// using numbers different from "REASON_" in user_interface.h (=0..6)
enum rst_reason_sw
{
    REASON_USER_SWEXCEPTION_RST = 254
};
static int s_user_reset_reason = REASON_DEFAULT_RST;

// From UMM, the last caller of a malloc/realloc/calloc which failed:
extern void *umm_last_fail_alloc_addr;
extern int umm_last_fail_alloc_size;
#if defined(DEBUG_ESP_OOM)
extern const char *umm_last_fail_alloc_file;
extern int umm_last_fail_alloc_line;
#endif

static void raise_exception() __attribute__((noreturn));

extern void __custom_crash_callback( struct rst_info * rst_info, uint32_t stack, uint32_t stack_end ) {
    (void) rst_info;
    (void) stack;
    (void) stack_end;
}

extern void custom_crash_callback( struct rst_info * rst_info, uint32_t stack, uint32_t stack_end ) __attribute__ ((weak, alias("__custom_crash_callback")));

// Prints need to use our library function to allow for file and function
// to be safely accessed from flash. This function encapsulates snprintf()
// [which by definition will 0-terminate] and dumping to the UART
static void ets_printf_P(const char *str, ...) {
    char destStr[160];
    char *c = destStr;
    va_list argPtr;
    va_start(argPtr, str);
    vsnprintf(destStr, sizeof(destStr), str, argPtr);
    va_end(argPtr);
    while (*c) {
        ets_uart_putc1(*(c++));
    }
}

void __wrap_system_restart_local() {
    register uint32_t sp asm("a1");
    uint32_t sp_dump = sp;

    struct rst_info rst_info;
    memset(&rst_info, 0, sizeof(rst_info));
    if (s_user_reset_reason == REASON_DEFAULT_RST)
    {
        system_rtc_mem_read(0, &rst_info, sizeof(rst_info));
        if (rst_info.reason != REASON_SOFT_WDT_RST &&
            rst_info.reason != REASON_EXCEPTION_RST &&
            rst_info.reason != REASON_WDT_RST)
        {
            rst_info.reason = REASON_DEFAULT_RST;
        }
    }
    else
        rst_info.reason = s_user_reset_reason;

    ets_install_putc1(&uart_write_char_d);

    if (s_panic_line) {
        ets_printf_P(PSTR("\nPanic %S:%d %S"), s_panic_file, s_panic_line, s_panic_func);
        if (s_panic_what) {
            ets_printf_P(PSTR(": Assertion '%S' failed."), s_panic_what);
        }
        ets_putc('\n');
    }
    else if (s_unhandled_exception) {
        ets_printf_P(PSTR("\nUnhandled C++ exception: %S\n"), s_unhandled_exception);
    }
    else if (s_abort_called) {
        ets_printf_P(PSTR("\nAbort called\n"));
    }
    else if (rst_info.reason == REASON_EXCEPTION_RST) {
        ets_printf_P(PSTR("\nException (%d):\nepc1=0x%08x epc2=0x%08x epc3=0x%08x excvaddr=0x%08x depc=0x%08x\n"),
            rst_info.exccause, rst_info.epc1, rst_info.epc2, rst_info.epc3, rst_info.excvaddr, rst_info.depc);
    }
    else if (rst_info.reason == REASON_SOFT_WDT_RST) {
        ets_printf_P(PSTR("\nSoft WDT reset\n"));
    }
    else {
        ets_printf_P(PSTR("\nGeneric Reset\n"));
    }

    uint32_t cont_stack_start = (uint32_t) &(g_pcont->stack);
    uint32_t cont_stack_end = (uint32_t) g_pcont->stack_end;
    uint32_t stack_end;

    // amount of stack taken by interrupt or exception handler
    // and everything up to __wrap_system_restart_local
    // (determined empirically, might break)
    uint32_t offset = 0;
    if (rst_info.reason == REASON_SOFT_WDT_RST) {
        offset = 0x1a0;
    }
    else if (rst_info.reason == REASON_EXCEPTION_RST) {
        offset = 0x190;
    }
    else if (rst_info.reason == REASON_WDT_RST) {
        offset = 0x10;
    }

    ets_printf_P(PSTR("\n>>>stack>>>\n"));

    if (sp_dump > stack_thunk_get_stack_bot() && sp_dump <= stack_thunk_get_stack_top()) {
        // BearSSL we dump the BSSL second stack and then reset SP back to the main cont stack
        ets_printf_P(PSTR("\nctx: bearssl\nsp: %08x end: %08x offset: %04x\n"), sp_dump, stack_thunk_get_stack_top(), offset);
        print_stack(sp_dump + offset, stack_thunk_get_stack_top());
        offset = 0; // No offset needed anymore, the exception info was stored in the bssl stack
        sp_dump = stack_thunk_get_cont_sp();
    }

    if (sp_dump > cont_stack_start && sp_dump < cont_stack_end) {
        ets_printf_P(PSTR("\nctx: cont\n"));
        stack_end = cont_stack_end;
    }
    else {
        ets_printf_P(PSTR("\nctx: sys\n"));
        stack_end = 0x3fffffb0;
        // it's actually 0x3ffffff0, but the stuff below ets_run
        // is likely not really relevant to the crash
    }

    ets_printf_P(PSTR("sp: %08x end: %08x offset: %04x\n"), sp_dump, stack_end, offset);

    print_stack(sp_dump + offset, stack_end);

    ets_printf_P(PSTR("<<<stack<<<\n"));

    // Use cap-X formatting to ensure the standard EspExceptionDecoder doesn't match the address
    if (umm_last_fail_alloc_addr) {
#if defined(DEBUG_ESP_OOM)
        ets_printf_P(PSTR("\nlast failed alloc call: %08X(%d)@%S:%d\n"),
            (uint32_t)umm_last_fail_alloc_addr, umm_last_fail_alloc_size,
            umm_last_fail_alloc_file, umm_last_fail_alloc_line);
#else
        ets_printf_P(PSTR("\nlast failed alloc call: %08X(%d)\n"), (uint32_t)umm_last_fail_alloc_addr, umm_last_fail_alloc_size);
#endif
    }

    custom_crash_callback( &rst_info, sp_dump + offset, stack_end );

    ets_delay_us(10000);
    __real_system_restart_local();
}

static void print_stack(uint32_t start, uint32_t end) {
    for (uint32_t pos = start; pos < end; pos += 0x10) {
        uint32_t* values = (uint32_t*)(pos);

        // rough indicator: stack frames usually have SP saved as the second word
        bool looksLikeStackFrame = (values[2] == pos + 0x10);

        ets_printf_P(PSTR("%08x:  %08x %08x %08x %08x %c\n"),
            pos, values[0], values[1], values[2], values[3], (looksLikeStackFrame)?'<':' ');
    }
}

static void uart_write_char_d(char c) {
    uart0_write_char_d(c);
    uart1_write_char_d(c);
}

static void uart0_write_char_d(char c) {
    while (((USS(0) >> USTXC) & 0xff)) { }

    if (c == '\n') {
        USF(0) = '\r';
    }
    USF(0) = c;
}

static void uart1_write_char_d(char c) {
    while (((USS(1) >> USTXC) & 0xff) >= 0x7e) { }

    if (c == '\n') {
        USF(1) = '\r';
    }
    USF(1) = c;
}

static void raise_exception() {
    if (gdb_present())
        __asm__ __volatile__ ("syscall"); // triggers GDB when enabled

    s_user_reset_reason = REASON_USER_SWEXCEPTION_RST;
    ets_printf_P(PSTR("\nUser exception (panic/abort/assert)"));
    __wrap_system_restart_local();

    while (1); // never reached, needed to satisfy "noreturn" attribute
}

void abort() {
    s_abort_called = true;
    raise_exception();
}

void __unhandled_exception(const char *str) {
    s_unhandled_exception = str;
    raise_exception();
}

void __assert_func(const char *file, int line, const char *func, const char *what) {
    s_panic_file = file;
    s_panic_line = line;
    s_panic_func = func;
    s_panic_what = what;
    gdb_do_break();     /* if GDB is not present, this is a no-op */
    raise_exception();
}

void __panic_func(const char* file, int line, const char* func) {
    s_panic_file = file;
    s_panic_line = line;
    s_panic_func = func;
    s_panic_what = 0;
    gdb_do_break();     /* if GDB is not present, this is a no-op */
    raise_exception();
}

};
<|endoftext|>


<commit_before>#include "test/test_syscoin_services.h"
#include "utiltime.h"
#include "rpcserver.h"
#include <boost/test/unit_test.hpp>
BOOST_GLOBAL_FIXTURE( SyscoinTestingSetup );

BOOST_FIXTURE_TEST_SUITE (syscoin_offer_tests, BasicSyscoinTestingSetup)

BOOST_AUTO_TEST_CASE (generate_offernew)
{
	UniValue r;

	GenerateBlocks(200);
	GenerateBlocks(200, "node2");
	GenerateBlocks(200, "node3");

	AliasNew("node1", "selleralias", "changeddata1");

	// generate a good offer
	string offerguid = OfferNew("node1", "selleralias", "category", "title", "100", "0.05", "description", "USD");

	// should fail: generate an offer with unknown alias
	BOOST_CHECK_THROW(r = CallRPC("node1", "offernew fooalias category title 100 0.05 description USD"), runtime_error);

	// should fail: generate an offer with negative quantity
	BOOST_CHECK_THROW(r = CallRPC("node1", "offernew selleralias category title -1 0.05 description USD"), runtime_error);

	// should fail: generate an offer with zero quantity
	BOOST_CHECK_THROW(r = CallRPC("node1", "offernew selleralias category title 0 0.05 description USD"), runtime_error);

	// should fail: generate an offer with zero price
	BOOST_CHECK_THROW(r = CallRPC("node1", "offernew selleralias category title 100 0 description USD"), runtime_error);

	// should fail: generate an offer with negative price
	BOOST_CHECK_THROW(r = CallRPC("node1", "offernew selleralias category title 100 -0.05 description USD"), runtime_error);

	// should fail: generate an offer too-large category
	string s256bytes =   "SfsdfdfsdsfSfsdfdfsdsfDsdsdsdsfsfsdsfsdsfdsfsdsfdsfsdsfsdSfsdfdfsdsfSfsdfdfsdsfDsdsdsdsfsfsdsfsdsfdsfsdsfdsfsdsfsdSfsdfdfsdsfSfsdfdfsdsfDsdsdsdsfsfsdsfsdsfdsfsdsfdsfsdsfsdSfsdfdfsdsfSfsdfdfsdsfDsdsdsdsfsfsdsfsdsfdsfsdsfdsfsdsfsdSfsdfdfsdsfSfsdfdfsdsDfdfddz";
	BOOST_CHECK_THROW(r = CallRPC("node1", "offernew selleralias " + s256bytes + " title 100 0.05 description USD"), runtime_error);

	// should fail: generate an offer too-large title
	BOOST_CHECK_THROW(r = CallRPC("node1", "offernew selleralias category " + s256bytes + " 100 0.05 description USD"), runtime_error);

	// should fail: generate an offer too-large description
	string s1024bytes =   "asdfasdfsadfsadassdsfsdfsdfsdfsdfsdsdfasdfasdfsadfsadassdsfsdfsdfsdfsdfsdsdfasdfasdfsadfsadassdsfsdfsdfsdfsdfsdsdfasdfasdfsadfsadassdsfsdfsdfsdfsdfsdsdfasdfasdfsadfsadassdsfsdfsdfsdfsdfsdsdfasdfasdfsadfsadassdsfsdfsdfsdfsdfsdsdfasdfasdfsadfsadassdsfsdfsdfsdfsdfsdsdfasdfasdfsadfsadassdsfsdfsdfsdfsdfsdsdfasdfasdfsadfsadassdsfsdfsdfsdfsdfsdsdfasdfasdfsadfsadassdsfsdfsdfsdfsdfsdsdfasdfasdfsadfsadassdsfsdfsdfsdfsdfsdsdfasdfasdfsadfsadassdsfsdfsdfsdfsdfsdsdfasdfasdfsadfsadassdsfsdfsdfsdfsdfsdsdfasdfasdfsadfsadassdsfsdfsdfsdfsdfsdsdfasdfasdfsadfsadassdsfsdfsdfsdfsdfsdsdfasdfasdfsadfsadassdsfsdfsdfsdfsdfsdsdfasdfasdfsadfsadassdsfsdfsdfsdfsdfsdsdfasdfasdfsadfsadassdsfsdfsdfsdfsdfsdsdfasdfasdfsadfsadassdsfsdfsdfsdfsdfsdsdfasdfasdfsadfsadassdsfsdfsdfsdfsdfsdsdfasdfasdfsadfsadassdsfsdfsdfsdfsdfsdsdfasdfasdfsadfsadassdsfsdfsdfsdfsdfsdsdfasdfasdfsadfsadassdsfsdfsdfsdfsdfsdsdfasdfasdfsadfsadassdsfsdfsdfsdfsdfsdsdfasdfasdfsadfsadassdsfsdfsdfsdfsdfsdsdfasdfasdfsadfsadassdsfsdfsdfsdfsdfsdsdfssdsfsdfsdfsdfsdfsdsdfdfsdfsdfsdfsdz";
	BOOST_CHECK_THROW(r = CallRPC("node1", "offernew selleralias category title 100 0.05 " + s1024bytes + " USD"), runtime_error);
}

BOOST_AUTO_TEST_CASE (generate_offerupdate)
{
	UniValue r;

	GenerateBlocks(200);
	GenerateBlocks(200, "node2");
	GenerateBlocks(200, "node3");

	AliasNew("node1", "selleralias2", "changeddata1");

	// generate a good offer
	string offerguid = OfferNew("node1", "selleralias2", "category", "title", "100", "0.05", "description", "USD");

	// perform a valid update
	OfferUpdate("node1", "selleralias2", offerguid, "category", "titlenew", "90", "0.15", "descriptionnew");

	// should fail: offer cannot be updated by someone other than owner
	BOOST_CHECK_THROW(r = CallRPC("node2", "offerupdate selleralias2 " + offerguid + " category title 90 0.15 description"), runtime_error);

	// should fail: generate an offer with unknown alias
	BOOST_CHECK_THROW(r = CallRPC("node1", "offerupdate fooalias " + offerguid + " category title 90 0.15 description"), runtime_error);

	// should fail: generate an offer with negative quantity
	//BOOST_CHECK_THROW(r = CallRPC("node1", "offerupdate selleralias2 " + offerguid + " category title -1 0.05 description"), runtime_error);

	// should fail: generate an offer with zero quantity
	//BOOST_CHECK_THROW(r = CallRPC("node1", "offerupdate selleralias2 " + offerguid + " category title 0 0.05 description"), runtime_error);

	// should fail: generate an offer with zero price
	BOOST_CHECK_THROW(r = CallRPC("node1", "offerupdate selleralias2 " + offerguid + " category title 90 0 description"), runtime_error);

	// should fail: generate an offer with negative price
	BOOST_CHECK_THROW(r = CallRPC("node1", "offerupdate selleralias2 " + offerguid + " category title 90 -0.05 description"), runtime_error);

	// should fail: generate an offer too-large category
	string s256bytes =   "SfsdfdfsdsfSfsdfdfsdsfDsdsdsdsfsfsdsfsdsfdsfsdsfdsfsdsfsdSfsdfdfsdsfSfsdfdfsdsfDsdsdsdsfsfsdsfsdsfdsfsdsfdsfsdsfsdSfsdfdfsdsfSfsdfdfsdsfDsdsdsdsfsfsdsfsdsfdsfsdsfdsfsdsfsdSfsdfdfsdsfSfsdfdfsdsfDsdsdsdsfsfsdsfsdsfdsfsdsfdsfsdsfsdSfsdfdfsdsfSfsdfdfsdsDfdfddz";
	BOOST_CHECK_THROW(r = CallRPC("node1", "offerupdate selleralias2 " + offerguid + " " + s256bytes + " title 90 0.15 description"), runtime_error);

	// should fail: generate an offer too-large title
	BOOST_CHECK_THROW(r = CallRPC("node1", "offerupdate selleralias2 " + offerguid + " category " + s256bytes + " 90 0.15 description"), runtime_error);

	// should fail: generate an offer too-large description
	string s1024bytes =   "asdfasdfsadfsadassdsfsdfsdfsdfsdfsdsdfasdfasdfsadfsadassdsfsdfsdfsdfsdfsdsdfasdfasdfsadfsadassdsfsdfsdfsdfsdfsdsdfasdfasdfsadfsadassdsfsdfsdfsdfsdfsdsdfasdfasdfsadfsadassdsfsdfsdfsdfsdfsdsdfasdfasdfsadfsadassdsfsdfsdfsdfsdfsdsdfasdfasdfsadfsadassdsfsdfsdfsdfsdfsdsdfasdfasdfsadfsadassdsfsdfsdfsdfsdfsdsdfasdfasdfsadfsadassdsfsdfsdfsdfsdfsdsdfasdfasdfsadfsadassdsfsdfsdfsdfsdfsdsdfasdfasdfsadfsadassdsfsdfsdfsdfsdfsdsdfasdfasdfsadfsadassdsfsdfsdfsdfsdfsdsdfasdfasdfsadfsadassdsfsdfsdfsdfsdfsdsdfasdfasdfsadfsadassdsfsdfsdfsdfsdfsdsdfasdfasdfsadfsadassdsfsdfsdfsdfsdfsdsdfasdfasdfsadfsadassdsfsdfsdfsdfsdfsdsdfasdfasdfsadfsadassdsfsdfsdfsdfsdfsdsdfasdfasdfsadfsadassdsfsdfsdfsdfsdfsdsdfasdfasdfsadfsadassdsfsdfsdfsdfsdfsdsdfasdfasdfsadfsadassdsfsdfsdfsdfsdfsdsdfasdfasdfsadfsadassdsfsdfsdfsdfsdfsdsdfasdfasdfsadfsadassdsfsdfsdfsdfsdfsdsdfasdfasdfsadfsadassdsfsdfsdfsdfsdfsdsdfasdfasdfsadfsadassdsfsdfsdfsdfsdfsdsdfasdfasdfsadfsadassdsfsdfsdfsdfsdfsdsdfasdfasdfsadfsadassdsfsdfsdfsdfsdfsdsdfssdsfsdfsdfsdfsdfsdsdfdfsdfsdfsdfsdz";
	BOOST_CHECK_THROW(r = CallRPC("node1", "offerupdate selleralias2 " + offerguid + " category title 90 0.15 " + s1024bytes), runtime_error);
}

BOOST_AUTO_TEST_SUITE_END ()<commit_msg>updated offernew test<commit_after>#include "test/test_syscoin_services.h"
#include "utiltime.h"
#include "rpcserver.h"
#include <boost/test/unit_test.hpp>
BOOST_GLOBAL_FIXTURE( SyscoinTestingSetup );

BOOST_FIXTURE_TEST_SUITE (syscoin_offer_tests, BasicSyscoinTestingSetup)

BOOST_AUTO_TEST_CASE (generate_offernew)
{
	UniValue r;

	GenerateBlocks(200);
	GenerateBlocks(200, "node2");
	GenerateBlocks(200, "node3");

	AliasNew("node1", "selleralias", "changeddata1");

	// generate a good offer
	string offerguid = OfferNew("node1", "selleralias", "category", "title", "100", "0.05", "description", "USD");

	// should fail: generate an offer with unknown alias
	BOOST_CHECK_THROW(r = CallRPC("node1", "offernew fooalias category title 100 0.05 description USD"), runtime_error);

	// should fail: generate an offer with negative quantity
	BOOST_CHECK_THROW(r = CallRPC("node1", "offernew selleralias category title -2 0.05 description USD"), runtime_error);

	// should fail: generate an offer with zero price
	BOOST_CHECK_THROW(r = CallRPC("node1", "offernew selleralias category title 100 0 description USD"), runtime_error);

	// should fail: generate an offer with negative price
	BOOST_CHECK_THROW(r = CallRPC("node1", "offernew selleralias category title 100 -0.05 description USD"), runtime_error);

	// should fail: generate an offer too-large category
	string s256bytes =   "SfsdfdfsdsfSfsdfdfsdsfDsdsdsdsfsfsdsfsdsfdsfsdsfdsfsdsfsdSfsdfdfsdsfSfsdfdfsdsfDsdsdsdsfsfsdsfsdsfdsfsdsfdsfsdsfsdSfsdfdfsdsfSfsdfdfsdsfDsdsdsdsfsfsdsfsdsfdsfsdsfdsfsdsfsdSfsdfdfsdsfSfsdfdfsdsfDsdsdsdsfsfsdsfsdsfdsfsdsfdsfsdsfsdSfsdfdfsdsfSfsdfdfsdsDfdfddz";
	BOOST_CHECK_THROW(r = CallRPC("node1", "offernew selleralias " + s256bytes + " title 100 0.05 description USD"), runtime_error);

	// should fail: generate an offer too-large title
	BOOST_CHECK_THROW(r = CallRPC("node1", "offernew selleralias category " + s256bytes + " 100 0.05 description USD"), runtime_error);

	// should fail: generate an offer too-large description
	string s1024bytes =   "asdfasdfsadfsadassdsfsdfsdfsdfsdfsdsdfasdfasdfsadfsadassdsfsdfsdfsdfsdfsdsdfasdfasdfsadfsadassdsfsdfsdfsdfsdfsdsdfasdfasdfsadfsadassdsfsdfsdfsdfsdfsdsdfasdfasdfsadfsadassdsfsdfsdfsdfsdfsdsdfasdfasdfsadfsadassdsfsdfsdfsdfsdfsdsdfasdfasdfsadfsadassdsfsdfsdfsdfsdfsdsdfasdfasdfsadfsadassdsfsdfsdfsdfsdfsdsdfasdfasdfsadfsadassdsfsdfsdfsdfsdfsdsdfasdfasdfsadfsadassdsfsdfsdfsdfsdfsdsdfasdfasdfsadfsadassdsfsdfsdfsdfsdfsdsdfasdfasdfsadfsadassdsfsdfsdfsdfsdfsdsdfasdfasdfsadfsadassdsfsdfsdfsdfsdfsdsdfasdfasdfsadfsadassdsfsdfsdfsdfsdfsdsdfasdfasdfsadfsadassdsfsdfsdfsdfsdfsdsdfasdfasdfsadfsadassdsfsdfsdfsdfsdfsdsdfasdfasdfsadfsadassdsfsdfsdfsdfsdfsdsdfasdfasdfsadfsadassdsfsdfsdfsdfsdfsdsdfasdfasdfsadfsadassdsfsdfsdfsdfsdfsdsdfasdfasdfsadfsadassdsfsdfsdfsdfsdfsdsdfasdfasdfsadfsadassdsfsdfsdfsdfsdfsdsdfasdfasdfsadfsadassdsfsdfsdfsdfsdfsdsdfasdfasdfsadfsadassdsfsdfsdfsdfsdfsdsdfasdfasdfsadfsadassdsfsdfsdfsdfsdfsdsdfasdfasdfsadfsadassdsfsdfsdfsdfsdfsdsdfasdfasdfsadfsadassdsfsdfsdfsdfsdfsdsdfssdsfsdfsdfsdfsdfsdsdfdfsdfsdfsdfsdz";
	BOOST_CHECK_THROW(r = CallRPC("node1", "offernew selleralias category title 100 0.05 " + s1024bytes + " USD"), runtime_error);
}

BOOST_AUTO_TEST_CASE (generate_offerupdate)
{
	UniValue r;

	GenerateBlocks(200);
	GenerateBlocks(200, "node2");
	GenerateBlocks(200, "node3");

	AliasNew("node1", "selleralias2", "changeddata1");

	// generate a good offer
	string offerguid = OfferNew("node1", "selleralias2", "category", "title", "100", "0.05", "description", "USD");

	// perform a valid update
	OfferUpdate("node1", "selleralias2", offerguid, "category", "titlenew", "90", "0.15", "descriptionnew");

	// should fail: offer cannot be updated by someone other than owner
	BOOST_CHECK_THROW(r = CallRPC("node2", "offerupdate selleralias2 " + offerguid + " category title 90 0.15 description"), runtime_error);

	// should fail: generate an offer with unknown alias
	BOOST_CHECK_THROW(r = CallRPC("node1", "offerupdate fooalias " + offerguid + " category title 90 0.15 description"), runtime_error);

	// should fail: generate an offer with zero price
	BOOST_CHECK_THROW(r = CallRPC("node1", "offerupdate selleralias2 " + offerguid + " category title 90 0 description"), runtime_error);

	// should fail: generate an offer with negative price
	BOOST_CHECK_THROW(r = CallRPC("node1", "offerupdate selleralias2 " + offerguid + " category title 90 -0.05 description"), runtime_error);

	// should fail: generate an offer too-large category
	string s256bytes =   "SfsdfdfsdsfSfsdfdfsdsfDsdsdsdsfsfsdsfsdsfdsfsdsfdsfsdsfsdSfsdfdfsdsfSfsdfdfsdsfDsdsdsdsfsfsdsfsdsfdsfsdsfdsfsdsfsdSfsdfdfsdsfSfsdfdfsdsfDsdsdsdsfsfsdsfsdsfdsfsdsfdsfsdsfsdSfsdfdfsdsfSfsdfdfsdsfDsdsdsdsfsfsdsfsdsfdsfsdsfdsfsdsfsdSfsdfdfsdsfSfsdfdfsdsDfdfddz";
	BOOST_CHECK_THROW(r = CallRPC("node1", "offerupdate selleralias2 " + offerguid + " " + s256bytes + " title 90 0.15 description"), runtime_error);

	// should fail: generate an offer too-large title
	BOOST_CHECK_THROW(r = CallRPC("node1", "offerupdate selleralias2 " + offerguid + " category " + s256bytes + " 90 0.15 description"), runtime_error);

	// should fail: generate an offer too-large description
	string s1024bytes =   "asdfasdfsadfsadassdsfsdfsdfsdfsdfsdsdfasdfasdfsadfsadassdsfsdfsdfsdfsdfsdsdfasdfasdfsadfsadassdsfsdfsdfsdfsdfsdsdfasdfasdfsadfsadassdsfsdfsdfsdfsdfsdsdfasdfasdfsadfsadassdsfsdfsdfsdfsdfsdsdfasdfasdfsadfsadassdsfsdfsdfsdfsdfsdsdfasdfasdfsadfsadassdsfsdfsdfsdfsdfsdsdfasdfasdfsadfsadassdsfsdfsdfsdfsdfsdsdfasdfasdfsadfsadassdsfsdfsdfsdfsdfsdsdfasdfasdfsadfsadassdsfsdfsdfsdfsdfsdsdfasdfasdfsadfsadassdsfsdfsdfsdfsdfsdsdfasdfasdfsadfsadassdsfsdfsdfsdfsdfsdsdfasdfasdfsadfsadassdsfsdfsdfsdfsdfsdsdfasdfasdfsadfsadassdsfsdfsdfsdfsdfsdsdfasdfasdfsadfsadassdsfsdfsdfsdfsdfsdsdfasdfasdfsadfsadassdsfsdfsdfsdfsdfsdsdfasdfasdfsadfsadassdsfsdfsdfsdfsdfsdsdfasdfasdfsadfsadassdsfsdfsdfsdfsdfsdsdfasdfasdfsadfsadassdsfsdfsdfsdfsdfsdsdfasdfasdfsadfsadassdsfsdfsdfsdfsdfsdsdfasdfasdfsadfsadassdsfsdfsdfsdfsdfsdsdfasdfasdfsadfsadassdsfsdfsdfsdfsdfsdsdfasdfasdfsadfsadassdsfsdfsdfsdfsdfsdsdfasdfasdfsadfsadassdsfsdfsdfsdfsdfsdsdfasdfasdfsadfsadassdsfsdfsdfsdfsdfsdsdfasdfasdfsadfsadassdsfsdfsdfsdfsdfsdsdfssdsfsdfsdfsdfsdfsdsdfdfsdfsdfsdfsdz";
	BOOST_CHECK_THROW(r = CallRPC("node1", "offerupdate selleralias2 " + offerguid + " category title 90 0.15 " + s1024bytes), runtime_error);
}

BOOST_AUTO_TEST_SUITE_END ()<|endoftext|>


<commit_before>#include <xercesc/dom/DOM.hpp>
#include <xercesc/sax/HandlerBase.hpp>
#include <xercesc/util/XMLString.hpp>
#include <xercesc/util/PlatformUtils.hpp>
#include <xercesc/dom/DOMDocument.hpp>
#include <xercesc/dom/DOMDocumentType.hpp>
#include <xercesc/dom/DOMElement.hpp>
#include <xercesc/dom/DOMImplementation.hpp>
#include <xercesc/dom/DOMImplementationLS.hpp>
#include <xercesc/dom/DOMNodeIterator.hpp>
#include <xercesc/dom/DOMNodeList.hpp>
#include <xercesc/dom/DOMText.hpp>
#include <xercesc/dom/DOMTreeWalker.hpp>
#include <xercesc/parsers/XercesdomParser.hpp>
#include <xercesc/util/XMLUni.hpp>

#include <string>
#include <stdexcept>

#include <iostream>

using namespace std;
using namespace xercesc;

class SimpleErrorHandler : public ErrorHandler
{
private:
	void printError(const SAXParseException& ex)
	{
		char* message = XMLString::transcode(ex.getMessage());
		//fprintf(stderr, "Error: Line %llu, column %llu: %s\n", ex.getColumnNumber(), ex.getLineNumber(), message);
		XMLString::release(&message);
	}

public:
	void error(const SAXParseException& ex)
	{
		printError(ex);
	}

	void fatalError(const SAXParseException& ex)
	{
		printError(ex);
	}

	void resetErrors()
	{
	}

	void warning(const SAXParseException& ex)
	{
		printError(ex);
	}
};

int main(int argc, const char *argv[])
{
	if (2 != argc)
	{
		fprintf(stderr, "ERROR! Correct usage: ex2 <xml file>\n");
		return -1;
	}

	XMLPlatformUtils::Initialize();

	XercesDOMParser *domParser = new XercesDOMParser();
	if (NULL == domParser->loadGrammar("measured-1-1-0.xsd", Grammar::SchemaGrammarType))
	{
		fprintf(stderr, "Unable to load schema measured-1-1-0.xsd\n");
		return 0;
	}

	SimpleErrorHandler parserErrorHandler;

	domParser->setErrorHandler(&parserErrorHandler);
	domParser->setValidationScheme(XercesDOMParser::Val_Always);
	domParser->setDoNamespaces(true);
	domParser->setDoSchema(true);
	//domParser->setValidationConstraintFatal(true);

	domParser->parse(argv[1]);
	if (0 == domParser->getErrorCount())
	{
		fprintf(stderr, "Validated sucessfully.\n");
	}
	else
	{
		fprintf(stderr, "Validated NOT sucessfully.\n");
	}

	DOMDocument *document = domParser->getDocument();
	DOMElement *rootNode = document->getDocumentElement();
	DOMTreeWalker *treeWalker =	document->createTreeWalker(rootNode, DOMNodeFilter::SHOW_ALL, NULL, true);
	DOMNode *currentNode = NULL;

	for (currentNode = treeWalker->getCurrentNode(); currentNode != NULL; currentNode = treeWalker->nextNode())
	{
		string str(XMLString::transcode(currentNode->getNodeName()));
		if (str.compare("amountOfPower")==0)
		{
			char * amountOfPowerValue = XMLString::transcode(currentNode->getAttributes()->getNamedItem(XMLString::transcode("value"))->getNodeValue());
			char * hour = XMLString::transcode(currentNode->getParentNode()->getAttributes()->getNamedItem(XMLString::transcode("hour"))->getNodeValue());
			char * date = XMLString::transcode(currentNode->getParentNode()->getParentNode()->getParentNode()->getAttributes()->getNamedItem(XMLString::transcode("date"))->getNodeValue());
			fprintf(stdout, "%s; %s; %s\n", date, hour, amountOfPowerValue);
		}
	}

	delete domParser;
	XMLPlatformUtils::Terminate();
	return 0;
}
<commit_msg>Added doxygen comments<commit_after>/*
 *  @file 	ex2.cpp
 *  @details  	This file is the solution to exercise 2.
 *  @author    	Alexander Rettkowski
 *  @date      	29.04.2017
 */

#include <xercesc/dom/DOM.hpp>
#include <xercesc/sax/HandlerBase.hpp>
#include <xercesc/util/XMLString.hpp>
#include <xercesc/util/PlatformUtils.hpp>
#include <xercesc/dom/DOMDocument.hpp>
#include <xercesc/dom/DOMDocumentType.hpp>
#include <xercesc/dom/DOMElement.hpp>
#include <xercesc/dom/DOMImplementation.hpp>
#include <xercesc/dom/DOMImplementationLS.hpp>
#include <xercesc/dom/DOMNodeIterator.hpp>
#include <xercesc/dom/DOMNodeList.hpp>
#include <xercesc/dom/DOMText.hpp>
#include <xercesc/dom/DOMTreeWalker.hpp>
#include <xercesc/parsers/XercesdomParser.hpp>
#include <xercesc/util/XMLUni.hpp>

#include <string>
#include <stdexcept>

#include <iostream>

using namespace std;
using namespace xercesc;

class SimpleErrorHandler : public ErrorHandler
{
private:
	/**
 	 * Prints an error message from an exception while parsing.
 	 * @param ex The caught exception.
 	*/
	void printError(const SAXParseException& ex)
	{
		char* message = XMLString::transcode(ex.getMessage());
		//fprintf(stderr, "Error: Line %llu, column %llu: %s\n", ex.getColumnNumber(), ex.getLineNumber(), message);
		XMLString::release(&message);
	}

public:
	void error(const SAXParseException& ex)
	{
		printError(ex);
	}

	void fatalError(const SAXParseException& ex)
	{
		printError(ex);
	}

	void resetErrors()
	{
	}

	void warning(const SAXParseException& ex)
	{
		printError(ex);
	}
};

/**
 * The main function that reads in a file and processes it.
 * @param argc Number of command line arguments.
 * @param *argv a pointer to the array of command line arguments.
 */
int main(int argc, const char *argv[])
{
	if (2 != argc)
	{
		fprintf(stderr, "ERROR! Correct usage: ex2 <xml file>\n");
		return -1;
	}

	XMLPlatformUtils::Initialize();

	XercesDOMParser *domParser = new XercesDOMParser();
	if (NULL == domParser->loadGrammar("measured-1-1-0.xsd", Grammar::SchemaGrammarType))
	{
		fprintf(stderr, "Unable to load schema measured-1-1-0.xsd\n");
		return 0;
	}

	SimpleErrorHandler parserErrorHandler;

	domParser->setErrorHandler(&parserErrorHandler);
	domParser->setValidationScheme(XercesDOMParser::Val_Always);
	domParser->setDoNamespaces(true);
	domParser->setDoSchema(true);
	//domParser->setValidationConstraintFatal(true);

	domParser->parse(argv[1]);
	if (0 == domParser->getErrorCount())
	{
		fprintf(stderr, "Validated sucessfully.\n");
	}
	else
	{
		fprintf(stderr, "Validated NOT sucessfully.\n");
	}

	DOMDocument *document = domParser->getDocument();
	DOMElement *rootNode = document->getDocumentElement();
	DOMTreeWalker *treeWalker =	document->createTreeWalker(rootNode, DOMNodeFilter::SHOW_ALL, NULL, true);
	DOMNode *currentNode = NULL;

	for (currentNode = treeWalker->getCurrentNode(); currentNode != NULL; currentNode = treeWalker->nextNode())
	{
		string str(XMLString::transcode(currentNode->getNodeName()));
		if (str.compare("amountOfPower")==0)
		{
			char * amountOfPowerValue = XMLString::transcode(currentNode->getAttributes()->getNamedItem(XMLString::transcode("value"))->getNodeValue());
			char * hour = XMLString::transcode(currentNode->getParentNode()->getAttributes()->getNamedItem(XMLString::transcode("hour"))->getNodeValue());
			char * date = XMLString::transcode(currentNode->getParentNode()->getParentNode()->getParentNode()->getAttributes()->getNamedItem(XMLString::transcode("date"))->getNodeValue());
			fprintf(stdout, "%s; %s; %s\n", date, hour, amountOfPowerValue);
		}
	}

	delete domParser;
	XMLPlatformUtils::Terminate();
	return 0;
}
<|endoftext|>


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

#include "modules/canbus/vehicle/gem/protocol/wheel_speed_rpt_7a.h"

#include "gtest/gtest.h"

namespace apollo {
namespace canbus {
namespace gem {

class Wheelspeedrpt7aTest : public ::testing::Test {
 public:
  virtual void SetUp() {}
};

TEST_F(Wheelspeedrpt7aTest, reset) {
  Wheelspeedrpt7a wheelspeed;
  int32_t length = 8;
  ChassisDetail chassis_detail;
  uint8_t bytes[8] = {0, 0};

  bytes[0] = 0b11111100;
  bytes[1] = 0b11111110;
  bytes[2] = 0b11111110;
  bytes[3] = 0b11111110;
  bytes[4] = 0b11111110;
  bytes[5] = 0b11111110;
  bytes[6] = 0b11111110;
  bytes[7] = 0b11111110;

  wheelspeed.Parse(bytes, length, &chassis_detail);
  EXPECT_DOUBLE_EQ(chassis_detail.gem().wheel_speed_rpt_7a().wheel_spd_rear_right(), -2.58);
  EXPECT_DOUBLE_EQ(chassis_detail.gem().wheel_speed_rpt_7a().wheel_spd_rear_left(), -2.6);
  EXPECT_DOUBLE_EQ(chassis_detail.gem().wheel_speed_rpt_7a().wheel_spd_front_right(), -2.6);
  EXPECT_DOUBLE_EQ(chassis_detail.gem().wheel_speed_rpt_7a().wheel_spd_front_left(), -2.6);
}

}  // namespace gem
}  // namespace canbus
}  // namespace apollo<commit_msg>modify test for wheel_speed_rpt_7a<commit_after>/******************************************************************************
 * Copyright 2018 The Apollo Authors. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *****************************************************************************/

#include "modules/canbus/vehicle/gem/protocol/wheel_speed_rpt_7a.h"

#include "gtest/gtest.h"

namespace apollo {
namespace canbus {
namespace gem {

class Wheelspeedrpt7aTest : public ::testing::Test {
 public:
  virtual void SetUp() {}
};

TEST_F(Wheelspeedrpt7aTest, reset) {
  Wheelspeedrpt7a wheelspeed;
  int32_t length = 8;
  ChassisDetail chassis_detail;
  uint8_t bytes[8] = {0, 0};uint8_t bytes[8] = {0x01, 0x02, 0x03, 0x04, 0x11, 0x12, 0x13, 0x14};

  wheelspeed.Parse(bytes, length, &chassis_detail);
  EXPECT_DOUBLE_EQ(chassis_detail.gem().wheel_speed_rpt_7a().wheel_spd_rear_right(), 258);
  EXPECT_DOUBLE_EQ(chassis_detail.gem().wheel_speed_rpt_7a().wheel_spd_rear_left(), 772);
  EXPECT_DOUBLE_EQ(chassis_detail.gem().wheel_speed_rpt_7a().wheel_spd_front_right(), 4370);
  EXPECT_DOUBLE_EQ(chassis_detail.gem().wheel_speed_rpt_7a().wheel_spd_front_left(), 4884);
}

}  // namespace gem
}  // namespace canbus
}  // namespace apollo
<|endoftext|>


<commit_before>#pragma once
//=====================================================================//
/*!	@file
	@brief	ルネサス RX 選択 @n
			Copyright 2016, 2017 Kunihito Hiramatsu
	@author	平松邦仁 (hira@rvf-rc45.net)
*/
//=====================================================================//
#include "common/byte_order.h"
#include "common/vect.h"
#include "common/delay.hpp"

#if defined(SIG_RX621)
#include "RX600/port.hpp"
#include "RX600/cmt.hpp"
#include "RX621/system.hpp"
#include "RX621/sci.hpp"
#include "RX621/icu.hpp"

#elif defined(SIG_RX24T)
#include "RX24T/peripheral.hpp"
#include "RX600/port.hpp"
#include "RX24T/system.hpp"
#include "RX24T/dtc.hpp"
#include "RX24T/icu.hpp"
#include "RX24T/mtu3.hpp"
#include "RX24T/poe3.hpp"
#include "RX24T/tmr.hpp"
#include "RX600/cmt.hpp"
#include "RX24T/sci.hpp"
#include "RX24T/riic.hpp"
#include "RX24T/rspi.hpp"
#include "RX24T/crc.hpp"
#include "RX24T/s12ad.hpp"
#include "RX24T/adc_io.hpp"
#include "RX24T/da.hpp"
#include "RX24T/cmpc.hpp"
#include "RX24T/doc.hpp"
#include "RX24T/port_map.hpp"
#include "RX24T/power_cfg.hpp"
#include "RX24T/icu_mgr.hpp"
#include "RX24T/flash.hpp"
#include "RX24T/flash_io.hpp"

#elif defined(SIG_RX63T)
#include "RX63T/peripheral.hpp"
#include "RX600/port.hpp"
#include "RX600/cmt.hpp"
#include "RX63T/system.hpp"
#include "RX63T/sci.hpp"
#include "RX63T/icu.hpp"
#include "RX63T/port_map.hpp"
#include "RX63T/power_cfg.hpp"
#include "RX63T/icu_mgr.hpp"

#elif defined(SIG_RX64M)
#include "RX64M/peripheral.hpp"
#include "RX600/port.hpp"
#include "RX600/cmt.hpp"
#include "RX64M/system.hpp"
#include "RX64M/bus.hpp"
#include "RX64M/mpc.hpp"
#include "RX64M/icu.hpp"
#include "RX64M/sci.hpp"
#include "RX64M/riic.hpp"
#include "RX64M/rspi.hpp"
#include "RX64M/port_map.hpp"
#include "RX64M/power_cfg.hpp"
#include "RX64M/icu_mgr.hpp"
#include "RX64M/sdhi.hpp"
#include "RX64M/s12adc.hpp"
#include "RX64M/adc_io.hpp"
#include "RX64M/sdram.hpp"
#include "RX64M/etherc.hpp"
#include "RX64M/edmac.hpp"
#include "RX64M/rtc.hpp"
#include "RX64M/rtc_io.hpp"
#include "RX64M/flash.hpp"
#include "RX64M/flash_io.hpp"
#include "RX64M/ether_io.hpp"

#else
#  error "Requires SIG_XXX to be defined"
#endif
<commit_msg>update include path for system_io<commit_after>#pragma once
//=====================================================================//
/*!	@file
	@brief	ルネサス RX 選択 @n
			Copyright 2016, 2017 Kunihito Hiramatsu
	@author	平松邦仁 (hira@rvf-rc45.net)
*/
//=====================================================================//
#include "common/byte_order.h"
#include "common/vect.h"
#include "common/delay.hpp"

#if defined(SIG_RX621)
#include "RX600/port.hpp"
#include "RX600/cmt.hpp"
#include "RX621/system.hpp"
#include "RX621/sci.hpp"
#include "RX621/icu.hpp"

#elif defined(SIG_RX24T)
#include "RX24T/peripheral.hpp"
#include "RX600/port.hpp"
#include "RX24T/system.hpp"
#include "RX24T/dtc.hpp"
#include "RX24T/icu.hpp"
#include "RX24T/mtu3.hpp"
#include "RX24T/poe3.hpp"
#include "RX24T/tmr.hpp"
#include "RX600/cmt.hpp"
#include "RX24T/sci.hpp"
#include "RX24T/riic.hpp"
#include "RX24T/rspi.hpp"
#include "RX24T/crc.hpp"
#include "RX24T/s12ad.hpp"
#include "RX24T/adc_io.hpp"
#include "RX24T/da.hpp"
#include "RX24T/cmpc.hpp"
#include "RX24T/doc.hpp"
#include "RX24T/port_map.hpp"
#include "RX24T/power_cfg.hpp"
#include "RX24T/icu_mgr.hpp"
#include "RX24T/flash.hpp"
#include "RX24T/flash_io.hpp"

#elif defined(SIG_RX63T)
#include "RX63T/peripheral.hpp"
#include "RX600/port.hpp"
#include "RX600/cmt.hpp"
#include "RX63T/system.hpp"
#include "RX63T/sci.hpp"
#include "RX63T/icu.hpp"
#include "RX63T/port_map.hpp"
#include "RX63T/power_cfg.hpp"
#include "RX63T/icu_mgr.hpp"

#elif defined(SIG_RX64M)
#include "RX64M/peripheral.hpp"
#include "RX600/port.hpp"
#include "RX600/cmt.hpp"
#include "RX64M/system.hpp"
#include "RX64M/system_io.hpp"
#include "RX64M/bus.hpp"
#include "RX64M/mpc.hpp"
#include "RX64M/icu.hpp"
#include "RX64M/sci.hpp"
#include "RX64M/riic.hpp"
#include "RX64M/rspi.hpp"
#include "RX64M/port_map.hpp"
#include "RX64M/power_cfg.hpp"
#include "RX64M/icu_mgr.hpp"
#include "RX64M/sdhi.hpp"
#include "RX64M/s12adc.hpp"
#include "RX64M/adc_io.hpp"
#include "RX64M/sdram.hpp"
#include "RX64M/etherc.hpp"
#include "RX64M/edmac.hpp"
#include "RX64M/rtc.hpp"
#include "RX64M/rtc_io.hpp"
#include "RX64M/flash.hpp"
#include "RX64M/flash_io.hpp"
#include "RX64M/ether_io.hpp"

#else
#  error "Requires SIG_XXX to be defined"
#endif
<|endoftext|>


<commit_before>#pragma comment(lib, "Shlwapi.lib")

#include "Observer.h"

#include <cstdio>
#include <cstdlib>
#include <cwchar>
#include <string>
#include <utility>
#include <functional>
#include <concurrent_unordered_map.h>

#include <Windows.h>
#include <Shlwapi.h>
#include "bass.h"
#include "bass_fx.h"
#include "Hooker.h"
#include "Server.h"

std::shared_ptr<Observer> Observer::instance;
std::once_flag Observer::once_flag;

BOOL WINAPI Observer::ReadFile(HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToRead, LPDWORD lpNumberOfBytesRead, LPOVERLAPPED lpOverlapped)
{
    Observer *self = Observer::GetInstance();
    if (!self->hookerReadFile.GetFunction()(hFile, lpBuffer, nNumberOfBytesToRead, lpNumberOfBytesRead, lpOverlapped))
    {
        return FALSE;
    }

    // osu!   ̸(260 ̻)  Ƿ,
    // szFilePath ̴ MAX_PATH ϰ ߰ Ҵϴ
    // GetFinalPathNameByHandle , szFilePath  \\?\D:\Games\osu!\...
    wchar_t szFilePath[MAX_PATH];
    DWORD nFilePathLength = GetFinalPathNameByHandle(hFile, szFilePath, MAX_PATH, VOLUME_NAME_DOS);
    // д  ũ  ƴϰų, osu! ɷ ʰ Ÿ library ۾?
    if (nFilePathLength == 0 || nFilePathLength > MAX_PATH || lpNumberOfBytesRead == NULL)
    {
        return TRUE;
    }

    DWORD dwFilePosition = SetFilePointer(hFile, 0, NULL, FILE_CURRENT) - *lpNumberOfBytesRead;
    //  д  Ʈ ̰ պκ оٸ    :
    // AudioFilename պκп  /  ڵ       !
    if (wcsnicmp(L".osu", &szFilePath[nFilePathLength - 4], 4) == 0 && dwFilePosition == 0)
    {
        // strtok ҽ ϹǷ ϴ
        // .osu  UTF-8(Multibyte) ڵ
        char *buffer = strdup((const char *) lpBuffer);
        for (char *line = strtok(buffer, "\n"); line != NULL; line = strtok(NULL, "\n"))
        {
            if (strnicmp(line, "AudioFilename:", 14) != 0)
            {
                continue;
            }

            // AudioFilename
            wchar_t szAudioFileName[MAX_PATH];
            mbstowcs(szAudioFileName, &line[14], MAX_PATH);
            StrTrim(szAudioFileName, L" \r");

            // Ʈ      ã
            wchar_t szAudioFilePath[MAX_PATH];
            wcscpy(szAudioFilePath, szFilePath);
            PathRemoveFileSpec(szAudioFilePath);
            PathCombine(szAudioFilePath, szAudioFilePath, szAudioFileName);

            // audioInfo   ˻  ҹ ϹǷ Ȯ
            WIN32_FIND_DATA fdata;
            FindClose(FindFirstFile(szAudioFilePath, &fdata));
            PathRemoveFileSpec(szAudioFilePath);
            PathCombine(szAudioFilePath, szAudioFilePath, fdata.cFileName);

            // PathCombineW \\?\(Long Unicode path prefix) ϴµ,
            // GetFinalPathNameByHandle 忡 ° ٽ ߰ؼ
            //  ٲ    ȥ
            wcscpy(szAudioFileName, szAudioFilePath);
            wcscpy(szAudioFilePath, L"\\\\?\\");
            wcscat(szAudioFilePath, szAudioFileName);

            // osu! Ʈ ٲ  Ź Ʈ   ʰ ĳÿ ҷ⵵
            // => Ʈ Ϻٴ       ؾ
            self->audioInfo.insert({szAudioFilePath, szFilePath});
            break;
        }
        free(buffer);
    }
    //  д  Ʈ      ϱ
    else
    {
        decltype(self->audioInfo)::iterator info;
        if ((info = self->audioInfo.find(szFilePath)) != self->audioInfo.end())
        {
            EnterCriticalSection(&self->hCritiaclSection);
            self->playing = {info->first.substr(4), info->second.substr(4)};
            LeaveCriticalSection(&self->hCritiaclSection);
        }
    }
    return TRUE;
}

inline long long GetSystemTimeAsFileTime()
{
    /*
    * Do not cast a pointer to a FILETIME structure to either a
    * ULARGE_INTEGER* or __int64* value because it can cause alignment faults on 64-bit Windows.
    * via  http://technet.microsoft.com/en-us/library/ms724284(v=vs.85).aspx
    */
    FILETIME ft;
    GetSystemTimeAsFileTime(&ft);
    return ((long long) ft.dwHighDateTime << 32) + ft.dwLowDateTime;
}

BOOL WINAPI Observer::BASS_ChannelPlay(DWORD handle, BOOL restart)
{
    Observer *self = Observer::GetInstance();
    if (!self->hookerBASS_ChannelPlay.GetFunction()(handle, restart))
    {
        return FALSE;
    }

    BASS_CHANNELINFO info;
    BASS_ChannelGetInfo(handle, &info);
    if (info.ctype & BASS_CTYPE_STREAM)
    {
        double currentTime = BASS_ChannelBytes2Seconds(handle, BASS_ChannelGetPosition(handle, BASS_POS_BYTE));
        float tempo = 0;
        BASS_ChannelGetAttribute(handle, BASS_ATTRIB_TEMPO, &tempo);
        self->Update(currentTime, tempo);
    }
    return TRUE;
}

BOOL WINAPI Observer::BASS_ChannelSetPosition(DWORD handle, QWORD pos, DWORD mode)
{
    Observer *self = Observer::GetInstance();
    if (!self->hookerBASS_ChannelSetPosition.GetFunction()(handle, pos, mode))
    {
        return FALSE;
    }

    BASS_CHANNELINFO info;
    BASS_ChannelGetInfo(handle, &info);
    if (info.ctype & BASS_CTYPE_STREAM)
    {
        double currentTime = BASS_ChannelBytes2Seconds(handle, pos);
        float tempo = 0;
        BASS_ChannelGetAttribute(handle, BASS_ATTRIB_TEMPO, &tempo);
        // !! pos   ,
        // ϸ BASS_ChannelPlay  Լ ȣǰ,
        // BASS_ChannelIsActive  BASS_ACTIVE_PAUSED.
        if (BASS_ChannelIsActive(handle) == BASS_ACTIVE_PAUSED)
        {
            tempo = -100;
        }
        self->Update(currentTime, tempo);
    }
    return TRUE;
}

BOOL WINAPI Observer::BASS_ChannelSetAttribute(DWORD handle, DWORD attrib, float value)
{
    Observer *self = Observer::GetInstance();
    if (!self->hookerBASS_ChannelSetAttribute.GetFunction()(handle, attrib, value))
    {
        return FALSE;
    }

    BASS_CHANNELINFO info;
    BASS_ChannelGetInfo(handle, &info);
    if ((info.ctype & BASS_CTYPE_STREAM) && attrib == BASS_ATTRIB_TEMPO)
    {
        double currentTime = BASS_ChannelBytes2Seconds(handle, BASS_ChannelGetPosition(handle, BASS_POS_BYTE));
        self->Update(currentTime, value);
    }
    return TRUE;
}

BOOL WINAPI Observer::BASS_ChannelPause(DWORD handle)
{
    Observer *self = Observer::GetInstance();
    if (!self->hookerBASS_ChannelPause.GetFunction()(handle))
    {
        return FALSE;
    }

    BASS_CHANNELINFO info;
    BASS_ChannelGetInfo(handle, &info);
    if (info.ctype & BASS_CTYPE_STREAM)
    {
        double currentTime = BASS_ChannelBytes2Seconds(handle, BASS_ChannelGetPosition(handle, BASS_POS_BYTE));
        self->Update(currentTime, -100);
    }
    return TRUE;
}

void Observer::Update(double currentTime, float tempo)
{
    Observer *self = Observer::GetInstance();
    wchar_t message[Server::nMessageLength];
    EnterCriticalSection(&self->hCritiaclSection);
    swprintf(message, L"%llx|%s|%lf|%f|%s\n",
        GetSystemTimeAsFileTime(),
        self->playing.first.c_str(),
        currentTime,
        tempo,
        self->playing.second.c_str()
    );
    LeaveCriticalSection(&self->hCritiaclSection);
    Server::GetInstance()->PushMessage(message);
}

void Observer::Run()
{
    this->hookerReadFile.Hook();

    this->hookerBASS_ChannelPlay.Hook();
    this->hookerBASS_ChannelSetPosition.Hook();
    this->hookerBASS_ChannelSetAttribute.Hook();
    this->hookerBASS_ChannelPause.Hook();
}

void Observer::Stop()
{
    this->hookerBASS_ChannelPause.Unhook();
    this->hookerBASS_ChannelSetAttribute.Unhook();
    this->hookerBASS_ChannelSetPosition.Unhook();
    this->hookerBASS_ChannelPlay.Unhook();

    this->hookerReadFile.Unhook();
}
<commit_msg>Revert "#31 해결"<commit_after>#pragma comment(lib, "Shlwapi.lib")

#include "Observer.h"

#include <cstdio>
#include <cstdlib>
#include <cwchar>
#include <string>
#include <utility>
#include <functional>
#include <concurrent_unordered_map.h>

#include <Windows.h>
#include <Shlwapi.h>
#include "bass.h"
#include "bass_fx.h"
#include "Hooker.h"
#include "Server.h"

std::shared_ptr<Observer> Observer::instance;
std::once_flag Observer::once_flag;

BOOL WINAPI Observer::ReadFile(HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToRead, LPDWORD lpNumberOfBytesRead, LPOVERLAPPED lpOverlapped)
{
    Observer *self = Observer::GetInstance();
    if (!self->hookerReadFile.GetFunction()(hFile, lpBuffer, nNumberOfBytesToRead, lpNumberOfBytesRead, lpOverlapped))
    {
        return FALSE;
    }

    // osu!   ̸(260 ̻)  Ƿ,
    // szFilePath ̴ MAX_PATH ϰ ߰ Ҵϴ
    // GetFinalPathNameByHandle , szFilePath  \\?\D:\Games\osu!\...
    wchar_t szFilePath[MAX_PATH];
    DWORD nFilePathLength = GetFinalPathNameByHandle(hFile, szFilePath, MAX_PATH, VOLUME_NAME_DOS);
    // д  ũ  ƴϰų, osu! ɷ ʰ Ÿ library ۾?
    if (nFilePathLength == 0 || nFilePathLength > MAX_PATH || lpNumberOfBytesRead == NULL)
    {
        return TRUE;
    }

    DWORD dwFilePosition = SetFilePointer(hFile, 0, NULL, FILE_CURRENT) - *lpNumberOfBytesRead;
    //  д  Ʈ ̰ պκ оٸ    :
    // AudioFilename պκп  /  ڵ       !
    if (wcsnicmp(L".osu", &szFilePath[nFilePathLength - 4], 4) == 0 && dwFilePosition == 0)
    {
        // strtok ҽ ϹǷ ϴ
        // .osu  UTF-8(Multibyte) ڵ
        char *buffer = strdup((const char *) lpBuffer);
        for (char *line = strtok(buffer, "\n"); line != NULL; line = strtok(NULL, "\n"))
        {
            if (strnicmp(line, "AudioFilename:", 14) != 0)
            {
                continue;
            }

            // AudioFilename
            wchar_t szAudioFileName[MAX_PATH];
            mbstowcs(szAudioFileName, &line[14], MAX_PATH);
            StrTrim(szAudioFileName, L" \r");

            // Ʈ      ã
            wchar_t szAudioFilePath[MAX_PATH];
            wcscpy(szAudioFilePath, szFilePath);
            PathRemoveFileSpec(szAudioFilePath);
            PathCombine(szAudioFilePath, szAudioFilePath, szAudioFileName);

            // audioInfo   ˻  ҹ ϹǷ Ȯ
            WIN32_FIND_DATA fdata;
            FindClose(FindFirstFile(szAudioFilePath, &fdata));
            PathRemoveFileSpec(szAudioFilePath);
            PathCombine(szAudioFilePath, szAudioFilePath, fdata.cFileName);

            // PathCombineW \\?\(Long Unicode path prefix) ϴµ,
            // GetFinalPathNameByHandle 忡 ° ٽ ߰ؼ
            //  ٲ    ȥ
            wcscpy(szAudioFileName, szAudioFilePath);
            wcscpy(szAudioFilePath, L"\\\\?\\");
            wcscat(szAudioFilePath, szAudioFileName);

            // osu! Ʈ ٲ  Ź Ʈ   ʰ ĳÿ ҷ⵵
            // => Ʈ Ϻٴ       ؾ
            self->audioInfo.insert({szAudioFilePath, szFilePath});
            break;
        }
        free(buffer);
    }
    //  д  Ʈ      ϱ
    else
    {
        decltype(self->audioInfo)::iterator info;
        if ((info = self->audioInfo.find(szFilePath)) != self->audioInfo.end())
        {
            EnterCriticalSection(&self->hCritiaclSection);
            self->playing = {info->first.substr(4), info->second.substr(4)};
            LeaveCriticalSection(&self->hCritiaclSection);
        }
    }
    return TRUE;
}

inline long long GetSystemTimeAsFileTime()
{
    /*
    * Do not cast a pointer to a FILETIME structure to either a
    * ULARGE_INTEGER* or __int64* value because it can cause alignment faults on 64-bit Windows.
    * via  http://technet.microsoft.com/en-us/library/ms724284(v=vs.85).aspx
    */
    FILETIME ft;
    GetSystemTimeAsFileTime(&ft);
    return ((long long) ft.dwHighDateTime << 32) + ft.dwLowDateTime;
}

BOOL WINAPI Observer::BASS_ChannelPlay(DWORD handle, BOOL restart)
{
    Observer *self = Observer::GetInstance();
    if (!self->hookerBASS_ChannelPlay.GetFunction()(handle, restart))
    {
        return FALSE;
    }

    BASS_CHANNELINFO info;
    BASS_ChannelGetInfo(handle, &info);
    if (info.ctype & BASS_CTYPE_STREAM)
    {
        double currentTime = BASS_ChannelBytes2Seconds(handle, BASS_ChannelGetPosition(handle, BASS_POS_BYTE));
        float tempo; BASS_ChannelGetAttribute(handle, BASS_ATTRIB_TEMPO, &tempo);
        self->Update(currentTime, tempo);
    }
    return TRUE;
}

BOOL WINAPI Observer::BASS_ChannelSetPosition(DWORD handle, QWORD pos, DWORD mode)
{
    Observer *self = Observer::GetInstance();
    if (!self->hookerBASS_ChannelSetPosition.GetFunction()(handle, pos, mode))
    {
        return FALSE;
    }

    BASS_CHANNELINFO info;
    BASS_ChannelGetInfo(handle, &info);
    if (info.ctype & BASS_CTYPE_STREAM)
    {
        double currentTime = BASS_ChannelBytes2Seconds(handle, pos);
        float tempo; BASS_ChannelGetAttribute(handle, BASS_ATTRIB_TEMPO, &tempo);
        // !! pos   ,
        // ϸ BASS_ChannelPlay  Լ ȣǰ,
        // BASS_ChannelIsActive  BASS_ACTIVE_PAUSED.
        if (BASS_ChannelIsActive(handle) == BASS_ACTIVE_PAUSED)
        {
            tempo = -100;
        }
        self->Update(currentTime, tempo);
    }
    return TRUE;
}

BOOL WINAPI Observer::BASS_ChannelSetAttribute(DWORD handle, DWORD attrib, float value)
{
    Observer *self = Observer::GetInstance();
    if (!self->hookerBASS_ChannelSetAttribute.GetFunction()(handle, attrib, value))
    {
        return FALSE;
    }

    BASS_CHANNELINFO info;
    BASS_ChannelGetInfo(handle, &info);
    if ((info.ctype & BASS_CTYPE_STREAM) && attrib == BASS_ATTRIB_TEMPO)
    {
        double currentTime = BASS_ChannelBytes2Seconds(handle, BASS_ChannelGetPosition(handle, BASS_POS_BYTE));
        self->Update(currentTime, value);
    }
    return TRUE;
}

BOOL WINAPI Observer::BASS_ChannelPause(DWORD handle)
{
    Observer *self = Observer::GetInstance();
    if (!self->hookerBASS_ChannelPause.GetFunction()(handle))
    {
        return FALSE;
    }

    BASS_CHANNELINFO info;
    BASS_ChannelGetInfo(handle, &info);
    if (info.ctype & BASS_CTYPE_STREAM)
    {
        double currentTime = BASS_ChannelBytes2Seconds(handle, BASS_ChannelGetPosition(handle, BASS_POS_BYTE));
        self->Update(currentTime, -100);
    }
    return TRUE;
}

void Observer::Update(double currentTime, float tempo)
{
    Observer *self = Observer::GetInstance();
    wchar_t message[Server::nMessageLength];
    EnterCriticalSection(&self->hCritiaclSection);
    swprintf(message, L"%llx|%s|%lf|%f|%s\n",
        GetSystemTimeAsFileTime(),
        self->playing.first.c_str(),
        currentTime,
        tempo,
        self->playing.second.c_str()
    );
    LeaveCriticalSection(&self->hCritiaclSection);
    Server::GetInstance()->PushMessage(message);
}

void Observer::Run()
{
    this->hookerReadFile.Hook();

    this->hookerBASS_ChannelPlay.Hook();
    this->hookerBASS_ChannelSetPosition.Hook();
    this->hookerBASS_ChannelSetAttribute.Hook();
    this->hookerBASS_ChannelPause.Hook();
}

void Observer::Stop()
{
    this->hookerBASS_ChannelPause.Unhook();
    this->hookerBASS_ChannelSetAttribute.Unhook();
    this->hookerBASS_ChannelSetPosition.Unhook();
    this->hookerBASS_ChannelPlay.Unhook();

    this->hookerReadFile.Unhook();
}
<|endoftext|>


<commit_before>//
//  GPUUniform.h
//  G3MiOSSDK
//
//  Created by Jose Miguel SN on 05/04/13.
//
//

#ifndef G3MiOSSDK_GPUUniform_h
#define G3MiOSSDK_GPUUniform_h

#include "GL.hpp"
#include "GLConstants.hpp"
#include "IGLUniformID.hpp"
#include "IStringBuilder.hpp"
#include "GPUVariable.hpp"

class GPUUniform;

class GPUUniformValue{
  const int _type;

  mutable GPUUniform* _uniform;

public:
  GPUUniformValue(int type):_type(type), _uniform(NULL){}
  int getType() const { return _type;}
  virtual ~GPUUniformValue(){}
  virtual void setUniform(GL* gl, const IGLUniformID* id) const = 0;
  virtual bool isEqualsTo(const GPUUniformValue* v) const = 0;
  virtual GPUUniformValue* deepCopy() const = 0;

  GPUUniform* getLinkedUniform() const { return _uniform;}

  virtual std::string description() const = 0;

  void linkToGPUUniform(GPUUniform* u) const{
    _uniform = u;
  }

  void unLinkToGPUUniform(){
    _uniform = NULL;
  }

  void setValueToLinkedUniform() const;

  virtual void setLastGPUUniformValue(GPUUniformValue* old){} //Used with matrix transform value

  virtual void copyFrom(GPUUniformValue* v) = 0;

  virtual GPUUniformValue* copyOrCreate(GPUUniformValue* value){return value;}
};

class GPUUniform: public GPUVariable{

protected:
  const IGLUniformID* _id;

  bool _dirty;
  GPUUniformValue* _value;
  const int _type;
public:

  virtual ~GPUUniform(){
    delete _id;
    delete _value;
  }

  GPUUniform(const std::string&name, IGLUniformID* id, int type):
  GPUVariable(name, UNIFORM),
  _id(id),
  _dirty(false),
  _value(NULL),
  _type(type){}

  const std::string getName() const{ return _name;}
  const IGLUniformID* getID() const{ return _id;}
  int getType() const{ return _type;}
  bool wasSet() const { return _value != NULL;}
  GPUUniformValue* getSetValue() const { return _value;}

  void unset(){
    if (_value != NULL){
      delete _value;
      _value = NULL;
    }
    _dirty = false;
  }

  void set(GPUUniformValue* v){
    if (_type != v->getType()){ //type checking
      ILogger::instance()->logError("Attempting to set uniform " + _name + "with invalid value type.");
      return;
    }
    if (_value == NULL || !_value->isEqualsTo(v)){
      _dirty = true;

      _value = v->copyOrCreate(_value);

//      if (_value == NULL){
//        _value = v->deepCopy();
//      } else{
//        v->setLastGPUUniformValue(_value); //Multiply matrix when needed
//        _value->copyFrom(v);
//      }
    }
  }

  virtual void applyChanges(GL* gl){
    if (_dirty){
      _value->setUniform(gl, _id);
      _dirty = false;
    } else{
      if (_value == NULL){
        ILogger::instance()->logError("Uniform " + _name + " was not set.");
      }
    }
  }
};

////////////////////////////////////////////////////////////////////////
class GPUUniformValueBool:public GPUUniformValue{
public:
  bool _value;

  GPUUniformValueBool(bool b):GPUUniformValue(GLType::glBool()),_value(b){}

  void setUniform(GL* gl, const IGLUniformID* id) const{
    _value? gl->uniform1i(id, 1) : gl->uniform1i(id, 0);
  }
  bool isEqualsTo(const GPUUniformValue* v) const{
    return _value == ((GPUUniformValueBool*)v)->_value;
  }
  GPUUniformValue* deepCopy() const{
    return new GPUUniformValueBool(_value);
  }

  GPUUniformValue* copyOrCreate(GPUUniformValue* value){
    if (value == NULL){
      return new GPUUniformValueBool(_value);
    } else{
      ((GPUUniformValueBool*)value)->_value = _value;
      return value;
    }
  }

  void copyFrom(GPUUniformValue* v){
    _value = ((GPUUniformValueBool*)v)->_value;
  }

  std::string description() const{
    IStringBuilder *isb = IStringBuilder::newStringBuilder();
    isb->addString("Uniform Value Boolean: ");
    isb->addBool(_value);
    std::string s = isb->getString();
    delete isb;
    return s;
  }
};
class GPUUniformBool: public GPUUniform{
public:
  GPUUniformBool(const std::string&name, IGLUniformID* id):GPUUniform(name,id, GLType::glBool()){}
};
////////////////////////////////////////////////////////////////////////
class GPUUniformValueVec2Float:public GPUUniformValue{
public:
  double _x, _y;

  GPUUniformValueVec2Float(double x, double y):GPUUniformValue(GLType::glVec2Float()), _x(x),_y(y){}

  void setUniform(GL* gl, const IGLUniformID* id) const{
    gl->uniform2f(id, (float)_x, (float)_y);
  }
  bool isEqualsTo(const GPUUniformValue* v) const{
    GPUUniformValueVec2Float *v2 = (GPUUniformValueVec2Float *)v;
    return (_x == v2->_x) && (_y == v2->_y);
  }
  GPUUniformValue* deepCopy() const{
    return new GPUUniformValueVec2Float(_x,_y);
  }

  void copyFrom(GPUUniformValue* v){
    _x = ((GPUUniformValueVec2Float*)v)->_x;
    _y = ((GPUUniformValueVec2Float*)v)->_y;
  }

  GPUUniformValue* copyOrCreate(GPUUniformValue* value){
    if (value == NULL){
      return new GPUUniformValueVec2Float(_x,_y);
    } else{
      ((GPUUniformValueVec2Float*)value)->_x = _x;
      ((GPUUniformValueVec2Float*)value)->_y = _y;
      return value;
    }
  }

  std::string description() const{
    IStringBuilder *isb = IStringBuilder::newStringBuilder();
    isb->addString("Uniform Value Vec2Float: x:");
    isb->addDouble(_x);
    isb->addString("y:");
    isb->addDouble(_y);
    std::string s = isb->getString();
    delete isb;
    return s;
  }
};
class GPUUniformVec2Float: public GPUUniform{
public:
  GPUUniformVec2Float(const std::string&name, IGLUniformID* id):GPUUniform(name,id, GLType::glVec2Float()){}
};
////////////////////////////////////////////////////////////////////////
class GPUUniformValueVec4Float:public GPUUniformValue{
public:
  double _x, _y, _z, _w;

  GPUUniformValueVec4Float(double x, double y, double z, double w):
  GPUUniformValue(GLType::glVec4Float()),_x(x),_y(y), _z(z), _w(w){}

  void setUniform(GL* gl, const IGLUniformID* id) const{
    gl->uniform4f(id, (float)_x, (float)_y, (float)_z, (float)_w);
  }
  bool isEqualsTo(const GPUUniformValue* v) const{
    GPUUniformValueVec4Float *v2 = (GPUUniformValueVec4Float *)v;
    return (_x == v2->_x) && (_y == v2->_y) && (_z == v2->_z) && (_w == v2->_w);
  }
  GPUUniformValue* deepCopy() const{
    return new GPUUniformValueVec4Float(_x,_y,_z,_w);
  }

  void copyFrom(GPUUniformValue* v){
    _x = ((GPUUniformValueVec4Float*)v)->_x;
    _y = ((GPUUniformValueVec4Float*)v)->_y;
    _z = ((GPUUniformValueVec4Float*)v)->_z;
    _w = ((GPUUniformValueVec4Float*)v)->_w;
  }

  GPUUniformValue* copyOrCreate(GPUUniformValue* value){
    if (value == NULL){
      return new GPUUniformValueVec4Float(_x,_y,_z,_w);
    } else{
      ((GPUUniformValueVec4Float*)value)->_x = _x;
      ((GPUUniformValueVec4Float*)value)->_y = _y;
      ((GPUUniformValueVec4Float*)value)->_z = _z;
      ((GPUUniformValueVec4Float*)value)->_w = _w;
      return value;
    }
  }

  std::string description() const{
    IStringBuilder *isb = IStringBuilder::newStringBuilder();
    isb->addString("Uniform Value Vec4Float: x:");
    isb->addDouble(_x);
    isb->addString("y:");
    isb->addDouble(_y);
    isb->addString("z:");
    isb->addDouble(_z);
    isb->addString("w:");
    isb->addDouble(_w);
    std::string s = isb->getString();
    delete isb;
    return s;
  }
};
class GPUUniformVec4Float: public GPUUniform{
public:
  GPUUniformVec4Float(const std::string&name, IGLUniformID* id):GPUUniform(name,id, GLType::glVec4Float()){}
};
////////////////////////////////////////////////////////////////////////
class GPUUniformValueMatrix4FloatTransform:public GPUUniformValue{

  GPUUniformValueMatrix4FloatTransform(const GPUUniformValueMatrix4FloatTransform* that):
  GPUUniformValue(GLType::glMatrix4Float()),
  _m(MutableMatrix44D(that->_m)),
  _isTransform(that->_isTransform)
   {}

public:
#ifdef C_CODE
  MutableMatrix44D _m;
#endif
#ifdef JAVA_CODE
  public MutableMatrix44D _m;
#endif

  bool _isTransform;

  GPUUniformValueMatrix4FloatTransform(const MutableMatrix44D& m, bool isTransform):
  GPUUniformValue(GLType::glMatrix4Float()),_m(m), _isTransform(isTransform)/*, _transformedMatrix(m)*/{}

  void setLastGPUUniformValue(GPUUniformValue* old){
    if (_isTransform){
      if (old == NULL){
        ILogger::instance()->logError("Trying to apply transformation to matrix without previous value");
      } else{
        const MutableMatrix44D* lastM = ((GPUUniformValueMatrix4FloatTransform*)old)->getValue();
      }
    }
  }

  void setUniform(GL* gl, const IGLUniformID* id) const{
    gl->uniformMatrix4fv(id, false, &_m);
  }

  bool isEqualsTo(const GPUUniformValue* v) const{
    GPUUniformValueMatrix4FloatTransform *v2 = (GPUUniformValueMatrix4FloatTransform *)v;
    return _m.isEqualsTo(v2->_m);
  }
  GPUUniformValue* deepCopy() const{
    return new GPUUniformValueMatrix4FloatTransform(this);
  }

  void copyFrom(GPUUniformValue* v){
    _m.copyValue( ((GPUUniformValueMatrix4FloatTransform*)v)->_m );
  }

  GPUUniformValue* copyOrCreate(GPUUniformValue* value){
    if (value == NULL){
      return new GPUUniformValueMatrix4FloatTransform(_m, _isTransform);
    } else{
      GPUUniformValueMatrix4FloatTransform* valueM = (GPUUniformValueMatrix4FloatTransform*)value;
      if (_isTransform){
        valueM->_m.copyValue(valueM->_m.multiply(_m));
      } else{
        valueM->_m.copyValue(_m);
      }
      return value;
    }
  }

  std::string description() const{
    IStringBuilder *isb = IStringBuilder::newStringBuilder();
    isb->addString("Uniform Value Matrix44D.");
    std::string s = isb->getString();
    delete isb;
    return s;
  }

  const MutableMatrix44D* getValue() const{
//    return &_transformedMatrix;
    return &_m;
  }
};
class GPUUniformMatrix4Float: public GPUUniform{
public:
  GPUUniformMatrix4Float(const std::string&name, IGLUniformID* id):GPUUniform(name,id, GLType::glMatrix4Float()){}
};
////////////////////////////////////////////////////////////////////////
class GPUUniformValueFloat:public GPUUniformValue{
public:
  double _value;

  GPUUniformValueFloat(double d):GPUUniformValue(GLType::glFloat()),_value(d){}

  void setUniform(GL* gl, const IGLUniformID* id) const{
    gl->uniform1f(id, (float)_value);
  }
  bool isEqualsTo(const GPUUniformValue* v) const{
    GPUUniformValueFloat *v2 = (GPUUniformValueFloat *)v;
    return _value == v2->_value;
  }
  GPUUniformValue* deepCopy() const{
    return new GPUUniformValueFloat(_value);
  }

  void copyFrom(GPUUniformValue* v){
    _value = ((GPUUniformValueFloat*)v)->_value;
  }

  GPUUniformValue* copyOrCreate(GPUUniformValue* value){
    if (value == NULL){
      return new GPUUniformValueFloat(_value);
    } else{
      ((GPUUniformValueFloat*)value)->_value = _value;
      return value;
    }
  }

  std::string description() const{
    IStringBuilder *isb = IStringBuilder::newStringBuilder();
    isb->addString("Uniform Value Float: ");
    isb->addDouble(_value);
    std::string s = isb->getString();
    delete isb;
    return s;
  }
};
class GPUUniformFloat: public GPUUniform{
public:
  GPUUniformFloat(const std::string&name, IGLUniformID* id):GPUUniform(name,id, GLType::glFloat()){}
};
////////////////////////////////////////////////////////////////////////
#endif
<commit_msg>less virtual functions<commit_after>//
//  GPUUniform.h
//  G3MiOSSDK
//
//  Created by Jose Miguel SN on 05/04/13.
//
//

#ifndef G3MiOSSDK_GPUUniform_h
#define G3MiOSSDK_GPUUniform_h

#include "GL.hpp"
#include "GLConstants.hpp"
#include "IGLUniformID.hpp"
#include "IStringBuilder.hpp"
#include "GPUVariable.hpp"

class GPUUniform;

class GPUUniformValue{
  const int _type;

  mutable GPUUniform* _uniform;

public:
  GPUUniformValue(int type):_type(type), _uniform(NULL){}
  int getType() const { return _type;}
  virtual ~GPUUniformValue(){}
  virtual void setUniform(GL* gl, const IGLUniformID* id) const = 0;
  virtual bool isEqualsTo(const GPUUniformValue* v) const = 0;

  GPUUniform* getLinkedUniform() const { return _uniform;}

  virtual std::string description() const = 0;

  void linkToGPUUniform(GPUUniform* u) const{
    _uniform = u;
  }

  void unLinkToGPUUniform(){
    _uniform = NULL;
  }

  void setValueToLinkedUniform() const;

  virtual GPUUniformValue* copyOrCreate(GPUUniformValue* value){return value;}

  bool linkToGPUProgram(const GPUProgram* prog, int key) const{
    GPUUniform* u = prog->getGPUUniform(key);
    if (u == NULL){
      ILogger::instance()->logError("UNIFORM WITH KEY %d NOT FOUND", key);
      return false;
    } else{
      _uniform = u;
      return true;
    }
  }
};

class GPUUniform: public GPUVariable{

protected:
  const IGLUniformID* _id;

  bool _dirty;
  GPUUniformValue* _value;
  const int _type;
public:

  virtual ~GPUUniform(){
    delete _id;
    delete _value;
  }

  GPUUniform(const std::string&name, IGLUniformID* id, int type):
  GPUVariable(name, UNIFORM),
  _id(id),
  _dirty(false),
  _value(NULL),
  _type(type){}

  const std::string getName() const{ return _name;}
  const IGLUniformID* getID() const{ return _id;}
  int getType() const{ return _type;}
  bool wasSet() const { return _value != NULL;}
  GPUUniformValue* getSetValue() const { return _value;}

  void unset(){
    if (_value != NULL){
      delete _value;
      _value = NULL;
    }
    _dirty = false;
  }

  void set(GPUUniformValue* v){
    if (_type != v->getType()){ //type checking
      ILogger::instance()->logError("Attempting to set uniform " + _name + "with invalid value type.");
      return;
    }
    if (_value == NULL || !_value->isEqualsTo(v)){
      _dirty = true;
      _value = v->copyOrCreate(_value);
    }
  }

  virtual void applyChanges(GL* gl){
    if (_dirty){
      _value->setUniform(gl, _id);
      _dirty = false;
    } else{
      if (_value == NULL){
        ILogger::instance()->logError("Uniform " + _name + " was not set.");
      }
    }
  }
};

////////////////////////////////////////////////////////////////////////
class GPUUniformValueBool:public GPUUniformValue{
public:
  bool _value;

  GPUUniformValueBool(bool b):GPUUniformValue(GLType::glBool()),_value(b){}

  void setUniform(GL* gl, const IGLUniformID* id) const{
    _value? gl->uniform1i(id, 1) : gl->uniform1i(id, 0);
  }
  bool isEqualsTo(const GPUUniformValue* v) const{
    return _value == ((GPUUniformValueBool*)v)->_value;
  }

  GPUUniformValue* copyOrCreate(GPUUniformValue* value){
    if (value == NULL){
      return new GPUUniformValueBool(_value);
    } else{
      ((GPUUniformValueBool*)value)->_value = _value;
      return value;
    }
  }

  std::string description() const{
    IStringBuilder *isb = IStringBuilder::newStringBuilder();
    isb->addString("Uniform Value Boolean: ");
    isb->addBool(_value);
    std::string s = isb->getString();
    delete isb;
    return s;
  }
};
class GPUUniformBool: public GPUUniform{
public:
  GPUUniformBool(const std::string&name, IGLUniformID* id):GPUUniform(name,id, GLType::glBool()){}
};
////////////////////////////////////////////////////////////////////////
class GPUUniformValueVec2Float:public GPUUniformValue{
public:
  double _x, _y;

  GPUUniformValueVec2Float(double x, double y):GPUUniformValue(GLType::glVec2Float()), _x(x),_y(y){}

  void setUniform(GL* gl, const IGLUniformID* id) const{
    gl->uniform2f(id, (float)_x, (float)_y);
  }
  bool isEqualsTo(const GPUUniformValue* v) const{
    GPUUniformValueVec2Float *v2 = (GPUUniformValueVec2Float *)v;
    return (_x == v2->_x) && (_y == v2->_y);
  }

  GPUUniformValue* copyOrCreate(GPUUniformValue* value){
    if (value == NULL){
      return new GPUUniformValueVec2Float(_x,_y);
    } else{
      ((GPUUniformValueVec2Float*)value)->_x = _x;
      ((GPUUniformValueVec2Float*)value)->_y = _y;
      return value;
    }
  }

  std::string description() const{
    IStringBuilder *isb = IStringBuilder::newStringBuilder();
    isb->addString("Uniform Value Vec2Float: x:");
    isb->addDouble(_x);
    isb->addString("y:");
    isb->addDouble(_y);
    std::string s = isb->getString();
    delete isb;
    return s;
  }
};
class GPUUniformVec2Float: public GPUUniform{
public:
  GPUUniformVec2Float(const std::string&name, IGLUniformID* id):GPUUniform(name,id, GLType::glVec2Float()){}
};
////////////////////////////////////////////////////////////////////////
class GPUUniformValueVec4Float:public GPUUniformValue{
public:
  double _x, _y, _z, _w;

  GPUUniformValueVec4Float(double x, double y, double z, double w):
  GPUUniformValue(GLType::glVec4Float()),_x(x),_y(y), _z(z), _w(w){}

  void setUniform(GL* gl, const IGLUniformID* id) const{
    gl->uniform4f(id, (float)_x, (float)_y, (float)_z, (float)_w);
  }
  bool isEqualsTo(const GPUUniformValue* v) const{
    GPUUniformValueVec4Float *v2 = (GPUUniformValueVec4Float *)v;
    return (_x == v2->_x) && (_y == v2->_y) && (_z == v2->_z) && (_w == v2->_w);
  }

  GPUUniformValue* copyOrCreate(GPUUniformValue* value){
    if (value == NULL){
      return new GPUUniformValueVec4Float(_x,_y,_z,_w);
    } else{
      ((GPUUniformValueVec4Float*)value)->_x = _x;
      ((GPUUniformValueVec4Float*)value)->_y = _y;
      ((GPUUniformValueVec4Float*)value)->_z = _z;
      ((GPUUniformValueVec4Float*)value)->_w = _w;
      return value;
    }
  }

  std::string description() const{
    IStringBuilder *isb = IStringBuilder::newStringBuilder();
    isb->addString("Uniform Value Vec4Float: x:");
    isb->addDouble(_x);
    isb->addString("y:");
    isb->addDouble(_y);
    isb->addString("z:");
    isb->addDouble(_z);
    isb->addString("w:");
    isb->addDouble(_w);
    std::string s = isb->getString();
    delete isb;
    return s;
  }
};
class GPUUniformVec4Float: public GPUUniform{
public:
  GPUUniformVec4Float(const std::string&name, IGLUniformID* id):GPUUniform(name,id, GLType::glVec4Float()){}
};
////////////////////////////////////////////////////////////////////////
class GPUUniformValueMatrix4FloatTransform:public GPUUniformValue{

  GPUUniformValueMatrix4FloatTransform(const GPUUniformValueMatrix4FloatTransform* that):
  GPUUniformValue(GLType::glMatrix4Float()),
  _m(MutableMatrix44D(that->_m)),
  _isTransform(that->_isTransform)
   {}

public:
#ifdef C_CODE
  MutableMatrix44D _m;
#endif
#ifdef JAVA_CODE
  public MutableMatrix44D _m;
#endif

  bool _isTransform;

  GPUUniformValueMatrix4FloatTransform(const MutableMatrix44D& m, bool isTransform):
  GPUUniformValue(GLType::glMatrix4Float()),_m(m), _isTransform(isTransform)/*, _transformedMatrix(m)*/{}

  void setUniform(GL* gl, const IGLUniformID* id) const{
    gl->uniformMatrix4fv(id, false, &_m);
  }

  bool isEqualsTo(const GPUUniformValue* v) const{
    GPUUniformValueMatrix4FloatTransform *v2 = (GPUUniformValueMatrix4FloatTransform *)v;
    return _m.isEqualsTo(v2->_m);
  }

  GPUUniformValue* copyOrCreate(GPUUniformValue* value){
    if (value == NULL){
      return new GPUUniformValueMatrix4FloatTransform(_m, _isTransform);
    } else{
      GPUUniformValueMatrix4FloatTransform* valueM = (GPUUniformValueMatrix4FloatTransform*)value;
      if (_isTransform){
        valueM->_m.copyValue(valueM->_m.multiply(_m));
      } else{
        valueM->_m.copyValue(_m);
      }
      return value;
    }
  }

  std::string description() const{
    IStringBuilder *isb = IStringBuilder::newStringBuilder();
    isb->addString("Uniform Value Matrix44D.");
    std::string s = isb->getString();
    delete isb;
    return s;
  }

  const MutableMatrix44D* getValue() const{
//    return &_transformedMatrix;
    return &_m;
  }
};
class GPUUniformMatrix4Float: public GPUUniform{
public:
  GPUUniformMatrix4Float(const std::string&name, IGLUniformID* id):GPUUniform(name,id, GLType::glMatrix4Float()){}
};
////////////////////////////////////////////////////////////////////////
class GPUUniformValueFloat:public GPUUniformValue{
public:
  double _value;

  GPUUniformValueFloat(double d):GPUUniformValue(GLType::glFloat()),_value(d){}

  void setUniform(GL* gl, const IGLUniformID* id) const{
    gl->uniform1f(id, (float)_value);
  }
  bool isEqualsTo(const GPUUniformValue* v) const{
    GPUUniformValueFloat *v2 = (GPUUniformValueFloat *)v;
    return _value == v2->_value;
  }

  GPUUniformValue* copyOrCreate(GPUUniformValue* value){
    if (value == NULL){
      return new GPUUniformValueFloat(_value);
    } else{
      ((GPUUniformValueFloat*)value)->_value = _value;
      return value;
    }
  }

  std::string description() const{
    IStringBuilder *isb = IStringBuilder::newStringBuilder();
    isb->addString("Uniform Value Float: ");
    isb->addDouble(_value);
    std::string s = isb->getString();
    delete isb;
    return s;
  }
};
class GPUUniformFloat: public GPUUniform{
public:
  GPUUniformFloat(const std::string&name, IGLUniformID* id):GPUUniform(name,id, GLType::glFloat()){}
};
////////////////////////////////////////////////////////////////////////
#endif
<|endoftext|>