<commit_before>#include "SettingsUI.h"

#include <iostream>

#include "../3RVX/CommCtl.h"

/* DLGTEMPLATEEX Structure */
#include <pshpack1.h>
typedef struct DLGTEMPLATEEX
{
    WORD dlgVer;
    WORD signature;
    DWORD helpID;
    DWORD exStyle;
    DWORD style;
    WORD cDlgItems;
    short x;
    short y;
    short cx;
    short cy;
} DLGTEMPLATEEX, *LPDLGTEMPLATEEX;
#include <poppack.h>

/* Needed to determine whether the Apply button is enabled/disabled */
#define IDD_APPLYNOW 0x3021

#include "../3RVX/3RVX.h"
#include "../3RVX/LanguageTranslator.h"
#include "../3RVX/Logger.h"
#include "../3RVX/Settings.h"
#include "UITranslator.h"

/* Tabs*/
#include "Tabs/Tab.h"
#include "Tabs/General.h"
#include "Tabs/Display.h"
#include "Tabs/Hotkeys.h"
#include "Tabs/About.h"
General general;
Display display;
Hotkeys hotkeys;
About about;
Tab *tabs[] = { &general, &display, &hotkeys, &about };

/* Startup x/y location offsets */
#define XOFFSET 70
#define YOFFSET 20

HANDLE mutex;
HWND mainWnd = NULL;
HWND tabWnd = NULL;
HINSTANCE hInst;
bool relaunch = false;

int APIENTRY wWinMain(
        _In_ HINSTANCE hInstance,
        _In_opt_ HINSTANCE hPrevInstance,
        _In_ LPTSTR lpCmdLine,
        _In_ int nCmdShow) {

    hInst = hInstance;
	UNREFERENCED_PARAMETER(hPrevInstance);
	UNREFERENCED_PARAMETER(lpCmdLine);

    Logger::Start();
    CLOG(L"Starting SettingsUI...");

    mutex = CreateMutex(NULL, FALSE, L"Local\\3RVXSettings");
    if (GetLastError() == ERROR_ALREADY_EXISTS) {
        if (mutex) {
            ReleaseMutex(mutex);
        }

        HWND settingsWnd = _3RVX::MasterSettingsHwnd();
        CLOG(L"A settings instance is already running. Moving window [%d] "
            L"to the foreground.", (int) settingsWnd);
        SetForegroundWindow(settingsWnd);
        SendMessage(
            settingsWnd,
            _3RVX::WM_3RVX_SETTINGSCTRL,
            _3RVX::MSG_ACTIVATE,
            NULL);

#if defined(ENABLE_3RVX_LOG) && (defined(ENABLE_3RVX_LOGTOFILE) == FALSE)
        CLOG(L"Press [enter] to terminate");
        std::cin.get();
#endif

        return EXIT_SUCCESS;
    }

    WNDCLASSEX wcex = { 0 };
    wcex.cbSize = sizeof(WNDCLASSEX);
    wcex.lpfnWndProc = WndProc;
    wcex.hInstance = hInst;
    wcex.hIcon = LoadIcon(NULL, MAKEINTRESOURCE(IDI_SETTINGS));
    wcex.hbrBackground = (HBRUSH) (COLOR_WINDOW);
    wcex.lpszClassName = _3RVX::CLASS_3RVX_SETTINGS;

    if (RegisterClassEx(&wcex) == 0) {
        CLOG(L"Could not register class: %d", GetLastError());
        return EXIT_FAILURE;
    }

    mainWnd = CreateWindowEx(
        NULL,
        _3RVX::CLASS_3RVX_SETTINGS, _3RVX::CLASS_3RVX_SETTINGS,
        NULL, 0, 0, 0, 0, NULL, NULL, hInst, NULL);

    INT_PTR result;
    do {
        result = LaunchPropertySheet();
        CLOG(L"RL: %s", relaunch ? L"TRUE" : L"FALSE");
    } while (relaunch == true);

    return result;
}

INT_PTR LaunchPropertySheet() {
    Settings *settings = Settings::Instance();
    settings->Load();
    PROPSHEETPAGE psp[4];

    LanguageTranslator *lt = settings->Translator();
    std::wstring genTitle = lt->Translate(std::wstring(L"General"));
    std::wstring dispTitle = lt->Translate(std::wstring(L"Display"));
    std::wstring hkTitle = lt->Translate(std::wstring(L"Hotkeys"));
    std::wstring aboutTitle = lt->Translate(std::wstring(L"About"));

    psp[0] = { 0 };
    psp[0].dwSize = sizeof(PROPSHEETPAGE);
    psp[0].dwFlags = PSP_USETITLE;
    psp[0].hInstance = hInst;
    psp[0].pszTemplate = MAKEINTRESOURCE(IDD_GENERAL);
    psp[0].pszIcon = NULL;
    psp[0].pfnDlgProc = (DLGPROC) GeneralTabProc;
    psp[0].pszTitle = &genTitle[0];
    psp[0].lParam = NULL;

    psp[1] = { 0 };
    psp[1].dwSize = sizeof(PROPSHEETPAGE);
    psp[1].dwFlags = PSP_USETITLE;
    psp[1].hInstance = hInst;
    psp[1].pszTemplate = MAKEINTRESOURCE(IDD_DISPLAY);
    psp[1].pszIcon = NULL;
    psp[1].pfnDlgProc = (DLGPROC) DisplayTabProc;
    psp[1].pszTitle = &dispTitle[0];
    psp[1].lParam = 0;

    psp[2] = { 0 };
    psp[2].dwSize = sizeof(PROPSHEETPAGE);
    psp[2].dwFlags = PSP_USETITLE;
    psp[2].hInstance = hInst;
    psp[2].pszTemplate = MAKEINTRESOURCE(IDD_HOTKEYS);
    psp[2].pszIcon = NULL;
    psp[2].pfnDlgProc = (DLGPROC) HotkeyTabProc;
    psp[2].pszTitle = &hkTitle[0];
    psp[2].lParam = 0;

    psp[3] = { 0 };
    psp[3].dwSize = sizeof(PROPSHEETPAGE);
    psp[3].dwFlags = PSP_USETITLE;
    psp[3].hInstance = hInst;
    psp[3].pszTemplate = MAKEINTRESOURCE(IDD_ABOUT);
    psp[3].pszIcon = NULL;
    psp[3].pfnDlgProc = (DLGPROC) AboutTabProc;
    psp[3].pszTitle = &aboutTitle[0];
    psp[3].lParam = 0;

    PROPSHEETHEADER psh = { 0 };
    psh.dwSize = sizeof(PROPSHEETHEADER);
    psh.dwFlags = PSH_PROPSHEETPAGE | PSH_USEICONID | PSH_USECALLBACK;
    psh.hwndParent = mainWnd;
    psh.hInstance = hInst;
    psh.pszIcon = MAKEINTRESOURCE(IDI_SETTINGS);
    psh.pszCaption = L"3RVX Settings";
    psh.nStartPage = 0;
    psh.nPages = sizeof(psp) / sizeof(PROPSHEETPAGE);
    psh.ppsp = (LPCPROPSHEETPAGE) &psp;
    psh.pfnCallback = (PFNPROPSHEETCALLBACK) PropSheetProc;

    tabWnd = NULL;

    /* Position the window if this is the first launch */
    if (relaunch == false) {
        POINT pt = { 0 };
        GetCursorPos(&pt);
        MoveWindow(mainWnd, pt.x - XOFFSET, pt.y - YOFFSET, 0, 0, TRUE);
    }

    relaunch = false;

    CLOG(L"Launching modal property sheet.");
    return PropertySheet(&psh);
}

LRESULT CALLBACK WndProc(
        HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {

    PAINTSTRUCT ps;
    HDC hdc;

    switch (message) {
    case WM_PAINT:
        hdc = BeginPaint(hWnd, &ps);
        EndPaint(hWnd, &ps);
        break;

    case WM_DESTROY:
        PostQuitMessage(0);
        break;
    }

    if (message == _3RVX::WM_3RVX_SETTINGSCTRL) {
        switch (wParam) {
        case _3RVX::MSG_ACTIVATE:
            CLOG(L"Received request to activate window from external program");
            SetActiveWindow(tabWnd);
            break;

        case _3RVX::MSG_LANGCHANGE:
            relaunch = true;
            break;
        }
    }

    return DefWindowProc(hWnd, message, wParam, lParam);
}

int CALLBACK PropSheetProc(HWND hWnd, UINT msg, LPARAM lParam) {
    switch (msg) {
    case PSCB_PRECREATE:
        /* Disable the help button: */
        if (((LPDLGTEMPLATEEX) lParam)->signature == 0xFFFF) {
            ((LPDLGTEMPLATEEX) lParam)->style &= ~DS_CONTEXTHELP;
        } else {
            ((LPDLGTEMPLATE) lParam)->style &= ~DS_CONTEXTHELP;
        }

        /* Show window in the taskbar: */
        ((LPDLGTEMPLATE) lParam)->dwExtendedStyle |= WS_EX_APPWINDOW;
        break;

    case PSCB_INITIALIZED:
        UITranslator::TranslateWindowText(hWnd);

        if (tabWnd == NULL) {
            tabWnd = hWnd;
        }

        /* These values are hard-coded in case the user has a non-english GUI
           but wants to change the program language */
        UITranslator::TranslateControlText(
            hWnd, IDOK, std::wstring(L"OK"));
        UITranslator::TranslateControlText(
            hWnd, IDCANCEL, std::wstring(L"Cancel"));
        UITranslator::TranslateControlText(
            hWnd, IDD_APPLYNOW, std::wstring(L"Apply"));
        break;

    case PSCB_BUTTONPRESSED:
        if (lParam == PSBTN_OK || lParam == PSBTN_APPLYNOW) {
            HWND hApply = GetDlgItem(hWnd, IDD_APPLYNOW);
            if (IsWindowEnabled(hApply)) {
                /* Save settings*/
                CLOG(L"Saving settings...");
                for (Tab *tab : tabs) {
                    tab->SaveSettings();
                }
                Settings::Instance()->Save();

                CLOG(L"Notifying 3RVX process of settings change");
                _3RVX::Message(_3RVX::MSG_LOAD, NULL, true);

                if (lParam == PSBTN_APPLYNOW && relaunch == true) {
                    /* Language was changed */
                    SendMessage(tabWnd, WM_CLOSE, NULL, NULL);
                } else {
                    relaunch = false;
                }
            }
        }
        break;
    }

    return TRUE;
}

DLGPROC GeneralTabProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) {
    return general.TabProc(hDlg, message, wParam, lParam);
}

DLGPROC DisplayTabProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) {
    return display.TabProc(hDlg, message, wParam, lParam);
}

DLGPROC HotkeyTabProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) {
    return hotkeys.TabProc(hDlg, message, wParam, lParam);
}

DLGPROC AboutTabProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) {
    return about.TabProc(hDlg, message, wParam, lParam);
}<commit_msg>For now, if the settings program is started in update mode, just exit.<commit_after>#include "SettingsUI.h"

#include <iostream>

#include "../3RVX/CommCtl.h"

/* DLGTEMPLATEEX Structure */
#include <pshpack1.h>
typedef struct DLGTEMPLATEEX
{
    WORD dlgVer;
    WORD signature;
    DWORD helpID;
    DWORD exStyle;
    DWORD style;
    WORD cDlgItems;
    short x;
    short y;
    short cx;
    short cy;
} DLGTEMPLATEEX, *LPDLGTEMPLATEEX;
#include <poppack.h>

