<commit_before>#include "twoDInfraredSensor.h"

#include <commonTwoDModel/engine/twoDModelEngineInterface.h>

using namespace trikKitInterpreter::robotModel::twoD::parts;

TwoDInfraredSensor::TwoDInfraredSensor(interpreterBase::robotModel::DeviceInfo const &info
		, interpreterBase::robotModel::PortInfo const &port
		, twoDModel::engine::TwoDModelEngineInterface &engine)
	: twoDModel::robotModel::parts::RangeSensor(info, port, engine)
{
}

void TwoDInfraredSensor::read()
{
	int const sonarDistanceValue = mEngine.readSonarSensor(port());
	int const linearDistance = 100 - sonarDistanceValue * 100 / 255;
	/// @todo: Know how real IR sensor works and model something similar to it.
	emit newData(linearDistance);
}
<commit_msg>IR sensor`s behavior made more realistic<commit_after>#include "twoDInfraredSensor.h"

#include <commonTwoDModel/engine/twoDModelEngineInterface.h>

using namespace trikKitInterpreter::robotModel::twoD::parts;

/// The maximal distance that returned by IR sensor; when the object is closer
/// IR sensor starts to return less values non-lineary.
int const maxDistance = 93;

TwoDInfraredSensor::TwoDInfraredSensor(interpreterBase::robotModel::DeviceInfo const &info
		, interpreterBase::robotModel::PortInfo const &port
		, twoDModel::engine::TwoDModelEngineInterface &engine)
	: twoDModel::robotModel::parts::RangeSensor(info, port, engine)
{
}

void TwoDInfraredSensor::read()
{
	int const sonarDistanceValue = mEngine.readSonarSensor(port());
	int const linearDistance = 100 - (sonarDistanceValue < 100 ? sonarDistanceValue : 100);
	int const spoiledDistance = linearDistance <= maxDistance
			? linearDistance
			// On small distances IR sensor starts to work non-lineary
			: 100 - (linearDistance - maxDistance) * 10;
	emit newData(spoiledDistance);
}
<|endoftext|>


<commit_before>#include "TrigModifyText.h"
#include "Chkdraft.h"
#include "Settings.h"

enum ID {
    TAB_META = 0,
    TAB_PLAYERS,
    TAB_CONDITIONS,
    TAB_ACTIONS,
    TAB_TEXT,

    EDIT_TRIGMODIFYTEXT = ID_FIRST,
    CHECK_AUTOCOMPILE,
    BUTTON_COMPILE,
    BUTTON_COMPILEANDSAVE,
    BUTTON_RELOAD
};

TrigModifyTextWindow::TrigModifyTextWindow() : trigIndex(0), autoCompile(false)
{

}

bool TrigModifyTextWindow::CreateThis(HWND hParent, u32 windowId)
{
    if ( getHandle() != NULL )
    {
        trigIndex = 0;
        return SetParent(hParent);
    }

    RECT rcCli;
    if ( GetWindowRect(hParent, &rcCli) &&
         ClassWindow::RegisterWindowClass(0, NULL, NULL, NULL, NULL, "TrigModifyTextWindow", NULL, false) &&
         ClassWindow::CreateClassWindow(0, "TrigModifyTextWindow", WS_CHILD,
            5, 62, rcCli.right-rcCli.left, rcCli.bottom-rcCli.top,
            hParent, (HMENU)windowId) )
    {
        CreateSubWindows(getHandle());
        return true;
    }
    else
        return false;
}

bool TrigModifyTextWindow::DestroyThis()
{
    return false;
}

void TrigModifyTextWindow::RefreshWindow(u32 trigIndex)
{
    this->trigIndex = trigIndex;
    TextTrigGenerator textTrigs(Settings::useAddressesForMemory, Settings::deathTableStart);
    if ( textTrigs.GenerateTextTrigs(CM, trigIndex, trigText) )
        editText.SetText(trigText.c_str());
    else
        mb(trigIndex, "Failed to generate text triggers.");
}

void TrigModifyTextWindow::DoSize()
{
    RECT rect;
    if ( getClientRect(rect) )
    {
        int width = rect.right-rect.left,
            height = rect.bottom-rect.top;

        buttonReload.MoveTo(rect.right-buttonReload.Width()-10,
            rect.bottom-buttonCompileAndSave.Height()-10);
        buttonCompileAndSave.MoveTo(buttonReload.Left()-buttonCompileAndSave.Width()-5,
            rect.bottom-buttonCompileAndSave.Height()-10);
        buttonCompile.MoveTo(buttonCompileAndSave.Left()-buttonCompile.Width()-5,
            rect.bottom-buttonCompile.Height()-10);
        checkAutoCompile.MoveTo(buttonCompile.Left()-checkAutoCompile.Width()-5,
            rect.bottom-checkAutoCompile.Height()-10);
        editText.SetPos(3, 1, width-5, rect.bottom-buttonCompile.Height()-20);
    }
}

void TrigModifyTextWindow::ParentHidden()
{
    OnLeave();
}

void TrigModifyTextWindow::CreateSubWindows(HWND hWnd)
{
    editText.CreateThis(hWnd, 0, 0, 100, 100, true, EDIT_TRIGMODIFYTEXT);
    checkAutoCompile.CreateThis(hWnd, 0, 0, 85, 20, false, "Auto-compile", CHECK_AUTOCOMPILE);

    buttonReload.CreateThis(hWnd, 0, 0, 75, 23, "Reset", BUTTON_RELOAD);
    buttonCompile.CreateThis(hWnd, 20, 105, 75, 23, "Compile", BUTTON_COMPILE);
    buttonCompileAndSave.CreateThis(hWnd, 75, 105, 93, 23, "Compile && Save", BUTTON_COMPILEANDSAVE);
}

bool TrigModifyTextWindow::unsavedChanges()
{
    std::string newText;
    if ( editText.GetWinText(newText) )
        return trigText.compare(newText) != 0;
    else
        return false;
}

void TrigModifyTextWindow::Compile(bool silent, bool saveAfter)
{
    if ( CM != nullptr )
    {
        std::string newText;
        if ( editText.GetWinText(newText) )
        {
            if ( trigText.compare(newText) != 0 )
            {
                if ( CompileEditText(newText) )
                {
                    trigText = newText;
                    CM->notifyChange(false);
                    CM->refreshScenario();
                    if ( saveAfter )
                    {
                        if ( chkd.maps.SaveCurr(false) )
                            MessageBox(NULL, "Success", "Compiler", MB_OK);
                        else
                            MessageBox(NULL, "Compile Succeeded, Save Failed", "Compiler", MB_OK);
                    }
                    else if ( !silent )
                        MessageBox(NULL, "Success", "Compiler", MB_OK);

                    RefreshWindow(trigIndex);
                }
            }
            else if ( !silent )
                MessageBox(NULL, "No change", NULL, MB_OK);
        }
        else if ( !silent )
            MessageBox(NULL, "Compilation failed, couldn't get edit text.", "Error!", MB_OK);
    }
    else
        Error("No map open!");
}

bool TrigModifyTextWindow::CompileEditText(std::string &newText)
{
    if ( CM != nullptr )
    {
        Trigger* trigger;
        if ( CM->getTrigger(trigger, trigIndex) )
        {
            TextTrigCompiler compiler(Settings::useAddressesForMemory, Settings::deathTableStart); // All data for compilation is gathered on-the-fly, no need to check for updates
            if ( compiler.CompileTrigger(newText, trigger, CM, chkd.scData) )
                return true;
            else
                MessageBox(NULL, "Compilation failed.", "Error!", MB_OK);
        }
        else
            MessageBox(NULL, "Compilation failed, couldn't find selected trigger", "Error!", MB_OK);
    }
    return false;
}

void TrigModifyTextWindow::OnLeave()
{
    if ( autoCompile )
        Compile(true, false);
    else if ( unsavedChanges() )
    {
        int result = MessageBox(NULL, "Compile changes?", "Message", MB_YESNO);
        if ( result == IDYES )
            Compile(false, false);
    }
}

LRESULT TrigModifyTextWindow::Command(HWND hWnd, WPARAM wParam, LPARAM lParam)
{
    switch ( LOWORD(wParam) )
    {
    case CHECK_AUTOCOMPILE:
        if ( HIWORD(wParam) == BN_CLICKED )
            autoCompile = checkAutoCompile.isChecked();
        break;
    case BUTTON_RELOAD:
        if ( HIWORD(wParam) == BN_CLICKED )
            RefreshWindow(trigIndex);
        break;
    case BUTTON_COMPILE:
        if ( HIWORD(wParam) == BN_CLICKED )
            Compile(false, false);
        break;
    case BUTTON_COMPILEANDSAVE:
        if ( HIWORD(wParam) == BN_CLICKED )
            Compile(false, true);
        break;
    }
    return ClassWindow::Command(hWnd, wParam, lParam);
}

LRESULT TrigModifyTextWindow::WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    switch ( msg )
    {
        case WM_SHOWWINDOW:
            if ( wParam == FALSE )
                OnLeave();
            else if ( wParam == TRUE )
                RefreshWindow(trigIndex);
            break;

        case WM_CLOSE:
            OnLeave();
            return ClassWindow::WndProc(hWnd, msg, wParam, lParam);
            break;

        default:
            return ClassWindow::WndProc(hWnd, msg, wParam, lParam);
            break;
    }
    return 0;
}
<commit_msg>Compile and Save Enhancement<commit_after>#include "TrigModifyText.h"
#include "Chkdraft.h"
#include "Settings.h"

enum ID {
    TAB_META = 0,
    TAB_PLAYERS,
    TAB_CONDITIONS,
    TAB_ACTIONS,
    TAB_TEXT,

    EDIT_TRIGMODIFYTEXT = ID_FIRST,
    CHECK_AUTOCOMPILE,
    BUTTON_COMPILE,
    BUTTON_COMPILEANDSAVE,
    BUTTON_RELOAD
};

TrigModifyTextWindow::TrigModifyTextWindow() : trigIndex(0), autoCompile(false)
{

}

bool TrigModifyTextWindow::CreateThis(HWND hParent, u32 windowId)
{
    if ( getHandle() != NULL )
    {
        trigIndex = 0;
        return SetParent(hParent);
    }

    RECT rcCli;
    if ( GetWindowRect(hParent, &rcCli) &&
         ClassWindow::RegisterWindowClass(0, NULL, NULL, NULL, NULL, "TrigModifyTextWindow", NULL, false) &&
         ClassWindow::CreateClassWindow(0, "TrigModifyTextWindow", WS_CHILD,
            5, 62, rcCli.right-rcCli.left, rcCli.bottom-rcCli.top,
            hParent, (HMENU)windowId) )
    {
        CreateSubWindows(getHandle());
        return true;
    }
    else
        return false;
}

bool TrigModifyTextWindow::DestroyThis()
{
    return false;
}

void TrigModifyTextWindow::RefreshWindow(u32 trigIndex)
{
    this->trigIndex = trigIndex;
    TextTrigGenerator textTrigs(Settings::useAddressesForMemory, Settings::deathTableStart);
    if ( textTrigs.GenerateTextTrigs(CM, trigIndex, trigText) )
        editText.SetText(trigText.c_str());
    else
        mb(trigIndex, "Failed to generate text triggers.");
}

void TrigModifyTextWindow::DoSize()
{
    RECT rect;
    if ( getClientRect(rect) )
    {
        int width = rect.right-rect.left,
            height = rect.bottom-rect.top;

        buttonReload.MoveTo(rect.right-buttonReload.Width()-10,
            rect.bottom-buttonCompileAndSave.Height()-10);
        buttonCompileAndSave.MoveTo(buttonReload.Left()-buttonCompileAndSave.Width()-5,
            rect.bottom-buttonCompileAndSave.Height()-10);
        buttonCompile.MoveTo(buttonCompileAndSave.Left()-buttonCompile.Width()-5,
            rect.bottom-buttonCompile.Height()-10);
        checkAutoCompile.MoveTo(buttonCompile.Left()-checkAutoCompile.Width()-5,
            rect.bottom-checkAutoCompile.Height()-10);
        editText.SetPos(3, 1, width-5, rect.bottom-buttonCompile.Height()-20);
    }
}

void TrigModifyTextWindow::ParentHidden()
{
    OnLeave();
}

void TrigModifyTextWindow::CreateSubWindows(HWND hWnd)
{
    editText.CreateThis(hWnd, 0, 0, 100, 100, true, EDIT_TRIGMODIFYTEXT);
    checkAutoCompile.CreateThis(hWnd, 0, 0, 85, 20, false, "Auto-compile", CHECK_AUTOCOMPILE);

    buttonReload.CreateThis(hWnd, 0, 0, 75, 23, "Reset", BUTTON_RELOAD);
    buttonCompile.CreateThis(hWnd, 20, 105, 75, 23, "Compile", BUTTON_COMPILE);
    buttonCompileAndSave.CreateThis(hWnd, 75, 105, 93, 23, "Compile && Save", BUTTON_COMPILEANDSAVE);
}

bool TrigModifyTextWindow::unsavedChanges()
{
    std::string newText;
    if ( editText.GetWinText(newText) )
        return trigText.compare(newText) != 0;
    else
        return false;
}

void TrigModifyTextWindow::Compile(bool silent, bool saveAfter)
{
    if ( CM != nullptr )
    {
        std::string newText;
        if ( editText.GetWinText(newText) )
        {
            if ( trigText.compare(newText) != 0 )
            {
                if ( CompileEditText(newText) )
                {
                    trigText = newText;
                    CM->notifyChange(false);
                    CM->refreshScenario();
                    if ( saveAfter )
                    {
                        if ( chkd.maps.SaveCurr(false) )
                            MessageBox(NULL, "Success", "Compiler", MB_OK);
                        else
                            MessageBox(NULL, "Compile Succeeded, Save Failed", "Compiler", MB_OK);
                    }
                    else if ( !silent )
                        MessageBox(NULL, "Success", "Compiler", MB_OK);

                    RefreshWindow(trigIndex);
                }
            }
            else if ( !silent && saveAfter )
            {
                if ( chkd.maps.SaveCurr(false) )
                    MessageBox(NULL, "Success", "Compiler", MB_OK);
                else
                    MessageBox(NULL, "Compile Succeeded, Save Failed", "Compiler", MB_OK);
            }
            else if ( !silent )
                MessageBox(NULL, "No change", NULL, MB_OK);
        }
        else if ( !silent )
            MessageBox(NULL, "Compilation failed, couldn't get edit text.", "Error!", MB_OK);
    }
    else
        Error("No map open!");
}

bool TrigModifyTextWindow::CompileEditText(std::string &newText)
{
    if ( CM != nullptr )
    {
        Trigger* trigger;
        if ( CM->getTrigger(trigger, trigIndex) )
        {
            TextTrigCompiler compiler(Settings::useAddressesForMemory, Settings::deathTableStart); // All data for compilation is gathered on-the-fly, no need to check for updates
            if ( compiler.CompileTrigger(newText, trigger, CM, chkd.scData) )
                return true;
            else
                MessageBox(NULL, "Compilation failed.", "Error!", MB_OK);
        }
        else
            MessageBox(NULL, "Compilation failed, couldn't find selected trigger", "Error!", MB_OK);
    }
    return false;
}

void TrigModifyTextWindow::OnLeave()
{
    if ( autoCompile )
        Compile(true, false);
    else if ( unsavedChanges() )
    {
        int result = MessageBox(NULL, "Compile changes?", "Message", MB_YESNO);
        if ( result == IDYES )
            Compile(false, false);
    }
}

LRESULT TrigModifyTextWindow::Command(HWND hWnd, WPARAM wParam, LPARAM lParam)
{
    switch ( LOWORD(wParam) )
    {
    case CHECK_AUTOCOMPILE:
        if ( HIWORD(wParam) == BN_CLICKED )
            autoCompile = checkAutoCompile.isChecked();
        break;
    case BUTTON_RELOAD:
        if ( HIWORD(wParam) == BN_CLICKED )
            RefreshWindow(trigIndex);
        break;
    case BUTTON_COMPILE:
        if ( HIWORD(wParam) == BN_CLICKED )
            Compile(false, false);
        break;
    case BUTTON_COMPILEANDSAVE:
        if ( HIWORD(wParam) == BN_CLICKED )
            Compile(false, true);
        break;
    }
    return ClassWindow::Command(hWnd, wParam, lParam);
}

LRESULT TrigModifyTextWindow::WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    switch ( msg )
    {
        case WM_SHOWWINDOW:
            if ( wParam == FALSE )
                OnLeave();
            else if ( wParam == TRUE )
                RefreshWindow(trigIndex);
            break;

        case WM_CLOSE:
            OnLeave();
            return ClassWindow::WndProc(hWnd, msg, wParam, lParam);
            break;

        default:
            return ClassWindow::WndProc(hWnd, msg, wParam, lParam);
            break;
    }
    return 0;
}
<|endoftext|>


<commit_before>
#include "cfgmap.h"
#include <stdio.h>
#include <iostream>

using namespace std;
//******************************************************************************

void EscapeStr(const string & input, string & output)
{
    string::const_iterator ch;
    for(ch = input.begin(); ch != input.end(); ++ch)
    {
        if(isprint(*ch) && *ch != '\\')
        {
            output += *ch;
        }
        else
        {
            char bfr[16];
            snprintf(bfr, 16, "\\%04X", (int)*ch);
            output += bfr;
        }
    }
} // EscapeStr()

void UnescapeStr(const string & input, string & output)
{
    string::const_iterator ch;
    ch = input.begin();
    while(ch != input.end())
    {
        if(*ch == '\\')
        {
            ++ch;
            char bfr[16];
            int j = 0;
            while(j < 4 && ch != input.end())
                bfr[j++] = *(ch++);
            bfr[j] = '\0';
            output += (char)strtol(bfr, NULL, 16);
        }
        else
        {
            output += *(ch++);
        }
    }
} // UnescapeStr()

void ReadParams(const std::string & path, std::map<std::string, std::string> & params)
{
    FILE * fin = fopen(path.c_str(), "rb");
    int ch = fgetc(fin);
    while(ch != EOF)
    {
        string key;
        while(ch != EOF && ch != ':') {
            key += (char)ch;
            ch = fgetc(fin);
        }

        if(ch == ':')
            ch = fgetc(fin);

        string encValue;
        while(ch != EOF && ch != '\n') {
            encValue += (char)ch;
            ch = fgetc(fin);
        }
        string value;
        UnescapeStr(encValue, value);
        params[key] = value;

        if(ch == '\n')
            ch = fgetc(fin);
    }
    fclose(fin);
} // ReadParams()

void WriteParams(const std::string & path, const std::map<std::string, std::string> & params)
{
    FILE * fout = fopen(path.c_str(), "wb");
    std::map<std::string, std::string>::const_iterator pitr;
    for(pitr = params.begin(); pitr != params.end(); ++pitr)
    {
        string escaped;
        EscapeStr(pitr->second, escaped);
        // Don't try to merge these. c_str() uses a static buffer.
        fprintf(fout, "%s:", pitr->first.c_str());
        fprintf(fout, "%s\n", escaped.c_str());
    }
    fclose(fout);
} // WriteParams()

//******************************************************************************

// g++ -DTEST_CFGMAP cfgmap.cpp -o test_cfgmap
#ifdef TEST_CFGMAP

void TestValue(const std::string & key, const std::string & value, const std::map<std::string, std::string> & params)
{
    std::map<std::string, std::string>::const_iterator pitr = params.find(key);
    if(pitr == params.end()) {
        cerr << "Test failed, key \"" << key << "\" not found in params" << endl;
        exit(EXIT_FAILURE);
    }
    if(pitr->second != value) {
        cerr << "Test failed, expected value \"" << value << "\", found \"" << pitr->second << "\"" << endl;
        exit(EXIT_FAILURE);
    }
}

int main(int argc, char * argv[])
{
    std::map<std::string, std::string> params;
    params["foo"] = "bar";
    params["Sernum"] = "51646135FA";
    params["addr"] = "192.168.3.21";
    params["complexString"] = "\\1, 2, 3,\n\\4, 5, 6";
    WriteParams("test.cfg", params);

    std::map<std::string, std::string> rparams;
    ReadParams("test.cfg", rparams);

    std::map<std::string, std::string>::const_iterator pitr;
    for(pitr = params.begin(); pitr != params.end(); ++pitr)
        TestValue(pitr->first, pitr->second, rparams);

    cerr << "Tests passed" << endl;

    return EXIT_SUCCESS;
}
#endif

<commit_msg>A couple additional tests and better handling of bad input for config map<commit_after>
#include "cfgmap.h"
#include <stdio.h>
#include <iostream>

using namespace std;
//******************************************************************************

void EscapeStr(const string & input, string & output)
{
    string::const_iterator ch;
    for(ch = input.begin(); ch != input.end(); ++ch)
    {
        if(isprint(*ch) && *ch != '\\')
        {
            output += *ch;
        }
        else
        {
            char bfr[16];
            snprintf(bfr, 16, "\\%04X", (int)*ch);
            output += bfr;
        }
    }
} // EscapeStr()

void UnescapeStr(const string & input, string & output)
{
    string::const_iterator ch;
    ch = input.begin();
    while(ch != input.end())
    {
        if(*ch == '\\')
        {
            ++ch;
            char bfr[16];
            int j = 0;
            while(j < 4 && ch != input.end())
                bfr[j++] = *(ch++);
            bfr[j] = '\0';
            output += (char)strtol(bfr, NULL, 16);
        }
        else
        {
            output += *(ch++);
        }
    }
} // UnescapeStr()

void ReadParams(const std::string & path, std::map<std::string, std::string> & params)
{
    FILE * fin = fopen(path.c_str(), "rb");
    int ch = fgetc(fin);
    while(ch != EOF)
    {
        string key;
        while(ch != EOF && ch != ':') {
            key += (char)ch;
            ch = fgetc(fin);
        }

        if(ch == ':')
            ch = fgetc(fin);
        else
            break;

        string encValue;
        while(ch != EOF && ch != '\n') {
            encValue += (char)ch;
            ch = fgetc(fin);
        }
        string value;
        UnescapeStr(encValue, value);
        params[key] = value;

        if(ch == '\n')
            ch = fgetc(fin);
    }
    fclose(fin);
} // ReadParams()

void WriteParams(const std::string & path, const std::map<std::string, std::string> & params)
{
    FILE * fout = fopen(path.c_str(), "wb");
    std::map<std::string, std::string>::const_iterator pitr;
    for(pitr = params.begin(); pitr != params.end(); ++pitr)
    {
        string escaped;
        EscapeStr(pitr->second, escaped);
        // Don't try to merge these. c_str() uses a static buffer.
        fprintf(fout, "%s:", pitr->first.c_str());
        fprintf(fout, "%s\n", escaped.c_str());
    }
    fclose(fout);
} // WriteParams()

//******************************************************************************

// g++ -DTEST_CFGMAP cfgmap.cpp -o test_cfgmap
#ifdef TEST_CFGMAP

void TestValue(const std::string & key, const std::string & value, const std::map<std::string, std::string> & params)
{
    std::map<std::string, std::string>::const_iterator pitr = params.find(key);
    if(pitr == params.end()) {
        cerr << "Test failed, key \"" << key << "\" not found in params" << endl;
        exit(EXIT_FAILURE);
    }
    if(pitr->second != value) {
        cerr << "Test failed, expected value \"" << value << "\", found \"" << pitr->second << "\"" << endl;
        exit(EXIT_FAILURE);
    }
}

int main(int argc, char * argv[])
{
    std::map<std::string, std::string> params;
    params["foo"] = "bar";
    params[""] = "keyless";
    params["valueless"] = "";
    params["Sernum"] = "5164:6135:FA";
    params["addr"] = "192.168.3.21";
    params["complexString"] = "\\1, 2, 3,\n\\4, 5, 6";
    WriteParams("test.cfg", params);

    std::map<std::string, std::string> rparams;
    ReadParams("test.cfg", rparams);

    std::map<std::string, std::string>::const_iterator pitr;
    for(pitr = params.begin(); pitr != params.end(); ++pitr)
        TestValue(pitr->first, pitr->second, rparams);

    cerr << "Tests passed" << endl;

    return EXIT_SUCCESS;
}
#endif

<|endoftext|>


<commit_before>#include "p2Defs.h"
#include "p2Log.h"
#include "j1App.h"
#include "j1Input.h"
#include "j1Textures.h"
#include "j1Audio.h"
#include "j1Render.h"
#include "j1Window.h"
#include "j1Map.h"
#include "j1Colliders.h"
#include "j1Pathfinding.h"
#include "j1Menu.h"
#include "j1Scene.h"
#include "j1Entities.h"
#include "Player.h"
#include "j1Gui.h"
#include "UIButton.h"

j1Scene::j1Scene() : j1Module()
{
	name.create("scene");
}

// Destructor
j1Scene::~j1Scene()
{}

// Called before render is available
bool j1Scene::Awake(pugi::xml_node& config)
{
	LOG("Loading Scene");
	bool ret = true;
	Map_1 = true;
	Map_2 = false;

	return ret;
}

// Called before the first frame
bool j1Scene::Start()
{
	if (!App->menu->active)
	{
		if (Map_1)
		{
			App->map->Load("Map_1.tmx");
			App->audio->PlayMusic("audio/music/map1_music.ogg");
			App->map->Draw_Colliders();
			App->colliders->AddCollider({ 25400,0,50,380 }, COLLIDER_WIN, this);

			//enemies
			App->entities->AddEnemy(ZOMBIE, 1300, 600);
			App->entities->AddEnemy(ZOMBIE, 2500, 600);
			App->entities->AddEnemy(ZOMBIE, 19369, 827);
			App->entities->AddEnemy(ZOMBIE, 7000, 600);
			App->entities->AddEnemy(ZOMBIE, 9812, 668);
			App->entities->AddEnemy(PLANE, 2000, 100);

			App->colliders->AddCollider({ 11104,636,608,64 }, COLLIDER_DEATH);
			App->colliders->AddCollider({ 22112,829,288,32 }, COLLIDER_DEATH);

			//gui
			button_play = { 400, 972, 183, 191 };
			App->gui->AddElementButton(1000, 100, BUTTON, &button_play, this);
			display_score = { 173, 3149, 397, 133 };
			App->gui->AddElementImage(250, 100, TEXTBOX, &display_score, this);
		}

		if (Map_2)
		{
			App->map->Load("Map_2.tmx");
			App->audio->PlayMusic("audio/music/map1_music.ogg");
			App->map->Draw_Colliders();

			App->colliders->AddCollider({ 25400,0,50,310 }, COLLIDER_WIN2, this);
			App->colliders->AddCollider({ 18923,0,50,310 }, COLLIDER_WIN2, this);
			App->colliders->AddCollider({ 21087,828,320,32 }, COLLIDER_DEATH);

			App->entities->AddEnemy(ZOMBIE, 19461, 825);
			App->entities->AddEnemy(ZOMBIE, 18467, 825);
			App->entities->AddEnemy(ZOMBIE, 4949, 828);

			App->entities->AddEnemy(PLANE, 1500, 100);

			display_score = { 173, 3149, 397, 133 };
			App->gui->AddElementImage(250, 100, TEXTBOX, &display_score, this);
		}
	}

	return true;
}

// Called each loop iteration
bool j1Scene::PreUpdate()
{
	BROFILER_CATEGORY("PreUpdate_Scene1 ", Profiler::Color::Orchid)
	return true;
}

// Called each loop iteration
bool j1Scene::Update(float dt)
{
	BROFILER_CATEGORY("Update_Scene1 ", Profiler::Color::MediumOrchid)

	//Camera Movement--------------------------------------
	int map_height = App->map->data.height * App->map->data.tile_height;
	int map_width = App->map->data.width * App->map->data.tile_width;
	int win_height = App->entities->player->win_height;
	int win_width = App->entities->player->win_width;
	int win_position_y = App->render->camera.y*-1;
	int limit_y = map_height - win_height;
	int limit_x = map_width - win_width / 2;

	if(App->input->GetKey(SDL_SCANCODE_F5) == KEY_DOWN)
		App->SaveGame();

	if(App->input->GetKey(SDL_SCANCODE_F6) == KEY_DOWN)
		App->LoadGame();

	if (App->input->GetKey(SDL_SCANCODE_F1) == KEY_DOWN)
	{
		if (Map_1)
		{
			StartCurrentScene();
		}
		else
		{
			ChangeScene(60, 215);
		}
	}

	if (App->input->GetKey(SDL_SCANCODE_F2) == KEY_DOWN)
		StartCurrentScene();

	if (App->input->GetKey(SDL_SCANCODE_F7) == KEY_DOWN)
		ChangeScene(60,215);

	if (App->input->GetKey(SDL_SCANCODE_F8) == KEY_DOWN)
	{
		App->pathfinding->ResetPath();
		iPoint PlayerPosition = { (int)App->entities->player->original_pos.x, (int)App->entities->player->position.y+50 };

		if (App->pathfinding->CreatePath({ 0,0 }, PlayerPosition) != -1)
		{
			App->pathfinding->Path(PlayerPosition.x, PlayerPosition.y, path_test);
		}
		LOG("Path created");
	}

	if (App->input->GetKey(SDL_SCANCODE_F11) == KEY_DOWN)
	{
		if (App->Cap_on)
		{
			App->Cap_on = false;
		}
		else
		{
			App->Cap_on = true;
		}
	}

	if (App->input->GetKey(SDL_SCANCODE_P) == KEY_DOWN)
	{
		if (App->GamePaused)
		{
			App->GamePaused = false;
		}
		else
		{
			App->GamePaused = true;
		}
	}

	if (App->entities->player->original_pos.x > win_width / 2 && App->entities->player->original_pos.x <= limit_x)
	{
		App->render->camera.x = App->entities->player->win_width / 2 - App->entities->player->original_pos.x;
	}

	if (!App->win->fullscreen_window && App->entities->player->original_pos.y > win_height / 2 && win_position_y+win_height <map_height)
	{
		if (App->entities->player->original_pos.y + win_height / 2 < map_height)
		{
			App->render->camera.y = -App->entities->player->original_pos.y + win_height / 2;
		}
	}

	App->map->Draw();
	App->pathfinding->DrawPath(path_test);

	p2SString title("%s",App->GetTitle());

	//gui
	score++;
	score_string.create("%i", score);
	Score=App->gui->AddElementText(260, 65, TEXT, this, score_string.GetString());

	return true;
}

// Called each loop iteration
bool j1Scene::PostUpdate()
{
	bool ret = true;
	BROFILER_CATEGORY("PosUpdate_Scene1 ", Profiler::Color::DarkOrchid)
	if(App->input->GetKey(SDL_SCANCODE_ESCAPE) == KEY_DOWN)
		ret = false;

	return ret;
}

// Called before quitting
bool j1Scene::CleanUp()
{
	LOG("Freeing scene");

	App->entities->CleanUp();
	App->colliders->CleanUp();
	App->map->CleanUp();
	App->pathfinding->CleanUp();
	App->gui->CleanUp();
	App->tex->CleanUp();

	return true;
}

//go to the begining
void j1Scene::StartCurrentScene()
{
	App->entities->player->original_pos.x = 60;
	App->entities->player->original_pos.y = 215;
	App->render->camera.x = 0;
	App->render->camera.y = 0;
}

//Change to scene 2
void j1Scene::ChangeScene(int x, int y)
{
	CleanUp();

	if (Map_1 && App->entities->player->Curr_map==1)
	{
		Map_1 = false;
		Map_2 = true;

		App->scene->Start();
		App->pathfinding->Start();
		App->entities->player->original_pos.y = y;
		App->entities->player->original_pos.x = x;
		App->render->camera.x = 0;
		App->render->camera.y = 0;
		App->entities->player->Curr_map = 2;
		App->entities->Start();
		App->gui->Start();
	}
	else
	{
		Map_1 = true;
		Map_2 = false;

		App->scene->Start();
		App->pathfinding->Start();
		App->entities->player->original_pos.y = y;
		App->entities->player->original_pos.x = x;
		App->render->camera.x = 0;
		App->render->camera.y = 0;
		App->entities->player->Curr_map = 1;
		App->entities->Start();
		App->gui->Start();
	}

}
<commit_msg>score commented<commit_after>#include "p2Defs.h"
#include "p2Log.h"
#include "j1App.h"
#include "j1Input.h"
#include "j1Textures.h"
#include "j1Audio.h"
#include "j1Render.h"
#include "j1Window.h"
#include "j1Map.h"
#include "j1Colliders.h"
#include "j1Pathfinding.h"
#include "j1Menu.h"
#include "j1Scene.h"
#include "j1Entities.h"
#include "Player.h"
#include "j1Gui.h"
#include "UIButton.h"

j1Scene::j1Scene() : j1Module()
{
	name.create("scene");
}

// Destructor
j1Scene::~j1Scene()
{}

// Called before render is available
bool j1Scene::Awake(pugi::xml_node& config)
{
	LOG("Loading Scene");
	bool ret = true;
	Map_1 = true;
	Map_2 = false;

	return ret;
}

// Called before the first frame
bool j1Scene::Start()
{
	if (!App->menu->active)
	{
		if (Map_1)
		{
			App->map->Load("Map_1.tmx");
			App->audio->PlayMusic("audio/music/map1_music.ogg");
			App->map->Draw_Colliders();
			App->colliders->AddCollider({ 25400,0,50,380 }, COLLIDER_WIN, this);

			//enemies
			App->entities->AddEnemy(ZOMBIE, 1300, 600);
			App->entities->AddEnemy(ZOMBIE, 2500, 600);
			App->entities->AddEnemy(ZOMBIE, 19369, 827);
			App->entities->AddEnemy(ZOMBIE, 7000, 600);
			App->entities->AddEnemy(ZOMBIE, 9812, 668);
			App->entities->AddEnemy(PLANE, 2000, 100);

			App->colliders->AddCollider({ 11104,636,608,64 }, COLLIDER_DEATH);
			App->colliders->AddCollider({ 22112,829,288,32 }, COLLIDER_DEATH);

			//gui
			button_play = { 400, 972, 183, 191 };
			App->gui->AddElementButton(1000, 100, BUTTON, &button_play, this);
			display_score = { 173, 3149, 397, 133 };
			App->gui->AddElementImage(250, 100, TEXTBOX, &display_score, this);
		}

		if (Map_2)
		{
			App->map->Load("Map_2.tmx");
			App->audio->PlayMusic("audio/music/map1_music.ogg");
			App->map->Draw_Colliders();

			App->colliders->AddCollider({ 25400,0,50,310 }, COLLIDER_WIN2, this);
			App->colliders->AddCollider({ 18923,0,50,310 }, COLLIDER_WIN2, this);
			App->colliders->AddCollider({ 21087,828,320,32 }, COLLIDER_DEATH);

			App->entities->AddEnemy(ZOMBIE, 19461, 825);
			App->entities->AddEnemy(ZOMBIE, 18467, 825);
			App->entities->AddEnemy(ZOMBIE, 4949, 828);

			App->entities->AddEnemy(PLANE, 1500, 100);

			display_score = { 173, 3149, 397, 133 };
			App->gui->AddElementImage(250, 100, TEXTBOX, &display_score, this);
		}
	}

	return true;
}

// Called each loop iteration
bool j1Scene::PreUpdate()
{
	BROFILER_CATEGORY("PreUpdate_Scene1 ", Profiler::Color::Orchid)
	return true;
}

// Called each loop iteration
bool j1Scene::Update(float dt)
{
	BROFILER_CATEGORY("Update_Scene1 ", Profiler::Color::MediumOrchid)

	//Camera Movement--------------------------------------
	int map_height = App->map->data.height * App->map->data.tile_height;
	int map_width = App->map->data.width * App->map->data.tile_width;
	int win_height = App->entities->player->win_height;
	int win_width = App->entities->player->win_width;
	int win_position_y = App->render->camera.y*-1;
	int limit_y = map_height - win_height;
	int limit_x = map_width - win_width / 2;

	if(App->input->GetKey(SDL_SCANCODE_F5) == KEY_DOWN)
		App->SaveGame();

	if(App->input->GetKey(SDL_SCANCODE_F6) == KEY_DOWN)
		App->LoadGame();

	if (App->input->GetKey(SDL_SCANCODE_F1) == KEY_DOWN)
	{
		if (Map_1)
		{
			StartCurrentScene();
		}
		else
		{
			ChangeScene(60, 215);
		}
	}

	if (App->input->GetKey(SDL_SCANCODE_F2) == KEY_DOWN)
		StartCurrentScene();

	if (App->input->GetKey(SDL_SCANCODE_F7) == KEY_DOWN)
		ChangeScene(60,215);

	if (App->input->GetKey(SDL_SCANCODE_F8) == KEY_DOWN)
	{
		App->pathfinding->ResetPath();
		iPoint PlayerPosition = { (int)App->entities->player->original_pos.x, (int)App->entities->player->position.y+50 };

		if (App->pathfinding->CreatePath({ 0,0 }, PlayerPosition) != -1)
		{
			App->pathfinding->Path(PlayerPosition.x, PlayerPosition.y, path_test);
		}
		LOG("Path created");
	}

	if (App->input->GetKey(SDL_SCANCODE_F11) == KEY_DOWN)
	{
		if (App->Cap_on)
		{
			App->Cap_on = false;
		}
		else
		{
			App->Cap_on = true;
		}
	}

	if (App->input->GetKey(SDL_SCANCODE_P) == KEY_DOWN)
	{
		if (App->GamePaused)
		{
			App->GamePaused = false;
		}
		else
		{
			App->GamePaused = true;
		}
	}

	if (App->entities->player->original_pos.x > win_width / 2 && App->entities->player->original_pos.x <= limit_x)
	{
		App->render->camera.x = App->entities->player->win_width / 2 - App->entities->player->original_pos.x;
	}

	if (!App->win->fullscreen_window && App->entities->player->original_pos.y > win_height / 2 && win_position_y+win_height <map_height)
	{
		if (App->entities->player->original_pos.y + win_height / 2 < map_height)
		{
			App->render->camera.y = -App->entities->player->original_pos.y + win_height / 2;
		}
	}

	App->map->Draw();
	App->pathfinding->DrawPath(path_test);

	p2SString title("%s",App->GetTitle());

	//gui
	//score++;
	score_string.create("%i", score);
	Score=App->gui->AddElementText(260, 65, TEXT, this, score_string.GetString());

	return true;
}

// Called each loop iteration
bool j1Scene::PostUpdate()
{
	bool ret = true;
	BROFILER_CATEGORY("PosUpdate_Scene1 ", Profiler::Color::DarkOrchid)
	if(App->input->GetKey(SDL_SCANCODE_ESCAPE) == KEY_DOWN)
		ret = false;

	return ret;
}

// Called before quitting
bool j1Scene::CleanUp()
{
	LOG("Freeing scene");

	App->entities->CleanUp();
	App->colliders->CleanUp();
	App->map->CleanUp();
	App->pathfinding->CleanUp();
	App->gui->CleanUp();
	App->tex->CleanUp();

	return true;
}

//go to the begining
void j1Scene::StartCurrentScene()
{
	App->entities->player->original_pos.x = 60;
	App->entities->player->original_pos.y = 215;
	App->render->camera.x = 0;
	App->render->camera.y = 0;
}

//Change to scene 2
void j1Scene::ChangeScene(int x, int y)
{
	CleanUp();

	if (Map_1 && App->entities->player->Curr_map==1)
	{
		Map_1 = false;
		Map_2 = true;

		App->scene->Start();
		App->pathfinding->Start();
		App->entities->player->original_pos.y = y;
		App->entities->player->original_pos.x = x;
		App->render->camera.x = 0;
		App->render->camera.y = 0;
		App->entities->player->Curr_map = 2;
		App->entities->Start();
		App->gui->Start();
	}
	else
	{
		Map_1 = true;
		Map_2 = false;

		App->scene->Start();
		App->pathfinding->Start();
		App->entities->player->original_pos.y = y;
		App->entities->player->original_pos.x = x;
		App->render->camera.x = 0;
		App->render->camera.y = 0;
		App->entities->player->Curr_map = 1;
		App->entities->Start();
		App->gui->Start();
	}

}
<|endoftext|>


<commit_before>// Time:  ctor:   O(n),
//        update: O(logn),
//        query:  O(logn)
// Space: O(n)

// Segment Tree solution.
class NumArray {
public:
    NumArray(vector<int> &nums) : nums_ref_(nums) {
        root_ = buildHelper(nums, 0, nums.size() - 1);
    }

    void update(int i, int val) {
        if (nums_ref_[i] != val) {
            nums_ref_[i] = val;
            updateHelper(root_, i, val);
        }
    }

    int sumRange(int i, int j) {
        return sumRangeHelper(root_, i, j);
    }

private:
    vector<int>& nums_ref_;

    class SegmentTreeNode {
    public:
        int start, end;
        int sum;
        SegmentTreeNode *left, *right;
        SegmentTreeNode(int i, int j, int s) :
            start(i), end(j), sum(s),
            left(nullptr), right(nullptr) {
        }
    };

    SegmentTreeNode *root_;

    // Build segment tree.
    SegmentTreeNode *buildHelper(const vector<int>& nums, int start, int end) {
        if (start > end) {
            return nullptr;
        }

        // The root's start and end is given by build method.
        SegmentTreeNode *root = new SegmentTreeNode(start, end, 0);

        // If start equals to end, there will be no children for this node.
        if (start == end) {
            root->sum = nums[start];
            return root;
        }

        // Left child: start=numsleft, end=(numsleft + numsright) / 2.
        root->left = buildHelper(nums, start, (start + end) / 2);

        // Right child: start=(numsleft + numsright) / 2 + 1, end=numsright.
        root->right = buildHelper(nums, (start + end) / 2 + 1, end);

        // Update sum.
        root->sum = (root->left != nullptr ? root->left->sum : 0) +
                    (root->right != nullptr ? root->right->sum : 0);
        return root;
    }

    void updateHelper(SegmentTreeNode *root, int i, int val) {
        // Out of range.
        if (root == nullptr || root->start > i || root->end < i) {
            return;
        }

        // Change the node's value with [i] to the new given value.
        if (root->start == i && root->end == i) {
            root->sum = val;
            return;
        }

        updateHelper(root->left, i, val);
        updateHelper(root->right, i, val);

        // Update sum.
        root->sum =  (root->left != nullptr ? root->left->sum : 0) +
                     (root->right != nullptr ? root->right->sum : 0);
    }

    int sumRangeHelper(SegmentTreeNode *root, int start, int end) {
        // Out of range.
        if (root == nullptr || root->start > end || root->end < start) {
            return 0;
        }

        // Current segment is totally within range [start, end]
        if (root->start >= start && root->end <= end) {
            return root->sum;
        }

        return sumRangeHelper(root->left, start, end) +
               sumRangeHelper(root->right, start, end);
    }
};

// Time:  ctor:   O(nlogn),
//        update: O(logn),
//        query:  O(logn)
// Space: O(n)
// Binary Indexed Tree (BIT) solution.
class NumArray2 {
public:
    NumArray(vector<int> &nums) :
        nums_(nums), n_(nums.size()) {

        bit_ = vector<int>(n_ + 1);
        for (int i = 0; i < n_; ++i) {
            add(i, nums_[i]);
        }
    }

    void update(int i, int val) {
        if (val - nums_[i]) {
            add(i, val - nums_[i]);
            nums_[i] = val;
        }
    }

    int sumRange(int i, int j) {
        int sum = sumRegion_bit(j);
        if (i > 0) {
            sum -= sumRegion_bit(i - 1);
        }
        return sum;
    }

private:
    vector<int> &nums_;
    vector<int> bit_;
    int n_;

    int sumRegion_bit(int i) {
        ++i;
        int sum = 0;
        for (; i > 0; i -= lower_bit(i)) {
            sum += bit_[i];
        }
        return sum;
    }

    void add(int i, int val) {
        ++i;
        for (; i <= n_; i += lower_bit(i)) {
            bit_[i] += val;
        }
    }

    int lower_bit(int i) {
        return i & -i;
    }
};

// Your NumArray object will be instantiated and called as such:
// NumArray numArray(nums);
// numArray.sumRange(0, 1);
// numArray.update(1, 10);
// numArray.sumRange(1, 2);
<commit_msg>Update range-sum-query-mutable.cpp<commit_after>// Time:  ctor:   O(n),
//        update: O(logn),
//        query:  O(logn)
// Space: O(n)

// Segment Tree solution.
class NumArray {
public:
    NumArray(vector<int> &nums) : nums_(nums) {
        root_ = buildHelper(nums, 0, nums.size() - 1);
    }

    void update(int i, int val) {
        if (nums_[i] != val) {
            nums_[i] = val;
            updateHelper(root_, i, val);
        }
    }

    int sumRange(int i, int j) {
        return sumRangeHelper(root_, i, j);
    }

private:
    vector<int>& nums_;

    class SegmentTreeNode {
    public:
        int start, end;
        int sum;
        SegmentTreeNode *left, *right;
        SegmentTreeNode(int i, int j, int s) :
            start(i), end(j), sum(s),
            left(nullptr), right(nullptr) {
        }
    };

    SegmentTreeNode *root_;

    // Build segment tree.
    SegmentTreeNode *buildHelper(const vector<int>& nums, int start, int end) {
        if (start > end) {
            return nullptr;
        }

        // The root's start and end is given by build method.
        SegmentTreeNode *root = new SegmentTreeNode(start, end, 0);

        // If start equals to end, there will be no children for this node.
        if (start == end) {
            root->sum = nums[start];
            return root;
        }

        // Left child: start=numsleft, end=(numsleft + numsright) / 2.
        root->left = buildHelper(nums, start, (start + end) / 2);

        // Right child: start=(numsleft + numsright) / 2 + 1, end=numsright.
        root->right = buildHelper(nums, (start + end) / 2 + 1, end);

        // Update sum.
        root->sum = (root->left != nullptr ? root->left->sum : 0) +
                    (root->right != nullptr ? root->right->sum : 0);
        return root;
    }

    void updateHelper(SegmentTreeNode *root, int i, int val) {
        // Out of range.
        if (root == nullptr || root->start > i || root->end < i) {
            return;
        }

        // Change the node's value with [i] to the new given value.
        if (root->start == i && root->end == i) {
            root->sum = val;
            return;
        }

        updateHelper(root->left, i, val);
        updateHelper(root->right, i, val);

        // Update sum.
        root->sum =  (root->left != nullptr ? root->left->sum : 0) +
                     (root->right != nullptr ? root->right->sum : 0);
    }

    int sumRangeHelper(SegmentTreeNode *root, int start, int end) {
        // Out of range.
        if (root == nullptr || root->start > end || root->end < start) {
            return 0;
        }

        // Current segment is totally within range [start, end]
        if (root->start >= start && root->end <= end) {
            return root->sum;
        }

        return sumRangeHelper(root->left, start, end) +
               sumRangeHelper(root->right, start, end);
    }
};

// Time:  ctor:   O(nlogn),
//        update: O(logn),
//        query:  O(logn)
// Space: O(n)
// Binary Indexed Tree (BIT) solution.
class NumArray2 {
public:
    NumArray(vector<int> &nums) :
        nums_(nums), n_(nums.size()) {

        bit_ = vector<int>(n_ + 1);
        for (int i = 0; i < n_; ++i) {
            add(i, nums_[i]);
        }
    }

    void update(int i, int val) {
        if (val - nums_[i]) {
            add(i, val - nums_[i]);
            nums_[i] = val;
        }
    }

    int sumRange(int i, int j) {
        int sum = sumRegion_bit(j);
        if (i > 0) {
            sum -= sumRegion_bit(i - 1);
        }
        return sum;
    }

private:
    vector<int> &nums_;
    vector<int> bit_;
    int n_;

    int sumRegion_bit(int i) {
        ++i;
        int sum = 0;
        for (; i > 0; i -= lower_bit(i)) {
            sum += bit_[i];
        }
        return sum;
    }

    void add(int i, int val) {
        ++i;
        for (; i <= n_; i += lower_bit(i)) {
            bit_[i] += val;
        }
    }

    int lower_bit(int i) {
        return i & -i;
    }
};

// Your NumArray object will be instantiated and called as such:
// NumArray numArray(nums);
// numArray.sumRange(0, 1);
// numArray.update(1, 10);
// numArray.sumRange(1, 2);
<|endoftext|>


<commit_before>
/*=========================================================================

Program:   ORFEO Toolbox
Language:  C++
Date:      $Date$
Version:   $Revision$

Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
See OTBCopyright.txt for details.

This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE.  See the above copyright notices for more information.

=========================================================================*/
#include "otbImageViewerManagerController.h"
#include "otbMsgReporter.h"

namespace otb
{

ImageViewerManagerController
::ImageViewerManagerController()
{

/** NewVisu */
  // Build a "visu"controller
  m_VisuController = VisuControllerType::New();
  m_PreviewVisuController = VisuControllerType::New();
}

ImageViewerManagerController
::~ImageViewerManagerController()
{}

void
ImageViewerManagerController
::OpenInputImage(const char * filename)
{
  try
  {
    std::string strFilename = filename;
    m_Model->OpenImage( strFilename );
  }
  catch (itk::ExceptionObject & err)
  {
    MsgReporter::GetInstance()->SendError(err.GetDescription());
  }
}

/**
*
*/
void
ImageViewerManagerController
::CloseImage(unsigned int selectedItem)
{
  try
  {
    m_Model->CloseImage( selectedItem );
  }
  catch (itk::ExceptionObject & err)
  {
    MsgReporter::GetInstance()->SendError(err.GetDescription());
  }
}

void
ImageViewerManagerController
::UpdateRGBChannelOrder(int redChoice , int greenChoice, int BlueChoice, unsigned int selectedItem)
{
  try
    {

    m_Model->UpdateRGBChannelOrder(redChoice,greenChoice,BlueChoice, selectedItem);
  }
  catch (itk::ExceptionObject & err)
  {
    MsgReporter::GetInstance()->SendError(err.GetDescription());
  }
}

void
ImageViewerManagerController
::UpdateGrayScaleChannelOrder(int choice, unsigned int selectedItem)
{
  try
    {

    m_Model->UpdateGrayScaleChannelOrder(choice, selectedItem);
  }
  catch (itk::ExceptionObject & err)
  {
    MsgReporter::GetInstance()->SendError(err.GetDescription());
  }
}

void
ImageViewerManagerController
::UpdateAmplitudeChannelOrder(int realChoice, int imChoice, unsigned int selectedItem)
{
  try
    {
      m_Model->UpdateAmplitudeChannelOrder(realChoice,imChoice, selectedItem);
    }
  catch (itk::ExceptionObject & err)
    {
      MsgReporter::GetInstance()->SendError(err.GetDescription());
    }
}

void
ImageViewerManagerController
::UpdatePhaseChannelOrder(int realChoice, int imChoice, unsigned int selectedItem)
{
  try
    {
      m_Model->UpdatePhaseChannelOrder(realChoice,imChoice, selectedItem);
    }
  catch (itk::ExceptionObject & err)
    {
      MsgReporter::GetInstance()->SendError(err.GetDescription());
    }
}

void
ImageViewerManagerController
::Link(unsigned int leftChoice, unsigned int rightChoice, OffsetType offset)
{
  try
    {
      m_Model->Link(leftChoice,rightChoice,offset);
    }
  catch (itk::ExceptionObject & err)
    {
      MsgReporter::GetInstance()->SendError(err.GetDescription());
    }
}

void
ImageViewerManagerController
::UpdateImageViewController(unsigned int selectedItem)
{
  try
    {
      m_Model->InitializeImageViewController(selectedItem);
    }
  catch (itk::ExceptionObject & err)
    {
      MsgReporter::GetInstance()->SendError(err.GetDescription());
    }
}

} // end namespace otb

<commit_msg>BUG: fix closing bug in ViewerManager<commit_after>
/*=========================================================================

Program:   ORFEO Toolbox
Language:  C++
Date:      $Date$
Version:   $Revision$

Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
See OTBCopyright.txt for details.

This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE.  See the above copyright notices for more information.

=========================================================================*/
#include "otbImageViewerManagerController.h"
#include "otbMsgReporter.h"

namespace otb
{

ImageViewerManagerController
::ImageViewerManagerController()
{

/** NewVisu */
  // Build a "visu"controller
  m_VisuController = VisuControllerType::New();
  m_PreviewVisuController = VisuControllerType::New();
}

ImageViewerManagerController
::~ImageViewerManagerController()
{
  MsgReporter::GetInstance()->Hide();
}

void
ImageViewerManagerController
::OpenInputImage(const char * filename)
{
  try
  {
    std::string strFilename = filename;
    m_Model->OpenImage( strFilename );
  }
  catch (itk::ExceptionObject & err)
  {
    MsgReporter::GetInstance()->SendError(err.GetDescription());
  }
}

/**
*
*/
void
ImageViewerManagerController
::CloseImage(unsigned int selectedItem)
{
  try
  {
    m_Model->CloseImage( selectedItem );
  }
  catch (itk::ExceptionObject & err)
  {
    MsgReporter::GetInstance()->SendError(err.GetDescription());
  }
}

void
ImageViewerManagerController
::UpdateRGBChannelOrder(int redChoice , int greenChoice, int BlueChoice, unsigned int selectedItem)
{
  try
    {

    m_Model->UpdateRGBChannelOrder(redChoice,greenChoice,BlueChoice, selectedItem);
  }
  catch (itk::ExceptionObject & err)
  {
    MsgReporter::GetInstance()->SendError(err.GetDescription());
  }
}

void
ImageViewerManagerController
::UpdateGrayScaleChannelOrder(int choice, unsigned int selectedItem)
{
  try
    {

    m_Model->UpdateGrayScaleChannelOrder(choice, selectedItem);
  }
  catch (itk::ExceptionObject & err)
  {
    MsgReporter::GetInstance()->SendError(err.GetDescription());
  }
}

void
ImageViewerManagerController
::UpdateAmplitudeChannelOrder(int realChoice, int imChoice, unsigned int selectedItem)
{
  try
    {
      m_Model->UpdateAmplitudeChannelOrder(realChoice,imChoice, selectedItem);
    }
  catch (itk::ExceptionObject & err)
    {
      MsgReporter::GetInstance()->SendError(err.GetDescription());
    }
}

void
ImageViewerManagerController
::UpdatePhaseChannelOrder(int realChoice, int imChoice, unsigned int selectedItem)
{
  try
    {
      m_Model->UpdatePhaseChannelOrder(realChoice,imChoice, selectedItem);
    }
  catch (itk::ExceptionObject & err)
    {
      MsgReporter::GetInstance()->SendError(err.GetDescription());
    }
}

void
ImageViewerManagerController
::Link(unsigned int leftChoice, unsigned int rightChoice, OffsetType offset)
{
  try
    {
      m_Model->Link(leftChoice,rightChoice,offset);
    }
  catch (itk::ExceptionObject & err)
    {
      MsgReporter::GetInstance()->SendError(err.GetDescription());
    }
}

void
ImageViewerManagerController
::UpdateImageViewController(unsigned int selectedItem)
{
  try
    {
      m_Model->InitializeImageViewController(selectedItem);
    }
  catch (itk::ExceptionObject & err)
    {
      MsgReporter::GetInstance()->SendError(err.GetDescription());
    }
}

} // end namespace otb

<|endoftext|>


<commit_before>#include <stack>
#include <string>
#include <string.h>

using namespace std;

bool IsOp(const char ch)
{
	return ch == '+' || ch == '-' || ch == '*' || ch == '/';
}
bool IsOp(const string &str)
{
	return str == "+" || str == "-" || str == "*" || str == "/";
}
bool IsEqualOrGreat(char ch1, char ch2)
{
	if(ch1 == '+' || ch1 == '-')
	{
		if(ch2 == '+' || ch2 == '-')
		{
			return true;
		}
		return false;
	}
	return true;
}
void CalculatePrefix(stack<string> &prefix)
{
	stack<int> cal;
	while(prefix.empty() == false)
	{
		string str = prefix.top();
		prefix.pop();
		if(IsOp(str) == false)
		{
			cal.push(atoi(str.data()));
		}
		else
		{
			int lhs = cal.top();
			cal.pop();
			int rhs = cal.top();
			cal.pop();
			switch(*str.data())
			{
			case '+':
				lhs += rhs;
				break;
			case '-':
				lhs -= rhs;
				break;
			case '*':
				lhs *= rhs;
				break;
			case '/':
				lhs /= rhs;
			}
			cal.push(lhs);
		}
	}
	printf("\nResult is: %d\n", cal.top());
}
void InfixToPrefix(const char *infix)
{
	stack<char> op;
	stack<string> prefix;
	int input_size = static_cast<int>(strlen(infix));
	for(int index = input_size - 1; index >= 0; )
	{
		if(isdigit(infix[index]))
		{
			int begin_index = index - 1;
			for(; begin_index >= 0 && isdigit(infix[begin_index]); --begin_index);
			if(begin_index < 0)
			{
				prefix.push(string(infix, index + 1));
				break;
			}
			else if(begin_index == 0)
			{
				if(infix[0] != '-')
				{
					prefix.push(string(infix + 1, index));
					index = 0;
				}
				else
				{
					prefix.push(string(infix, index + 1));
					break;
				}
			}
			else
			{
				if(IsOp(infix[begin_index - 1]) && infix[begin_index] == '-')
				{
					prefix.push(string(infix + begin_index, index - begin_index + 1));
					index = begin_index - 1;
				}
				else
				{
					prefix.push(string(infix + begin_index + 1, index - begin_index));
					index = begin_index;
				}
			}
		}
		else if(IsOp(infix[index]))
		{
			if(op.empty() == true || op.top() == ')' || IsEqualOrGreat(infix[index], op.top()))
			{
				op.push(infix[index]);
				--index;
			}
			else
			{
				prefix.push(string(&op.top(), 1));
				op.pop();
				continue;
			}
		}
		else
		{
			if(infix[index] == ')')
			{
				op.push(infix[index]);
			}
			else
			{
				while(op.top() != ')')
				{
					prefix.push(string(&op.top(), 1));
					op.pop();
				}
				op.pop();
			}
			--index;
		}
	}
	while(op.empty() == false)
	{
		prefix.push(string(&op.top(), 1));
		op.pop();
	}
	stack<string> temp;
	printf("Prefix is: ");
	while(prefix.empty() == false)
	{
		temp.push(prefix.top());
		printf("%s,", prefix.top().data());
		prefix.pop();
	}
	CalculatePrefix(temp);
}
/*

int main()
{
	const int kInputSize = 1024;
	char infix[kInputSize];
	while(scanf("%s", infix) == 1)
	{
		InfixToPrefix(infix);
	}
}
(-23)+(4+56)*78+(-5)+6*(-78)+123#
**********************************
Prefix is: +,+,+,+,-23,*,+,4,56,78,-5,*,6,-78,123,
Result is: 4307
*/

/*   数据结构分析与学习专栏
*   Copyright (c) 2015, 山东大学 计算机科学与技术专业 学生
*   All rights reserved.
*   作    者：   高祥
*   完成日期：  2015 年 4 月 5 日
*   版 本 号：011

*任务：使用栈实现表达式求值

*算法思想：判断运算符的优先级并执行相应的操作

*功能：
1.对负数、浮点数均有效
2.可进行多括号的复杂运算

*主要函数：
*   1.void InitNumberStack(Number &NumberStack);//初始化数字栈
*   2.void InitOperatorStack(Operator &OperatorStack);//初始化运算符栈
*   3.void NumberPush(Number &NumberStack,double number);//压入数字栈
*   4.void NumberPop(Number &NumberStack);//弹出数字栈
*   5.void OperatorPush(Operator &OperatorStack,char op);//压入运算符栈
*   6.void OperatorPop(Operator &OperatorStack);//弹出运算符栈
*   7.char GetTopOperator(Operator &OperatorStack);//得到运算符栈栈顶元素
*   8.double GetTopNumber(Number &NumberStack);//得到数字栈栈顶元素
*   9.double ToNumber(string s);//字符串转换成数字函数
*   10.char Precede(char stacktop,char willpush);//判断运算符的优先级
*   11.double calculate(double a,double b,char op);//计算
*   12.int IsDigit(char ch);//判断字符是否为数字

*运行示例：
请输入运算表达式（表达时应当合法且不含空格且负数必须使用括号括起来且以‘#’结尾，仅输入‘#’表示退出）：
1+2-3+4-5#
运算结果为：-1
请输入运算表达式（表达时应当合法且不含空格且负数必须使用括号括起来且以‘#’结尾，仅输入‘#’表示退出）：
1.23+3.45-6.78+9.01#
运算结果为：6.91
请输入运算表达式（表达时应当合法且不含空格且负数必须使用括号括起来且以‘#’结尾，仅输入‘#’表示退出）：
1+2*3+4/5-6#
运算结果为：1.8
请输入运算表达式（表达时应当合法且不含空格且负数必须使用括号括起来且以‘#’结尾，仅输入‘#’表示退出）：
1+((-3)*3+7.2*5/9)/((-4)*6+25-7/2)+23.9#
运算结果为：26.9
请输入运算表达式（表达时应当合法且不含空格且负数必须使用括号括起来且以‘#’结尾，仅输入‘#’表示退出）：
#

*/
#include<iostream>
#include<cstdlib>
using namespace std;

#define MAXSIZE 100

typedef struct
{
	double *top;
	double *base;
} Number; //数字栈类型

typedef struct
{
	char *top;
	char *base;
} Operator;//运算符栈类型

void InitNumberStack(Number &NumberStack);//初始化数字栈
void InitOperatorStack(Operator &OperatorStack);//初始化运算符栈
void NumberPush(Number &NumberStack,double number);//压入数字栈
void  NumberPop(Number &NumberStack);//弹出数字栈
void OperatorPush(Operator &OperatorStack,char op);//压入运算符栈
void OperatorPop(Operator &OperatorStack);//弹出运算符栈
char GetTopOperator(Operator &OperatorStack);//得到运算符栈栈顶元素
double GetTopNumber(Number &NumberStack);//得到数字栈栈顶元素
double ToNumber(string s);//字符串转换成数字函数
char Precede(char stacktop,char willpush);//判断运算符的优先级
double calculate(double a,double b,char op);//计算
int IsDigit(char ch);//判断字符是否为数字

int main()
{
	string str;
	cout<<"请输入运算表达式（表达时应当合法且不含空格且负数必须使用括号括起来且以‘#’结尾，仅输入‘#’表示退出）：\n";

	while(getline(cin,str)&&str!="#")
	{
		Operator OperatorStack;
		Number NumberStack;

		InitNumberStack(NumberStack);//初始化两个栈
		InitOperatorStack(OperatorStack);

		OperatorPush(OperatorStack,'#');//运算符栈中预存一个‘#’便于判断运算符的优先级

		for(int i=0; i<static_cast<int>(str.size()); i++)//遍历表达式
		{
			if(IsDigit(str[i]))//若当前字符为数字，将该数字全部截取出来
			{
				int j=i;//数字字符串的起点索引

				while(i<str.size()&&(IsDigit(str[i])||str[i]=='.'))
					//当不越界且字符为数字或小数点时，数字字符串未结束
				{
					i++;
				}
				//利用转换函数将截取的数字字符串转换为数字并压入数字栈中
				NumberPush(NumberStack,ToNumber(str.substr(j,i-j)));
				i--;//索引减1
			}
			else if(str[i]=='('&&str[i+1]=='-')//若遇到负数
			{
				int j=i;

				i++;//细节
				while(i<str.size()&&(IsDigit(str[i])||str[i]=='.'||str[i]=='-'||str[i]==')'))
					//注意连同负数的左右括号一同截取，防止对后续的判断造成影响
				{
					i++;
				}
				NumberPush(NumberStack,ToNumber(str.substr(j,i-j)));
				i--;
			}
			else//不是数字
			{
				switch(Precede(GetTopOperator(OperatorStack),str[i]))
					//Precede函数判断运算符栈栈顶运算符和将要压入的运算符的优先级，以此来决定操作
				{
				case '<'://栈顶运算符优先级低
					OperatorPush(OperatorStack,str[i]);//压入优先级高的运算符
					break;
				case '='://优先级相同：表明括号内运算完成
					OperatorPop(OperatorStack);//弹出栈顶的括号
					break;
				case '>'://栈顶运算符优先级高：执行栈顶运算符代表的运算
					char op=GetTopOperator(OperatorStack);//得到栈顶运算符
					OperatorPop(OperatorStack);//删除运算符栈栈顶运算符

					double b=GetTopNumber(NumberStack);//得到第二个运算数字，注意是后进先出
					NumberPop(NumberStack);//删除数字栈栈顶数字
					double a=GetTopNumber(NumberStack);//得到第一个运算数字
					NumberPop(NumberStack);//删除数字栈栈顶数字
					NumberPush(NumberStack,calculate(a,b,op));//执行运算并将结果压入数字栈

					i--;//推迟压入运算符栈中，避免运算符栈内出现能运算但未运算的运算符
					break;
				}
			}
		}

		cout<<"运算结果为："<<GetTopNumber(NumberStack)<<endl;
		cout<<"请输入运算表达式（表达时应当合法且不含空格且负数必须使用括号括起来且以‘#’结尾，仅输入‘#’表示退出）：\n";
	}
	return 0;
}

double ToNumber(string s)//字符串转换成数字函数
{
	string s1;//去掉括号的部分
	if(s[0]=='(')
	{
		s1=s.substr(2,s.size()-3);
	}
	else
	{
		s1=s;
	}

	double num=0.0;//返回值
	int i;
	for(i=0; i<s1.size(); i++)
	{
		if(s1[i]=='.')//整数部分转换完成
		{
			break;
		}
		num=num*10+s1[i]-'0';
	}

	//转换小数部分
	double j=0.1;
	for(i=i+1; i<s1.size(); i++)
	{
		num=num+(s1[i]-'0')*j;
		j=j*0.1;
	}

	if(s1==s)//非负数
	{
		return num;
	}
	return -1*num;//负数添负号再返回
}

char Precede(char stacktop,char willpush)//判断运算符的优先级
{
	switch(stacktop)
	{
	case '#':
		if(willpush=='#')
		{
			return '=';
		}
		return '<';

	case '+':
	case '-':
		if(willpush=='+'||willpush=='-'||willpush==')'||willpush=='#')
		{
			return '>';
		}
		return '<';

	case '*':
	case '/':
		if(willpush=='(')
		{
			return '<';
		}
		return '>';

	case '(':
		if(willpush==')')
		{
			return '=';
		}
		return '<';

	case ')':
		return '>';
	}
}

double calculate(double a,double b,char op)//计算
{
	switch(op)
	{
	case '+':
		return a+b;
	case '-':
		return a-b;
	case '*':
		return a*b;
	case '/':
		return a/b;
	}
}

void InitNumberStack(Number &NumberStack)//初始化数字栈
{
	NumberStack.base=(double*)malloc(MAXSIZE*sizeof(double));
	NumberStack.top=NumberStack.base;
}

void InitOperatorStack(Operator &OperatorStack)//初始化运算符栈
{
	OperatorStack.base=(char*)malloc(MAXSIZE*sizeof(char));
	OperatorStack.top=OperatorStack.base;
}

void NumberPush(Number &NumberStack,double number)//压入数字栈
{
	*NumberStack.top=number;
	NumberStack.top++;
}

void  NumberPop(Number &NumberStack)//弹出数字栈
{
	NumberStack.top--;
}

void OperatorPush(Operator &OperatorStack,char op)//压入运算符栈
{
	*OperatorStack.top=op;
	OperatorStack.top++;
}

void OperatorPop(Operator &OperatorStack)//弹出运算符栈
{
	OperatorStack.top--;
}

char GetTopOperator(Operator &OperatorStack)//得到运算符栈栈顶元素
{
	return *(OperatorStack.top-1);
}

double GetTopNumber(Number &NumberStack)//得到数字栈栈顶元素
{
	return *(NumberStack.top-1);
}

int IsDigit(char ch)//判断字符是否为数字
{
	if(ch>='0'&&ch<='9')
	{
		return 1;
	}
	return 0;
}
<commit_msg>feat: convert number<commit_after>#include <stack>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
using namespace std;

int StringToInt(const char *str, int length)
{
	char buf[length + 1];
	memmove(buf, str, length);
	buf[length] = 0;
	return atoi(buf);
}
void CalculateInfix(const char *infix)
{
	int length = static_cast<int>(strlen(infix));
	stack<int> num;
	for(int index = 0; index < length; )
	{
		if(isdigit(infix[index]) || // Non-negative number
		        (infix[index] == '(' && infix[index + 1] == '-')) // Negative number
		{
			index = infix[index] == '(' ? index + 1 : index;
			int last = index + 1;
			for(; last < length && isdigit(infix[last]); ++last);
			num.push(StringToInt(infix + index, last - index));
			index = infix[last] == ')' ? last + 1 : last;
			printf("%d\n", num.top());
		}
		else
		{
			++index;
		}
	}
}

int main()
{
	const int kInputSize = 1024;
	char infix[kInputSize];
	while(scanf("%s", infix) == 1)
	{
		CalculateInfix(infix);
	}
}
/*
(-23)+(4+56)*78+(-5)+6*(-78)+123#
*************************************
4307
*/
/*
bool IsOp(const char ch)
{
	return ch == '+' || ch == '-' || ch == '*' || ch == '/';
}
bool IsOp(const string &str)
{
	return str == "+" || str == "-" || str == "*" || str == "/";
}
bool IsEqualOrGreat(char ch1, char ch2)
{
	if(ch1 == '+' || ch1 == '-')
	{
		if(ch2 == '+' || ch2 == '-')
		{
			return true;
		}
		return false;
	}
	return true;
}
void CalculatePrefix(stack<string> &prefix)
{
	stack<int> cal;
	while(prefix.empty() == false)
	{
		string str = prefix.top();
		prefix.pop();
		if(IsOp(str) == false)
		{
			cal.push(atoi(str.data()));
		}
		else
		{
			int lhs = cal.top();
			cal.pop();
			int rhs = cal.top();
			cal.pop();
			switch(*str.data())
			{
			case '+':
				lhs += rhs;
				break;
			case '-':
				lhs -= rhs;
				break;
			case '*':
				lhs *= rhs;
				break;
			case '/':
				lhs /= rhs;
			}
			cal.push(lhs);
		}
	}
	printf("\nResult is: %d\n", cal.top());
}
void InfixToPrefix(const char *infix)
{
	stack<char> op;
	stack<string> prefix;
	int input_size = static_cast<int>(strlen(infix));
	for(int index = input_size - 1; index >= 0; )
	{
		if(isdigit(infix[index]))
		{
			int begin_index = index - 1;
			for(; begin_index >= 0 && isdigit(infix[begin_index]); --begin_index);
			if(begin_index < 0)
			{
				prefix.push(string(infix, index + 1));
				break;
			}
			else if(begin_index == 0)
			{
				if(infix[0] != '-')
				{
					prefix.push(string(infix + 1, index));
					index = 0;
				}
				else
				{
					prefix.push(string(infix, index + 1));
					break;
				}
			}
			else
			{
				if(IsOp(infix[begin_index - 1]) && infix[begin_index] == '-')
				{
					prefix.push(string(infix + begin_index, index - begin_index + 1));
					index = begin_index - 1;
				}
				else
				{
					prefix.push(string(infix + begin_index + 1, index - begin_index));
					index = begin_index;
				}
			}
		}
		else if(IsOp(infix[index]))
		{
			if(op.empty() == true || op.top() == ')' || IsEqualOrGreat(infix[index], op.top()))
			{
				op.push(infix[index]);
				--index;
			}
			else
			{
				prefix.push(string(&op.top(), 1));
				op.pop();
				continue;
			}
		}
		else
		{
			if(infix[index] == ')')
			{
				op.push(infix[index]);
			}
			else
			{
				while(op.top() != ')')
				{
					prefix.push(string(&op.top(), 1));
					op.pop();
				}
				op.pop();
			}
			--index;
		}
	}
	while(op.empty() == false)
	{
		prefix.push(string(&op.top(), 1));
		op.pop();
	}
	stack<string> temp;
	printf("Prefix is: ");
	while(prefix.empty() == false)
	{
		temp.push(prefix.top());
		printf("%s,", prefix.top().data());
		prefix.pop();
	}
	CalculatePrefix(temp);
}
*/
//
<|endoftext|>


<commit_before>#include "ezxml.h"
#include "cfg.h"
#include <string>
#include <iostream>
#include <string.h>

void cfgNode::Fill(ezxml_t arg) {
	if(arg==NULL) {
		name=NULL;
		value=NULL;
		attrs=NULL;
		next=NULL;
		child=NULL;
		return;
	}

	int i=0;
	attrs=(char**)malloc(2*sizeof(char*));
	while( (arg->attr)[i]!=0 ) {
		attrs=(char**)realloc(attrs, (i+4)*sizeof(char*));
		attrs[i]=strdup(arg->attr[i]);
		++i;
	}
	attrs[i+1]=NULL;
	attrs[i]=NULL;
	name=strdup(arg->name);
	value=strdup(arg->txt);
	next=NULL;
	child=NULL;
	//There will be many cascaded creators... maybe not a good idea ?
	if(arg->ordered)
		next=new cfgNode(arg->ordered);
	if(arg->child)
		child=new cfgNode(arg->child);
}

cfgNode::cfgNode() {
	Fill(NULL);
}

cfgNode::cfgNode(const cfgNode &cfg, bool wholeTree) {
	if(wholeTree==true)
		throw "Copy a cfgNode as a whole isn't supported at the moment";
	int i=0;
	attrs=(char**)malloc(2*sizeof(char*));
	while( cfg.attrs && (cfg.attrs)[i]!=0 ) {
		attrs=(char**)realloc(attrs, (i+4)*sizeof(char*));
		attrs[i]=strdup(cfg.attrs[i]);
		++i;
	}
	attrs[i+1]=NULL;
	attrs[i]=NULL;
	name=strdup(cfg.name);
	value=strdup(cfg.value);
	next=cfg.next;
	child=cfg.child;
}

cfgNode::~cfgNode() {
	if(name)
		free(name);
	if(value)
		free(value);

	int i=0;
	if(attrs) {
		while( attrs[i]!=0 ) {
			free(attrs[i]);
			attrs[i]=NULL;
			++i;
		}
		free(attrs);
	}
	attrs=NULL;
}

cfgNode::cfgNode(ezxml_t arg) {
	Fill(arg);
}

cfgNode::cfgNode(const char *path) {
	ezxml_t node=ezxml_parse_file(path);
	if(!node)
		throw "Can't access requested config file";
	Fill(node->child);
	ezxml_free(node);
}

cfgNode::cfgNode(char *buf, int ln) {
	ezxml_t node=ezxml_parse_str(buf, ln);
	if(!node)
		throw "Can't parse this string";
	Fill(node->child);
	ezxml_free(node);
}

cfgNode::cfgNode(int fd) {
	ezxml_t node=ezxml_parse_fd(fd);
	if(!node)
		throw "Can't parse this file";
	Fill(node->child);
	ezxml_free(node);
}

const char *cfgNode::operator[](const char *name) const {
	int i=0;
	while(attrs[2*i]) {
		if(strcmp(attrs[2*i], name)==0)
			return attrs[2*i+1];
		++i;
	}
	return NULL;
}

const char *cfgNode::operator()() const {
	return value;
}

void cfgNode::operator++() {
	int i=0;
	if(attrs) {
		for(i=0; attrs[i]!=NULL; ++i) {
			free(attrs[i]);
			attrs[i]=NULL;
		}
		free(attrs);
		attrs=NULL;
	}
	free(value);
	free(name);
	if(!next) {
		Fill(NULL);
		return;
	}

	attrs=(char**)malloc(2*sizeof(char*));
	for(i=0; (next->attrs)[i]!=0;  ++i) {
		attrs=(char**)realloc(attrs, (i+4)*sizeof(char*));
		attrs[i]=strdup(next->attrs[i]);
	}
	attrs[i+1]=NULL;
	attrs[i]=NULL;
	child=next->child;
	value=strdup(next->value);
	name=strdup(next->name);
	next=next->next;
}

void cfgNode::operator=(const cfgNode &cfg) {
	if(!cfg) {
		Fill(NULL);
		return;
	}
	int i=0;
	if(attrs) {
		for(i=0; attrs[i]!=NULL; ++i) {
			free(attrs[i]);
			attrs[i]=NULL;
		}
		free(attrs);
		attrs=NULL;
	}
	free(value);
	free(name);

	attrs=(char**)malloc(2*sizeof(char*));
	for(i=0; (cfg.attrs)[i]!=0;  ++i) {
		attrs=(char**)realloc(attrs, (i+4)*sizeof(char*));
		attrs[i]=strdup(cfg.attrs[i]);
	}
	attrs[i+1]=NULL;
	attrs[i]=NULL;
	child=cfg.child;
	value=strdup(cfg.value);
	name=strdup(cfg.name);
	next=cfg.next;
}

bool cfgNode::operator!() const {
	if(name)
		return false;
	return true;
}

bool cfgNode::operator!=(const char *arg) const {
	if(name && strcmp(name, arg)==0)
		return true;
	return false;
}

void cfgNode::Free() {
	if(child) {
		child->Free();
		delete child;
	}
	if(next) {
		next->Free();
		delete next;
	}
}

cfgNode *cfgNode::addAttr(const char *name, const char *value) {
	int i;
	for(i=0;attrs[i];++i);
	printf("Set %s=%s\n", name, value);
	attrs=(char**)realloc(attrs, (i+4)*sizeof(char*));
	if( (i%2)==1)
		throw "First nil attr is not a name!";
	attrs[i]=strdup(name);
	if(value)
		attrs[i+1]=strdup(value);
	else
		attrs[i+1]=strdup("");
	attrs[i+2]=NULL;
	attrs[i+3]=NULL;
	return this;
}
<commit_msg>cfgNode[] won't segfault without inner attrs<commit_after>#include "ezxml.h"
#include "cfg.h"
#include <string>
#include <iostream>
#include <string.h>

void cfgNode::Fill(ezxml_t arg) {
	if(arg==NULL) {
		name=NULL;
		value=NULL;
		attrs=NULL;
		next=NULL;
		child=NULL;
		return;
	}

	int i=0;
	attrs=(char**)malloc(2*sizeof(char*));
	while( (arg->attr)[i]!=0 ) {
		attrs=(char**)realloc(attrs, (i+4)*sizeof(char*));
		attrs[i]=strdup(arg->attr[i]);
		++i;
	}
	attrs[i+1]=NULL;
	attrs[i]=NULL;
	name=strdup(arg->name);
	value=strdup(arg->txt);
	next=NULL;
	child=NULL;
	//There will be many cascaded creators... maybe not a good idea ?
	if(arg->ordered)
		next=new cfgNode(arg->ordered);
	if(arg->child)
		child=new cfgNode(arg->child);
}

cfgNode::cfgNode() {
	Fill(NULL);
}

cfgNode::cfgNode(const cfgNode &cfg, bool wholeTree) {
	if(wholeTree==true)
		throw "Copy a cfgNode as a whole isn't supported at the moment";
	int i=0;
	attrs=(char**)malloc(2*sizeof(char*));
	while( cfg.attrs && (cfg.attrs)[i]!=0 ) {
		attrs=(char**)realloc(attrs, (i+4)*sizeof(char*));
		attrs[i]=strdup(cfg.attrs[i]);
		++i;
	}
	attrs[i+1]=NULL;
	attrs[i]=NULL;
	name=strdup(cfg.name);
	value=strdup(cfg.value);
	next=cfg.next;
	child=cfg.child;
}

cfgNode::~cfgNode() {
	if(name)
		free(name);
	if(value)
		free(value);

	int i=0;
	if(attrs) {
		while( attrs[i]!=0 ) {
			free(attrs[i]);
			attrs[i]=NULL;
			++i;
		}
		free(attrs);
	}
	attrs=NULL;
}

cfgNode::cfgNode(ezxml_t arg) {
	Fill(arg);
}

cfgNode::cfgNode(const char *path) {
	ezxml_t node=ezxml_parse_file(path);
	if(!node)
		throw "Can't access requested config file";
	Fill(node->child);
	ezxml_free(node);
}

cfgNode::cfgNode(char *buf, int ln) {
	ezxml_t node=ezxml_parse_str(buf, ln);
	if(!node)
		throw "Can't parse this string";
	Fill(node->child);
	ezxml_free(node);
}

cfgNode::cfgNode(int fd) {
	ezxml_t node=ezxml_parse_fd(fd);
	if(!node)
		throw "Can't parse this file";
	Fill(node->child);
	ezxml_free(node);
}

const char *cfgNode::operator[](const char *name) const {
	int i=0;
	if(!attrs)
		return NULL;
	while(attrs[2*i]) {
		if(strcmp(attrs[2*i], name)==0)
			return attrs[2*i+1];
		++i;
	}
	return NULL;
}

const char *cfgNode::operator()() const {
	return value;
}

void cfgNode::operator++() {
	int i=0;
	if(attrs) {
		for(i=0; attrs[i]!=NULL; ++i) {
			free(attrs[i]);
			attrs[i]=NULL;
		}
		free(attrs);
		attrs=NULL;
	}
	free(value);
	free(name);
	if(!next) {
		Fill(NULL);
		return;
	}

	attrs=(char**)malloc(2*sizeof(char*));
	for(i=0; (next->attrs)[i]!=0;  ++i) {
		attrs=(char**)realloc(attrs, (i+4)*sizeof(char*));
		attrs[i]=strdup(next->attrs[i]);
	}
	attrs[i+1]=NULL;
	attrs[i]=NULL;
	child=next->child;
	value=strdup(next->value);
	name=strdup(next->name);
	next=next->next;
}

void cfgNode::operator=(const cfgNode &cfg) {
	if(!cfg) {
		Fill(NULL);
		return;
	}
	int i=0;
	if(attrs) {
		for(i=0; attrs[i]!=NULL; ++i) {
			free(attrs[i]);
			attrs[i]=NULL;
		}
		free(attrs);
		attrs=NULL;
	}
	free(value);
	free(name);

	attrs=(char**)malloc(2*sizeof(char*));
	for(i=0; (cfg.attrs)[i]!=0;  ++i) {
		attrs=(char**)realloc(attrs, (i+4)*sizeof(char*));
		attrs[i]=strdup(cfg.attrs[i]);
	}
	attrs[i+1]=NULL;
	attrs[i]=NULL;
	child=cfg.child;
	value=strdup(cfg.value);
	name=strdup(cfg.name);
	next=cfg.next;
}

bool cfgNode::operator!() const {
	if(name)
		return false;
	return true;
}

bool cfgNode::operator!=(const char *arg) const {
	if(name && strcmp(name, arg)==0)
		return true;
	return false;
}

void cfgNode::Free() {
	if(child) {
		child->Free();
		delete child;
	}
	if(next) {
		next->Free();
		delete next;
	}
}

cfgNode *cfgNode::addAttr(const char *name, const char *value) {
	int i;
	for(i=0;attrs[i];++i);
	printf("Set %s=%s\n", name, value);
	attrs=(char**)realloc(attrs, (i+4)*sizeof(char*));
	if( (i%2)==1)
		throw "First nil attr is not a name!";
	attrs[i]=strdup(name);
	if(value)
		attrs[i+1]=strdup(value);
	else
		attrs[i+1]=strdup("");
	attrs[i+2]=NULL;
	attrs[i+3]=NULL;
	return this;
}
<|endoftext|>


<commit_before>#include <ncurses.h>
#include <locale>
#include <chrono>
#include <thread>
#include <string>
#include <vector>
#include <regex>
#include <iostream>
#include <stdexcept>
using namespace std::literals::string_literals;
using std::string;
using std::tuple;
using std::vector;

bool is_utf8_first(uint8_t ch)
{
  return (ch & 0xC0) != 0x80 && (ch & 0xFE) != 0xFE && ((ch & 0x80) == 0 || (ch & 0xC0) == 0xC0);
}

bool is_utf8_cont(uint8_t ch) { return (ch & 0xC0) == 0x80; }

size_t get_utf8_char_length(uint8_t ch)
{
  if (!is_utf8_first(ch)) {
    throw std::runtime_error(string(__FUNCTION__) + ": the first byte is not UTF8");
  }

  for (int i = 0; i < 6; ++i) {
    if ((ch & (0x01 << (7 - i))) == 0) {
      return std::max(1, i);
    }
  }

  throw std::runtime_error(string(__FUNCTION__) + ": unreachable");
}

std::string get_utf8_char()
{
  std::array<uint8_t, 6> buf{0};

  auto ch0 = static_cast<uint8_t>(::getch() & 0x000000FF);
  size_t len = get_utf8_char_length(ch0);
  buf[0] = ch0;

  for (size_t i = 1; i < len; ++i) {
    auto ch = static_cast<uint8_t>(::getch() & 0x000000FF);
    if (!is_utf8_cont(ch)) {
      throw std::runtime_error(string(__FUNCTION__) + ": wrong byte exists");
    }
    buf[i] = ch;
  }

  return std::string(buf.data(), buf.data() + len);
}

void pop_back_utf8(std::string& str)
{
  if (str.empty())
    return;

  for (size_t len = str.size() - 1; len >= 0; --len) {
    if (!is_utf8_cont(str[len])) {
      str.resize(len);
      return;
    }
  }
}

class Coco {
  enum class Status {
    Selected,
    Escaped,
    Continue,
  };

  std::vector<std::string> const& lines;
  std::vector<std::string> filtered;
  std::string query;
  size_t cursor = 0;
  size_t offset = 0;

public:
  Coco(std::vector<std::string> const& lines) : lines(lines), filtered(lines) {}

  std::tuple<bool, std::string> run();

private:
  void render_screen();
  Status handle_key_event();

  void filter_by_query();
};

void Coco::render_screen()
{
  std::string query_str = "QUERY> " + query;

  ::werase(stdscr);

  int width, height;
  getmaxyx(stdscr, height, width);

  for (size_t y = 0; y < std::min<size_t>(filtered.size() - offset, width - 1); ++y) {
    mvwaddstr(stdscr, y + 1, 1, filtered[y + offset].c_str());
  }
  mvwaddstr(stdscr, cursor + 1, 0, ">");

  mvwaddstr(stdscr, 0, 0, query_str.c_str());

  ::wrefresh(stdscr);
}

auto Coco::handle_key_event() -> Status
{
  int ch = ::getch();
  if (ch == 10) { // 10 = enter
    return filtered.size() > 0 ? Status::Selected : Status::Escaped;
  }
  else if (ch == 27) {
    ::nodelay(stdscr, true);
    int ch = ::getch();
    if (ch == -1) { // Escape
      return Status::Escaped;
    }
    ::ungetch(ch);
    ::nodelay(stdscr, false);
    return Status::Continue;
  }
  else if (ch == KEY_UP) {
    if (cursor == 0) {
      offset = std::max(0, (int)offset - 1);
    }
    else {
      cursor--;
    }
    return Status::Continue;
  }
  else if (ch == KEY_DOWN) {
    int width, height;
    getmaxyx(stdscr, height, width);

    if (cursor == height - 2) {
      offset = std::min<size_t>(offset + 1, std::max<int>(0, filtered.size() - height + 1));
    }
    else {
      cursor = std::min<size_t>(cursor + 1, std::min<size_t>(filtered.size() - offset, height - 1) - 1);
    }
    return Status::Continue;
  }
  else if (ch == 127) { // 127 = backspace
    if (!query.empty()) {
      pop_back_utf8(query);
      filter_by_query();
    }
    return Status::Continue;
  }
  else if (is_utf8_first(ch & 0xFF)) { // utf-8 character
    ::ungetch(ch);
    auto ch = get_utf8_char();
    query += ch;
    filter_by_query();
    return Status::Continue;
  }

  throw std::logic_error(std::string(__FUNCTION__) + ": unreachable");
}

std::tuple<bool, std::string> Coco::run()
{
  render_screen();

  while (true) {
    auto result = handle_key_event();
    if (result == Status::Selected) {
      return std::make_tuple(true, filtered[cursor]);
    }
    else if (result == Status::Escaped) {
      break;
    }
    render_screen();
  }

  return std::make_tuple(false, ""s);
}

void Coco::filter_by_query()
{
  cursor = 0;
  offset = 0;

  if (query.empty()) {
    filtered = lines;
  }
  else {
    std::regex re(query);
    filtered.resize(0);
    for (auto&& line : lines) {
      if (std::regex_search(line, re)) {
        filtered.push_back(line);
      }
    }
  }
}

class Ncurses {
public:
  Ncurses()
  {
    freopen("/dev/tty", "rw", stdin);
    ::initscr();
    ::noecho();
    ::cbreak();
    ::keypad(stdscr, true);
    ::ESCDELAY = 25;
  }
  ~Ncurses() { ::endwin(); }
};

int main()
{
  std::setlocale(LC_ALL, "");

  try {
    // read lines from stdin.
    std::regex ansi(R"(\x1B\[([0-9]{1,2}(;[0-9]{1,2})?)?[m|K])");
    std::vector<std::string> lines;
    for (std::string line; std::getline(std::cin, line);) {
      lines.push_back(std::regex_replace(line, ansi, ""));
    }

    bool is_selected;
    std::string selection;
    {
      Ncurses ncurses;
      Coco coco{lines};
      std::tie(is_selected, selection) = coco.run();
    }

    if (is_selected) {
      std::cout << selection << std::endl;
    }
    return 0;
  }
  catch (std::exception& e) {
    std::cerr << "An error is thrown: " << e.what() << std::endl;
    return -1;
  }
}<commit_msg>support color<commit_after>#include <ncurses.h>
#include <locale>
#include <chrono>
#include <thread>
#include <string>
#include <vector>
#include <regex>
#include <iostream>
#include <stdexcept>
using namespace std::literals::string_literals;
using std::string;
using std::tuple;
using std::vector;

bool is_utf8_first(uint8_t ch)
{
  return (ch & 0xC0) != 0x80 && (ch & 0xFE) != 0xFE && ((ch & 0x80) == 0 || (ch & 0xC0) == 0xC0);
}

bool is_utf8_cont(uint8_t ch) { return (ch & 0xC0) == 0x80; }

size_t get_utf8_char_length(uint8_t ch)
{
  if (!is_utf8_first(ch)) {
    throw std::runtime_error(string(__FUNCTION__) + ": the first byte is not UTF8");
  }

  for (int i = 0; i < 6; ++i) {
    if ((ch & (0x01 << (7 - i))) == 0) {
      return std::max(1, i);
    }
  }

  throw std::runtime_error(string(__FUNCTION__) + ": unreachable");
}

std::string get_utf8_char()
{
  std::array<uint8_t, 6> buf{0};

  auto ch0 = static_cast<uint8_t>(::getch() & 0x000000FF);
  size_t len = get_utf8_char_length(ch0);
  buf[0] = ch0;

  for (size_t i = 1; i < len; ++i) {
    auto ch = static_cast<uint8_t>(::getch() & 0x000000FF);
    if (!is_utf8_cont(ch)) {
      throw std::runtime_error(string(__FUNCTION__) + ": wrong byte exists");
    }
    buf[i] = ch;
  }

  return std::string(buf.data(), buf.data() + len);
}

void pop_back_utf8(std::string& str)
{
  if (str.empty())
    return;

  for (size_t len = str.size() - 1; len >= 0; --len) {
    if (!is_utf8_cont(str[len])) {
      str.resize(len);
      return;
    }
  }
}

class Coco {
  enum class Status {
    Selected,
    Escaped,
    Continue,
  };

  std::vector<std::string> const& lines;
  std::vector<std::string> filtered;
  std::string query;
  size_t cursor = 0;
  size_t offset = 0;

public:
  Coco(std::vector<std::string> const& lines) : lines(lines), filtered(lines) {}

  std::tuple<bool, std::string> run();

private:
  void render_screen();
  Status handle_key_event();

  void filter_by_query();
};

void Coco::render_screen()
{
  std::string query_str = "QUERY> " + query;

  ::werase(stdscr);

  int width, height;
  getmaxyx(stdscr, height, width);

  for (size_t y = 0; y < std::min<size_t>(filtered.size() - offset, width - 1); ++y) {
    mvwaddstr(stdscr, y + 1, 0, filtered[y + offset].c_str());
    if (y == cursor) {
      attrset(COLOR_PAIR(2));
      mvwchgat(stdscr, y + 1, 0, -1, A_NORMAL, 2, nullptr);
      attrset(COLOR_PAIR(1));
    }
  }

  mvwaddstr(stdscr, 0, 0, query_str.c_str());

  ::wrefresh(stdscr);
}

auto Coco::handle_key_event() -> Status
{
  int ch = ::getch();
  if (ch == 10) { // 10 = enter
    return filtered.size() > 0 ? Status::Selected : Status::Escaped;
  }
  else if (ch == 27) {
    ::nodelay(stdscr, true);
    int ch = ::getch();
    if (ch == -1) { // Escape
      return Status::Escaped;
    }
    ::ungetch(ch);
    ::nodelay(stdscr, false);
    return Status::Continue;
  }
  else if (ch == KEY_UP) {
    if (cursor == 0) {
      offset = std::max(0, (int)offset - 1);
    }
    else {
      cursor--;
    }
    return Status::Continue;
  }
  else if (ch == KEY_DOWN) {
    int width, height;
    getmaxyx(stdscr, height, width);

    if (cursor == height - 2) {
      offset = std::min<size_t>(offset + 1, std::max<int>(0, filtered.size() - height + 1));
    }
    else {
      cursor = std::min<size_t>(cursor + 1, std::min<size_t>(filtered.size() - offset, height - 1) - 1);
    }
    return Status::Continue;
  }
  else if (ch == 127) { // 127 = backspace
    if (!query.empty()) {
      pop_back_utf8(query);
      filter_by_query();
    }
    return Status::Continue;
  }
  else if (is_utf8_first(ch & 0xFF)) { // utf-8 character
    ::ungetch(ch);
    auto ch = get_utf8_char();
    query += ch;
    filter_by_query();
    return Status::Continue;
  }

  throw std::logic_error(std::string(__FUNCTION__) + ": unreachable");
}

std::tuple<bool, std::string> Coco::run()
{
  render_screen();

  while (true) {
    auto result = handle_key_event();
    if (result == Status::Selected) {
      return std::make_tuple(true, filtered[cursor]);
    }
    else if (result == Status::Escaped) {
      break;
    }
    render_screen();
  }

  return std::make_tuple(false, ""s);
}

void Coco::filter_by_query()
{
  cursor = 0;
  offset = 0;

  if (query.empty()) {
    filtered = lines;
  }
  else {
    std::regex re(query);
    filtered.resize(0);
    for (auto&& line : lines) {
      if (std::regex_search(line, re)) {
        filtered.push_back(line);
      }
    }
  }
}

class Ncurses {
public:
  Ncurses()
  {
    freopen("/dev/tty", "rw", stdin);
    ::initscr();
    ::noecho();
    ::cbreak();
    ::keypad(stdscr, true);
    ::ESCDELAY = 25;

    start_color();
    ::init_pair(1, COLOR_WHITE, COLOR_BLACK);
    ::init_pair(2, COLOR_RED, COLOR_WHITE);
  }
  ~Ncurses() { ::endwin(); }
};

int main()
{
  std::setlocale(LC_ALL, "");

  try {
    // read lines from stdin.
    std::regex ansi(R"(\x1B\[([0-9]{1,2}(;[0-9]{1,2})?)?[m|K])");
    std::vector<std::string> lines;
    for (std::string line; std::getline(std::cin, line);) {
      lines.push_back(std::regex_replace(line, ansi, ""));
    }

    bool is_selected;
    std::string selection;
    {
      Ncurses ncurses;
      Coco coco{lines};
      std::tie(is_selected, selection) = coco.run();
    }

    if (is_selected) {
      std::cout << selection << std::endl;
    }
    return 0;
  }
  catch (std::exception& e) {
    std::cerr << "An error is thrown: " << e.what() << std::endl;
    return -1;
  }
}<|endoftext|>


<commit_before>/*
 * fPls - playlist handler for fIcy
 * Copyright(c) 2004-2005 of wave++ (Yuri D'Elia) <wavexx@users.sf.net>
 * Distributed under GNU LGPL without ANY warranty.
 */

// local headers
#include "fIcy.hh"
#include "msg.hh"
#include "htfollow.hh"
#include "plsparse.hh"
#include "tmparse.hh"
#include "authparse.hh"
using std::string;
using std::list;
using std::map;

// system headers
#include <fstream>
using std::ifstream;

#include <sstream>
using std::istringstream;

#include <iostream>
using std::cout;

#include <memory>
using std::auto_ptr;

#include <stdexcept>
using std::runtime_error;

// c system headers
#include <cstdlib>
using std::strtoul;
using std::strtol;

#include <stdarg.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>
#include <time.h>
#include <errno.h>
#include <fcntl.h>

/*
 * Parameters handling
 */
class Params
{
public:
  explicit
  Params(int argc, char* argv[]);

  ~Params() throw()
  {
    if(fIcyParams)
      delete[] fIcyParams;
  }

  const char* uri;
  char** fIcyParams;
  size_t urlPos;
  size_t timePos;
  size_t maxRetries;
  long maxLoops;
  time_t waitSecs;
  time_t maxTime;
  time_t idleTime;
  size_t maxFollow;
  char* daemonize;
  char* auth;
  Http::Auth authData;
  bool help;
};

Params::Params(int argc, char* argv[])
{
  // defaults
  prg = argv[0];
  maxRetries = fIcy::maxRetries;
  maxLoops = fIcy::maxLoops;
  waitSecs = fIcy::waitSecs;
  maxTime = 0;
  maxFollow = fIcy::maxFollow;
  idleTime = 0;
  verbose = help = false;
  daemonize = NULL;
  auth = NULL;

  // locals
  char* path = "fIcy";
  char* maxFollowBuf;
  char* idleTimeBuf;
  int arg;

  // let's again put a bit of SHAME... those FSC**BEEP GNU extensions.
  // WHY _NOT_ BEING POSIXLY_CORRECT BY DEFAULT EH? oooh, "features"! I see.
  while((arg = getopt(argc, argv, "+P:R:L:T:M:l:d:a:vhi:")) != -1)
    switch(arg)
    {
    case 'P':
      path = optarg;
      break;

    case 'R':
      maxRetries = strtoul(optarg, NULL, 0);
      break;

    case 'L':
      maxLoops = strtol(optarg, NULL, 0);
      break;

    case 'T':
      waitSecs = tmParse(optarg);
      break;

    case 'M':
      maxTime = tmParse(optarg);
      break;

    case 'l':
      maxFollowBuf = optarg;
      maxFollow = strtol(optarg, NULL, 0);
      break;

    case 'd':
      daemonize = optarg;
      break;

    case 'h':
      help = true;
      break;

    case 'a':
      auth = optarg;
      break;

    case 'v':
      verbose = true;
      break;

    case 'i':
      idleTimeBuf = optarg;
      idleTime = tmParse(optarg);
      break;
    }

  // fetch authentication tokens immediately to avoid further requests
  if(auth)
    authParse(authData, auth);

  // playlist
  argc -= optind;
  uri = argv[optind++];

  // fIcy parameters
  if(--argc >= 0)
  {
    fIcyParams = new char*[argc + 13];
    fIcyParams[0] = path;
    arg = 1;

    // parameters we allow to override
    if(auth)
    {
      fIcyParams[arg++] = "-a";
      fIcyParams[arg++] = auth;
    }
    if(maxFollow)
    {
      fIcyParams[arg++] = "-l";
      fIcyParams[arg++] = maxFollowBuf;
    }
    if(idleTime)
    {
      fIcyParams[arg++] = "-i";
      fIcyParams[arg++] = idleTimeBuf;
    }

    // forward other parameters
    for(int i = 1; i <= argc; ++i)
      fIcyParams[arg++] = argv[optind++];

    // imposed parameters
    fIcyParams[arg++] = "-M";
    timePos = arg++;

    if(daemonize)
      fIcyParams[arg++] = "-d";

    fIcyParams[arg++] = "--";
    urlPos = arg++;

    fIcyParams[arg++] = NULL;
  }
  else
    fIcyParams = NULL;
}

void
show_help()
{
  cout << prg << fIcy::fPlsHelp << prg << " v" << fIcy::version <<
    " is\n" << fIcy::copyright;
}

void
load_file(string& out, const char* file)
{
  ifstream in(file);
  if(!in)
    throw runtime_error(string("cannot open ") + file);

  // load the file
  char buf[fIcy::bufSz];

  do
  {
    in.read(buf, sizeof(buf));
    out.append(buf, in.gcount());
  }
  while(in);

  if(!in.eof())
    throw runtime_error(string("errors while reading from ") + file);
}

void
load_file(string& out, const URL& url, const size_t maxFollow,
    const time_t idleTime, const Http::Auth* auth)
{
  // setup headers
  Http::Header qHeaders;
  qHeaders.push_back(fIcy::userAgent);
  if(auth)
    qHeaders.push_back(auth->basicHeader());

  // connection
  map<string, string> pReply;
  auto_ptr<Socket> s(htFollow(pReply, url, qHeaders, maxFollow, idleTime));

  // load the file
  char buf[fIcy::bufSz];
  size_t ret;

  while((ret = s->read(buf, sizeof(buf))) > 0)
    out.append(buf, ret);
}

void
load_list(string& buf, const char* uri, const size_t maxFollow,
    const time_t idleTime, const Http::Auth* auth)
{
  URL url(uri);

  if(url.proto == Http::Proto::proto)
    load_file(buf, url, maxFollow, idleTime, auth);
  else if(!url.proto.size())
  {
    msg("loading playlist from %s", uri);
    load_file(buf, uri);
  }
  else
    throw runtime_error(string("unknown protocol ") + url.proto);
}

// exec fIcy and return the exit code
int
exec_fIcy(Params& params, const time_t maxTime, const char* stream)
{
  char** args = params.fIcyParams;
  char buf[16];
  snprintf(buf, sizeof(buf), "%lu", maxTime);
  args[params.timePos] = const_cast<char*>(buf);
  args[params.urlPos] = const_cast<char*>(stream);
  int ret;

  switch(fork())
  {
  case -1:
    err("cannot fork");
    return Exit::args;

  case 0:
    execvp(args[0], args);
    err("cannot exec fIcy: %s", strerror(errno));
    exit(Exit::args);
  }

  wait(&ret);
  return (WIFEXITED(ret)? WEXITSTATUS(ret): Exit::args);
}

void
daemonize(const char* logFile)
{
  int fd;

  // ensure correctness before daemonization
  if(logFile)
    if((fd = open(logFile, O_WRONLY | O_APPEND | O_CREAT, 0666)) == -1)
      throw runtime_error((string("cannot open log file ") + logFile).c_str());

  // daemonize
#ifdef __sgi
  if(_daemonize(0, fd, -1, -1) == -1)
#else
  if(daemon(0, 0) == -1)
#endif
    throw runtime_error("cannot daemonize process");

  // fix stderr
  if(logFile)
    dup2(fd, STDERR_FILENO);
}

int
main(int argc, char* argv[]) try
{
  // initialize
  Params params(argc, argv);
  if(!params.uri && !params.help)
  {
    err("bad parameters; see %s -h", prg);
    return Exit::args;
  }
  if(params.help)
  {
    show_help();
    return Exit::args;
  }

  // fetch and parse the playlist
  list<string> playlist;
  {
    string buf;
    load_list(buf, params.uri, params.maxFollow, params.idleTime,
	(params.auth? &params.authData: NULL));
    istringstream stream(buf);
    plsParse(playlist, stream);
  }
  msg("loaded %d elements", playlist.size());

  // daemonize now if requested
  if(params.daemonize)
    daemonize(params.daemonize);

  // residual playing time
  time_t resTime(params.maxTime);

  // main loop
  for(size_t loop = 0; static_cast<long>(loop) != params.maxLoops; ++loop)
  {
    for(list<string>::const_iterator it = playlist.begin();
	it != playlist.end(); ++it)
    {
      for(size_t retry = 0; retry != params.maxRetries; ++retry)
      {
	// sweet dreams on temporary failures
	if(loop || it != playlist.begin())
	  sleep(params.waitSecs);

	time_t start(time(NULL));
	msg("stream %s: retry %d of loop %d", it->c_str(), retry + 1, loop + 1);

	int ret = exec_fIcy(params, resTime, it->c_str());
	if(ret == Exit::args)
	  return Exit::fail;

	// update residual
	if(params.maxTime)
	{
	  time_t d(time(NULL) - start + params.waitSecs);
	  if(d >= resTime)
	    return ret;
	  resTime -= d;
	}

	// check for success after maxTime
	if(ret == Exit::success)
	  break;
      }
    }
  }

  return Exit::success;
}
catch(runtime_error& err)
{
  ::err("%s", err.what());
  return Exit::fail;
}
catch(...)
{
  err("unknown error, aborting");
  abort();
}
<commit_msg>Fix automatic forwarding of -il with defaults.<commit_after>/*
 * fPls - playlist handler for fIcy
 * Copyright(c) 2004-2005 of wave++ (Yuri D'Elia) <wavexx@users.sf.net>
 * Distributed under GNU LGPL without ANY warranty.
 */

// local headers
#include "fIcy.hh"
#include "msg.hh"
#include "htfollow.hh"
#include "plsparse.hh"
#include "tmparse.hh"
#include "authparse.hh"
using std::string;
using std::list;
using std::map;

// system headers
#include <fstream>
using std::ifstream;

#include <sstream>
using std::istringstream;

#include <iostream>
using std::cout;

#include <memory>
using std::auto_ptr;

#include <stdexcept>
using std::runtime_error;

// c system headers
#include <cstdlib>
using std::strtoul;
using std::strtol;

#include <stdarg.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>
#include <time.h>
#include <errno.h>
#include <fcntl.h>

/*
 * Parameters handling
 */
class Params
{
public:
  explicit
  Params(int argc, char* argv[]);

  ~Params() throw()
  {
    if(fIcyParams)
      delete[] fIcyParams;
  }

  const char* uri;
  char** fIcyParams;
  size_t urlPos;
  size_t timePos;
  size_t maxRetries;
  long maxLoops;
  time_t waitSecs;
  time_t maxTime;
  time_t idleTime;
  size_t maxFollow;
  char* daemonize;
  char* auth;
  Http::Auth authData;
  bool help;
};

Params::Params(int argc, char* argv[])
{
  // defaults
  prg = argv[0];
  maxRetries = fIcy::maxRetries;
  maxLoops = fIcy::maxLoops;
  waitSecs = fIcy::waitSecs;
  maxTime = 0;
  maxFollow = fIcy::maxFollow;
  idleTime = 0;
  verbose = help = false;
  daemonize = NULL;
  auth = NULL;

  // locals
  char* path = "fIcy";
  char* maxFollowBuf = NULL;
  char* idleTimeBuf = NULL;
  int arg;

  // let's again put a bit of SHAME... those FSC**BEEP GNU extensions.
  // WHY _NOT_ BEING POSIXLY_CORRECT BY DEFAULT EH? oooh, "features"! I see.
  while((arg = getopt(argc, argv, "+P:R:L:T:M:l:d:a:vhi:")) != -1)
    switch(arg)
    {
    case 'P':
      path = optarg;
      break;

    case 'R':
      maxRetries = strtoul(optarg, NULL, 0);
      break;

    case 'L':
      maxLoops = strtol(optarg, NULL, 0);
      break;

    case 'T':
      waitSecs = tmParse(optarg);
      break;

    case 'M':
      maxTime = tmParse(optarg);
      break;

    case 'l':
      maxFollowBuf = optarg;
      maxFollow = strtol(optarg, NULL, 0);
      break;

    case 'd':
      daemonize = optarg;
      break;

    case 'h':
      help = true;
      break;

    case 'a':
      auth = optarg;
      break;

    case 'v':
      verbose = true;
      break;

    case 'i':
      idleTimeBuf = optarg;
      idleTime = tmParse(optarg);
      break;
    }

  // fetch authentication tokens immediately to avoid further requests
  if(auth)
    authParse(authData, auth);

  // playlist
  argc -= optind;
  uri = argv[optind++];

  // fIcy parameters
  if(--argc >= 0)
  {
    fIcyParams = new char*[argc + 13];
    fIcyParams[0] = path;
    arg = 1;

    // parameters we allow to override
    if(auth)
    {
      fIcyParams[arg++] = "-a";
      fIcyParams[arg++] = auth;
    }
    if(maxFollowBuf)
    {
      fIcyParams[arg++] = "-l";
      fIcyParams[arg++] = maxFollowBuf;
    }
    if(idleTimeBuf)
    {
      fIcyParams[arg++] = "-i";
      fIcyParams[arg++] = idleTimeBuf;
    }

    // forward other parameters
    for(int i = 1; i <= argc; ++i)
      fIcyParams[arg++] = argv[optind++];

    // imposed parameters
    fIcyParams[arg++] = "-M";
    timePos = arg++;

    if(daemonize)
      fIcyParams[arg++] = "-d";

    fIcyParams[arg++] = "--";
    urlPos = arg++;

    fIcyParams[arg++] = NULL;
  }
  else
    fIcyParams = NULL;
}

void
show_help()
{
  cout << prg << fIcy::fPlsHelp << prg << " v" << fIcy::version <<
    " is\n" << fIcy::copyright;
}

void
load_file(string& out, const char* file)
{
  ifstream in(file);
  if(!in)
    throw runtime_error(string("cannot open ") + file);

  // load the file
  char buf[fIcy::bufSz];

  do
  {
    in.read(buf, sizeof(buf));
    out.append(buf, in.gcount());
  }
  while(in);

  if(!in.eof())
    throw runtime_error(string("errors while reading from ") + file);
}

void
load_file(string& out, const URL& url, const size_t maxFollow,
    const time_t idleTime, const Http::Auth* auth)
{
  // setup headers
  Http::Header qHeaders;
  qHeaders.push_back(fIcy::userAgent);
  if(auth)
    qHeaders.push_back(auth->basicHeader());

  // connection
  map<string, string> pReply;
  auto_ptr<Socket> s(htFollow(pReply, url, qHeaders, maxFollow, idleTime));

  // load the file
  char buf[fIcy::bufSz];
  size_t ret;

  while((ret = s->read(buf, sizeof(buf))) > 0)
    out.append(buf, ret);
}

void
load_list(string& buf, const char* uri, const size_t maxFollow,
    const time_t idleTime, const Http::Auth* auth)
{
  URL url(uri);

  if(url.proto == Http::Proto::proto)
    load_file(buf, url, maxFollow, idleTime, auth);
  else if(!url.proto.size())
  {
    msg("loading playlist from %s", uri);
    load_file(buf, uri);
  }
  else
    throw runtime_error(string("unknown protocol ") + url.proto);
}

// exec fIcy and return the exit code
int
exec_fIcy(Params& params, const time_t maxTime, const char* stream)
{
  char** args = params.fIcyParams;
  char buf[16];
  snprintf(buf, sizeof(buf), "%lu", maxTime);
  args[params.timePos] = const_cast<char*>(buf);
  args[params.urlPos] = const_cast<char*>(stream);
  int ret;

  switch(fork())
  {
  case -1:
    err("cannot fork");
    return Exit::args;

  case 0:
    execvp(args[0], args);
    err("cannot exec fIcy: %s", strerror(errno));
    exit(Exit::args);
  }

  wait(&ret);
  return (WIFEXITED(ret)? WEXITSTATUS(ret): Exit::args);
}

void
daemonize(const char* logFile)
{
  int fd;

  // ensure correctness before daemonization
  if(logFile)
    if((fd = open(logFile, O_WRONLY | O_APPEND | O_CREAT, 0666)) == -1)
      throw runtime_error((string("cannot open log file ") + logFile).c_str());

  // daemonize
#ifdef __sgi
  if(_daemonize(0, fd, -1, -1) == -1)
#else
  if(daemon(0, 0) == -1)
#endif
    throw runtime_error("cannot daemonize process");

  // fix stderr
  if(logFile)
    dup2(fd, STDERR_FILENO);
}

int
main(int argc, char* argv[]) try
{
  // initialize
  Params params(argc, argv);
  if(!params.uri && !params.help)
  {
    err("bad parameters; see %s -h", prg);
    return Exit::args;
  }
  if(params.help)
  {
    show_help();
    return Exit::args;
  }

  // fetch and parse the playlist
  list<string> playlist;
  {
    string buf;
    load_list(buf, params.uri, params.maxFollow, params.idleTime,
	(params.auth? &params.authData: NULL));
    istringstream stream(buf);
    plsParse(playlist, stream);
  }
  msg("loaded %d elements", playlist.size());

  // daemonize now if requested
  if(params.daemonize)
    daemonize(params.daemonize);

  // residual playing time
  time_t resTime(params.maxTime);

  // main loop
  for(size_t loop = 0; static_cast<long>(loop) != params.maxLoops; ++loop)
  {
    for(list<string>::const_iterator it = playlist.begin();
	it != playlist.end(); ++it)
    {
      for(size_t retry = 0; retry != params.maxRetries; ++retry)
      {
	// sweet dreams on temporary failures
	if(loop || it != playlist.begin())
	  sleep(params.waitSecs);

	time_t start(time(NULL));
	msg("stream %s: retry %d of loop %d", it->c_str(), retry + 1, loop + 1);

	int ret = exec_fIcy(params, resTime, it->c_str());
	if(ret == Exit::args)
	  return Exit::fail;

	// update residual
	if(params.maxTime)
	{
	  time_t d(time(NULL) - start + params.waitSecs);
	  if(d >= resTime)
	    return ret;
	  resTime -= d;
	}

	// check for success after maxTime
	if(ret == Exit::success)
	  break;
      }
    }
  }

  return Exit::success;
}
catch(runtime_error& err)
{
  ::err("%s", err.what());
  return Exit::fail;
}
catch(...)
{
  err("unknown error, aborting");
  abort();
}
<|endoftext|>