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

#include "BrewPiTouch.h"
#include "application.h"
#include <limits.h>
// includes for getting a median:
#undef min
#undef max
#undef swap
#include <vector>
#include <algorithm>

BrewPiTouch::BrewPiTouch(SPIArbiter & spia, uint8_t cs, uint8_t irq) : _spi(spia),  pinCS(cs), pinIRQ(irq) {
}

BrewPiTouch::~BrewPiTouch() {
}

void BrewPiTouch::init(uint8_t configuration) {
    // default is:
    // 12bit (mode=0)
    // power down between conversions, penIRQ enabled (PD1,PD0 = 00)
    // Differential reference (SER/DFR = 0)
    config = configuration;
    width = 1600;
    height = 1600;
    tftWidth = 320;
    tftHeight = 240;
    xOffset = 0;
    yOffset = 0;
    setStabilityThreshold(); // default threshold
    pinMode(pinCS, OUTPUT);
    pinMode(pinIRQ, INPUT);
    _spi.setClockDivider(SPI_CLOCK_DIV64);
    _spi.setClockDivider(SPI_MODE0);
    _spi.begin(pinCS);
    _spi.transfer(config);
    _spi.end();

    filterX.init(width/2);
    filterX.setCoefficients(SETTLING_TIME_25_SAMPLES);
    filterY.init(height/2);
    filterY.setCoefficients(SETTLING_TIME_25_SAMPLES);
    update();
}

void BrewPiTouch::set8bit() {
    config = config | MODE;
}

void BrewPiTouch::set12bit() {
    config = config & ~MODE;
}

bool BrewPiTouch::is8bit() {
    return (config & MODE) ? 1 : 0;
}

bool BrewPiTouch::is12bit() {
    return (config & MODE) ? 0 : 1;
}

uint16_t BrewPiTouch::readChannel() {
    uint16_t data;
    data = _spi.transfer(0);
    if (is12bit()) {
        data = data << 8;
        data += _spi.transfer(0);
        data = data >> 4;
    }
    return data;
}

bool BrewPiTouch::isTouched() {
    return (digitalRead(pinIRQ) == HIGH ? 0 : 1);
}

int16_t BrewPiTouch::getXRaw() {
    return filterX.readInput();
}

int16_t BrewPiTouch::getYRaw() {
    return filterY.readInput();
}

int16_t BrewPiTouch::getX() {
    int32_t val = getXRaw(); // create room for multiplication
    val -= xOffset; // remove offset
    val = val * tftWidth / width; //scale
    return val;
}

int16_t BrewPiTouch::getY() {
    int32_t val = getYRaw(); // create room for multiplication
    val -= yOffset; // remove offset
    val = val * tftHeight / height; //scale
    return val;
}

/*
 *  update() updates the x and y coordinates of the touch screen
 *  It reads numSamples values and takes the median
 *  The result is fed to the low pass filters
 */
bool BrewPiTouch::update(uint16_t numSamples) {
    std::vector<int16_t> samplesX;
    std::vector<int16_t> samplesY;

    _spi.begin();
    bool valid = true;
    for (uint16_t i = 0; i < numSamples; i++) {
        if (!isTouched()) {
            valid = false;
            break;
        }
        pinMode(pinIRQ, OUTPUT); // reverse bias diode during conversion
        digitalWrite(pinIRQ, LOW); // as recommended in SBAA028
        _spi.transfer((config & CHMASK) | CHX); // select channel x
        samplesX.push_back(readChannel());

        _spi.transfer((config & CHMASK) | CHY); // select channel y
        samplesY.push_back(readChannel());
        pinMode(pinIRQ, INPUT); // Set back to input
    }
    if (valid) {
        // get median
        size_t middle = samplesX.size() / 2;
        std::nth_element(samplesX.begin(), samplesX.begin() + middle, samplesX.end());
        std::nth_element(samplesY.begin(), samplesY.begin() + middle, samplesY.end());
        // feed to filter to check stability
        filterX.add(samplesX[middle]);
        filterY.add(samplesY[middle]);
    }
    _spi.end();
    return valid && isStable();
}

void BrewPiTouch::setStabilityThreshold(int16_t threshold){
    stabilityThreshold = threshold;
}

/* isStable() returns true if the difference between the last sample and
 * a low pass filtered value of past samples is under a certain threshold
 */
bool BrewPiTouch::isStable() {
    if (abs(filterX.readInput() - filterX.readOutput()) > stabilityThreshold) {
        return false;
    }
    if (abs(filterY.readInput() - filterY.readOutput()) > stabilityThreshold) {
        return false;
    }
    return true;
}

/*
void BrewPiTouch::calibrate(Adafruit_ILI9341 * tft) {
    int32_t xTouch[3];
    int32_t yTouch[3];

    tftWidth = tft->width();
    tftHeight = tft->height();

    int32_t xDisplay[3] = {CALIBRATE_FROM_EDGE, CALIBRATE_FROM_EDGE, tftWidth - CALIBRATE_FROM_EDGE};
    int32_t yDisplay[3] = {CALIBRATE_FROM_EDGE, tftHeight - CALIBRATE_FROM_EDGE, tftHeight / 2};

    volatile int16_t samples;

    const int16_t requiredSamples = 1024;
    tft->fillScreen(ILI9341_BLACK);
    for (uint8_t i = 0; i < 3; i++) {
        tft->drawCrossHair(xDisplay[i], yDisplay[i], 10, ILI9341_GREEN);
        while (!isTouched()); // wait for touch
        do {
            samples = 0;
            xTouch[i] = 0;
            yTouch[i] = 0;
            tft->drawFastHLine(0, 0, tftWidth, ILI9341_RED);
            while (isTouched()) {
                update();
                if (!isStable()) {
                    // update is not valid, reset
                    break;
                }
                int32_t xSample = getXRaw();
                int32_t ySample = getYRaw();

                xTouch[i] += xSample;
                yTouch[i] += ySample;
                samples++;

                int32_t xAverage = xTouch[i] / samples;
                int32_t yAverage = yTouch[i] / samples;

                int16_t xCalibrated = getX();
                int16_t yCalibrated = getY();
                tft->fillCircle(xCalibrated, yCalibrated, 2, ILI9341_WHITE);

                // print progress line
                uint16_t progress = samples * tftWidth / requiredSamples;
                tft->drawFastHLine(0, 0, progress, ILI9341_BLUE);

                // stop when required number of samples is reached
                if (samples >= requiredSamples) {
                    tft->drawFastHLine(0, 0, tftWidth, ILI9341_GREEN);
                    tft->fillCircle(xDisplay[i], yDisplay[i], 8, ILI9341_BLUE);
                    while (isTouched()); // wait until released
                    break;
                }

                if (abs(xSample - xAverage) > 50 || abs(ySample - yAverage) > 50) {
                    // if new sample deviates too much from average, reset
                    break;
                }
            }
        } while (samples < requiredSamples || isTouched());
        xTouch[i] = xTouch[i] / samples;
        yTouch[i] = yTouch[i] / samples;
    }

    width = tftWidth * (xTouch[2] - xTouch[0]) / (xDisplay[2] - xDisplay[0]);
    height = tftHeight * (yTouch[1] - yTouch[0]) / (yDisplay[1] - yDisplay[0]);
    xOffset = xTouch[0] - xDisplay[0] * width / tftWidth;
    yOffset = yTouch[0] - yDisplay[0] * height / tftHeight;
}
 */
<commit_msg>fixed calling setClockDivider twice instead of setDataMode<commit_after>/*
 * Copyright 2014 BrewPi/Elco Jacobs.
 *
 * This file is part of BrewPi.
 *
 * BrewPi is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * BrewPi is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with BrewPi.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "BrewPiTouch.h"
#include "application.h"
#include <limits.h>
// includes for getting a median:
#undef min
#undef max
#undef swap
#include <vector>
#include <algorithm>

BrewPiTouch::BrewPiTouch(SPIArbiter & spia, uint8_t cs, uint8_t irq) : _spi(spia),  pinCS(cs), pinIRQ(irq) {
}

BrewPiTouch::~BrewPiTouch() {
}

void BrewPiTouch::init(uint8_t configuration) {
    // default is:
    // 12bit (mode=0)
    // power down between conversions, penIRQ enabled (PD1,PD0 = 00)
    // Differential reference (SER/DFR = 0)
    config = configuration;
    width = 1600;
    height = 1600;
    tftWidth = 320;
    tftHeight = 240;
    xOffset = 0;
    yOffset = 0;
    setStabilityThreshold(); // default threshold
    pinMode(pinCS, OUTPUT);
    pinMode(pinIRQ, INPUT);
    _spi.setClockDivider(SPI_CLOCK_DIV64);
    _spi.setDataMode(SPI_MODE0);
    _spi.begin(pinCS);
    _spi.transfer(config);
    _spi.end();

    filterX.init(width/2);
    filterX.setCoefficients(SETTLING_TIME_25_SAMPLES);
    filterY.init(height/2);
    filterY.setCoefficients(SETTLING_TIME_25_SAMPLES);
    update();
}

void BrewPiTouch::set8bit() {
    config = config | MODE;
}

void BrewPiTouch::set12bit() {
    config = config & ~MODE;
}

bool BrewPiTouch::is8bit() {
    return (config & MODE) ? 1 : 0;
}

bool BrewPiTouch::is12bit() {
    return (config & MODE) ? 0 : 1;
}

uint16_t BrewPiTouch::readChannel() {
    uint16_t data;
    data = _spi.transfer(0);
    if (is12bit()) {
        data = data << 8;
        data += _spi.transfer(0);
        data = data >> 4;
    }
    return data;
}

bool BrewPiTouch::isTouched() {
    return (digitalRead(pinIRQ) == HIGH ? 0 : 1);
}

int16_t BrewPiTouch::getXRaw() {
    return filterX.readInput();
}

int16_t BrewPiTouch::getYRaw() {
    return filterY.readInput();
}

int16_t BrewPiTouch::getX() {
    int32_t val = getXRaw(); // create room for multiplication
    val -= xOffset; // remove offset
    val = val * tftWidth / width; //scale
    return val;
}

int16_t BrewPiTouch::getY() {
    int32_t val = getYRaw(); // create room for multiplication
    val -= yOffset; // remove offset
    val = val * tftHeight / height; //scale
    return val;
}

/*
 *  update() updates the x and y coordinates of the touch screen
 *  It reads numSamples values and takes the median
 *  The result is fed to the low pass filters
 */
bool BrewPiTouch::update(uint16_t numSamples) {
    std::vector<int16_t> samplesX;
    std::vector<int16_t> samplesY;

    _spi.begin();
    bool valid = true;
    for (uint16_t i = 0; i < numSamples; i++) {
        if (!isTouched()) {
            valid = false;
            break;
        }
        pinMode(pinIRQ, OUTPUT); // reverse bias diode during conversion
        digitalWrite(pinIRQ, LOW); // as recommended in SBAA028
        _spi.transfer((config & CHMASK) | CHX); // select channel x
        samplesX.push_back(readChannel());

        _spi.transfer((config & CHMASK) | CHY); // select channel y
        samplesY.push_back(readChannel());
        pinMode(pinIRQ, INPUT); // Set back to input
    }
    if (valid) {
        // get median
        size_t middle = samplesX.size() / 2;
        std::nth_element(samplesX.begin(), samplesX.begin() + middle, samplesX.end());
        std::nth_element(samplesY.begin(), samplesY.begin() + middle, samplesY.end());
        // feed to filter to check stability
        filterX.add(samplesX[middle]);
        filterY.add(samplesY[middle]);
    }
    _spi.end();
    return valid && isStable();
}

void BrewPiTouch::setStabilityThreshold(int16_t threshold){
    stabilityThreshold = threshold;
}

/* isStable() returns true if the difference between the last sample and
 * a low pass filtered value of past samples is under a certain threshold
 */
bool BrewPiTouch::isStable() {
    if (abs(filterX.readInput() - filterX.readOutput()) > stabilityThreshold) {
        return false;
    }
    if (abs(filterY.readInput() - filterY.readOutput()) > stabilityThreshold) {
        return false;
    }
    return true;
}