/* Needed to determine whether the Apply button is enabled/disabled */
#define IDD_APPLYNOW 0x3021

#include "../3RVX/3RVX.h"
#include "../3RVX/LanguageTranslator.h"
#include "../3RVX/Logger.h"
#include "../3RVX/Settings.h"
#include "UITranslator.h"

/* Tabs*/
#include "Tabs/Tab.h"
#include "Tabs/General.h"
#include "Tabs/Display.h"
#include "Tabs/Hotkeys.h"
#include "Tabs/About.h"
General general;
Display display;
Hotkeys hotkeys;
About about;
Tab *tabs[] = { &general, &display, &hotkeys, &about };

/* Startup x/y location offsets */
#define XOFFSET 70
#define YOFFSET 20

HANDLE mutex;
HWND mainWnd = NULL;
HWND tabWnd = NULL;
HINSTANCE hInst;
bool relaunch = false;

int APIENTRY wWinMain(
        _In_ HINSTANCE hInstance,
        _In_opt_ HINSTANCE hPrevInstance,
        _In_ LPTSTR lpCmdLine,
        _In_ int nCmdShow) {

    hInst = hInstance;
	UNREFERENCED_PARAMETER(hPrevInstance);
	UNREFERENCED_PARAMETER(lpCmdLine);

    std::wstring cmdLine(lpCmdLine);
    if (cmdLine.find(L"-update") != std::wstring::npos) {
        return 0;
    }

    Logger::Start();
    CLOG(L"Starting SettingsUI...");

    mutex = CreateMutex(NULL, FALSE, L"Local\\3RVXSettings");
    if (GetLastError() == ERROR_ALREADY_EXISTS) {
        if (mutex) {
            ReleaseMutex(mutex);
        }

        HWND settingsWnd = _3RVX::MasterSettingsHwnd();
        CLOG(L"A settings instance is already running. Moving window [%d] "
            L"to the foreground.", (int) settingsWnd);
        SetForegroundWindow(settingsWnd);
        SendMessage(
            settingsWnd,
            _3RVX::WM_3RVX_SETTINGSCTRL,
            _3RVX::MSG_ACTIVATE,
            NULL);

#if defined(ENABLE_3RVX_LOG) && (defined(ENABLE_3RVX_LOGTOFILE) == FALSE)
        CLOG(L"Press [enter] to terminate");
        std::cin.get();
#endif

        return EXIT_SUCCESS;
    }

    WNDCLASSEX wcex = { 0 };
    wcex.cbSize = sizeof(WNDCLASSEX);
    wcex.lpfnWndProc = WndProc;
    wcex.hInstance = hInst;
    wcex.hIcon = LoadIcon(NULL, MAKEINTRESOURCE(IDI_SETTINGS));
    wcex.hbrBackground = (HBRUSH) (COLOR_WINDOW);
    wcex.lpszClassName = _3RVX::CLASS_3RVX_SETTINGS;

    if (RegisterClassEx(&wcex) == 0) {
        CLOG(L"Could not register class: %d", GetLastError());
        return EXIT_FAILURE;
    }

    mainWnd = CreateWindowEx(
        NULL,
        _3RVX::CLASS_3RVX_SETTINGS, _3RVX::CLASS_3RVX_SETTINGS,
        NULL, 0, 0, 0, 0, NULL, NULL, hInst, NULL);

    INT_PTR result;
    do {
        result = LaunchPropertySheet();
        CLOG(L"RL: %s", relaunch ? L"TRUE" : L"FALSE");
    } while (relaunch == true);

    return result;
}

INT_PTR LaunchPropertySheet() {
    Settings *settings = Settings::Instance();
    settings->Load();
    PROPSHEETPAGE psp[4];

    LanguageTranslator *lt = settings->Translator();
    std::wstring genTitle = lt->Translate(std::wstring(L"General"));
    std::wstring dispTitle = lt->Translate(std::wstring(L"Display"));
    std::wstring hkTitle = lt->Translate(std::wstring(L"Hotkeys"));
    std::wstring aboutTitle = lt->Translate(std::wstring(L"About"));

    psp[0] = { 0 };
    psp[0].dwSize = sizeof(PROPSHEETPAGE);
    psp[0].dwFlags = PSP_USETITLE;
    psp[0].hInstance = hInst;
    psp[0].pszTemplate = MAKEINTRESOURCE(IDD_GENERAL);
    psp[0].pszIcon = NULL;
    psp[0].pfnDlgProc = (DLGPROC) GeneralTabProc;
    psp[0].pszTitle = &genTitle[0];
    psp[0].lParam = NULL;

    psp[1] = { 0 };
    psp[1].dwSize = sizeof(PROPSHEETPAGE);
    psp[1].dwFlags = PSP_USETITLE;
    psp[1].hInstance = hInst;
    psp[1].pszTemplate = MAKEINTRESOURCE(IDD_DISPLAY);
    psp[1].pszIcon = NULL;
    psp[1].pfnDlgProc = (DLGPROC) DisplayTabProc;
    psp[1].pszTitle = &dispTitle[0];
    psp[1].lParam = 0;

    psp[2] = { 0 };
    psp[2].dwSize = sizeof(PROPSHEETPAGE);
    psp[2].dwFlags = PSP_USETITLE;
    psp[2].hInstance = hInst;
    psp[2].pszTemplate = MAKEINTRESOURCE(IDD_HOTKEYS);
    psp[2].pszIcon = NULL;
    psp[2].pfnDlgProc = (DLGPROC) HotkeyTabProc;
    psp[2].pszTitle = &hkTitle[0];
    psp[2].lParam = 0;

    psp[3] = { 0 };
    psp[3].dwSize = sizeof(PROPSHEETPAGE);
    psp[3].dwFlags = PSP_USETITLE;
    psp[3].hInstance = hInst;
    psp[3].pszTemplate = MAKEINTRESOURCE(IDD_ABOUT);
    psp[3].pszIcon = NULL;
    psp[3].pfnDlgProc = (DLGPROC) AboutTabProc;
    psp[3].pszTitle = &aboutTitle[0];
    psp[3].lParam = 0;

    PROPSHEETHEADER psh = { 0 };
    psh.dwSize = sizeof(PROPSHEETHEADER);
    psh.dwFlags = PSH_PROPSHEETPAGE | PSH_USEICONID | PSH_USECALLBACK;
    psh.hwndParent = mainWnd;
    psh.hInstance = hInst;
    psh.pszIcon = MAKEINTRESOURCE(IDI_SETTINGS);
    psh.pszCaption = L"3RVX Settings";
    psh.nStartPage = 0;
    psh.nPages = sizeof(psp) / sizeof(PROPSHEETPAGE);
    psh.ppsp = (LPCPROPSHEETPAGE) &psp;
    psh.pfnCallback = (PFNPROPSHEETCALLBACK) PropSheetProc;

    tabWnd = NULL;

    /* Position the window if this is the first launch */
    if (relaunch == false) {
        POINT pt = { 0 };
        GetCursorPos(&pt);
        MoveWindow(mainWnd, pt.x - XOFFSET, pt.y - YOFFSET, 0, 0, TRUE);
    }

    relaunch = false;

    CLOG(L"Launching modal property sheet.");
    return PropertySheet(&psh);
}

LRESULT CALLBACK WndProc(
        HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {

    PAINTSTRUCT ps;
    HDC hdc;

    switch (message) {
    case WM_PAINT:
        hdc = BeginPaint(hWnd, &ps);
        EndPaint(hWnd, &ps);
        break;

    case WM_DESTROY:
        PostQuitMessage(0);
        break;
    }

    if (message == _3RVX::WM_3RVX_SETTINGSCTRL) {
        switch (wParam) {
        case _3RVX::MSG_ACTIVATE:
            CLOG(L"Received request to activate window from external program");
            SetActiveWindow(tabWnd);
            break;

        case _3RVX::MSG_LANGCHANGE:
            relaunch = true;
            break;
        }
    }

    return DefWindowProc(hWnd, message, wParam, lParam);
}

int CALLBACK PropSheetProc(HWND hWnd, UINT msg, LPARAM lParam) {
    switch (msg) {
    case PSCB_PRECREATE:
        /* Disable the help button: */
        if (((LPDLGTEMPLATEEX) lParam)->signature == 0xFFFF) {
            ((LPDLGTEMPLATEEX) lParam)->style &= ~DS_CONTEXTHELP;
        } else {
            ((LPDLGTEMPLATE) lParam)->style &= ~DS_CONTEXTHELP;
        }

        /* Show window in the taskbar: */
        ((LPDLGTEMPLATE) lParam)->dwExtendedStyle |= WS_EX_APPWINDOW;
        break;

    case PSCB_INITIALIZED:
        UITranslator::TranslateWindowText(hWnd);

        if (tabWnd == NULL) {
            tabWnd = hWnd;
        }

        /* These values are hard-coded in case the user has a non-english GUI
           but wants to change the program language */
        UITranslator::TranslateControlText(
            hWnd, IDOK, std::wstring(L"OK"));
        UITranslator::TranslateControlText(
            hWnd, IDCANCEL, std::wstring(L"Cancel"));
        UITranslator::TranslateControlText(
            hWnd, IDD_APPLYNOW, std::wstring(L"Apply"));
        break;

    case PSCB_BUTTONPRESSED:
        if (lParam == PSBTN_OK || lParam == PSBTN_APPLYNOW) {
            HWND hApply = GetDlgItem(hWnd, IDD_APPLYNOW);
            if (IsWindowEnabled(hApply)) {
                /* Save settings*/
                CLOG(L"Saving settings...");
                for (Tab *tab : tabs) {
                    tab->SaveSettings();
                }
                Settings::Instance()->Save();

                CLOG(L"Notifying 3RVX process of settings change");
                _3RVX::Message(_3RVX::MSG_LOAD, NULL, true);

                if (lParam == PSBTN_APPLYNOW && relaunch == true) {
                    /* Language was changed */
                    SendMessage(tabWnd, WM_CLOSE, NULL, NULL);
                } else {
                    relaunch = false;
                }
            }
        }
        break;
    }

    return TRUE;
}

DLGPROC GeneralTabProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) {
    return general.TabProc(hDlg, message, wParam, lParam);
}

DLGPROC DisplayTabProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) {
    return display.TabProc(hDlg, message, wParam, lParam);
}

DLGPROC HotkeyTabProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) {
    return hotkeys.TabProc(hDlg, message, wParam, lParam);
}

DLGPROC AboutTabProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) {
    return about.TabProc(hDlg, message, wParam, lParam);
}<|endoftext|>


<commit_before>#include "Console.h"
#include "App.h"
#include "ModuleInput.h"
#include "imgui.h"
#include "Functions.h"

Console::Console(bool start_enabled) : EditorElement(start_enabled)
{
	memset(input_buffer, 0, sizeof(input_buffer));
}

Console::~Console()
{
}

void Console::Draw()
{
	bool ret = true;

	AddLogs();

	if (App->input->GetKey(SDL_SCANCODE_GRAVE) == KEY_DOWN)
	{
		visible = !visible;
		return;
	}

	if (!visible)
		return;

	ImGui::SetNextWindowSize(ImVec2(450, 500), ImGuiCond_FirstUseEver);

	if (ImGui::Begin("Console", &visible))
	{
		if (ImGui::SmallButton("Clear"))
			CommandInput(".Clear");

		ImGui::SameLine();

		if (ImGui::SmallButton("Help"))
			CommandInput(".Help");

		ImGui::Separator();

		// Scrollable
		ImGui::BeginChild("ScrollingRegion", ImVec2(0, -ImGui::GetItemsLineHeightWithSpacing()), false, ImGuiWindowFlags_HorizontalScrollbar);
		ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(4, 1));

		// Scrollable texts
		for (list<console_text>::iterator it = console_items.begin(); it != console_items.end(); it++)
		{
			ImVec4 col = GetColorByTextType((*it).type);
			ImGui::PushStyleColor(ImGuiCol_Text, col);
			ImGui::TextUnformatted((*it).txt.c_str());
			ImGui::PopStyleColor();
		}

		// Scroll to bottom
		if (scroll_bottom)
		{
			ImGui::SetScrollHere();
			scroll_bottom = false;
		}

		ImGui::PopStyleVar();
		ImGui::EndChild();

		ImGui::Separator();

		// Text input
		if (ImGui::InputText("", input_buffer, 254, ImGuiInputTextFlags_EnterReturnsTrue | ImGuiInputTextFlags_CallbackCompletion
			| ImGuiInputTextFlags_CallbackHistory, &TextChangeCallback, (void*)this))
		{
			send_text_input = true;
		}

		// Keep focus on text input
		if (ImGui::IsItemHovered() || (ImGui::IsRootWindowOrAnyChildFocused() && !ImGui::IsAnyItemActive() && !ImGui::IsMouseClicked(0)))
			ImGui::SetKeyboardFocusHere(-1);

		// Submit button
		ImGui::SameLine();
		if (ImGui::Button("Submit", { 100, 23 }))
		{
			send_text_input = true;
		}

		// Input text
		if (send_text_input)
		{
			if (input_buffer != "")
				CommandInput(input_buffer);

			strcpy(input_buffer, "");

			send_text_input = false;
		}
	}
	ImGui::End();
}

void Console::AddLog(const char * txt, console_text_type type)
{
	console_text ct;
	ct.txt = txt;
	ct.type = type;

	console_items.push_back(ct);

	if (console_items.size() > MAX_LINES) {
		console_items.pop_front();
	}

	ScrollBottom();
}

void Console::Clear()
{
	console_items.clear();
}

void Console::ScrollBottom()
{
	scroll_bottom = true;
}

void Console::CommandInput(const char * txt)
{
	if (strcmp(txt, ".Clear") == 0)
	{
		Clear();
	}
	else if (strcmp(txt, ".Help") == 0)
	{
		AddLog("-------------------------HELP-------------------------");
		AddLog("||\t.Clear  \t||\tClears the console");
		AddLog("||\t.Help   \t||\tShows the list of commands");
	}
}

ImColor Console::GetColorByTextType(console_text_type type)
{
	ImColor ret(255, 255, 255, 255);

	switch (type)
	{
	case console_text_type::console_text_type_default:
		ret = { 255, 255, 255, 255 };
		break;

	case console_text_type::console_text_type_info:
		ret = { 255, 255, 255, 255 };
		break;

	case console_text_type::console_text_type_error:
		ret = { 255, 80, 80, 255 };
		break;

	case console_text_type::console_text_type_succes:
		ret = { 255, 255, 255, 255 };
		break;

	case console_text_type::console_text_type_warning:
		ret = { 255, 255, 255, 255 };
		break;
	default:
		break;
	}

	return ret;
}

void Console::AddLogs()
{
	for (list<string>::iterator it = App->logs.begin(); it != App->logs.end(); it++)
	{
		AddLog((*it).c_str());
	}

	App->logs.clear();
}

static int TextChangeCallback(ImGuiTextEditCallbackData * data)
{
	int i = 0;
	return 1;
}<commit_msg>Simon the console size should not be saved<commit_after>#include "Console.h"
#include "App.h"
#include "ModuleInput.h"
#include "imgui.h"
#include "Functions.h"

Console::Console(bool start_enabled) : EditorElement(start_enabled)
{
	memset(input_buffer, 0, sizeof(input_buffer));
}

Console::~Console()
{
}

void Console::Draw()
{
	bool ret = true;

	AddLogs();

	if (App->input->GetKey(SDL_SCANCODE_GRAVE) == KEY_DOWN)
	{
		visible = !visible;
		return;
	}

	if (!visible)
		return;

	ImGui::SetNextWindowSize(ImVec2(450, 500), 2);

	if (ImGui::Begin("Console", &visible))
	{
		if (ImGui::SmallButton("Clear"))
			CommandInput(".Clear");

		ImGui::SameLine();

		if (ImGui::SmallButton("Help"))
			CommandInput(".Help");

		ImGui::Separator();

		// Scrollable
		ImGui::BeginChild("ScrollingRegion", ImVec2(0, -ImGui::GetItemsLineHeightWithSpacing()), false, ImGuiWindowFlags_HorizontalScrollbar);
		ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(4, 1));

		// Scrollable texts
		for (list<console_text>::iterator it = console_items.begin(); it != console_items.end(); it++)
		{
			ImVec4 col = GetColorByTextType((*it).type);
			ImGui::PushStyleColor(ImGuiCol_Text, col);
			ImGui::TextUnformatted((*it).txt.c_str());
			ImGui::PopStyleColor();
		}

		// Scroll to bottom
		if (scroll_bottom)
		{
			ImGui::SetScrollHere();
			scroll_bottom = false;
		}

		ImGui::PopStyleVar();
		ImGui::EndChild();

		ImGui::Separator();

		// Text input
		if (ImGui::InputText("", input_buffer, 254, ImGuiInputTextFlags_EnterReturnsTrue | ImGuiInputTextFlags_CallbackCompletion
			| ImGuiInputTextFlags_CallbackHistory, &TextChangeCallback, (void*)this))
		{
			send_text_input = true;
		}

		// Keep focus on text input
		if (ImGui::IsItemHovered() || (ImGui::IsRootWindowOrAnyChildFocused() && !ImGui::IsAnyItemActive() && !ImGui::IsMouseClicked(0)))
			ImGui::SetKeyboardFocusHere(-1);

		// Submit button
		ImGui::SameLine();
		if (ImGui::Button("Submit", { 100, 23 }))
		{
			send_text_input = true;
		}

		// Input text
		if (send_text_input)
		{
			if (input_buffer != "")
				CommandInput(input_buffer);

			strcpy(input_buffer, "");

			send_text_input = false;
		}
	}
	ImGui::End();
}

void Console::AddLog(const char * txt, console_text_type type)
{
	console_text ct;
	ct.txt = txt;
	ct.type = type;

	console_items.push_back(ct);

	if (console_items.size() > MAX_LINES) {
		console_items.pop_front();
	}

	ScrollBottom();
}

void Console::Clear()
{
	console_items.clear();
}

void Console::ScrollBottom()
{
	scroll_bottom = true;
}

void Console::CommandInput(const char * txt)
{
	if (strcmp(txt, ".Clear") == 0)
	{
		Clear();
	}
	else if (strcmp(txt, ".Help") == 0)
	{
		AddLog("-------------------------HELP-------------------------");
		AddLog("||\t.Clear  \t||\tClears the console");
		AddLog("||\t.Help   \t||\tShows the list of commands");
	}
}

ImColor Console::GetColorByTextType(console_text_type type)
{
	ImColor ret(255, 255, 255, 255);

	switch (type)
	{
	case console_text_type::console_text_type_default:
		ret = { 255, 255, 255, 255 };
		break;

	case console_text_type::console_text_type_info:
		ret = { 255, 255, 255, 255 };
		break;

	case console_text_type::console_text_type_error:
		ret = { 255, 80, 80, 255 };
		break;

	case console_text_type::console_text_type_succes:
		ret = { 255, 255, 255, 255 };
		break;

	case console_text_type::console_text_type_warning:
		ret = { 255, 255, 255, 255 };
		break;
	default:
		break;
	}

	return ret;
}

void Console::AddLogs()
{
	for (list<string>::iterator it = App->logs.begin(); it != App->logs.end(); it++)
	{
		AddLog((*it).c_str());
	}

	App->logs.clear();
}

static int TextChangeCallback(ImGuiTextEditCallbackData * data)
{
	int i = 0;
	return 1;
}<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: linkmgr.hxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: jp $ $Date: 2001-03-08 21:14:34 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/
#ifndef _SVXLINKMGR_HXX
#define _SVXLINKMGR_HXX

#ifndef _LINKMGR_HXX
#include <so3/linkmgr.hxx>
#endif

class Graphic;
class Size;

// Damit der Link ueber den Status der zu ladenen Grafik informierten werden
// verschickt das FileObject ein SvData, mit der FormatId
// "RegisterStatusInfoId" und ein einem String als Datentraeger. Dieser
// enthaelt den folgenden enum.
enum LinkState
{
    STATE_LOAD_OK,
    STATE_LOAD_ERROR,
    STATE_LOAD_ABORT
};

class SvxLinkManager : public so3::SvLinkManager
{
    SvxLinkManager( const SvxLinkManager& );
    SvxLinkManager& operator=( const SvxLinkManager& );

public:
    SvxLinkManager( SvPersist * pCacheCont );

    // den Link mit einem PseudoObject verbinden und in die Liste eintragen
    BOOL InsertFileLink( so3::SvBaseLink&,
                        USHORT nFileType,
                        const String& rTxt,
                        const String* pFilterNm = 0,
                        const String* pRange = 0 );

            // falls am Link schon alles eingestellt ist !
    BOOL InsertFileLink( so3::SvBaseLink& );

        // erfrage die Strings fuer den Dialog
    virtual BOOL GetDisplayNames( const so3::SvBaseLink*,
                                    String* pType,
                                    String* pFile = 0,
                                    String* pLink = 0,
                                    String* pFilter = 0 ) const;

    virtual so3::SvLinkSourceRef CreateObj( so3::SvBaseLink * );

    // eine Uebertragung wird abgebrochen, also alle DownloadMedien canceln
    // (ist zur Zeit nur fuer die FileLinks interressant!)
    void CancelTransfers();

    static void SetTransferPriority( so3::SvBaseLink& rLink, USHORT nPrio );

    // um Status Informationen aus dem FileObject an den BaseLink zu
    // senden, gibt es eine eigene ClipBoardId. Das SvData-Object hat
    // dann die entsprechenden Informationen als String.
    // Wird zur Zeit fuer FileObject in Verbindung mit JavaScript benoetigt
    // - das braucht Informationen ueber Load/Abort/Error
    static ULONG  RegisterStatusInfoId();

    // if the mimetype says graphic/bitmap/gdimetafile then get the
    // graphic from the Any. Return says no errors
    static BOOL GetGraphicFromAny( const String& rMimeType,
                                const ::com::sun::star::uno::Any & rValue,
                                Graphic& rGrf );

};

#endif

<commit_msg>INTEGRATION: CWS mav09 (1.3.714); FILE MERGED 2004/04/14 14:01:48 mba 1.3.714.1: #i27773#: DDE moved from so3<commit_after>/*************************************************************************
 *
 *  $RCSfile: linkmgr.hxx,v $
 *
 *  $Revision: 1.4 $
 *
 *  last change: $Author: kz $ $Date: 2004-10-04 17:44:08 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/
#ifndef _SVXLINKMGR_HXX
#define _SVXLINKMGR_HXX

#ifndef _LINKMGR_HXX
#include <sfx2/linkmgr.hxx>
#endif

class Graphic;
class Size;

// Damit der Link ueber den Status der zu ladenen Grafik informierten werden
// verschickt das FileObject ein SvData, mit der FormatId
// "RegisterStatusInfoId" und ein einem String als Datentraeger. Dieser
// enthaelt den folgenden enum.
enum LinkState
{
    STATE_LOAD_OK,
    STATE_LOAD_ERROR,
    STATE_LOAD_ABORT
};