/*
void BrewPiTouch::calibrate(Adafruit_ILI9341 * tft) {
    int32_t xTouch[3];
    int32_t yTouch[3];

    tftWidth = tft->width();
    tftHeight = tft->height();

    int32_t xDisplay[3] = {CALIBRATE_FROM_EDGE, CALIBRATE_FROM_EDGE, tftWidth - CALIBRATE_FROM_EDGE};
    int32_t yDisplay[3] = {CALIBRATE_FROM_EDGE, tftHeight - CALIBRATE_FROM_EDGE, tftHeight / 2};

    volatile int16_t samples;

    const int16_t requiredSamples = 1024;
    tft->fillScreen(ILI9341_BLACK);
    for (uint8_t i = 0; i < 3; i++) {
        tft->drawCrossHair(xDisplay[i], yDisplay[i], 10, ILI9341_GREEN);
        while (!isTouched()); // wait for touch
        do {
            samples = 0;
            xTouch[i] = 0;
            yTouch[i] = 0;
            tft->drawFastHLine(0, 0, tftWidth, ILI9341_RED);
            while (isTouched()) {
                update();
                if (!isStable()) {
                    // update is not valid, reset
                    break;
                }
                int32_t xSample = getXRaw();
                int32_t ySample = getYRaw();

                xTouch[i] += xSample;
                yTouch[i] += ySample;
                samples++;

                int32_t xAverage = xTouch[i] / samples;
                int32_t yAverage = yTouch[i] / samples;

                int16_t xCalibrated = getX();
                int16_t yCalibrated = getY();
                tft->fillCircle(xCalibrated, yCalibrated, 2, ILI9341_WHITE);

                // print progress line
                uint16_t progress = samples * tftWidth / requiredSamples;
                tft->drawFastHLine(0, 0, progress, ILI9341_BLUE);

                // stop when required number of samples is reached
                if (samples >= requiredSamples) {
                    tft->drawFastHLine(0, 0, tftWidth, ILI9341_GREEN);
                    tft->fillCircle(xDisplay[i], yDisplay[i], 8, ILI9341_BLUE);
                    while (isTouched()); // wait until released
                    break;
                }

                if (abs(xSample - xAverage) > 50 || abs(ySample - yAverage) > 50) {
                    // if new sample deviates too much from average, reset
                    break;
                }
            }
        } while (samples < requiredSamples || isTouched());
        xTouch[i] = xTouch[i] / samples;
        yTouch[i] = yTouch[i] / samples;
    }

    width = tftWidth * (xTouch[2] - xTouch[0]) / (xDisplay[2] - xDisplay[0]);
    height = tftHeight * (yTouch[1] - yTouch[0]) / (yDisplay[1] - yDisplay[0]);
    xOffset = xTouch[0] - xDisplay[0] * width / tftWidth;
    yOffset = yTouch[0] - yDisplay[0] * height / tftHeight;
}
 */
<|endoftext|>


<commit_before>//------------------------------------------------------------------------------
//  UI.cc
//------------------------------------------------------------------------------
#include "UI.h"
#include "yakc_app/Util.h"
#include "MemoryWindow.h"
#include "MemoryMapWindow.h"
#include "DebugWindow.h"
#include "DisasmWindow.h"
#include "PIOWindow.h"
#include "CTCWindow.h"
#include "ModuleWindow.h"
#include "KeyboardWindow.h"
#include "LoadWindow.h"
#include "Time/Clock.h"
#include "Input/Input.h"
#include "Core/String/StringBuilder.h"
#include "yakc_roms/roms.h"

using namespace Oryol;
using namespace yakc;

const ImVec4 UI::ColorText = ImColor(255, 255, 255).Value;
const ImVec4 UI::ColorDetail = ImColor(164, 17, 6).Value;
const ImVec4 UI::ColorDetailBright = ImColor(230, 17, 6).Value;
const ImVec4 UI::ColorDetailDark = ImColor(94, 17, 6).Value;
const ImVec4 UI::ColorBackground = ImColor(32, 32, 32).Value;
const ImVec4 UI::ColorBackgroundLight = ImColor(96, 96, 96).Value;

//------------------------------------------------------------------------------
void
UI::Setup(kc85& kc) {
    IMUI::Setup();

    ImGuiStyle& style = ImGui::GetStyle();
    style.WindowRounding = 0.0f;
    style.Alpha = 1.0f;
    style.WindowFillAlphaDefault = 1.0f;
    style.WindowTitleAlign = ImGuiAlign_Center;
    style.TouchExtraPadding = ImVec2(5.0f, 5.0f);
    style.AntiAliasedLines = false;
    style.AntiAliasedShapes = false;

    /*
    style.Colors[ImGuiCol_Text] = ColorText;
    style.Colors[ImGuiCol_Border] = ColorDetail;
    style.Colors[ImGuiCol_TitleBg] = ColorDetail;
    style.Colors[ImGuiCol_FrameBg] = ColorBackgroundLight;
    style.Colors[ImGuiCol_FrameBgHovered] = ColorDetail;
    style.Colors[ImGuiCol_FrameBgActive] = ColorDetail;
    style.Colors[ImGuiCol_WindowBg] = ColorBackground;
    style.Colors[ImGuiCol_ChildWindowBg] = ColorBackground;
    style.Colors[ImGuiCol_TitleBgActive] = ColorDetail;
    style.Colors[ImGuiCol_MenuBarBg] = ColorDetail;
    style.Colors[ImGuiCol_CheckMark] = ColorDetailBright;
    style.Colors[ImGuiCol_SliderGrab] = ColorDetail;
    style.Colors[ImGuiCol_SliderGrabActive] = ColorDetail;
    style.Colors[ImGuiCol_Button] = ColorDetail;
    style.Colors[ImGuiCol_ButtonHovered] = ColorDetailBright;
    style.Colors[ImGuiCol_ButtonActive] = ColorDetailDark;
    style.Colors[ImGuiCol_ScrollbarBg] = ColorBackgroundLight;
    style.Colors[ImGuiCol_ScrollbarGrab] = ColorDetail;
    style.Colors[ImGuiCol_ScrollbarGrabHovered] = ColorDetailBright;
    style.Colors[ImGuiCol_ScrollbarGrabActive] = ColorDetailBright;
    */

    this->fileLoader.Setup(kc);
    this->curTime = Clock::Now();
}

//------------------------------------------------------------------------------
void
UI::Discard() {
    this->fileLoader.Discard();
    this->windows.Clear();
    IMUI::Discard();
}

//------------------------------------------------------------------------------
void
UI::Toggle() {
    this->uiEnabled = !this->uiEnabled;
}

//------------------------------------------------------------------------------
void
UI::OpenWindow(kc85& kc, const Ptr<WindowBase>& win) {
    win->Setup(kc);
    this->windows.Add(win);
}

//------------------------------------------------------------------------------
void
UI::OnFrame(kc85& kc) {
    IMUI::NewFrame(Clock::LapTime(this->curTime));
    if (this->uiEnabled) {
        if (ImGui::BeginMainMenuBar()) {
            if (ImGui::BeginMenu(kc.model() == kc85_model::kc85_3 ? "KC85/3":"KC85/4")) {
                if (ImGui::MenuItem("Load File...")) {
                    auto loadWindow = LoadWindow::Create();
                    loadWindow->SetFileLoader(&this->fileLoader);
                    this->OpenWindow(kc, loadWindow);
                }
                if (ImGui::MenuItem("Power Cycle")) {
                    kc.switchoff();
                    kc.switchon(kc.model(), kc.caos_rom(), kc.caos_rom_size());
                }
                if (ImGui::MenuItem("Reset")) {
                    kc.reset();
                }
                if (ImGui::BeginMenu("KC 85/3")) {
                    if (ImGui::MenuItem("CAOS 3.1")) {
                        kc.switchoff();
                        kc.switchon(kc85_model::kc85_3, dump_caos31, sizeof(dump_caos31));
                    }
                    ImGui::EndMenu();
                }
                if (ImGui::MenuItem("KC85/4 (TODO)")) {
                    // FIXME
                }
                ImGui::EndMenu();
            }
            if (ImGui::BeginMenu("Hardware")) {
                if (ImGui::MenuItem("Keyboard")) {
                    this->OpenWindow(kc, KeyboardWindow::Create());
                }
                if (ImGui::MenuItem("Expansion Slots")) {
                    this->OpenWindow(kc, ModuleWindow::Create());
                }
                if (ImGui::MenuItem("Memory Map")) {
                    this->OpenWindow(kc, MemoryMapWindow::Create());
                }
                if (ImGui::MenuItem("Z80 PIO")) {
                    this->OpenWindow(kc, PIOWindow::Create());
                }
                if (ImGui::MenuItem("Z80 CTC")) {
                    this->OpenWindow(kc, CTCWindow::Create());
                }
                ImGui::EndMenu();
            }
            if (ImGui::BeginMenu("Debugging")) {
                if (ImGui::MenuItem("Debugger")) {
                    this->OpenWindow(kc, DebugWindow::Create());
                }
                if (ImGui::MenuItem("Disassembler")) {
                    this->OpenWindow(kc, DisasmWindow::Create());
                }
                if (ImGui::MenuItem("Memory Editor")) {
                    this->OpenWindow(kc, MemoryWindow::Create());
                }
                ImGui::EndMenu();
            }
            if (ImGui::BeginMenu("Settings")) {
                if (ImGui::MenuItem("CRT Effect", nullptr, this->Settings.crtEffect)) {
                    this->Settings.crtEffect = !this->Settings.crtEffect;
                }
                if (ImGui::MenuItem("Color TV", nullptr, this->Settings.colorTV)) {
                    this->Settings.colorTV = !this->Settings.colorTV;
                }
                ImGui::SliderFloat("CRT Warp", &this->Settings.crtWarp, 0.0f, 1.0f/16.0f);
                ImGui::SliderInt("CPU Speed", &this->Settings.cpuSpeed, 1, 8, "%.0fx");
                if (ImGui::MenuItem("Reset To Defaults")) {
                    this->Settings = settings();
                }
                ImGui::EndMenu();
            }
            ImGui::EndMainMenuBar();
        }

        // draw open windows
        for (auto& win : this->windows) {
            win->Draw(kc);
        }
    }
    else {
        // if UI is disabled, draw a simple overlay with help on how to toggle UI
        if (helpOpen) {
            ImGui::SetNextWindowPosCenter();
            if (ImGui::Begin("Help", &this->helpOpen, ImVec2(0,0), 0.75f, ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoResize))
            {
                ImGui::Text("Press TAB or double-tap to toggle UI!");
                ImGui::Dummy(ImVec2(96,0)); ImGui::SameLine();
                if (ImGui::Button("Got it!")) {
                    this->helpOpen = false;
                }
            }
            ImGui::End();
        }
    }
    ImGui::Render();

    // delete closed windows
    for (int i = this->windows.Size() - 1; i >= 0; i--) {
        if (!this->windows[i]->Visible) {
            this->windows.Erase(i);
        }
    }
}
<commit_msg>Added a quickstart menu for games<commit_after>//------------------------------------------------------------------------------
//  UI.cc
//------------------------------------------------------------------------------
#include "UI.h"
#include "yakc_app/Util.h"
#include "MemoryWindow.h"
#include "MemoryMapWindow.h"
#include "DebugWindow.h"
#include "DisasmWindow.h"
#include "PIOWindow.h"
#include "CTCWindow.h"
#include "ModuleWindow.h"
#include "KeyboardWindow.h"
#include "LoadWindow.h"
#include "Time/Clock.h"
#include "Input/Input.h"
#include "Core/String/StringBuilder.h"
#include "yakc_roms/roms.h"

using namespace Oryol;
using namespace yakc;

const ImVec4 UI::ColorText = ImColor(255, 255, 255).Value;
const ImVec4 UI::ColorDetail = ImColor(164, 17, 6).Value;
const ImVec4 UI::ColorDetailBright = ImColor(230, 17, 6).Value;
const ImVec4 UI::ColorDetailDark = ImColor(94, 17, 6).Value;
const ImVec4 UI::ColorBackground = ImColor(32, 32, 32).Value;
const ImVec4 UI::ColorBackgroundLight = ImColor(96, 96, 96).Value;

//------------------------------------------------------------------------------
void
UI::Setup(kc85& kc) {
    IMUI::Setup();

    ImGuiStyle& style = ImGui::GetStyle();
    style.WindowRounding = 0.0f;
    style.Alpha = 1.0f;
    style.WindowFillAlphaDefault = 1.0f;
    style.WindowTitleAlign = ImGuiAlign_Center;
    style.TouchExtraPadding = ImVec2(5.0f, 5.0f);
    style.AntiAliasedLines = false;
    style.AntiAliasedShapes = false;

    /*
    style.Colors[ImGuiCol_Text] = ColorText;
    style.Colors[ImGuiCol_Border] = ColorDetail;
    style.Colors[ImGuiCol_TitleBg] = ColorDetail;
    style.Colors[ImGuiCol_FrameBg] = ColorBackgroundLight;
    style.Colors[ImGuiCol_FrameBgHovered] = ColorDetail;
    style.Colors[ImGuiCol_FrameBgActive] = ColorDetail;
    style.Colors[ImGuiCol_WindowBg] = ColorBackground;
    style.Colors[ImGuiCol_ChildWindowBg] = ColorBackground;
    style.Colors[ImGuiCol_TitleBgActive] = ColorDetail;
    style.Colors[ImGuiCol_MenuBarBg] = ColorDetail;
    style.Colors[ImGuiCol_CheckMark] = ColorDetailBright;
    style.Colors[ImGuiCol_SliderGrab] = ColorDetail;
    style.Colors[ImGuiCol_SliderGrabActive] = ColorDetail;
    style.Colors[ImGuiCol_Button] = ColorDetail;
    style.Colors[ImGuiCol_ButtonHovered] = ColorDetailBright;
    style.Colors[ImGuiCol_ButtonActive] = ColorDetailDark;
    style.Colors[ImGuiCol_ScrollbarBg] = ColorBackgroundLight;
    style.Colors[ImGuiCol_ScrollbarGrab] = ColorDetail;
    style.Colors[ImGuiCol_ScrollbarGrabHovered] = ColorDetailBright;
    style.Colors[ImGuiCol_ScrollbarGrabActive] = ColorDetailBright;
    */

    this->fileLoader.Setup(kc);
    this->curTime = Clock::Now();
}