class SvxLinkManager : public ::sfx2::SvLinkManager
{
    SvxLinkManager( const SvxLinkManager& );
    SvxLinkManager& operator=( const SvxLinkManager& );

public:
    SvxLinkManager( SfxObjectShell * pCacheCont );

    // den Link mit einem PseudoObject verbinden und in die Liste eintragen
    BOOL InsertFileLink( sfx2::SvBaseLink&,
                        USHORT nFileType,
                        const String& rTxt,
                        const String* pFilterNm = 0,
                        const String* pRange = 0 );

            // falls am Link schon alles eingestellt ist !
    BOOL InsertFileLink( sfx2::SvBaseLink& );

        // erfrage die Strings fuer den Dialog
    virtual BOOL GetDisplayNames( const sfx2::SvBaseLink*,
                                    String* pType,
                                    String* pFile = 0,
                                    String* pLink = 0,
                                    String* pFilter = 0 ) const;

    virtual sfx2::SvLinkSourceRef CreateObj( sfx2::SvBaseLink * );

    // eine Uebertragung wird abgebrochen, also alle DownloadMedien canceln
    // (ist zur Zeit nur fuer die FileLinks interressant!)
    void CancelTransfers();

    static void SetTransferPriority( sfx2::SvBaseLink& rLink, USHORT nPrio );

    // um Status Informationen aus dem FileObject an den BaseLink zu
    // senden, gibt es eine eigene ClipBoardId. Das SvData-Object hat
    // dann die entsprechenden Informationen als String.
    // Wird zur Zeit fuer FileObject in Verbindung mit JavaScript benoetigt
    // - das braucht Informationen ueber Load/Abort/Error
    static ULONG  RegisterStatusInfoId();

    // if the mimetype says graphic/bitmap/gdimetafile then get the
    // graphic from the Any. Return says no errors
    static BOOL GetGraphicFromAny( const String& rMimeType,
                                const ::com::sun::star::uno::Any & rValue,
                                Graphic& rGrf );

};

#endif

<|endoftext|>


<commit_before>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you under the Apache
 *   License, Version 2.0 (the "License"); you may not use this file
 *   except in compliance with the License. You may obtain a copy of
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
 */
#ifndef __DBGOUTSW_HXX
#define __DBGOUTSW_HXX

#ifdef DBG_UTIL

#include <boost/unordered_map.hpp>
#include <tox.hxx>
#include <cstdio>
#include "tools/string.hxx"

class SwNode;
class SwTxtAttr;
class SwpHints;
class SfxPoolItem;
class SfxItemSet;
struct SwPosition;
class SwPaM;
class SwNodeNum;
class SwUndo;
class SwRect;
class SwFrmFmt;
class SwFrmFmts;
class SwNodes;
class SwRewriter;
class SwNumRuleTbl;
class SwNumRule;
class SwOutlineNodes;
class SwTxtFmtColl;
class SwNodeRange;

extern bool bDbgOutStdErr;
extern bool bDbgOutPrintAttrSet;

SW_DLLPUBLIC const char * dbg_out(const void * pVoid);
SW_DLLPUBLIC const char * dbg_out(const OUString & aStr);
SW_DLLPUBLIC const char * dbg_out(const SwRect & rRect);
SW_DLLPUBLIC const char * dbg_out(const SwFrmFmt & rFrmFmt);
SW_DLLPUBLIC const char * dbg_out(const SwNode & rNode);
SW_DLLPUBLIC const char * dbg_out(const SwTxtAttr & rAttr);
SW_DLLPUBLIC const char * dbg_out(const SwpHints &rHints);
SW_DLLPUBLIC const char * dbg_out(const SfxPoolItem & rItem);
SW_DLLPUBLIC const char * dbg_out(const SfxPoolItem * pItem);
SW_DLLPUBLIC const char * dbg_out(const SfxItemSet & rSet);
SW_DLLPUBLIC const char * dbg_out(SwNodes & rNodes);
SW_DLLPUBLIC const char * dbg_out(const SwPosition & rPos);
SW_DLLPUBLIC const char * dbg_out(const SwPaM & rPam);
SW_DLLPUBLIC const char * dbg_out(const SwNodeNum & rNum);
SW_DLLPUBLIC const char * dbg_out(const SwUndo & rUndo);
SW_DLLPUBLIC const char * dbg_out(const SwRewriter & rRewriter);
SW_DLLPUBLIC const char * dbg_out(const SwNumRule & rRule);
SW_DLLPUBLIC const char * dbg_out(const SwTxtFmtColl & rFmt);
SW_DLLPUBLIC const char * dbg_out(const SwFrmFmts & rFrmFmts);
SW_DLLPUBLIC const char * dbg_out(const SwNumRuleTbl & rTbl);
SW_DLLPUBLIC const char * dbg_out(const SwNodeRange & rRange);

template<typename tKey, typename tMember, typename fHashFunction>
OUString lcl_dbg_out(const boost::unordered_map<tKey, tMember, fHashFunction> & rMap)
{
    OUString aResult("[", RTL_TEXTENCODING_ASCII_US);

    typename boost::unordered_map<tKey, tMember, fHashFunction>::const_iterator aIt;

    for (aIt = rMap.begin(); aIt != rMap.end(); aIt++)
    {
        if (aIt != rMap.begin())
            aResult += ", ";

        aResult += aIt->first;

        char sBuffer[256];
        sprintf(sBuffer, "(%p)", aIt->second);
        aResult += OUString(sBuffer, strlen(sBuffer), RTL_TEXTENCODING_ASCII_US);
    }

    aResult += "]";

    return aResult;
}

template<typename tKey, typename tMember, typename fHashFunction>
const char * dbg_out(const boost::unordered_map<tKey, tMember, fHashFunction> & rMap)
{
    return dbg_out(lcl_dbg_out(rMap));
}
SW_DLLPUBLIC const char * dbg_out(const SwFormToken & rToken);
SW_DLLPUBLIC const char * dbg_out(const SwFormTokens & rTokens);
#endif // DBG_UTIL
#endif // __DBGOUTSW_HXX

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<commit_msg>fix OUString conversion in sw/inc/dbgoutsw.hxx<commit_after>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you under the Apache
 *   License, Version 2.0 (the "License"); you may not use this file
 *   except in compliance with the License. You may obtain a copy of
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
 */
#ifndef __DBGOUTSW_HXX
#define __DBGOUTSW_HXX

#ifdef DBG_UTIL

#include <boost/unordered_map.hpp>
#include <tox.hxx>
#include <cstdio>
#include "tools/string.hxx"

class SwNode;
class SwTxtAttr;
class SwpHints;
class SfxPoolItem;
class SfxItemSet;
struct SwPosition;
class SwPaM;
class SwNodeNum;
class SwUndo;
class SwRect;
class SwFrmFmt;
class SwFrmFmts;
class SwNodes;
class SwRewriter;
class SwNumRuleTbl;
class SwNumRule;
class SwOutlineNodes;
class SwTxtFmtColl;
class SwNodeRange;

extern bool bDbgOutStdErr;
extern bool bDbgOutPrintAttrSet;

SW_DLLPUBLIC const char * dbg_out(const void * pVoid);
SW_DLLPUBLIC const char * dbg_out(const OUString & aStr);
SW_DLLPUBLIC const char * dbg_out(const SwRect & rRect);
SW_DLLPUBLIC const char * dbg_out(const SwFrmFmt & rFrmFmt);
SW_DLLPUBLIC const char * dbg_out(const SwNode & rNode);
SW_DLLPUBLIC const char * dbg_out(const SwTxtAttr & rAttr);
SW_DLLPUBLIC const char * dbg_out(const SwpHints &rHints);
SW_DLLPUBLIC const char * dbg_out(const SfxPoolItem & rItem);
SW_DLLPUBLIC const char * dbg_out(const SfxPoolItem * pItem);
SW_DLLPUBLIC const char * dbg_out(const SfxItemSet & rSet);
SW_DLLPUBLIC const char * dbg_out(SwNodes & rNodes);
SW_DLLPUBLIC const char * dbg_out(const SwPosition & rPos);
SW_DLLPUBLIC const char * dbg_out(const SwPaM & rPam);
SW_DLLPUBLIC const char * dbg_out(const SwNodeNum & rNum);
SW_DLLPUBLIC const char * dbg_out(const SwUndo & rUndo);
SW_DLLPUBLIC const char * dbg_out(const SwRewriter & rRewriter);
SW_DLLPUBLIC const char * dbg_out(const SwNumRule & rRule);
SW_DLLPUBLIC const char * dbg_out(const SwTxtFmtColl & rFmt);
SW_DLLPUBLIC const char * dbg_out(const SwFrmFmts & rFrmFmts);
SW_DLLPUBLIC const char * dbg_out(const SwNumRuleTbl & rTbl);
SW_DLLPUBLIC const char * dbg_out(const SwNodeRange & rRange);

template<typename tKey, typename tMember, typename fHashFunction>
OUString lcl_dbg_out(const boost::unordered_map<tKey, tMember, fHashFunction> & rMap)
{
    OUString aResult("[");

    typename boost::unordered_map<tKey, tMember, fHashFunction>::const_iterator aIt;

    for (aIt = rMap.begin(); aIt != rMap.end(); aIt++)
    {
        if (aIt != rMap.begin())
            aResult += ", ";

        aResult += aIt->first;

        char sBuffer[256];
        sprintf(sBuffer, "(%p)", aIt->second);
        aResult += OUString(sBuffer, strlen(sBuffer), RTL_TEXTENCODING_ASCII_US);
    }

    aResult += "]";

    return aResult;
}

template<typename tKey, typename tMember, typename fHashFunction>
const char * dbg_out(const boost::unordered_map<tKey, tMember, fHashFunction> & rMap)
{
    return dbg_out(lcl_dbg_out(rMap));
}
SW_DLLPUBLIC const char * dbg_out(const SwFormToken & rToken);
SW_DLLPUBLIC const char * dbg_out(const SwFormTokens & rTokens);
#endif // DBG_UTIL
#endif // __DBGOUTSW_HXX

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<|endoftext|>


<commit_before>/***********************************************************************************************************************
**
** Copyright (c) 2011, 2014 ETH Zurich
** All rights reserved.
**
** Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
** following conditions are met:
**
**    * Redistributions of source code must retain the above copyright notice, this list of conditions and the following
**      disclaimer.
**    * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
**      following disclaimer in the documentation and/or other materials provided with the distribution.
**    * Neither the name of the ETH Zurich nor the names of its contributors may be used to endorse or promote products
**      derived from this software without specific prior written permission.
**
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
** INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
** DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
** SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
** WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**
***********************************************************************************************************************/

#include "OutlineTypePicker.h"