//------------------------------------------------------------------------------
void
UI::Discard() {
    this->fileLoader.Discard();
    this->windows.Clear();
    IMUI::Discard();
}

//------------------------------------------------------------------------------
void
UI::Toggle() {
    this->uiEnabled = !this->uiEnabled;
}

//------------------------------------------------------------------------------
void
UI::OpenWindow(kc85& kc, const Ptr<WindowBase>& win) {
    win->Setup(kc);
    this->windows.Add(win);
}

//------------------------------------------------------------------------------
void
UI::OnFrame(kc85& kc) {
    IMUI::NewFrame(Clock::LapTime(this->curTime));
    if (this->uiEnabled) {
        if (ImGui::BeginMainMenuBar()) {
            if (ImGui::BeginMenu(kc.model() == kc85_model::kc85_3 ? "KC85/3":"KC85/4")) {
                if (ImGui::MenuItem("Load File...")) {
                    auto loadWindow = LoadWindow::Create();
                    loadWindow->SetFileLoader(&this->fileLoader);
                    this->OpenWindow(kc, loadWindow);
                }
                if (ImGui::MenuItem("Power Cycle")) {
                    kc.switchoff();
                    kc.switchon(kc.model(), kc.caos_rom(), kc.caos_rom_size());
                }
                if (ImGui::MenuItem("Reset")) {
                    kc.reset();
                }
                if (ImGui::BeginMenu("KC 85/3")) {
                    if (ImGui::MenuItem("CAOS 3.1")) {
                        kc.switchoff();
                        kc.switchon(kc85_model::kc85_3, dump_caos31, sizeof(dump_caos31));
                    }
                    ImGui::EndMenu();
                }
                if (ImGui::MenuItem("KC85/4 (TODO)")) {
                    // FIXME
                }
                ImGui::EndMenu();
            }
            if (ImGui::BeginMenu("Games")) {
                for (const auto& item : this->fileLoader.Items) {
                    if (ImGui::MenuItem(item.Name.AsCStr())) {
                        this->fileLoader.LoadAndStart(kc, item);
                    }
                }
                ImGui::EndMenu();
            }
            if (ImGui::BeginMenu("Hardware")) {
                if (ImGui::MenuItem("Keyboard")) {
                    this->OpenWindow(kc, KeyboardWindow::Create());
                }
                if (ImGui::MenuItem("Expansion Slots")) {
                    this->OpenWindow(kc, ModuleWindow::Create());
                }
                if (ImGui::MenuItem("Memory Map")) {
                    this->OpenWindow(kc, MemoryMapWindow::Create());
                }
                if (ImGui::MenuItem("Z80 PIO")) {
                    this->OpenWindow(kc, PIOWindow::Create());
                }
                if (ImGui::MenuItem("Z80 CTC")) {
                    this->OpenWindow(kc, CTCWindow::Create());
                }
                ImGui::EndMenu();
            }
            if (ImGui::BeginMenu("Debugging")) {
                if (ImGui::MenuItem("Debugger")) {
                    this->OpenWindow(kc, DebugWindow::Create());
                }
                if (ImGui::MenuItem("Disassembler")) {
                    this->OpenWindow(kc, DisasmWindow::Create());
                }
                if (ImGui::MenuItem("Memory Editor")) {
                    this->OpenWindow(kc, MemoryWindow::Create());
                }
                ImGui::EndMenu();
            }
            if (ImGui::BeginMenu("Settings")) {
                if (ImGui::MenuItem("CRT Effect", nullptr, this->Settings.crtEffect)) {
                    this->Settings.crtEffect = !this->Settings.crtEffect;
                }
                if (ImGui::MenuItem("Color TV", nullptr, this->Settings.colorTV)) {
                    this->Settings.colorTV = !this->Settings.colorTV;
                }
                ImGui::SliderFloat("CRT Warp", &this->Settings.crtWarp, 0.0f, 1.0f/16.0f);
                ImGui::SliderInt("CPU Speed", &this->Settings.cpuSpeed, 1, 8, "%.0fx");
                if (ImGui::MenuItem("Reset To Defaults")) {
                    this->Settings = settings();
                }
                ImGui::EndMenu();
            }
            ImGui::EndMainMenuBar();
        }

        // draw open windows
        for (auto& win : this->windows) {
            win->Draw(kc);
        }
    }
    else {
        // if UI is disabled, draw a simple overlay with help on how to toggle UI
        if (helpOpen) {
            ImGui::SetNextWindowPosCenter();
            if (ImGui::Begin("Help", &this->helpOpen, ImVec2(0,0), 0.75f, ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoResize))
            {
                ImGui::Text("Press TAB or double-tap to toggle UI!");
                ImGui::Dummy(ImVec2(96,0)); ImGui::SameLine();
                if (ImGui::Button("Got it!")) {
                    this->helpOpen = false;
                }
            }
            ImGui::End();
        }
    }
    ImGui::Render();

    // delete closed windows
    for (int i = this->windows.Size() - 1; i >= 0; i--) {
        if (!this->windows[i]->Visible) {
            this->windows.Erase(i);
        }
    }
}
<|endoftext|>


<commit_before>/*
 * This file is part of telepathy-accounts-kcm
 *
 * Copyright (C) 2009 Collabora Ltd. <info@collabora.com>
 * Copyright (C) 2011 Thomas Richard <thomas.richard@proan.be>
 *
 * 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 "profile-list-model.h"

#include "profile-item.h"

#include <TelepathyQt/Feature>
#include <TelepathyQt/PendingReady>
#include <TelepathyQt/ProfileManager>
#include <TelepathyQt/PendingStringList>

#include <KDebug>
#include <KIcon>

ProfileListModel::ProfileListModel(QObject *parent)
 : QAbstractListModel(parent)
{
    m_profileItems.clear();
    m_profileManager = Tp::ProfileManager::create(QDBusConnection::sessionBus());
    // FIXME: Until all distros ship correct profile files, we should fake them
    connect(m_profileManager->becomeReady(Tp::Features() << Tp::ProfileManager::FeatureFakeProfiles),
            SIGNAL(finished(Tp::PendingOperation*)),
            this,
            SLOT(onProfileManagerReady(Tp::PendingOperation*)));
}

ProfileListModel::~ProfileListModel()
{
}

void ProfileListModel::onProfileManagerReady(Tp::PendingOperation *op)
{
    // Check the pending operation completed successfully.
    if (op->isError()) {
        kDebug() << "becomeReady() failed:" << op->errorName() << op->errorMessage();
        return;
    }
    Tp::PendingStringList* pendingNames = Tp::ConnectionManager::listNames();
    connect(pendingNames, SIGNAL(finished(Tp::PendingOperation*)), SLOT(onConnectionManagerNamesFetched(Tp::PendingOperation*)));
}

int ProfileListModel::rowCount(const QModelIndex &index) const
{
    // If the index is the root item, then return the row count.
    if (index == QModelIndex()) {
       return m_profileItems.size();
    }

    // Otherwise, return 0 (as this is a list model, so all items
    // are children of the root item).
    return 0;
}

QVariant ProfileListModel::data(const QModelIndex &index, int role) const
{
    // FIXME: This is a basic implementation just so I can see what's going
    // on while developing this code further. Needs expanding.
    QVariant data;

    switch (role) {
    case Qt::DisplayRole:
        data = QVariant(m_profileItems.at(index.row())->localizedName());
        break;
    case Qt::DecorationRole:
        data = QVariant(m_profileItems.at(index.row())->icon());
        break;
    case ProfileListModel::ProfileProtocolNameRole:
        data = QVariant(m_profileItems.at(index.row())->protocolName());
        break;
    case ProfileListModel::ProfileCmNameRole:
        data = QVariant(m_profileItems.at(index.row())->cmName());
        break;
    default:
        break;
    }

    return data;
}

ProfileItem *ProfileListModel::itemForIndex(const QModelIndex &index) const
{
    return m_profileItems.at(index.row());
}

ProfileItem *ProfileListModel::itemForService(const QString &serviceName) const
{
    Q_FOREACH (ProfileItem *profileItem, m_profileItems) {
        if (profileItem->serviceName() == serviceName) {
            return profileItem;
        }
    }

    return 0;
}

bool ProfileListModel::hasNonFakeProfile(const Tp::ProfilePtr& profile, const QList<Tp::ProfilePtr> &profiles) const
{
    //loop through all profiles, and look for a non autogenerated profile which matches this name.
    Q_FOREACH (const Tp::ProfilePtr &otherProfile, profiles) {
        if (profile->protocolName() == otherProfile->protocolName() && !otherProfile->isFake()) {
            // check if this profile is for a special service or for this protocol in general
            if (otherProfile->serviceName() == otherProfile->cmName().append(QLatin1Char('-')).append(otherProfile->protocolName())
            || otherProfile->serviceName() == otherProfile->protocolName()) {

                //check we have a valid CM for the non-fake profile
                if (m_connectionManagerNames.contains(otherProfile->cmName())) {
                    return true;
                }
            }
        }
    }

    return false;
}

void ProfileListModel::populateList()
{
    Q_FOREACH (ProfileItem *item, m_profileItems) {
        delete item;
        item = 0;
    }

    m_profileItems.clear();

    QList<Tp::ProfilePtr> profiles = m_profileManager->profiles();

    QList<ProfileItem*> insertItems;
    Q_FOREACH (const Tp::ProfilePtr &profile, profiles) {
        if (profile->isFake()) {
            if (hasNonFakeProfile(profile, profiles)) {
                continue;
            }
        }

        //don't include profiles which we don't have a CM for
        if (! m_connectionManagerNames.contains(profile->cmName())) {
            continue;
        }

        insertItems.append(new ProfileItem(profile, this));
    }

    if (insertItems.size() > 0) {
      beginInsertRows(QModelIndex(), 0, insertItems.size()-1);
      m_profileItems.append(insertItems);
      endInsertRows();
    } else {
      return;
    }
}

void ProfileListModel::onConnectionManagerNamesFetched(Tp::PendingOperation *operation)
{
    Tp::PendingStringList* connectionManagerNamesOperation = qobject_cast<Tp::PendingStringList*>(operation);

    Q_ASSERT(connectionManagerNamesOperation);
    m_connectionManagerNames = connectionManagerNamesOperation->result();

    populateList();
}

#include "profile-list-model.moc"
<commit_msg>Disable creation of IRC accounts in the GUI<commit_after>/*
 * This file is part of telepathy-accounts-kcm
 *
 * Copyright (C) 2009 Collabora Ltd. <info@collabora.com>
 * Copyright (C) 2011 Thomas Richard <thomas.richard@proan.be>
 *
 * 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 "profile-list-model.h"

#include "profile-item.h"

#include <TelepathyQt/Feature>
#include <TelepathyQt/PendingReady>
#include <TelepathyQt/ProfileManager>
#include <TelepathyQt/PendingStringList>

#include <KDebug>
#include <KIcon>

ProfileListModel::ProfileListModel(QObject *parent)
 : QAbstractListModel(parent)
{
    m_profileItems.clear();
    m_profileManager = Tp::ProfileManager::create(QDBusConnection::sessionBus());
    // FIXME: Until all distros ship correct profile files, we should fake them
    connect(m_profileManager->becomeReady(Tp::Features() << Tp::ProfileManager::FeatureFakeProfiles),
            SIGNAL(finished(Tp::PendingOperation*)),
            this,
            SLOT(onProfileManagerReady(Tp::PendingOperation*)));
}

ProfileListModel::~ProfileListModel()
{
}

void ProfileListModel::onProfileManagerReady(Tp::PendingOperation *op)
{
    // Check the pending operation completed successfully.
    if (op->isError()) {
        kDebug() << "becomeReady() failed:" << op->errorName() << op->errorMessage();
        return;
    }
    Tp::PendingStringList* pendingNames = Tp::ConnectionManager::listNames();
    connect(pendingNames, SIGNAL(finished(Tp::PendingOperation*)), SLOT(onConnectionManagerNamesFetched(Tp::PendingOperation*)));
}

int ProfileListModel::rowCount(const QModelIndex &index) const
{
    // If the index is the root item, then return the row count.
    if (index == QModelIndex()) {
       return m_profileItems.size();
    }

    // Otherwise, return 0 (as this is a list model, so all items
    // are children of the root item).
    return 0;
}

QVariant ProfileListModel::data(const QModelIndex &index, int role) const
{
    // FIXME: This is a basic implementation just so I can see what's going
    // on while developing this code further. Needs expanding.
    QVariant data;

    switch (role) {
    case Qt::DisplayRole:
        data = QVariant(m_profileItems.at(index.row())->localizedName());
        break;
    case Qt::DecorationRole:
        data = QVariant(m_profileItems.at(index.row())->icon());
        break;
    case ProfileListModel::ProfileProtocolNameRole:
        data = QVariant(m_profileItems.at(index.row())->protocolName());
        break;
    case ProfileListModel::ProfileCmNameRole:
        data = QVariant(m_profileItems.at(index.row())->cmName());
        break;
    default:
        break;
    }

    return data;
}

ProfileItem *ProfileListModel::itemForIndex(const QModelIndex &index) const
{
    return m_profileItems.at(index.row());
}

ProfileItem *ProfileListModel::itemForService(const QString &serviceName) const
{
    Q_FOREACH (ProfileItem *profileItem, m_profileItems) {
        if (profileItem->serviceName() == serviceName) {
            return profileItem;
        }
    }

    return 0;
}

bool ProfileListModel::hasNonFakeProfile(const Tp::ProfilePtr& profile, const QList<Tp::ProfilePtr> &profiles) const
{
    //loop through all profiles, and look for a non autogenerated profile which matches this name.
    Q_FOREACH (const Tp::ProfilePtr &otherProfile, profiles) {
        if (profile->protocolName() == otherProfile->protocolName() && !otherProfile->isFake()) {
            // check if this profile is for a special service or for this protocol in general
            if (otherProfile->serviceName() == otherProfile->cmName().append(QLatin1Char('-')).append(otherProfile->protocolName())
            || otherProfile->serviceName() == otherProfile->protocolName()) {

                //check we have a valid CM for the non-fake profile
                if (m_connectionManagerNames.contains(otherProfile->cmName())) {
                    return true;
                }
            }
        }
    }

    return false;
}

void ProfileListModel::populateList()
{
    Q_FOREACH (ProfileItem *item, m_profileItems) {
        delete item;
        item = 0;
    }

    m_profileItems.clear();

    QList<Tp::ProfilePtr> profiles = m_profileManager->profiles();

    QList<ProfileItem*> insertItems;
    Q_FOREACH (const Tp::ProfilePtr &profile, profiles) {
        if (profile->isFake()) {
            if (hasNonFakeProfile(profile, profiles)) {
                continue;
            }
        }

        //don't include profiles which we don't have a CM for
        if (! m_connectionManagerNames.contains(profile->cmName())) {
            continue;
        }

        //Hide all IRC accounts
        //this is a deliberate decision from Akademy meeting 2012
        //"no, we don't support IRC", it's a different usage and in order to have a semi-decent IRC experience
        //we need to add a lot more that we simply don't have resources to do.
        //It's a better user experience to learn how to use a different app than to try using this.

        //Remove this "continue" to re-enable IRC support, for personal reasons or hacking
        //this topic can be discussed again as of July 2013

        if(profile->serviceName() == QLatin1String("irc")) {
                continue;
        }

        insertItems.append(new ProfileItem(profile, this));
    }

    if (insertItems.size() > 0) {
      beginInsertRows(QModelIndex(), 0, insertItems.size()-1);
      m_profileItems.append(insertItems);
      endInsertRows();
    } else {
      return;
    }
}

void ProfileListModel::onConnectionManagerNamesFetched(Tp::PendingOperation *operation)
{
    Tp::PendingStringList* connectionManagerNamesOperation = qobject_cast<Tp::PendingStringList*>(operation);

    Q_ASSERT(connectionManagerNamesOperation);
    m_connectionManagerNames = connectionManagerNamesOperation->result();

    populateList();
}

#include "profile-list-model.moc"
<|endoftext|>


<commit_before><commit_msg>no mkdtemp on AIX either<commit_after><|endoftext|>


<commit_before>// -------------------------------------------------------------------------
//    @FileName         :    NFCDataList.h
//    @Author           :    LvSheng.Huang
//    @Date             :    2012-03-01
//    @Module           :    NFCDataList
//
// -------------------------------------------------------------------------

#include <cstdarg>
#include "NFCDataList.h"
#include "NFIDataList.h"

NFCDataList::NFCDataList()
: NFIDataList()
{
}

NFCDataList::NFCDataList(const char* str, const char* strSplit)
{
    Clear();

    Split(str, strSplit);
}

NFCDataList::NFCDataList(const NFCDataList& src)
{
    Clear();

    InnerAppendEx(src, 0, src.GetCount());
}

NFCDataList::NFCDataList(const NFIDataList& src)
{
    Clear();

    InnerAppendEx(src, 0, src.GetCount());
}

NFCDataList::~NFCDataList()
{
    Clear();
};

/*
NFCDataList& NFCDataList::operator=(const NFCDataList& src)
{
    Clear();
    InnerAppendEx(src, 0, src.GetCount());

    return *this;
}

NFCDataList& NFCDataList::operator=(const NFIDataList& src)
{
    Clear();
    InnerAppendEx(src, 0, src.GetCount());

    return *this;
}

*/
//
bool NFCDataList::Append(const NFIDataList& src, const int start, const int count)
{
    if (start >= src.GetCount())
    {
        return false;
    }

    int end = start + count;

    if (end > src.GetCount())
    {
        return false;
    }

    InnerAppendEx(src, start, end);

    return true;
}

bool NFCDataList::Append(const NFIDataList::TData& TData)
{
    if (TData.nType <= TDATA_UNKNOWN
        || TData.nType >= TDATA_MAX)
    {
        return false;
    }

	switch (TData.nType)
	{
	case TDATA_INT:
	case TDATA_FLOAT:
	case TDATA_DOUBLE:
	case TDATA_OBJECT:
		{
			AddValue(TData.nType, TData.variantData);
		}
		break;
	case TDATA_STRING:
		{
			const std::string& strData = boost::get<std::string>(TData.variantData);
			AddString(strData);
		}
		break;
	default:
		break;
	}

    return false;
}

bool NFCDataList::Append( const NFIDataList& src )
{
	return Append(src, 0, src.GetCount());
}

bool NFCDataList::Add(const NFINT64 value)
{
    return NFIDataList::AddValue<NFINT64>(TDATA_INT, value);
}

bool NFCDataList::Add(const float value)
{
    return AddValue<float>(TDATA_FLOAT, value);
}

bool NFCDataList::Add(const double value)
{
    return AddValue<double>(TDATA_DOUBLE, value);
}

bool NFCDataList::Add(const char* value)
{
    return AddValue<std::string>(TDATA_STRING, std::string(value));
}

bool NFCDataList::Add(const std::string& value)
{
    return AddValue<std::string>(TDATA_STRING, value);
}

bool NFCDataList::Add(const NFIDENTID& value)
{
    return AddValue<NFIDENTID>(TDATA_OBJECT, value);
}

bool NFCDataList::Add(const void* value)
{
    //return AddNumber<const void*>(TDATA_POINTER, value);
    return true;
}

bool NFCDataList::Set(const int index, const NFINT64 value)
{
    if (index < GetCount() && index >= 0)
    {
        return SetValue(index, value);
    }

    return false;
}
bool NFCDataList::Set(const int index, const float value)
{
    if (index < GetCount() && index >= 0)
    {
        return SetValue(index, value);
    }

    return false;
}
bool NFCDataList::Set(const int index, const double value)
{
    if (index < GetCount() && index >= 0)
    {
        return SetValue(index, value);
    }

    return false;
}
bool NFCDataList::Set(const int index, const char* value)
{
    if (index < GetCount() && index > 0)
    {
		return SetString(index, value);
    }

    return false;
}

bool NFCDataList::Set(const int index, const NFIDENTID& value)
{
    if (index < GetCount() && index >= 0)
    {
        return SetValue<NFIDENTID>(index, value);
    }

    return false;
}

bool NFCDataList::Set(const int index, const void* value)
{
    if (index < GetCount() && index >= 0)
    {
        //return SetNumber(index, value);
    }

    return false;
}

NFINT64 NFCDataList::Int(const int index) const
{
    if (index < GetCount() && index >= 0)
    {
        return NumberVal<NFINT64>(index);
    }

    return 0;
}

float NFCDataList::Float(const int index) const
{
    if (index < GetCount() && index >= 0)
    {
        return NumberVal<float>(index);
    }

    return 0.0f;
}

double NFCDataList::Double(const int index) const
{
    if (index < GetCount() && index >= 0)
    {
        return NumberVal<double>(index);
    }

    return 0.0f;
}

const std::string& NFCDataList::String(const int index) const
{
    if (index < GetCount() && index >= 0)
    {
        const NF_SHARE_PTR<TData> var = mvList[index];
        if (var && TDATA_STRING == var->nType)
        {
            return boost::get<const std::string&>(var->variantData);
        }
    }

    return NULL_STR;
}

NFIDENTID NFCDataList::Object(const int index) const
{
//    if (index < GetCount() && index >= 0)
//    {
//        return NumberVal<NFIDENTID>(index);
//    }

    if (index < GetCount() && index >= 0)
    {
        NFIDENTID result;
        if (index < GetCount() && index >= 0)
        {
            TDATA_TYPE type = Type(index);
            if (type == TDATA_OBJECT)
            {
                NF_SHARE_PTR<TData> var = GetStack(index);
                result = boost::get<NFIDENTID>(var->variantData);
            }
        }

        return result;
    }

    return NFIDENTID();
}

void* NFCDataList::Pointer(const int index) const
{
    if (index < GetCount() && index >= 0)
    {
        return NumberVal<void*>(index);
    }

    return NULL;
}

bool NFCDataList::Split(const char* str, const char* strSplit)
{
	Clear();

    std::string strData(str);
    if (strData.empty())
    {
        return true;
    }

    std::string temstrSplit(strSplit);
    std::string::size_type pos;
    strData += temstrSplit;
    std::string::size_type size = strData.length();

    for (std::string::size_type i = 0; i < size; i++)
    {
        pos = int(strData.find(temstrSplit, i));
        if (pos < size)
        {
            std::string strSub = strData.substr(i, pos - i);
            Add(strSub.c_str());

            i = pos + temstrSplit.size() - 1;
        }
    }

    return true;
}

TDATA_TYPE NFCDataList::Type(const int index) const
{
    if (index >= GetCount() || index < 0)
    {
        return TDATA_UNKNOWN;
    }

    if (index < STACK_SIZE)
    {
        return mvList[index]->nType;
    }
    else
    {
        const NF_SHARE_PTR<TData> pData = GetStack(index);
        if (pData)
        {
            return pData->nType;
        }
    }

    return TDATA_UNKNOWN;
}

bool NFCDataList::TypeEx(const int nType, ...) const
{
    bool bRet = true;

    if (TDATA_UNKNOWN == nType)
    {
        bRet = false;
        return bRet;
    }

    TDATA_TYPE pareType = (TDATA_TYPE)nType;
    va_list arg_ptr;
    va_start(arg_ptr, nType);
    int index = 0;

    while (pareType != TDATA_UNKNOWN)
    {
        //Ƚ
        TDATA_TYPE varType = Type(index);
        if (varType != pareType)
        {
            bRet = false;
            break;
        }

        ++index;
        pareType = (TDATA_TYPE)va_arg(arg_ptr, int);   //ȡһ
    }

    va_end(arg_ptr); //

    return bRet;
}

bool NFCDataList::Concat(const NFIDataList& src)
{
    InnerAppendEx(src, 0, src.GetCount());
    return true;
}

void NFCDataList::Clear()
{
	mnUseSize = 0;
    //mnCapacity = STACK_SIZE;
	//8Ժ
	if (mvList.size() > STACK_SIZE)
	{
		for (int i = 0; i < STACK_SIZE; ++i)
		{
			mvList[i]->nType = TDATA_UNKNOWN;
		}

		mvList.erase(mvList.begin() + 8, mvList.end());
	}
}

bool NFCDataList::IsEmpty() const
{
    return (0 == mnUseSize);
}

int NFCDataList::GetCount() const
{
    return mnUseSize;
}