namespace Comments{

OutlineTypePicker::OutlineTypePicker(QWidget *parent) : QToolButton{parent}
{
	QMenu* menu = new QMenu;
	QWidgetAction* wiAction = new QWidgetAction{this};

	QSignalMapper* signalMapper = new QSignalMapper{this};
	connect(signalMapper,  (void (QSignalMapper::*)(int)) &QSignalMapper::mapped,
			  this, &OutlineTypePicker::handleOutlineTypePicked);

	QPixmap pixmap{96, 24};
	QWidget* aWidget = new QWidget{this};
	QVBoxLayout* aLayout = new QVBoxLayout;
	aLayout->setSpacing(0);
	aWidget->setLayout(aLayout);
	wiAction->setDefaultWidget(aWidget);

	QToolButton* aButton;
	pixmap.fill(Qt::transparent);
	QPainter* aPainter = new QPainter{&pixmap};
	QPen aPen;
	aPen.setColor(Qt::black);
	aPen.setWidth(4);
	pixList_.append(QPixmap{});
	for (int i = 1; i < 6; i++)
	{
		pixmap.fill(Qt::transparent);

		aPen.setStyle(static_cast<Qt::PenStyle>(i));
		aPainter->setPen(aPen);
		aPainter->drawLine(2, 13, 94, 13);
		pixList_.append(pixmap);
		aButton = new QToolButton;
		aButton->setIconSize(QSize{96, 24});
		aButton->setStyleSheet("border: none;");
		aButton->setIcon(QIcon{pixmap});
		aLayout->addWidget(aButton);
		signalMapper->setMapping(aButton, i);
		connect(aButton,  &QToolButton::clicked, signalMapper,
				  (void (QSignalMapper::*)()) &QSignalMapper::map);
	}
	aPainter->end();

	menu->addAction(wiAction);
	this->setMenu(menu);
	this->setPopupMode(QToolButton::InstantPopup);
}

void OutlineTypePicker::handleOutlineTypePicked(int aType)
{
	this->setIcon(pixList_.at(aType));
	this->menu()->close();
	Q_EMIT outlineTypeChanged(aType);
}

void OutlineTypePicker::setselectedOutlineType(int aType)
{
	this->setIcon(pixList_.at(aType));
}

}
<commit_msg>Enable no-lines style for shapes in a comment diagram<commit_after>/***********************************************************************************************************************
**
** Copyright (c) 2011, 2014 ETH Zurich
** All rights reserved.
**
** Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
** following conditions are met:
**
**    * Redistributions of source code must retain the above copyright notice, this list of conditions and the following
**      disclaimer.
**    * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
**      following disclaimer in the documentation and/or other materials provided with the distribution.
**    * Neither the name of the ETH Zurich nor the names of its contributors may be used to endorse or promote products
**      derived from this software without specific prior written permission.
**
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
** INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
** DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
** SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
** WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**
***********************************************************************************************************************/

#include "OutlineTypePicker.h"

namespace Comments{

OutlineTypePicker::OutlineTypePicker(QWidget *parent) : QToolButton{parent}
{
	QMenu* menu = new QMenu;
	QWidgetAction* wiAction = new QWidgetAction{this};

	QSignalMapper* signalMapper = new QSignalMapper{this};
	connect(signalMapper,  (void (QSignalMapper::*)(int)) &QSignalMapper::mapped,
			  this, &OutlineTypePicker::handleOutlineTypePicked);

	QPixmap pixmap{96, 24};
	QWidget* aWidget = new QWidget{this};
	QVBoxLayout* aLayout = new QVBoxLayout;
	aLayout->setSpacing(0);
	aWidget->setLayout(aLayout);
	wiAction->setDefaultWidget(aWidget);

	QToolButton* aButton;
	pixmap.fill(Qt::transparent);
	QPainter* aPainter = new QPainter{&pixmap};
	QPen aPen;
	aPen.setColor(Qt::black);
	aPen.setWidth(4);
	pixList_.append(QPixmap{});
	for (int i = 0; i < 6; i++)
	{
		pixmap.fill(Qt::transparent);

		aPen.setStyle(static_cast<Qt::PenStyle>(i));
		aPainter->setPen(aPen);
		aPainter->drawLine(2, 13, 94, 13);
		pixList_.append(pixmap);
		aButton = new QToolButton;
		aButton->setIconSize(QSize{96, 24});
		aButton->setStyleSheet("border: none;");
		aButton->setIcon(QIcon{pixmap});
		aLayout->addWidget(aButton);
		signalMapper->setMapping(aButton, i);
		connect(aButton,  &QToolButton::clicked, signalMapper,
				  (void (QSignalMapper::*)()) &QSignalMapper::map);
	}
	aPainter->end();

	menu->addAction(wiAction);
	this->setMenu(menu);
	this->setPopupMode(QToolButton::InstantPopup);
}

void OutlineTypePicker::handleOutlineTypePicked(int aType)
{
	this->setIcon(pixList_.at(aType));
	this->menu()->close();
	Q_EMIT outlineTypeChanged(aType);
}

void OutlineTypePicker::setselectedOutlineType(int aType)
{
	this->setIcon(pixList_.at(aType));
}

}
<|endoftext|>


<commit_before>/**
 *  Copyright (c) 2014-present, Facebook, Inc.
 *  All rights reserved.
 *
 *  This source code is licensed in accordance with the terms specified in
 *  the LICENSE file found in the root directory of this source tree.
 */

#include <mach/mach.h>

#include <IOKit/IOKitLib.h>
#include <SystemConfiguration/SystemConfiguration.h>

#include <boost/algorithm/string.hpp>

#include <osquery/utils/conversions/darwin/iokit.h>
#include <osquery/logger.h>
#include <osquery/sql.h>
#include <osquery/system.h>
#include <osquery/tables.h>
#include <osquery/utils/conversions/darwin/cfstring.h>

namespace osquery {
namespace tables {

static inline void genHostInfo(Row& r) {
  auto host = mach_host_self();

  host_basic_info_data_t host_data;
  mach_msg_type_number_t count = HOST_BASIC_INFO_COUNT;
  if (host_info(host, HOST_BASIC_INFO, (host_info_t)&host_data, &count) !=
      KERN_SUCCESS) {
    return;
  }

  char* cpu_type = nullptr;
  char* cpu_subtype = nullptr;
  // Get human readable strings
  slot_name(host_data.cpu_type, host_data.cpu_subtype, &cpu_type, &cpu_subtype);

  r["cpu_type"] = (cpu_type != nullptr) ? std::string(cpu_type) : "";
  r["cpu_subtype"] = (cpu_subtype != nullptr) ? std::string(cpu_subtype) : "";

  r["cpu_physical_cores"] = INTEGER(host_data.physical_cpu_max);
  r["cpu_logical_cores"] = INTEGER(host_data.logical_cpu_max);
  r["physical_memory"] = BIGINT(host_data.max_mem);
}

static inline void genHardwareInfo(Row& r) {
  auto root = IORegistryEntryFromPath(kIOMasterPortDefault, "IODeviceTree:/");
  if (root == MACH_PORT_NULL) {
    VLOG(1) << "Cannot get hardware information from IOKit";
    return;
  }

  CFMutableDictionaryRef properties = nullptr;
  auto kr = IORegistryEntryCreateCFProperties(
      root, &properties, kCFAllocatorDefault, kNilOptions);
  IOObjectRelease(root);

  if (kr != KERN_SUCCESS) {
    VLOG(1) << "Cannot get hardware properties from IOKit";
    return;
  }

  r["hardware_version"] = getIOKitProperty(properties, "version");
  r["hardware_vendor"] = getIOKitProperty(properties, "manufacturer");
  r["hardware_model"] = getIOKitProperty(properties, "product-name");
  r["hardware_serial"] = getIOKitProperty(properties, "IOPlatformSerialNumber");

  // version, manufacturer, and product-name have a trailing space
  boost::trim(r["hardware_version"]);
  boost::trim(r["hardware_vendor"]);
  boost::trim(r["hardware_model"]);

  CFRelease(properties);
}

QueryData genSystemInfo(QueryContext& context) {
  QueryData results;
  Row r;

  // OS X also defines a friendly ComputerName along with a hostname.
  r["hostname"] = osquery::getFqdn();
  auto cn = SCDynamicStoreCopyComputerName(nullptr, nullptr);
  if (cn != nullptr) {
    r["computer_name"] = stringFromCFString(cn);
    CFRelease(cn);
  } else {
    r["computer_name"] = getHostname();
  }

  auto lhn = SCDynamicStoreCopyLocalHostName(nullptr);
  if (lhn != nullptr) {
    r["local_hostname"] = stringFromCFString(lhn);
    CFRelease(lhn);
  } else {
    r["local_hostname"] = getHostname();
  }

  // The UUID for Apple devices is a device identifier.
  std::string uuid;
  r["uuid"] = (osquery::getHostUUID(uuid)) ? uuid : "";

  genHostInfo(r);
  genHardwareInfo(r);

  // The CPU brand string also exists in system_controls.
  auto qd = SQL::selectAllFrom("cpuid");
  for (const auto& row : qd) {
    if (row.at("feature") == "product_name") {
      r["cpu_brand"] = row.at("value");
      boost::trim(r["cpu_brand"]);
    }
  }

  results.push_back(r);
  return results;
}
}
}
<commit_msg>Trim whitespace in Darwin system_info table from hardware_serial column<commit_after>/**
 *  Copyright (c) 2014-present, Facebook, Inc.
 *  All rights reserved.
 *
 *  This source code is licensed in accordance with the terms specified in
 *  the LICENSE file found in the root directory of this source tree.
 */

#include <mach/mach.h>

#include <IOKit/IOKitLib.h>
#include <SystemConfiguration/SystemConfiguration.h>

#include <boost/algorithm/string.hpp>

#include <osquery/utils/conversions/darwin/iokit.h>
#include <osquery/logger.h>
#include <osquery/sql.h>
#include <osquery/system.h>
#include <osquery/tables.h>
#include <osquery/utils/conversions/darwin/cfstring.h>

namespace osquery {
namespace tables {

static inline void genHostInfo(Row& r) {
  auto host = mach_host_self();

  host_basic_info_data_t host_data;
  mach_msg_type_number_t count = HOST_BASIC_INFO_COUNT;
  if (host_info(host, HOST_BASIC_INFO, (host_info_t)&host_data, &count) !=
      KERN_SUCCESS) {
    return;
  }

  char* cpu_type = nullptr;
  char* cpu_subtype = nullptr;
  // Get human readable strings
  slot_name(host_data.cpu_type, host_data.cpu_subtype, &cpu_type, &cpu_subtype);

  r["cpu_type"] = (cpu_type != nullptr) ? std::string(cpu_type) : "";
  r["cpu_subtype"] = (cpu_subtype != nullptr) ? std::string(cpu_subtype) : "";

  r["cpu_physical_cores"] = INTEGER(host_data.physical_cpu_max);
  r["cpu_logical_cores"] = INTEGER(host_data.logical_cpu_max);
  r["physical_memory"] = BIGINT(host_data.max_mem);
}

static inline void genHardwareInfo(Row& r) {
  auto root = IORegistryEntryFromPath(kIOMasterPortDefault, "IODeviceTree:/");
  if (root == MACH_PORT_NULL) {
    VLOG(1) << "Cannot get hardware information from IOKit";
    return;
  }

  CFMutableDictionaryRef properties = nullptr;
  auto kr = IORegistryEntryCreateCFProperties(
      root, &properties, kCFAllocatorDefault, kNilOptions);
  IOObjectRelease(root);

  if (kr != KERN_SUCCESS) {
    VLOG(1) << "Cannot get hardware properties from IOKit";
    return;
  }

  r["hardware_version"] = getIOKitProperty(properties, "version");
  r["hardware_vendor"] = getIOKitProperty(properties, "manufacturer");
  r["hardware_model"] = getIOKitProperty(properties, "product-name");
  r["hardware_serial"] = getIOKitProperty(properties, "IOPlatformSerialNumber");

  // version, manufacturer, and product-name have a trailing space
  boost::trim(r["hardware_version"]);
  boost::trim(r["hardware_vendor"]);
  boost::trim(r["hardware_model"]);
  boost::trim(r["hardware_serial"]);

  CFRelease(properties);
}

QueryData genSystemInfo(QueryContext& context) {
  QueryData results;
  Row r;

  // OS X also defines a friendly ComputerName along with a hostname.
  r["hostname"] = osquery::getFqdn();
  auto cn = SCDynamicStoreCopyComputerName(nullptr, nullptr);
  if (cn != nullptr) {
    r["computer_name"] = stringFromCFString(cn);
    CFRelease(cn);
  } else {
    r["computer_name"] = getHostname();
  }

  auto lhn = SCDynamicStoreCopyLocalHostName(nullptr);
  if (lhn != nullptr) {
    r["local_hostname"] = stringFromCFString(lhn);
    CFRelease(lhn);
  } else {
    r["local_hostname"] = getHostname();
  }

  // The UUID for Apple devices is a device identifier.
  std::string uuid;
  r["uuid"] = (osquery::getHostUUID(uuid)) ? uuid : "";

  genHostInfo(r);
  genHardwareInfo(r);

  // The CPU brand string also exists in system_controls.
  auto qd = SQL::selectAllFrom("cpuid");
  for (const auto& row : qd) {
    if (row.at("feature") == "product_name") {
      r["cpu_brand"] = row.at("value");
      boost::trim(r["cpu_brand"]);
    }
  }

  results.push_back(r);
  return results;
}
}
}
<|endoftext|>


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