void NFCDataList::InnerAppendEx(const NFIDataList& src, const int start, const int end)
{
    for (int i = start; i < end; ++i)
    {
        TDATA_TYPE vType = src.Type(i);
        switch (vType)
        {
            case TDATA_INT:
                AddValue<NFINT64>(vType, src.Int(i));
                break;
            case TDATA_FLOAT:
                AddValue<float>(vType, src.Float(i));
                break;
            case TDATA_DOUBLE:
                AddValue<double>(vType, src.Double(i));
                break;
            case TDATA_STRING:
                AddString(src.String(i).c_str());
                break;
            case TDATA_OBJECT:
                AddValue<NFIDENTID>(vType, src.Object(i));
                break;
                //case TDATA_POINTER:
                //    AddNumber<void*>(vType, src.NumberVal<void*>(i));
                //    break;
            default:
                //Assert(0);
                break;
        }
    }
}

std::string NFCDataList::StringValEx(const int index, const bool bForce) const
{
    if (index < GetCount() && index >= 0)
    {
        TDATA_TYPE type =  Type(index);
        if (type == TDATA_STRING)
        {
            return String(index);
        }

//         const NF_SHARE_PTR<NFIDataList::TData> var = GetStack(index);
//         if (var)
//         {
//             //return boost::lexical_cast<std::string>(var->variantData);
//         }
    }

    return NULL_STR;
}

bool NFCDataList::ToString(std::string& str, const char* strSplit) const
{
    for (int i = 0; i < GetCount(); ++i)
    {
        std::string strVal = StringValEx(i, true);
        str += strVal;
        str += strSplit;
    }

    std::string strTempSplit(strSplit);
    std::string::size_type nPos = str.rfind(strSplit);
    if (nPos == str.length() - strTempSplit.length())
    {
        str = str.substr(0, nPos);
    }

    return true;
}
<commit_msg>fixed bug for set data<commit_after>// -------------------------------------------------------------------------
//    @FileName         :    NFCDataList.h
//    @Author           :    LvSheng.Huang
//    @Date             :    2012-03-01
//    @Module           :    NFCDataList
//
// -------------------------------------------------------------------------

#include <cstdarg>
#include "NFCDataList.h"
#include "NFIDataList.h"

NFCDataList::NFCDataList()
: NFIDataList()
{
}

NFCDataList::NFCDataList(const char* str, const char* strSplit)
{
    Clear();

    Split(str, strSplit);
}

NFCDataList::NFCDataList(const NFCDataList& src)
{
    Clear();

    InnerAppendEx(src, 0, src.GetCount());
}

NFCDataList::NFCDataList(const NFIDataList& src)
{
    Clear();

    InnerAppendEx(src, 0, src.GetCount());
}

NFCDataList::~NFCDataList()
{
    Clear();
};

/*
NFCDataList& NFCDataList::operator=(const NFCDataList& src)
{
    Clear();
    InnerAppendEx(src, 0, src.GetCount());

    return *this;
}

NFCDataList& NFCDataList::operator=(const NFIDataList& src)
{
    Clear();
    InnerAppendEx(src, 0, src.GetCount());

    return *this;
}

*/
//
bool NFCDataList::Append(const NFIDataList& src, const int start, const int count)
{
    if (start >= src.GetCount())
    {
        return false;
    }

    int end = start + count;

    if (end > src.GetCount())
    {
        return false;
    }

    InnerAppendEx(src, start, end);

    return true;
}

bool NFCDataList::Append(const NFIDataList::TData& TData)
{
    if (TData.nType <= TDATA_UNKNOWN
        || TData.nType >= TDATA_MAX)
    {
        return false;
    }

	switch (TData.nType)
	{
	case TDATA_INT:
	case TDATA_FLOAT:
	case TDATA_DOUBLE:
	case TDATA_OBJECT:
		{
			AddValue(TData.nType, TData.variantData);
		}
		break;
	case TDATA_STRING:
		{
			const std::string& strData = boost::get<std::string>(TData.variantData);
			AddString(strData);
		}
		break;
	default:
		break;
	}

    return false;
}

bool NFCDataList::Append( const NFIDataList& src )
{
	return Append(src, 0, src.GetCount());
}

bool NFCDataList::Add(const NFINT64 value)
{
    return NFIDataList::AddValue<NFINT64>(TDATA_INT, value);
}

bool NFCDataList::Add(const float value)
{
    return AddValue<float>(TDATA_FLOAT, value);
}

bool NFCDataList::Add(const double value)
{
    return AddValue<double>(TDATA_DOUBLE, value);
}

bool NFCDataList::Add(const char* value)
{
    return AddValue<std::string>(TDATA_STRING, std::string(value));
}

bool NFCDataList::Add(const std::string& value)
{
    return AddValue<std::string>(TDATA_STRING, value);
}

bool NFCDataList::Add(const NFIDENTID& value)
{
    return AddValue<NFIDENTID>(TDATA_OBJECT, value);
}

bool NFCDataList::Add(const void* value)
{
    //return AddNumber<const void*>(TDATA_POINTER, value);
    return true;
}

bool NFCDataList::Set(const int index, const NFINT64 value)
{
    if (index < GetCount() && index >= 0)
    {
        return SetValue(index, value);
    }

    return false;
}
bool NFCDataList::Set(const int index, const float value)
{
    if (index < GetCount() && index >= 0)
    {
        return SetValue(index, value);
    }

    return false;
}
bool NFCDataList::Set(const int index, const double value)
{
    if (index < GetCount() && index >= 0)
    {
        return SetValue(index, value);
    }

    return false;
}
bool NFCDataList::Set(const int index, const char* value)
{
    if (index < GetCount() && index >= 0)
    {
		return SetString(index, value);
    }

    return false;
}

bool NFCDataList::Set(const int index, const NFIDENTID& value)
{
    if (index < GetCount() && index >= 0)
    {
        return SetValue<NFIDENTID>(index, value);
    }

    return false;
}

bool NFCDataList::Set(const int index, const void* value)
{
    if (index < GetCount() && index >= 0)
    {
        //return SetNumber(index, value);
    }

    return false;
}

NFINT64 NFCDataList::Int(const int index) const
{
    if (index < GetCount() && index >= 0)
    {
        return NumberVal<NFINT64>(index);
    }

    return 0;
}

float NFCDataList::Float(const int index) const
{
    if (index < GetCount() && index >= 0)
    {
        return NumberVal<float>(index);
    }

    return 0.0f;
}

double NFCDataList::Double(const int index) const
{
    if (index < GetCount() && index >= 0)
    {
        return NumberVal<double>(index);
    }

    return 0.0f;
}

const std::string& NFCDataList::String(const int index) const
{
    if (index < GetCount() && index >= 0)
    {
        const NF_SHARE_PTR<TData> var = mvList[index];
        if (var && TDATA_STRING == var->nType)
        {
            return boost::get<const std::string&>(var->variantData);
        }
    }

    return NULL_STR;
}

NFIDENTID NFCDataList::Object(const int index) const
{
//    if (index < GetCount() && index >= 0)
//    {
//        return NumberVal<NFIDENTID>(index);
//    }

    if (index < GetCount() && index >= 0)
    {
        NFIDENTID result;
        if (index < GetCount() && index >= 0)
        {
            TDATA_TYPE type = Type(index);
            if (type == TDATA_OBJECT)
            {
                NF_SHARE_PTR<TData> var = GetStack(index);
                result = boost::get<NFIDENTID>(var->variantData);
            }
        }

        return result;
    }

    return NFIDENTID();
}

void* NFCDataList::Pointer(const int index) const
{
    if (index < GetCount() && index >= 0)
    {
        return NumberVal<void*>(index);
    }

    return NULL;
}

bool NFCDataList::Split(const char* str, const char* strSplit)
{
	Clear();

    std::string strData(str);
    if (strData.empty())
    {
        return true;
    }

    std::string temstrSplit(strSplit);
    std::string::size_type pos;
    strData += temstrSplit;
    std::string::size_type size = strData.length();

    for (std::string::size_type i = 0; i < size; i++)
    {
        pos = int(strData.find(temstrSplit, i));
        if (pos < size)
        {
            std::string strSub = strData.substr(i, pos - i);
            Add(strSub.c_str());

            i = pos + temstrSplit.size() - 1;
        }
    }

    return true;
}

TDATA_TYPE NFCDataList::Type(const int index) const
{
    if (index >= GetCount() || index < 0)
    {
        return TDATA_UNKNOWN;
    }

    if (index < STACK_SIZE)
    {
        return mvList[index]->nType;
    }
    else
    {
        const NF_SHARE_PTR<TData> pData = GetStack(index);
        if (pData)
        {
            return pData->nType;
        }
    }

    return TDATA_UNKNOWN;
}

bool NFCDataList::TypeEx(const int nType, ...) const
{
    bool bRet = true;

    if (TDATA_UNKNOWN == nType)
    {
        bRet = false;
        return bRet;
    }

    TDATA_TYPE pareType = (TDATA_TYPE)nType;
    va_list arg_ptr;
    va_start(arg_ptr, nType);
    int index = 0;

    while (pareType != TDATA_UNKNOWN)
    {
        //Ƚ
        TDATA_TYPE varType = Type(index);
        if (varType != pareType)
        {
            bRet = false;
            break;
        }

        ++index;
        pareType = (TDATA_TYPE)va_arg(arg_ptr, int);   //ȡһ
    }

    va_end(arg_ptr); //

    return bRet;
}

bool NFCDataList::Concat(const NFIDataList& src)
{
    InnerAppendEx(src, 0, src.GetCount());
    return true;
}

void NFCDataList::Clear()
{
	mnUseSize = 0;
    //mnCapacity = STACK_SIZE;
	//8Ժ
	if (mvList.size() > STACK_SIZE)
	{
		for (int i = 0; i < STACK_SIZE; ++i)
		{
			mvList[i]->nType = TDATA_UNKNOWN;
		}

		mvList.erase(mvList.begin() + 8, mvList.end());
	}
}

bool NFCDataList::IsEmpty() const
{
    return (0 == mnUseSize);
}

int NFCDataList::GetCount() const
{
    return mnUseSize;
}

void NFCDataList::InnerAppendEx(const NFIDataList& src, const int start, const int end)
{
    for (int i = start; i < end; ++i)
    {
        TDATA_TYPE vType = src.Type(i);
        switch (vType)
        {
            case TDATA_INT:
                AddValue<NFINT64>(vType, src.Int(i));
                break;
            case TDATA_FLOAT:
                AddValue<float>(vType, src.Float(i));
                break;
            case TDATA_DOUBLE:
                AddValue<double>(vType, src.Double(i));
                break;
            case TDATA_STRING:
                AddString(src.String(i).c_str());
                break;
            case TDATA_OBJECT:
                AddValue<NFIDENTID>(vType, src.Object(i));
                break;
                //case TDATA_POINTER:
                //    AddNumber<void*>(vType, src.NumberVal<void*>(i));
                //    break;
            default:
                //Assert(0);
                break;
        }
    }
}

std::string NFCDataList::StringValEx(const int index, const bool bForce) const
{
    if (index < GetCount() && index >= 0)
    {
        TDATA_TYPE type =  Type(index);
        if (type == TDATA_STRING)
        {
            return String(index);
        }

//         const NF_SHARE_PTR<NFIDataList::TData> var = GetStack(index);
//         if (var)
//         {
//             //return boost::lexical_cast<std::string>(var->variantData);
//         }
    }

    return NULL_STR;
}

bool NFCDataList::ToString(std::string& str, const char* strSplit) const
{
    for (int i = 0; i < GetCount(); ++i)
    {
        std::string strVal = StringValEx(i, true);
        str += strVal;
        str += strSplit;
    }

    std::string strTempSplit(strSplit);
    std::string::size_type nPos = str.rfind(strSplit);
    if (nPos == str.length() - strTempSplit.length())
    {
        str = str.substr(0, nPos);
    }

    return true;
}
<|endoftext|>


<commit_before>#include "util.h"
#include <string>
#include <sstream>
#include <algorithm>
#include <glog/logging.h>
#include <openssl/sha.h>
#include <curl/curl.h>

namespace {
  const uint32_t buff_size = 1024;
  const uint32_t json_buff_size = 1024 * 4;
  const char *json_base =
      "{\"host\": \"%s\", \"service\": \"%s\", \"description\": \"%s\""
      ",\"state\": \"%s\", \"metric\": %f, \"time\": %i, \"tags\": [%s] %s}";
}

std::string metric_to_string(const Event& e) {
  std::ostringstream ss;
  if (e.has_metric_f()) {
    ss << e.metric_f();
  } else if (e.has_metric_d()) {
    ss << e.metric_d();
  } else if (e.has_metric_sint64()) {
    ss << e.metric_sint64();
  } else {
    ss << "";
  }
  return ss.str();
}

std::string ttl_to_string(const Event& e) {
  std::ostringstream ss;
  ss << e.ttl();
  return ss.str();
}

double metric_to_double(const Event &e) {
  if (e.has_metric_f()) {
    return e.metric_f();
  } else if (e.has_metric_sint64()) {
    return e.metric_sint64();
  } else if (e.has_metric_d()) {
    return e.metric_d();
  } else {
    return 0;
  }
}

void clear_metrics(Event & e) {
  e.clear_metric_d();
  e.clear_metric_f();
  e.clear_metric_sint64();
}

bool metric_set(const Event & e) {
  return (e.has_metric_f() || e.has_metric_d() || e.has_metric_sint64());
}

std::string string_to_value(const Event& e, const std::string& key) {
  if (key == "host") {
    return e.host();
  } else if (key == "service") {
    return e.service();
  } else if (key == "description") {
    return e.description();
  } else if (key == "state") {
    return e.state();
  } else if (key == "metric") {
    return metric_to_string(e);
  }  else if (key == "ttl") {
    return ttl_to_string(e);
  } else {
    return "__nil__";
  }
}

std::string event_to_json(const Event &e) {
  char tags[buff_size] =  "";
  char attrs[buff_size] = "";

  for (int i = 0; i < e.tags_size(); i++) {
    if (i != 0) {
      strncat(tags, ", ", buff_size- strlen(tags));
    }
    strncat(tags, "\"", buff_size - strlen(tags));
    strncat(tags, e.tags(i).c_str(), buff_size - strlen(tags));
    strncat(tags, "\"", buff_size - strlen(tags));
  }

  for (int i = 0; i < e.attributes_size(); i++) {
    strncat(attrs, ", ", buff_size - strlen(attrs));
    strncat(attrs, "\"", buff_size - strlen(attrs));
    strncat(attrs, e.attributes(i).key().c_str(), buff_size - strlen(attrs));
    strncat(attrs, "\": ", buff_size - strlen(attrs));
    strncat(attrs, "\"", buff_size - strlen(attrs));
    strncat(attrs, e.attributes(i).value().c_str(), buff_size - strlen(attrs));
    strncat(attrs, "\"", buff_size - strlen(attrs));
  }

 double metric;
 if (e.has_metric_f()) {
    metric = (double)e.metric_f();
  } else if (e.has_metric_d()) {
    metric =  e.metric_d();
  } else if (e.has_metric_sint64()) {
    metric = (double) e.metric_sint64();
  } else {
    metric = 0;
  }

  char json_buffer[json_buff_size];
  size_t r = snprintf(json_buffer, json_buff_size, json_base,
                e.host().c_str(), e.service().c_str(), e.description().c_str(),
                e.state().c_str(), metric, e.time(), tags, attrs);

  if (r >= json_buff_size) {
    VLOG(1) << "json string is too big";
    return "";
  } else {
    return json_buffer;
  }
}

void set_event_value(
    Event& e,
    const std::string& key,
    const std::string& value,
    const bool& replace)
{
  if (key == "host") {
    if (replace || (!e.has_host())) {
      e.set_host(value);
    }
  } else if (key == "service") {
    if (replace || (!e.has_service())) {
      e.set_service(value);
    }
  } else if (key == "description") {
    if (replace || (!e.has_description())) {
      e.set_description(value);
    }
  } else if (key == "state") {
    if (replace || (!e.has_state())) {
      e.set_state(value);
    }
  } else {
    auto att = e.add_attributes();
    att->set_key(key);
    att->set_value(value);
  }
}

bool no_metric_set(const Event & e) {
  return (!e.has_metric_sint64() && !e.has_metric_d() && ! e.has_metric_f());
}

void set_event_value(
    Event& e,
    const std::string & key,
    const int & value,
    const bool & replace)
{
  if (key == "metric") {
   if (replace) {
      e.clear_metric_d();
      e.clear_metric_f();
      e.set_metric_sint64(value);
    } else if (no_metric_set(e)) {
      e.set_metric_sint64(value);
    }
  } else if (key == "ttl") {
    if (replace || (!e.has_ttl())) {
      e.set_ttl(value);
    }
  } else {
    LOG(ERROR) << "set_event_value() wrong key: " << key;
  }
}

void set_event_value(
    Event& e,
    const std::string & key,
    const double & value,
    const bool & replace)
{
  if (key == "metric") {
    if (replace) {
      e.clear_metric_sint64();
      e.clear_metric_f();
      e.set_metric_d(value);
    } else if (no_metric_set(e)) {
      e.set_metric_d(value);
    }
  } else {
    LOG(ERROR) << "set_event_value() wrong key: " << key;
  }
}

void set_event_value(
    Event & e,
    const std::string & key,
    const boost::variant<std::string, int, double> & val,
    const bool & replace)
{
  switch (val.which()) {
    case 0:
      set_event_value(e, key, boost::get<std::string>(val), replace);
      break;
    case 1:
      set_event_value(e, key, boost::get<int>(val), replace);
      break;
    case 2:
      set_event_value(e, key, boost::get<double>(val), replace);
      break;
  }
}

bool tag_exists(const Event& e, const std::string& tag) {
  for (int i = 0; i < e.tags_size(); i++) {
    if (e.tags(i) == tag) {
      return true;
    }
  }
  return false;
}

bool attribute_exists(const Event& e, const std::string& attribute) {
  for (int i = 0; i < e.attributes_size(); i++) {
    if (e.attributes(i).key() == attribute) {
      return true;
    }
  }
  return false;
}

#include <iostream>
std::string attribute_value(const Event& e, const std::string& attribute) {
  if (attribute_exists(e, attribute)) {
    for (int i = 0; i < e.attributes_size(); i++) {
      if (e.attributes(i).key() == attribute) {
        return e.attributes(i).value();
      }
    }
  }
  return "";
}

std::string sha1(const std::string& str) {
  unsigned char hash[SHA_DIGEST_LENGTH];
  SHA1((const unsigned char*)str.c_str(), (unsigned long)str.size(), hash);
  return std::string((char*)hash, SHA_DIGEST_LENGTH);
}

/* Taken and slightly modified from
   http://en.wikibooks.org/wiki/Algorithm_Implementation/Miscellaneous/Base64 */