#include "jvm_tooling.h"

#include <fstream>
#include <iostream>
#include <utility>
#include <vector>

#include "absl/strings/str_format.h"
#include "absl/strings/str_join.h"
#include "absl/strings/str_split.h"
#include "gflags/gflags.h"
#include "glog/logging.h"
#include "libfuzzer_callbacks.h"
#include "utils.h"

DEFINE_string(cp, ".",
              "the jvm class path which should include the fuzz target class, "
              "instrumentor "
              "runtime and further dependencies separated by a colon \":\"");
DEFINE_string(jvm_args, "",
              "arguments passed to the jvm separated by semicolon \";\"");
DEFINE_string(agent_path, "", "location of the fuzzing instrumentation agent");

// Arguments that are passed to the instrumentation agent.
// The instrumentation agent takes arguments in the form
// <option_1>=<option_1_val>,<option_2>=<option_2_val>,... To not expose this
// format to the user the available options are defined here as flags and
// combined during the initialization of the JVM.
DEFINE_string(instrumentation_includes, "",
              "list of glob patterns for classes that will be instrumented for "
              "fuzzing. Separated by colon \":\"");
DEFINE_string(instrumentation_excludes, "",
              "list of glob patterns for classes that will not be instrumented "
              "for fuzzing. Separated by colon \":\"");

DEFINE_string(custom_hook_includes, "",
              "list of glob patterns for classes that will only be "
              "instrumented using custom hooks. Separated by colon \":\"");
DEFINE_string(custom_hook_excludes, "",
              "list of glob patterns for classes that will not be instrumented "
              "using custom hooks. Separated by colon \":\"");
DEFINE_string(custom_hooks, "",
              "list of classes containing custom instrumentation hooks. "
              "Separated by colon \":\"");
DEFINE_string(
    trace, "",
    "list of instrumentation to perform separated by colon \":\". "
    "Available options are cov, cmp, div, gep, all. These options "
    "correspond to the \"-fsanitize-coverage=trace-*\" flags in clang.");
DEFINE_string(
    id_sync_file, "",
    "path to a file that should be used to synchronize coverage IDs "
    "between parallel fuzzing processes. Defaults to a temporary file "
    "created for this purpose if running in parallel.");

DECLARE_bool(hooks);

namespace {
constexpr auto kInstrumentorAgentBazelDir = "agent";
constexpr auto kAgentFileName = "jazzer_agent_deploy.jar";
constexpr const char kExceptionUtilsClassName[] =
    "com/code_intelligence/jazzer/runtime/ExceptionUtils";
}  // namespace

namespace jazzer {

std::string dirFromFullPath(const std::string &path) {
  const auto pos = path.rfind(kPathSeparator);
  if (pos != std::string::npos) {
    return path.substr(0, pos);
  }
  return "";
}

// getInstrumentorAgentPath searches for the fuzzing instrumentation agent and
// returns the location if it is found. Otherwise it calls exit(0).
std::string getInstrumentorAgentPath(const std::string &executable_path) {
  // user provided agent location takes precedence
  if (!FLAGS_agent_path.empty()) {
    if (std::ifstream(FLAGS_agent_path).good()) return FLAGS_agent_path;
    LOG(ERROR) << "Could not find " << kAgentFileName << "in \""
               << FLAGS_agent_path << "\"";
    exit(0);
  }

  {
    // first check if we are running inside the bazel tree
    auto bazel_path = absl::StrFormat("%s%c%s", kInstrumentorAgentBazelDir,
                                      kPathSeparator, kAgentFileName);
    if (std::ifstream(bazel_path).good()) return bazel_path;
  }

  {
    // if the agent is not in the bazel path we look next to the
    // libfuzzer_runner binary
    const auto dir = dirFromFullPath(executable_path);
    auto agent_path =
        absl::StrFormat("%s%c%s", dir, kPathSeparator, kAgentFileName);
    if (std::ifstream(agent_path).good()) return agent_path;
  }
  LOG(ERROR) << "Could not find " << kAgentFileName
             << ". Please provide "
                "the pathname via the --agent_path flag.";
  exit(1);
}

std::string agentArgsFromFlags() {
  std::vector<std::string> args;
  for (const auto &flag_pair :
       std::vector<std::pair<std::string, const std::string &>>{
           // {<agent option>, <ref to glog flag> }
           {"instrumentation_includes", FLAGS_instrumentation_includes},
           {"instrumentation_excludes", FLAGS_instrumentation_excludes},
           {"custom_hooks", FLAGS_custom_hooks},
           {"custom_hook_includes", FLAGS_custom_hook_includes},
           {"custom_hook_excludes", FLAGS_custom_hook_excludes},
           {"trace", FLAGS_trace},
           {"id_sync_file", FLAGS_id_sync_file},
       }) {
    if (!flag_pair.second.empty()) {
      args.push_back(flag_pair.first + "=" + flag_pair.second);
    }
  }
  return absl::StrJoin(args, ",");
}

JVM::JVM(const std::string &executable_path) {
  // combine class path from command line flags and JAVA_FUZZER_CLASSPATH env
  // variable
  std::string class_path = absl::StrFormat("-Djava.class.path=%s", FLAGS_cp);
  const auto class_path_from_env = std::getenv("JAVA_FUZZER_CLASSPATH");
  if (class_path_from_env) {
    class_path += absl::StrFormat(":%s", class_path_from_env);
  }
  class_path +=
      absl::StrFormat(":%s", getInstrumentorAgentPath(executable_path));
  LOG(INFO) << "got class path " << class_path;

  std::vector<JavaVMOption> options;
  options.push_back(
      JavaVMOption{.optionString = const_cast<char *>(class_path.c_str())});
  // set the maximum heap size
  options.push_back(JavaVMOption{.optionString = (char *)"-Xmx4096m"});
  options.push_back(JavaVMOption{.optionString = (char *)"-enableassertions"});

  // add additional jvm options set through command line flags
  std::vector<std::string> jvm_args;
  if (!FLAGS_jvm_args.empty()) {
    jvm_args = absl::StrSplit(FLAGS_jvm_args, ';');
  }
  for (const auto &arg : jvm_args) {
    options.push_back(
        JavaVMOption{.optionString = const_cast<char *>(arg.c_str())});
  }

  std::string agent_jvm_arg;
  if (FLAGS_hooks) {
    agent_jvm_arg = absl::StrFormat("-javaagent:%s=%s",
                                    getInstrumentorAgentPath(executable_path),
                                    agentArgsFromFlags());
    options.push_back(JavaVMOption{
        .optionString = const_cast<char *>(agent_jvm_arg.c_str())});
  }

  JavaVMInitArgs jvm_init_args = {.version = JNI_VERSION_1_6,
                                  .nOptions = (int)options.size(),
                                  .options = options.data(),
                                  .ignoreUnrecognized = JNI_FALSE};

  auto ret = JNI_CreateJavaVM(&jvm_, (void **)&env_, &jvm_init_args);
  if (ret != JNI_OK) {
    throw std::runtime_error(
        absl::StrFormat("JNI_CreateJavaVM returned code %d", ret));
  }
}

JNIEnv &JVM::GetEnv() const { return *env_; }

JVM::~JVM() { jvm_->DestroyJavaVM(); }

jclass JVM::FindClass(std::string class_name) const {
  auto &env = GetEnv();
  std::replace(class_name.begin(), class_name.end(), '.', '/');
  const auto ret = env.FindClass(class_name.c_str());
  if (ret == nullptr) {
    if (env.ExceptionCheck()) {
      env.ExceptionDescribe();
      throw std::runtime_error(
          absl::StrFormat("Could not find class %s", class_name));
    } else {
      throw std::runtime_error(absl::StrFormat(
          "Java class '%s' not found without exception", class_name));
    }
  }
  return ret;
}

jmethodID JVM::GetStaticMethodID(jclass jclass, const std::string &jmethod,
                                 const std::string &signature,
                                 bool is_required) const {
  auto &env = GetEnv();
  const auto ret =
      env.GetStaticMethodID(jclass, jmethod.c_str(), signature.c_str());
  if (ret == nullptr) {
    if (is_required) {
      if (env.ExceptionCheck()) {
        env.ExceptionDescribe();
      }
      throw std::runtime_error(
          absl::StrFormat("Static method '%s' not found", jmethod));
    } else {
      LOG(INFO) << "did not find method " << jmethod << " with signature "
                << signature;
      env.ExceptionClear();
    }
  }
  return ret;
}

jmethodID JVM::GetMethodID(jclass jclass, const std::string &jmethod,
                           const std::string &signature) const {
  auto &env = GetEnv();
  const auto ret = env.GetMethodID(jclass, jmethod.c_str(), signature.c_str());
  if (ret == nullptr) {
    if (env.ExceptionCheck()) {
      env.ExceptionDescribe();
    }
    throw std::runtime_error(absl::StrFormat("Method '%s' not found", jmethod));
  }
  return ret;
}

jfieldID JVM::GetStaticFieldID(jclass class_id, const std::string &field_name,
                               const std::string &type) const {
  auto &env = GetEnv();
  const auto ret =
      env.GetStaticFieldID(class_id, field_name.c_str(), type.c_str());
  if (ret == nullptr) {
    if (env.ExceptionCheck()) {
      env.ExceptionDescribe();
    }
    throw std::runtime_error(
        absl::StrFormat("Field '%s' not found", field_name));
  }
  return ret;
}

ExceptionPrinter::ExceptionPrinter(JVM &jvm)
    : jvm_(jvm),
      string_writer_class_(jvm.FindClass("java/io/StringWriter")),
      string_writer_constructor_(
          jvm.GetMethodID(string_writer_class_, "<init>", "()V")),
      string_writer_to_string_method_(jvm.GetMethodID(
          string_writer_class_, "toString", "()Ljava/lang/String;")),
      print_writer_class_(jvm.FindClass("java/io/PrintWriter")),
      print_writer_constructor_(jvm.GetMethodID(print_writer_class_, "<init>",
                                                "(Ljava/io/Writer;)V")) {
  auto throwable_class = jvm.FindClass("java/lang/Throwable");
  print_stack_trace_method_ = jvm.GetMethodID(
      throwable_class, "printStackTrace", "(Ljava/io/PrintWriter;)V");
  if (FLAGS_hooks) {
    exception_utils_ = jvm.FindClass(kExceptionUtilsClassName);
    compute_dedup_token_method_ = jvm.GetStaticMethodID(
        exception_utils_, "computeDedupToken", "(Ljava/lang/Throwable;)J");
    preprocess_throwable_method_ =
        jvm.GetStaticMethodID(exception_utils_, "preprocessThrowable",
                              "(Ljava/lang/Throwable;)Ljava/lang/Throwable;");
  }
}

// The JNI way of writing:
//    StringWriter stringWriter = new StringWriter();
//    PrintWriter printWriter = new PrintWriter(stringWriter);
//    e.printStackTrace(printWriter);
//    return stringWriter.toString();
std::string ExceptionPrinter::getStackTrace(jthrowable exception) const {
  auto &env = jvm_.GetEnv();
  if (exception == nullptr) {
    return "";
  }

  auto string_writer =
      env.NewObject(string_writer_class_, string_writer_constructor_);
  if (string_writer == nullptr) {
    env.ExceptionDescribe();
    return "";
  }
  auto print_writer = env.NewObject(print_writer_class_,
                                    print_writer_constructor_, string_writer);
  if (print_writer == nullptr) {
    env.ExceptionDescribe();
    return "";
  }

  env.CallVoidMethod(exception, print_stack_trace_method_, print_writer);
  if (env.ExceptionCheck()) {
    env.ExceptionDescribe();
    return "";
  }
  auto exception_string_object = reinterpret_cast<jstring>(
      env.CallObjectMethod(string_writer, string_writer_to_string_method_));
  if (env.ExceptionCheck()) {
    env.ExceptionDescribe();
    return "";
  }

  auto char_pointer = env.GetStringUTFChars(exception_string_object, nullptr);
  std::string exception_string(char_pointer);
  env.ReleaseStringUTFChars(exception_string_object, char_pointer);
  return exception_string;
}

jthrowable ExceptionPrinter::preprocessException(jthrowable exception) const {
  if (exception == nullptr) return nullptr;
  auto &env = jvm_.GetEnv();
  if (!FLAGS_hooks || !preprocess_throwable_method_) return exception;
  auto processed_exception = (jthrowable)(env.CallStaticObjectMethod(
      exception_utils_, preprocess_throwable_method_, exception));
  if (env.ExceptionCheck()) {
    env.ExceptionDescribe();
    return exception;
  }
  return processed_exception;
}

jlong ExceptionPrinter::computeDedupToken(jthrowable exception) const {
  auto &env = jvm_.GetEnv();
  if (!FLAGS_hooks || exception == nullptr ||
      compute_dedup_token_method_ == nullptr)
    return 0;
  const auto dedup_token = env.CallStaticLongMethod(
      exception_utils_, compute_dedup_token_method_, exception);
  if (env.ExceptionCheck()) {
    env.ExceptionDescribe();
    return 0;
  }
  return dedup_token;
}

}  // namespace jazzer
<commit_msg>Keep stack traces even on hot paths<commit_after>// Copyright 2021 Code Intelligence GmbH
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "jvm_tooling.h"

#include <fstream>
#include <iostream>
#include <utility>
#include <vector>

#include "absl/strings/str_format.h"
#include "absl/strings/str_join.h"
#include "absl/strings/str_split.h"
#include "gflags/gflags.h"
#include "glog/logging.h"
#include "libfuzzer_callbacks.h"
#include "utils.h"

DEFINE_string(cp, ".",
              "the jvm class path which should include the fuzz target class, "
              "instrumentor "
              "runtime and further dependencies separated by a colon \":\"");
DEFINE_string(jvm_args, "",
              "arguments passed to the jvm separated by semicolon \";\"");
DEFINE_string(agent_path, "", "location of the fuzzing instrumentation agent");

// Arguments that are passed to the instrumentation agent.
// The instrumentation agent takes arguments in the form
// <option_1>=<option_1_val>,<option_2>=<option_2_val>,... To not expose this
// format to the user the available options are defined here as flags and
// combined during the initialization of the JVM.
DEFINE_string(instrumentation_includes, "",
              "list of glob patterns for classes that will be instrumented for "
              "fuzzing. Separated by colon \":\"");
DEFINE_string(instrumentation_excludes, "",
              "list of glob patterns for classes that will not be instrumented "
              "for fuzzing. Separated by colon \":\"");

DEFINE_string(custom_hook_includes, "",
              "list of glob patterns for classes that will only be "
              "instrumented using custom hooks. Separated by colon \":\"");
DEFINE_string(custom_hook_excludes, "",
              "list of glob patterns for classes that will not be instrumented "
              "using custom hooks. Separated by colon \":\"");
DEFINE_string(custom_hooks, "",
              "list of classes containing custom instrumentation hooks. "
              "Separated by colon \":\"");
DEFINE_string(
    trace, "",
    "list of instrumentation to perform separated by colon \":\". "
    "Available options are cov, cmp, div, gep, all. These options "
    "correspond to the \"-fsanitize-coverage=trace-*\" flags in clang.");
DEFINE_string(
    id_sync_file, "",
    "path to a file that should be used to synchronize coverage IDs "
    "between parallel fuzzing processes. Defaults to a temporary file "
    "created for this purpose if running in parallel.");

DECLARE_bool(hooks);

namespace {
constexpr auto kInstrumentorAgentBazelDir = "agent";
constexpr auto kAgentFileName = "jazzer_agent_deploy.jar";
constexpr const char kExceptionUtilsClassName[] =
    "com/code_intelligence/jazzer/runtime/ExceptionUtils";
}  // namespace

namespace jazzer {

std::string dirFromFullPath(const std::string &path) {
  const auto pos = path.rfind(kPathSeparator);
  if (pos != std::string::npos) {
    return path.substr(0, pos);
  }
  return "";
}

// getInstrumentorAgentPath searches for the fuzzing instrumentation agent and
// returns the location if it is found. Otherwise it calls exit(0).
std::string getInstrumentorAgentPath(const std::string &executable_path) {
  // user provided agent location takes precedence
  if (!FLAGS_agent_path.empty()) {
    if (std::ifstream(FLAGS_agent_path).good()) return FLAGS_agent_path;
    LOG(ERROR) << "Could not find " << kAgentFileName << "in \""
               << FLAGS_agent_path << "\"";
    exit(0);
  }

  {
    // first check if we are running inside the bazel tree
    auto bazel_path = absl::StrFormat("%s%c%s", kInstrumentorAgentBazelDir,
                                      kPathSeparator, kAgentFileName);
    if (std::ifstream(bazel_path).good()) return bazel_path;
  }

  {
    // if the agent is not in the bazel path we look next to the
    // libfuzzer_runner binary
    const auto dir = dirFromFullPath(executable_path);
    auto agent_path =
        absl::StrFormat("%s%c%s", dir, kPathSeparator, kAgentFileName);
    if (std::ifstream(agent_path).good()) return agent_path;
  }
  LOG(ERROR) << "Could not find " << kAgentFileName
             << ". Please provide "
                "the pathname via the --agent_path flag.";
  exit(1);
}

std::string agentArgsFromFlags() {
  std::vector<std::string> args;
  for (const auto &flag_pair :
       std::vector<std::pair<std::string, const std::string &>>{
           // {<agent option>, <ref to glog flag> }
           {"instrumentation_includes", FLAGS_instrumentation_includes},
           {"instrumentation_excludes", FLAGS_instrumentation_excludes},
           {"custom_hooks", FLAGS_custom_hooks},
           {"custom_hook_includes", FLAGS_custom_hook_includes},
           {"custom_hook_excludes", FLAGS_custom_hook_excludes},
           {"trace", FLAGS_trace},
           {"id_sync_file", FLAGS_id_sync_file},
       }) {
    if (!flag_pair.second.empty()) {
      args.push_back(flag_pair.first + "=" + flag_pair.second);
    }
  }
  return absl::StrJoin(args, ",");
}

JVM::JVM(const std::string &executable_path) {
  // combine class path from command line flags and JAVA_FUZZER_CLASSPATH env
  // variable
  std::string class_path = absl::StrFormat("-Djava.class.path=%s", FLAGS_cp);
  const auto class_path_from_env = std::getenv("JAVA_FUZZER_CLASSPATH");
  if (class_path_from_env) {
    class_path += absl::StrFormat(":%s", class_path_from_env);
  }
  class_path +=
      absl::StrFormat(":%s", getInstrumentorAgentPath(executable_path));
  LOG(INFO) << "got class path " << class_path;

  std::vector<JavaVMOption> options;
  options.push_back(
      JavaVMOption{.optionString = const_cast<char *>(class_path.c_str())});
  // set the maximum heap size
  options.push_back(JavaVMOption{.optionString = (char *)"-Xmx4096m"});
  options.push_back(JavaVMOption{.optionString = (char *)"-enableassertions"});
  // Preserve and emit stack trace information even on hot paths.
  // This may hurt performance, but also helps find flaky bugs.
  options.push_back(
      JavaVMOption{.optionString = (char *)"-XX:-OmitStackTraceInFastThrow"});

  // add additional jvm options set through command line flags
  std::vector<std::string> jvm_args;
  if (!FLAGS_jvm_args.empty()) {
    jvm_args = absl::StrSplit(FLAGS_jvm_args, ';');
  }
  for (const auto &arg : jvm_args) {
    options.push_back(
        JavaVMOption{.optionString = const_cast<char *>(arg.c_str())});
  }

  std::string agent_jvm_arg;
  if (FLAGS_hooks) {
    agent_jvm_arg = absl::StrFormat("-javaagent:%s=%s",
                                    getInstrumentorAgentPath(executable_path),
                                    agentArgsFromFlags());
    options.push_back(JavaVMOption{
        .optionString = const_cast<char *>(agent_jvm_arg.c_str())});
  }

  JavaVMInitArgs jvm_init_args = {.version = JNI_VERSION_1_6,
                                  .nOptions = (int)options.size(),
                                  .options = options.data(),
                                  .ignoreUnrecognized = JNI_FALSE};

  auto ret = JNI_CreateJavaVM(&jvm_, (void **)&env_, &jvm_init_args);
  if (ret != JNI_OK) {
    throw std::runtime_error(
        absl::StrFormat("JNI_CreateJavaVM returned code %d", ret));
  }
}

JNIEnv &JVM::GetEnv() const { return *env_; }

JVM::~JVM() { jvm_->DestroyJavaVM(); }

jclass JVM::FindClass(std::string class_name) const {
  auto &env = GetEnv();
  std::replace(class_name.begin(), class_name.end(), '.', '/');
  const auto ret = env.FindClass(class_name.c_str());
  if (ret == nullptr) {
    if (env.ExceptionCheck()) {
      env.ExceptionDescribe();
      throw std::runtime_error(
          absl::StrFormat("Could not find class %s", class_name));
    } else {
      throw std::runtime_error(absl::StrFormat(
          "Java class '%s' not found without exception", class_name));
    }
  }
  return ret;
}

jmethodID JVM::GetStaticMethodID(jclass jclass, const std::string &jmethod,
                                 const std::string &signature,
                                 bool is_required) const {
  auto &env = GetEnv();
  const auto ret =
      env.GetStaticMethodID(jclass, jmethod.c_str(), signature.c_str());
  if (ret == nullptr) {
    if (is_required) {
      if (env.ExceptionCheck()) {
        env.ExceptionDescribe();
      }
      throw std::runtime_error(
          absl::StrFormat("Static method '%s' not found", jmethod));
    } else {
      LOG(INFO) << "did not find method " << jmethod << " with signature "
                << signature;
      env.ExceptionClear();
    }
  }
  return ret;
}

jmethodID JVM::GetMethodID(jclass jclass, const std::string &jmethod,
                           const std::string &signature) const {
  auto &env = GetEnv();
  const auto ret = env.GetMethodID(jclass, jmethod.c_str(), signature.c_str());
  if (ret == nullptr) {
    if (env.ExceptionCheck()) {
      env.ExceptionDescribe();
    }
    throw std::runtime_error(absl::StrFormat("Method '%s' not found", jmethod));
  }
  return ret;
}

jfieldID JVM::GetStaticFieldID(jclass class_id, const std::string &field_name,
                               const std::string &type) const {
  auto &env = GetEnv();
  const auto ret =
      env.GetStaticFieldID(class_id, field_name.c_str(), type.c_str());
  if (ret == nullptr) {
    if (env.ExceptionCheck()) {
      env.ExceptionDescribe();
    }
    throw std::runtime_error(
        absl::StrFormat("Field '%s' not found", field_name));
  }
  return ret;
}

ExceptionPrinter::ExceptionPrinter(JVM &jvm)
    : jvm_(jvm),
      string_writer_class_(jvm.FindClass("java/io/StringWriter")),
      string_writer_constructor_(
          jvm.GetMethodID(string_writer_class_, "<init>", "()V")),
      string_writer_to_string_method_(jvm.GetMethodID(
          string_writer_class_, "toString", "()Ljava/lang/String;")),
      print_writer_class_(jvm.FindClass("java/io/PrintWriter")),
      print_writer_constructor_(jvm.GetMethodID(print_writer_class_, "<init>",
                                                "(Ljava/io/Writer;)V")) {
  auto throwable_class = jvm.FindClass("java/lang/Throwable");
  print_stack_trace_method_ = jvm.GetMethodID(
      throwable_class, "printStackTrace", "(Ljava/io/PrintWriter;)V");
  if (FLAGS_hooks) {
    exception_utils_ = jvm.FindClass(kExceptionUtilsClassName);
    compute_dedup_token_method_ = jvm.GetStaticMethodID(
        exception_utils_, "computeDedupToken", "(Ljava/lang/Throwable;)J");
    preprocess_throwable_method_ =
        jvm.GetStaticMethodID(exception_utils_, "preprocessThrowable",
                              "(Ljava/lang/Throwable;)Ljava/lang/Throwable;");
  }
}

// The JNI way of writing:
//    StringWriter stringWriter = new StringWriter();
//    PrintWriter printWriter = new PrintWriter(stringWriter);
//    e.printStackTrace(printWriter);
//    return stringWriter.toString();
std::string ExceptionPrinter::getStackTrace(jthrowable exception) const {
  auto &env = jvm_.GetEnv();
  if (exception == nullptr) {
    return "";
  }

  auto string_writer =
      env.NewObject(string_writer_class_, string_writer_constructor_);
  if (string_writer == nullptr) {
    env.ExceptionDescribe();
    return "";
  }
  auto print_writer = env.NewObject(print_writer_class_,
                                    print_writer_constructor_, string_writer);
  if (print_writer == nullptr) {
    env.ExceptionDescribe();
    return "";
  }

  env.CallVoidMethod(exception, print_stack_trace_method_, print_writer);
  if (env.ExceptionCheck()) {
    env.ExceptionDescribe();
    return "";
  }
  auto exception_string_object = reinterpret_cast<jstring>(
      env.CallObjectMethod(string_writer, string_writer_to_string_method_));
  if (env.ExceptionCheck()) {
    env.ExceptionDescribe();
    return "";
  }

  auto char_pointer = env.GetStringUTFChars(exception_string_object, nullptr);
  std::string exception_string(char_pointer);
  env.ReleaseStringUTFChars(exception_string_object, char_pointer);
  return exception_string;
}

jthrowable ExceptionPrinter::preprocessException(jthrowable exception) const {
  if (exception == nullptr) return nullptr;
  auto &env = jvm_.GetEnv();
  if (!FLAGS_hooks || !preprocess_throwable_method_) return exception;
  auto processed_exception = (jthrowable)(env.CallStaticObjectMethod(
      exception_utils_, preprocess_throwable_method_, exception));
  if (env.ExceptionCheck()) {
    env.ExceptionDescribe();
    return exception;
  }
  return processed_exception;
}

jlong ExceptionPrinter::computeDedupToken(jthrowable exception) const {
  auto &env = jvm_.GetEnv();
  if (!FLAGS_hooks || exception == nullptr ||
      compute_dedup_token_method_ == nullptr)
    return 0;
  const auto dedup_token = env.CallStaticLongMethod(
      exception_utils_, compute_dedup_token_method_, exception);
  if (env.ExceptionCheck()) {
    env.ExceptionDescribe();
    return 0;
  }
  return dedup_token;
}

}  // namespace jazzer
<|endoftext|>