const static char encodeLookup[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
const static char padCharacter = '=';
std::basic_string<char> base64Encode(std::vector<unsigned char> inputBuffer)
{
  std::basic_string<char> encodedString;
  encodedString.reserve(((inputBuffer.size()/3) + (inputBuffer.size() % 3 > 0)) * 4);
  long temp;
  std::vector<unsigned char>::iterator cursor = inputBuffer.begin();
  for(size_t idx = 0; idx < inputBuffer.size()/3; idx++)
  {
    temp  = (*cursor++) << 16; //Convert to big endian
    temp += (*cursor++) << 8;
    temp += (*cursor++);
    encodedString.append(1,encodeLookup[(temp & 0x00FC0000) >> 18]);
    encodedString.append(1,encodeLookup[(temp & 0x0003F000) >> 12]);
    encodedString.append(1,encodeLookup[(temp & 0x00000FC0) >> 6 ]);
    encodedString.append(1,encodeLookup[(temp & 0x0000003F)      ]);
  }
  switch(inputBuffer.size() % 3)
  {
    case 1:
      temp  = (*cursor++) << 16; //Convert to big endian
      encodedString.append(1,encodeLookup[(temp & 0x00FC0000) >> 18]);
      encodedString.append(1,encodeLookup[(temp & 0x0003F000) >> 12]);
      encodedString.append(2,padCharacter);
      break;
    case 2:
      temp  = (*cursor++) << 16; //Convert to big endian
      temp += (*cursor++) << 8;
      encodedString.append(1,encodeLookup[(temp & 0x00FC0000) >> 18]);
      encodedString.append(1,encodeLookup[(temp & 0x0003F000) >> 12]);
      encodedString.append(1,encodeLookup[(temp & 0x00000FC0) >> 6 ]);
      encodedString.append(1,padCharacter);
      break;
  }
  return encodedString;
}

std::string uri_unescape(const std::string& uri) {
  VLOG(3) << "uri_unescape() uri: " << uri;
  CURL *curl = curl_easy_init();

  if (curl == NULL) {
    LOG(ERROR) << "uri_unescape(): curl_easy_init() failed";
    return uri;
  }

  char *ret =  curl_easy_unescape(curl, uri.c_str(), uri.size(), 0);
  VLOG(3) << "*ret " << ret;
  const std::string unescaped(ret);
  curl_free(ret);
  curl_easy_cleanup(curl);
  return unescaped;
}

bool parse_uri(
    const std::string& escaped_uri,
    std::string& index,
    std::map<std::string, std::string>& params )
{
  VLOG(3) << "parse_uri() escaped_uri: " << escaped_uri;
  std::string uri = uri_unescape(escaped_uri);
  VLOG(3) << "parse_uri() uri: " << uri;

  auto it = uri.begin();
  if (*it != '/') {
    LOG(ERROR) << "uri doesn't start with /";
    return false;
  }

  while (it != uri.end() && *it != '?') {
    index += *it;
    it++;
  }

  if (it == uri.end()) {
    LOG(ERROR) << "uri doesn't contain '?'";
    return false;
  }
  it++;

  VLOG(3) << "index name: " << index;

  while(true) {
    std::string key;
    while (it != uri.end() && *it != '=') {
      key += *it;
      it++;
    }

    if (it == uri.end()) {
      LOG(ERROR) << "uri doesn't contain '='";
      return false;
    }
    it++;

    VLOG(3) << "key: " << key;

    std::string value;
    while (it != uri.end() && *it != '&') {
      value += *it;
      it++;
    }

    VLOG(3) << "value: " << value;
    params.insert({key, value});

    if (it == uri.end()) {
      break;
    } else if (*it == '&') {
      it++;
    }
  }

  return true;
}

<commit_msg>Fix time_t format<commit_after>#include "util.h"
#include <string>
#include <sstream>
#include <algorithm>
#include <glog/logging.h>
#include <openssl/sha.h>
#include <curl/curl.h>

namespace {
  const uint32_t buff_size = 1024;
  const uint32_t json_buff_size = 1024 * 4;
  const char *json_base =
      "{\"host\": \"%s\", \"service\": \"%s\", \"description\": \"%s\""
      ",\"state\": \"%s\", \"metric\": %f, \"time\": %lld, \"tags\": [%s] %s}";
}

std::string metric_to_string(const Event& e) {
  std::ostringstream ss;
  if (e.has_metric_f()) {
    ss << e.metric_f();
  } else if (e.has_metric_d()) {
    ss << e.metric_d();
  } else if (e.has_metric_sint64()) {
    ss << e.metric_sint64();
  } else {
    ss << "";
  }
  return ss.str();
}

std::string ttl_to_string(const Event& e) {
  std::ostringstream ss;
  ss << e.ttl();
  return ss.str();
}

double metric_to_double(const Event &e) {
  if (e.has_metric_f()) {
    return e.metric_f();
  } else if (e.has_metric_sint64()) {
    return e.metric_sint64();
  } else if (e.has_metric_d()) {
    return e.metric_d();
  } else {
    return 0;
  }
}

void clear_metrics(Event & e) {
  e.clear_metric_d();
  e.clear_metric_f();
  e.clear_metric_sint64();
}

bool metric_set(const Event & e) {
  return (e.has_metric_f() || e.has_metric_d() || e.has_metric_sint64());
}

std::string string_to_value(const Event& e, const std::string& key) {
  if (key == "host") {
    return e.host();
  } else if (key == "service") {
    return e.service();
  } else if (key == "description") {
    return e.description();
  } else if (key == "state") {
    return e.state();
  } else if (key == "metric") {
    return metric_to_string(e);
  }  else if (key == "ttl") {
    return ttl_to_string(e);
  } else {
    return "__nil__";
  }
}

std::string event_to_json(const Event &e) {
  char tags[buff_size] =  "";
  char attrs[buff_size] = "";

  for (int i = 0; i < e.tags_size(); i++) {
    if (i != 0) {
      strncat(tags, ", ", buff_size- strlen(tags));
    }
    strncat(tags, "\"", buff_size - strlen(tags));
    strncat(tags, e.tags(i).c_str(), buff_size - strlen(tags));
    strncat(tags, "\"", buff_size - strlen(tags));
  }

  for (int i = 0; i < e.attributes_size(); i++) {
    strncat(attrs, ", ", buff_size - strlen(attrs));
    strncat(attrs, "\"", buff_size - strlen(attrs));
    strncat(attrs, e.attributes(i).key().c_str(), buff_size - strlen(attrs));
    strncat(attrs, "\": ", buff_size - strlen(attrs));
    strncat(attrs, "\"", buff_size - strlen(attrs));
    strncat(attrs, e.attributes(i).value().c_str(), buff_size - strlen(attrs));
    strncat(attrs, "\"", buff_size - strlen(attrs));
  }

 double metric;
 if (e.has_metric_f()) {
    metric = (double)e.metric_f();
  } else if (e.has_metric_d()) {
    metric =  e.metric_d();
  } else if (e.has_metric_sint64()) {
    metric = (double) e.metric_sint64();
  } else {
    metric = 0;
  }

  char json_buffer[json_buff_size];
  size_t r = snprintf(json_buffer, json_buff_size, json_base,
                e.host().c_str(), e.service().c_str(), e.description().c_str(),
                e.state().c_str(), metric, e.time(), tags, attrs);

  if (r >= json_buff_size) {
    VLOG(1) << "json string is too big";
    return "";
  } else {
    return json_buffer;
  }
}

void set_event_value(
    Event& e,
    const std::string& key,
    const std::string& value,
    const bool& replace)
{
  if (key == "host") {
    if (replace || (!e.has_host())) {
      e.set_host(value);
    }
  } else if (key == "service") {
    if (replace || (!e.has_service())) {
      e.set_service(value);
    }
  } else if (key == "description") {
    if (replace || (!e.has_description())) {
      e.set_description(value);
    }
  } else if (key == "state") {
    if (replace || (!e.has_state())) {
      e.set_state(value);
    }
  } else {
    auto att = e.add_attributes();
    att->set_key(key);
    att->set_value(value);
  }
}

bool no_metric_set(const Event & e) {
  return (!e.has_metric_sint64() && !e.has_metric_d() && ! e.has_metric_f());
}

void set_event_value(
    Event& e,
    const std::string & key,
    const int & value,
    const bool & replace)
{
  if (key == "metric") {
   if (replace) {
      e.clear_metric_d();
      e.clear_metric_f();
      e.set_metric_sint64(value);
    } else if (no_metric_set(e)) {
      e.set_metric_sint64(value);
    }
  } else if (key == "ttl") {
    if (replace || (!e.has_ttl())) {
      e.set_ttl(value);
    }
  } else {
    LOG(ERROR) << "set_event_value() wrong key: " << key;
  }
}

void set_event_value(
    Event& e,
    const std::string & key,
    const double & value,
    const bool & replace)
{
  if (key == "metric") {
    if (replace) {
      e.clear_metric_sint64();
      e.clear_metric_f();
      e.set_metric_d(value);
    } else if (no_metric_set(e)) {
      e.set_metric_d(value);
    }
  } else {
    LOG(ERROR) << "set_event_value() wrong key: " << key;
  }
}

void set_event_value(
    Event & e,
    const std::string & key,
    const boost::variant<std::string, int, double> & val,
    const bool & replace)
{
  switch (val.which()) {
    case 0:
      set_event_value(e, key, boost::get<std::string>(val), replace);
      break;
    case 1:
      set_event_value(e, key, boost::get<int>(val), replace);
      break;
    case 2:
      set_event_value(e, key, boost::get<double>(val), replace);
      break;
  }
}

bool tag_exists(const Event& e, const std::string& tag) {
  for (int i = 0; i < e.tags_size(); i++) {
    if (e.tags(i) == tag) {
      return true;
    }
  }
  return false;
}

bool attribute_exists(const Event& e, const std::string& attribute) {
  for (int i = 0; i < e.attributes_size(); i++) {
    if (e.attributes(i).key() == attribute) {
      return true;
    }
  }
  return false;
}

#include <iostream>
std::string attribute_value(const Event& e, const std::string& attribute) {
  if (attribute_exists(e, attribute)) {
    for (int i = 0; i < e.attributes_size(); i++) {
      if (e.attributes(i).key() == attribute) {
        return e.attributes(i).value();
      }
    }
  }
  return "";
}

std::string sha1(const std::string& str) {
  unsigned char hash[SHA_DIGEST_LENGTH];
  SHA1((const unsigned char*)str.c_str(), (unsigned long)str.size(), hash);
  return std::string((char*)hash, SHA_DIGEST_LENGTH);
}

/* Taken and slightly modified from
   http://en.wikibooks.org/wiki/Algorithm_Implementation/Miscellaneous/Base64 */

const static char encodeLookup[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
const static char padCharacter = '=';
std::basic_string<char> base64Encode(std::vector<unsigned char> inputBuffer)
{
  std::basic_string<char> encodedString;
  encodedString.reserve(((inputBuffer.size()/3) + (inputBuffer.size() % 3 > 0)) * 4);
  long temp;
  std::vector<unsigned char>::iterator cursor = inputBuffer.begin();
  for(size_t idx = 0; idx < inputBuffer.size()/3; idx++)
  {
    temp  = (*cursor++) << 16; //Convert to big endian
    temp += (*cursor++) << 8;
    temp += (*cursor++);
    encodedString.append(1,encodeLookup[(temp & 0x00FC0000) >> 18]);
    encodedString.append(1,encodeLookup[(temp & 0x0003F000) >> 12]);
    encodedString.append(1,encodeLookup[(temp & 0x00000FC0) >> 6 ]);
    encodedString.append(1,encodeLookup[(temp & 0x0000003F)      ]);
  }
  switch(inputBuffer.size() % 3)
  {
    case 1:
      temp  = (*cursor++) << 16; //Convert to big endian
      encodedString.append(1,encodeLookup[(temp & 0x00FC0000) >> 18]);
      encodedString.append(1,encodeLookup[(temp & 0x0003F000) >> 12]);
      encodedString.append(2,padCharacter);
      break;
    case 2:
      temp  = (*cursor++) << 16; //Convert to big endian
      temp += (*cursor++) << 8;
      encodedString.append(1,encodeLookup[(temp & 0x00FC0000) >> 18]);
      encodedString.append(1,encodeLookup[(temp & 0x0003F000) >> 12]);
      encodedString.append(1,encodeLookup[(temp & 0x00000FC0) >> 6 ]);
      encodedString.append(1,padCharacter);
      break;
  }
  return encodedString;
}

std::string uri_unescape(const std::string& uri) {
  VLOG(3) << "uri_unescape() uri: " << uri;
  CURL *curl = curl_easy_init();

  if (curl == NULL) {
    LOG(ERROR) << "uri_unescape(): curl_easy_init() failed";
    return uri;
  }

  char *ret =  curl_easy_unescape(curl, uri.c_str(), uri.size(), 0);
  VLOG(3) << "*ret " << ret;
  const std::string unescaped(ret);
  curl_free(ret);
  curl_easy_cleanup(curl);
  return unescaped;
}

bool parse_uri(
    const std::string& escaped_uri,
    std::string& index,
    std::map<std::string, std::string>& params )
{
  VLOG(3) << "parse_uri() escaped_uri: " << escaped_uri;
  std::string uri = uri_unescape(escaped_uri);
  VLOG(3) << "parse_uri() uri: " << uri;

  auto it = uri.begin();
  if (*it != '/') {
    LOG(ERROR) << "uri doesn't start with /";
    return false;
  }

  while (it != uri.end() && *it != '?') {
    index += *it;
    it++;
  }

  if (it == uri.end()) {
    LOG(ERROR) << "uri doesn't contain '?'";
    return false;
  }
  it++;

  VLOG(3) << "index name: " << index;

  while(true) {
    std::string key;
    while (it != uri.end() && *it != '=') {
      key += *it;
      it++;
    }

    if (it == uri.end()) {
      LOG(ERROR) << "uri doesn't contain '='";
      return false;
    }
    it++;

    VLOG(3) << "key: " << key;

    std::string value;
    while (it != uri.end() && *it != '&') {
      value += *it;
      it++;
    }

    VLOG(3) << "value: " << value;
    params.insert({key, value});

    if (it == uri.end()) {
      break;
    } else if (*it == '&') {
      it++;
    }
  }

  return true;
}

<|endoftext|>


<commit_before>// -------------------------------------------------------------------------
//    @FileName         :    NFCProperty.cpp
//    @Author           :    LvSheng.Huang
//    @Date             :    2012-03-01
//    @Module           :    NFCProperty
//
// -------------------------------------------------------------------------

#include "NFCProperty.h"
#include <complex>

NFCProperty::NFCProperty()
{
    mbPublic = false;
    mbPrivate = false;
    mbSave = false;
    mSelf = NFGUID();
    eType = TDATA_UNKNOWN;

    msPropertyName = "";
}

NFCProperty::NFCProperty(const NFGUID& self, const std::string& strPropertyName, const TDATA_TYPE varType, bool bPublic,  bool bPrivate,  bool bSave, bool bView, int nIndex, const std::string& strScriptFunction)
{

    mbPublic = bPublic;
    mbPrivate = bPrivate;
    mbSave = bSave;
    mbView = bView;
    mnIndex = nIndex;
    mSelf = self;

    msPropertyName = strPropertyName;
    eType = varType;
}

NFCProperty::~NFCProperty()
{
    for (TPROPERTYCALLBACKEX::iterator iter = mtPropertyCallback.begin(); iter != mtPropertyCallback.end(); ++iter)
    {
        iter->reset();
    }

    mtPropertyCallback.clear();
    mxData.reset();
}

void NFCProperty::SetValue(const NFIDataList::TData& TData)
{
    if (eType != TData.GetType())
    {
        return;
    }

    if (!mxData.get())
    {
        if (!TData.IsNullValue())
        {
            return;
        }

        mxData = NF_SHARE_PTR<NFIDataList::TData>(NF_NEW NFIDataList::TData(TData));
    }

    NFCDataList::TData oldValue;
    oldValue = *mxData;

    mxData->variantData = TData.variantData;

    NFCDataList::TData newValue;
    newValue = *mxData;

    OnEventHandler(oldValue , newValue);
}

void NFCProperty::SetValue(const NFIProperty* pProperty)
{
    SetValue(pProperty->GetValue());
}

const NFIDataList::TData& NFCProperty::GetValue() const
{
    if (mxData.get())
    {
        return *mxData;
    }

    return NULL_TDATA;
}

const std::string&  NFCProperty::GetKey() const
{
    return msPropertyName;
}

const bool NFCProperty::GetSave() const
{
    return mbSave;
}

const bool NFCProperty::GetView() const
{
    return mbView;
}

const bool NFCProperty::GetPublic() const
{
    return mbPublic;
}

const bool NFCProperty::GetPrivate() const
{
    return mbPrivate;
}

const int NFCProperty::GetIndex() const
{
    return mnIndex;
};

const std::string& NFCProperty::GetRelationValue() const
{
    return NULL_STR;//msScriptFunction;
}

void NFCProperty::SetSave(bool bSave)
{
    mbSave = bSave;
}

void NFCProperty::SetView(bool bView)
{
    mbView = bView;
}

void NFCProperty::SetPublic(bool bPublic)
{
    mbPublic = bPublic;
}

void NFCProperty::SetPrivate(bool bPrivate)
{
    mbPrivate = bPrivate;
}

void NFCProperty::SetScriptFunction(const std::string& strScriptFunction)
{
    //msScriptFunction = strScriptFunction;
}

NFINT64 NFCProperty::GetInt() const
{
    if (!mxData.get())
    {
        return 0;
    }

    return mxData->GetInt();
}

double NFCProperty::GetFloat() const
{
    if (!mxData.get())
    {
        return 0.0;
    }

    return mxData->GetFloat();
}

const std::string& NFCProperty::GetString() const
{
    if (!mxData.get())
    {
        return NULL_STR;
    }

    return mxData->GetString();
}

const NFGUID& NFCProperty::GetObject() const
{
    if (!mxData.get())
    {
        return NULL_OBJECT;
    }

    return mxData->GetObject();
}

void NFCProperty::RegisterCallback(const PROPERTY_EVENT_FUNCTOR_PTR& cb)
{
    mtPropertyCallback.push_back(cb);
}

int NFCProperty::OnEventHandler(const NFIDataList::TData& oldVar, const NFIDataList::TData& newVar)
{
    if (mtPropertyCallback.size() <= 0)
    {
        return 0;
    }

    TPROPERTYCALLBACKEX::iterator it = mtPropertyCallback.begin();
    TPROPERTYCALLBACKEX::iterator end = mtPropertyCallback.end();
    for (it; it != end; ++it)
    {
        //NFIDataList:OLDֵNEWֵ, ARG(pKernel,self)
        PROPERTY_EVENT_FUNCTOR_PTR& pFunPtr = *it;
        PROPERTY_EVENT_FUNCTOR* pFunc = pFunPtr.get();
        int nTemRet = pFunc->operator()(mSelf, msPropertyName, oldVar, newVar);
    }

    return 0;
}

bool NFCProperty::SetInt(const NFINT64 value)
{
    if (eType != TDATA_INT)
    {
        return false;
    }

	if (!mxData.get())
	{
		//ǿվΪûݣûݵľͲ
		if (0 == value)
		{
			return false;
		}

		mxData = NF_SHARE_PTR<NFIDataList::TData>(NF_NEW NFIDataList::TData(TDATA_INT));
		mxData->SetInt(0);
	}

	if (value == mxData->GetInt())
	{
		return false;
	}

	NFCDataList::TData oldValue;
	oldValue = *mxData;

	mxData->SetInt(value);

	OnEventHandler(oldValue , value);

	return true;
}

bool NFCProperty::SetFloat(const double value)
{
    if (eType != TDATA_FLOAT)
    {
        return false;
    }

    if (!mxData.get())
    {
        //ǿվΪûݣûݵľͲ
		if (std::abs(value) < 0.001)
		{
            return false;
        }

        mxData = NF_SHARE_PTR<NFIDataList::TData>(NF_NEW NFIDataList::TData(TDATA_FLOAT));
        mxData->SetFloat(0.0);
    }

    if (value - mxData->GetFloat() < 0.001)
    {
        return false;
    }

	NFCDataList::TData oldValue;
	oldValue = *mxData;

	mxData->SetFloat(value);

	OnEventHandler(oldValue , newValue);

	return true;
}

bool NFCProperty::SetString(const std::string& value)
{
    if (eType != TDATA_STRING)
    {
        return false;
    }

    if (!mxData.get())
    {
        //ǿվΪûݣûݵľͲ
        if (value.empty())
        {
            return false;
        }

        mxData = NF_SHARE_PTR<NFIDataList::TData>(NF_NEW NFIDataList::TData(TDATA_STRING));
        mxData->SetString(NULL_STR);
    }

    if (value == mxData->GetString())
    {
        return false;
    }

	NFCDataList::TData oldValue;
	oldValue = *mxData;

	mxData->SetString(value);

	OnEventHandler(oldValue , newValue);

	return true;
}

bool NFCProperty::SetObject(const NFGUID& value)
{
    if (eType != TDATA_OBJECT)
    {
        return false;
    }

    if (!mxData.get())
    {
        //ǿվΪûݣûݵľͲ
        if (value.IsNull())
        {
            return false;
        }

        mxData = NF_SHARE_PTR<NFIDataList::TData>(NF_NEW NFIDataList::TData(TDATA_OBJECT));
        mxData->SetObject(NFGUID());

    }

    if (value == mxData->GetObject())
    {
        return false;
    }

    NFCDataList::TData oldValue;
    oldValue = *mxData;

    mxData->SetObject(value);

    OnEventHandler(oldValue , *mxData);

    return true;
}

bool NFCProperty::Changed() const
{
    return GetValue().IsNullValue();
}

const TDATA_TYPE NFCProperty::GetType() const
{
    return eType;
}

const bool NFCProperty::GeUsed() const
{
    if (mxData.get())
    {
        return true;
    }

    return false;
}

std::string NFCProperty::ToString()
{
    std::string strData;
    const TDATA_TYPE eType = GetType();
    switch (eType)
    {
    case TDATA_INT:
        strData = lexical_cast<std::string> (GetInt());
        break;

    case TDATA_FLOAT:
        strData = lexical_cast<std::string> (GetFloat());
        break;

    case TDATA_STRING:
        strData = lexical_cast<std::string> (GetString());
        break;
    case TDATA_OBJECT:
        strData = GetObject().ToString();
        break;
    default:

        strData = NULL_STR;
        break;
    }

    return strData;
}

bool NFCProperty::FromString( const std::string& strData )
{
    const TDATA_TYPE eType = GetType();
    bool bRet = false;
    switch (eType)
    {
    case TDATA_INT:
        {
            NFINT64  nValue = 0;
            bRet = NF_StrTo(strData, nValue);
            SetInt(nValue);
        }
        break;

    case TDATA_FLOAT:
        {
            double  dValue = 0;
            bRet = NF_StrTo(strData, dValue);
            SetFloat(dValue);
        }
        break;

    case TDATA_STRING:
        {
            SetString(strData);
            bRet = true;
        }
        break;
    case TDATA_OBJECT:
        {
            NFGUID xID;

            bRet = xID.FromString(strData);
            SetObject(xID);
        }
        break;
    default:
        break;
    }

    return bRet;
}
<commit_msg>fixed for error commit<commit_after>// -------------------------------------------------------------------------
//    @FileName         :    NFCProperty.cpp
//    @Author           :    LvSheng.Huang
//    @Date             :    2012-03-01
//    @Module           :    NFCProperty
//
// -------------------------------------------------------------------------

#include "NFCProperty.h"
#include <complex>

NFCProperty::NFCProperty()
{
    mbPublic = false;
    mbPrivate = false;
    mbSave = false;
    mSelf = NFGUID();
    eType = TDATA_UNKNOWN;

    msPropertyName = "";
}

NFCProperty::NFCProperty(const NFGUID& self, const std::string& strPropertyName, const TDATA_TYPE varType, bool bPublic,  bool bPrivate,  bool bSave, bool bView, int nIndex, const std::string& strScriptFunction)
{

    mbPublic = bPublic;
    mbPrivate = bPrivate;
    mbSave = bSave;
    mbView = bView;
    mnIndex = nIndex;
    mSelf = self;

    msPropertyName = strPropertyName;
    eType = varType;
}

NFCProperty::~NFCProperty()
{
    for (TPROPERTYCALLBACKEX::iterator iter = mtPropertyCallback.begin(); iter != mtPropertyCallback.end(); ++iter)
    {
        iter->reset();
    }

    mtPropertyCallback.clear();
    mxData.reset();
}

void NFCProperty::SetValue(const NFIDataList::TData& TData)
{
    if (eType != TData.GetType())
    {
        return;
    }

    if (!mxData.get())
    {
        if (!TData.IsNullValue())
        {
            return;
        }

        mxData = NF_SHARE_PTR<NFIDataList::TData>(NF_NEW NFIDataList::TData(TData));
    }

    NFCDataList::TData oldValue;
    oldValue = *mxData;

    mxData->variantData = TData.variantData;

    NFCDataList::TData newValue;
    newValue = *mxData;

    OnEventHandler(oldValue , newValue);
}

void NFCProperty::SetValue(const NFIProperty* pProperty)
{
    SetValue(pProperty->GetValue());
}

const NFIDataList::TData& NFCProperty::GetValue() const
{
    if (mxData.get())
    {
        return *mxData;
    }

    return NULL_TDATA;
}

const std::string&  NFCProperty::GetKey() const
{
    return msPropertyName;
}

const bool NFCProperty::GetSave() const
{
    return mbSave;
}

const bool NFCProperty::GetView() const
{
    return mbView;
}

const bool NFCProperty::GetPublic() const
{
    return mbPublic;
}

const bool NFCProperty::GetPrivate() const
{
    return mbPrivate;
}

const int NFCProperty::GetIndex() const
{
    return mnIndex;
};

const std::string& NFCProperty::GetRelationValue() const
{
    return NULL_STR;//msScriptFunction;
}

void NFCProperty::SetSave(bool bSave)
{
    mbSave = bSave;
}

void NFCProperty::SetView(bool bView)
{
    mbView = bView;
}

void NFCProperty::SetPublic(bool bPublic)
{
    mbPublic = bPublic;
}

void NFCProperty::SetPrivate(bool bPrivate)
{
    mbPrivate = bPrivate;
}

void NFCProperty::SetScriptFunction(const std::string& strScriptFunction)
{
    //msScriptFunction = strScriptFunction;
}

NFINT64 NFCProperty::GetInt() const
{
    if (!mxData.get())
    {
        return 0;
    }

    return mxData->GetInt();
}

double NFCProperty::GetFloat() const
{
    if (!mxData.get())
    {
        return 0.0;
    }

    return mxData->GetFloat();
}

const std::string& NFCProperty::GetString() const
{
    if (!mxData.get())
    {
        return NULL_STR;
    }

    return mxData->GetString();
}

const NFGUID& NFCProperty::GetObject() const
{
    if (!mxData.get())
    {
        return NULL_OBJECT;
    }

    return mxData->GetObject();
}

void NFCProperty::RegisterCallback(const PROPERTY_EVENT_FUNCTOR_PTR& cb)
{
    mtPropertyCallback.push_back(cb);
}

int NFCProperty::OnEventHandler(const NFIDataList::TData& oldVar, const NFIDataList::TData& newVar)
{
    if (mtPropertyCallback.size() <= 0)
    {
        return 0;
    }

    TPROPERTYCALLBACKEX::iterator it = mtPropertyCallback.begin();
    TPROPERTYCALLBACKEX::iterator end = mtPropertyCallback.end();
    for (it; it != end; ++it)
    {
        //NFIDataList:OLDֵNEWֵ, ARG(pKernel,self)
        PROPERTY_EVENT_FUNCTOR_PTR& pFunPtr = *it;
        PROPERTY_EVENT_FUNCTOR* pFunc = pFunPtr.get();
        int nTemRet = pFunc->operator()(mSelf, msPropertyName, oldVar, newVar);
    }

    return 0;
}

bool NFCProperty::SetInt(const NFINT64 value)
{
    if (eType != TDATA_INT)
    {
        return false;
    }

	if (!mxData.get())
	{
		//ǿվΪûݣûݵľͲ
		if (0 == value)
		{
			return false;
		}

		mxData = NF_SHARE_PTR<NFIDataList::TData>(NF_NEW NFIDataList::TData(TDATA_INT));
		mxData->SetInt(0);
	}

	if (value == mxData->GetInt())
	{
		return false;
	}

	NFCDataList::TData oldValue;
	oldValue = *mxData;

	mxData->SetInt(value);

	OnEventHandler(oldValue, *mxData);

	return true;
}

bool NFCProperty::SetFloat(const double value)
{
    if (eType != TDATA_FLOAT)
    {
        return false;
    }

    if (!mxData.get())
    {
        //ǿվΪûݣûݵľͲ
		if (std::abs(value) < 0.001)
		{
            return false;
        }

        mxData = NF_SHARE_PTR<NFIDataList::TData>(NF_NEW NFIDataList::TData(TDATA_FLOAT));
        mxData->SetFloat(0.0);
    }

    if (value - mxData->GetFloat() < 0.001)
    {
        return false;
    }

	NFCDataList::TData oldValue;
	oldValue = *mxData;

	mxData->SetFloat(value);

	OnEventHandler(oldValue, *mxData);

	return true;
}

bool NFCProperty::SetString(const std::string& value)
{
    if (eType != TDATA_STRING)
    {
        return false;
    }

    if (!mxData.get())
    {
        //ǿվΪûݣûݵľͲ
        if (value.empty())
        {
            return false;
        }

        mxData = NF_SHARE_PTR<NFIDataList::TData>(NF_NEW NFIDataList::TData(TDATA_STRING));
        mxData->SetString(NULL_STR);
    }

    if (value == mxData->GetString())
    {
        return false;
    }

	NFCDataList::TData oldValue;
	oldValue = *mxData;

	mxData->SetString(value);

	OnEventHandler(oldValue, *mxData);

	return true;
}

bool NFCProperty::SetObject(const NFGUID& value)
{
    if (eType != TDATA_OBJECT)
    {
        return false;
    }

    if (!mxData.get())
    {
        //ǿվΪûݣûݵľͲ
        if (value.IsNull())
        {
            return false;
        }

        mxData = NF_SHARE_PTR<NFIDataList::TData>(NF_NEW NFIDataList::TData(TDATA_OBJECT));
        mxData->SetObject(NFGUID());

    }

    if (value == mxData->GetObject())
    {
        return false;
    }

    NFCDataList::TData oldValue;
    oldValue = *mxData;

    mxData->SetObject(value);

    OnEventHandler(oldValue , *mxData);

    return true;
}

bool NFCProperty::Changed() const
{
    return GetValue().IsNullValue();
}

const TDATA_TYPE NFCProperty::GetType() const
{
    return eType;
}

const bool NFCProperty::GeUsed() const
{
    if (mxData.get())
    {
        return true;
    }

    return false;
}

std::string NFCProperty::ToString()
{
    std::string strData;
    const TDATA_TYPE eType = GetType();
    switch (eType)
    {
    case TDATA_INT:
        strData = lexical_cast<std::string> (GetInt());
        break;

    case TDATA_FLOAT:
        strData = lexical_cast<std::string> (GetFloat());
        break;

    case TDATA_STRING:
        strData = lexical_cast<std::string> (GetString());
        break;
    case TDATA_OBJECT:
        strData = GetObject().ToString();
        break;
    default:

        strData = NULL_STR;
        break;
    }

    return strData;
}

bool NFCProperty::FromString( const std::string& strData )
{
    const TDATA_TYPE eType = GetType();
    bool bRet = false;
    switch (eType)
    {
    case TDATA_INT:
        {
            NFINT64  nValue = 0;
            bRet = NF_StrTo(strData, nValue);
            SetInt(nValue);
        }
        break;

    case TDATA_FLOAT:
        {
            double  dValue = 0;
            bRet = NF_StrTo(strData, dValue);
            SetFloat(dValue);
        }
        break;

    case TDATA_STRING:
        {
            SetString(strData);
            bRet = true;
        }
        break;
    case TDATA_OBJECT:
        {
            NFGUID xID;

            bRet = xID.FromString(strData);
            SetObject(xID);
        }
        break;
    default:
        break;
    }

    return bRet;
}
<|endoftext|>