<commit_before>#include "topic.h"
#include "consumer.h"

using namespace std;

Consumer::Consumer(const std::string& root, const std::string& topic, const std::string& name, TopicOpt* opt) : _topic(EnvManager::getEnv(root)->getTopic(topic)), _name(name), _current(0), _lastOffset(0), _env(nullptr), _db(0), _rtxn(nullptr), _cursor(nullptr) {
    if (opt) {
        _opt = *opt;
    } else {
        /* Default opt */
        _opt.chunkSize = 1024 * 1024 * 1024;
        _opt.chunksToKeep = 8;
    }

    Txn txn(_topic->getEnv(), NULL);
    openHead(&txn);
    txn.commit();
}

Consumer::~Consumer() {
    closeCurrent();
}

void Consumer::pull(BatchType& result, size_t cnt) {
    result.reserve(cnt);
    bool shouldRotate = false;

    {
        Txn txn(_topic->getEnv(), NULL);
        mdb_txn_renew(_rtxn);

        uint64_t head = _topic->getConsumerHead(txn, _name);
        int rc = _cursor->seek(head);

        if (rc == 0) {
            uint64_t offset = 0;
            for (; rc == 0 && cnt > 0; --cnt) {
                offset = _cursor->key<uint64_t>();
                const char* data = (const char*)_cursor->val().mv_data;
                size_t len = _cursor->val().mv_size;
                result.push_back(ItemType(offset, data, len));
                rc = _cursor->next();
            }

            if (offset > 0) {
                _topic->setConsumerHead(txn, _name, offset + 1);
                txn.commit();
            }
        } else {
            if (rc != MDB_NOTFOUND) cout << "Consumer seek error: " << mdb_strerror(rc) << endl;

            if (head < _topic->getProducerHead(txn)) {
                shouldRotate = true;
            }
        }
    }

    if (shouldRotate) {
        rotate();
        pull(result, cnt);
    }
}

void Consumer::openHead(Txn* txn) {
    _current = _topic->getConsumerHeadFile(*txn, _name, _current);

    char path[4096];
    _topic->getChunkFilePath(path, _current);

    mdb_env_create(&_env);
    mdb_env_set_mapsize(_env, _opt.chunkSize);
    int rc = mdb_env_open(_env, path, MDB_RDONLY | MDB_NOSYNC | MDB_NOSUBDIR, 0664);

    int cleared = 0;
    mdb_reader_check(_env, &cleared);

    if (rc != 0) {
        mdb_env_close(_env);
        _env = nullptr;
        printf("Consumer open error.\n%s\n", mdb_strerror(rc));
        return;
    }

    MDB_txn *otxn;
    mdb_txn_begin(_env, NULL, MDB_RDONLY, &otxn);
    mdb_dbi_open(otxn, NULL, MDB_CREATE, &_db);
    mdb_set_compare(otxn, _db, mdbIntCmp<uint64_t>);
    mdb_txn_commit(otxn);

    mdb_txn_begin(_env, NULL, MDB_RDONLY, &_rtxn);
    _cursor = new MDBCursor(_db, _rtxn);
    mdb_txn_reset(_rtxn);
}

void Consumer::closeCurrent() {
    delete _cursor;
    mdb_txn_abort(_rtxn);
    mdb_dbi_close(_env, _db);
    mdb_env_close(_env);
}

void Consumer::rotate() {
    Txn txn(_topic->getEnv(), NULL);
    closeCurrent();
    openHead(&txn);
    txn.commit();
}<commit_msg>fix consumer rotate  error on producer rotated.<commit_after>#include "topic.h"
#include "consumer.h"

using namespace std;

Consumer::Consumer(const std::string& root, const std::string& topic, const std::string& name, TopicOpt* opt) : _topic(EnvManager::getEnv(root)->getTopic(topic)), _name(name), _current(0), _lastOffset(0), _env(nullptr), _db(0), _rtxn(nullptr), _cursor(nullptr) {
    if (opt) {
        _opt = *opt;
    } else {
        /* Default opt */
        _opt.chunkSize = 1024 * 1024 * 1024;
        _opt.chunksToKeep = 8;
    }

    Txn txn(_topic->getEnv(), NULL);
    openHead(&txn);
    txn.commit();
}

Consumer::~Consumer() {
    closeCurrent();
}

void Consumer::pull(BatchType& result, size_t cnt) {
    result.reserve(cnt);
    bool shouldRotate = false;

    {
        Txn txn(_topic->getEnv(), NULL);
        mdb_txn_renew(_rtxn);

        uint64_t head = _topic->getConsumerHead(txn, _name);
        int rc = _cursor->gte(head);

        if (rc == 0) {
            uint64_t offset = 0;
            for (; rc == 0 && cnt > 0; --cnt) {
                offset = _cursor->key<uint64_t>();
                const char* data = (const char*)_cursor->val().mv_data;
                size_t len = _cursor->val().mv_size;
                result.push_back(ItemType(offset, data, len));
                rc = _cursor->next();
            }

            if (offset > 0) {
                _topic->setConsumerHead(txn, _name, offset + 1);
                txn.commit();
            }
        } else {
            if (rc != MDB_NOTFOUND) cout << "Consumer seek error: " << mdb_strerror(rc) << endl;

            if (head < _topic->getProducerHead(txn)) {
                shouldRotate = true;
            }
        }
    }

    if (shouldRotate) {
        rotate();
        pull(result, cnt);
    }
}

void Consumer::openHead(Txn* txn) {
    _current = _topic->getConsumerHeadFile(*txn, _name, _current);

    char path[4096];
    _topic->getChunkFilePath(path, _current);

    mdb_env_create(&_env);
    mdb_env_set_mapsize(_env, _opt.chunkSize);
    int rc = mdb_env_open(_env, path, MDB_RDONLY | MDB_NOSYNC | MDB_NOSUBDIR, 0664);

    int cleared = 0;
    mdb_reader_check(_env, &cleared);

    if (rc != 0) {
        mdb_env_close(_env);
        _env = nullptr;
        printf("Consumer open error.\n%s\n", mdb_strerror(rc));
        return;
    }

    MDB_txn *otxn;
    mdb_txn_begin(_env, NULL, MDB_RDONLY, &otxn);
    mdb_dbi_open(otxn, NULL, MDB_CREATE, &_db);
    mdb_set_compare(otxn, _db, mdbIntCmp<uint64_t>);
    mdb_txn_commit(otxn);

    mdb_txn_begin(_env, NULL, MDB_RDONLY, &_rtxn);
    _cursor = new MDBCursor(_db, _rtxn);
    mdb_txn_reset(_rtxn);
}

void Consumer::closeCurrent() {
    delete _cursor;
    mdb_txn_abort(_rtxn);
    mdb_dbi_close(_env, _db);
    mdb_env_close(_env);
}

void Consumer::rotate() {
    Txn txn(_topic->getEnv(), NULL);
    closeCurrent();
    openHead(&txn);
    txn.commit();
}<|endoftext|>