<commit_before>#include <ctrcommon/app.hpp>
#include <ctrcommon/gpu.hpp>
#include <ctrcommon/input.hpp>
#include <ctrcommon/nor.hpp>
#include <ctrcommon/platform.hpp>
#include <ctrcommon/ui.hpp>

#include "rop.h"

#include <sys/errno.h>
#include <stdio.h>
#include <string.h>

#include <sstream>
#include <iomanip>

typedef enum {
    INSTALL_CIA,
    DELETE_CIA,
    DELETE_TITLE,
    LAUNCH_TITLE
} Mode;

int main(int argc, char **argv) {
    if(!platformInit()) {
        return 0;
    }

    bool ninjhax = platformIsNinjhax();

    std::vector<std::string> extensions;
    extensions.push_back("cia");

    MediaType destination = SD;
    Mode mode = INSTALL_CIA;
    bool exit = false;
    bool showNetworkPrompts = true;
    u64 freeSpace = fsGetFreeSpace(destination);

    std::string batchInfo = "";
    int prevProgress = -1;
    auto onProgress = [&](u64 pos, u64 totalSize) {
        u32 progress = (u32) ((pos * 100) / totalSize);
        if(prevProgress != (int) progress) {
            prevProgress = (int) progress;

            std::stringstream details;
            details << batchInfo;
            details << "Press B to cancel.";

            uiDisplayProgress(TOP_SCREEN, "Installing", details.str(), true, progress);
        }

        inputPoll();
        return !inputIsPressed(BUTTON_B);
    };

    auto onLoop = [&]() {
        if(ninjhax && inputIsPressed(BUTTON_START)) {
            exit = true;
            return true;
        }

        bool breakLoop = false;

        if(inputIsPressed(BUTTON_L)) {
            if(destination == SD) {
                destination = NAND;
            } else {
                destination = SD;
            }

            freeSpace = fsGetFreeSpace(destination);
            if(mode == DELETE_TITLE || mode == LAUNCH_TITLE) {
                breakLoop = true;
            }
        }

        if(inputIsPressed(BUTTON_R)) {
            if(mode == INSTALL_CIA) {
                mode = DELETE_CIA;
            } else if(mode == DELETE_CIA) {
                mode = DELETE_TITLE;
                breakLoop = true;
            } else if(mode == DELETE_TITLE) {
                mode = LAUNCH_TITLE;
            } else if(mode == LAUNCH_TITLE) {
                mode = INSTALL_CIA;
                breakLoop = true;
            }
        }

        if(mode == INSTALL_CIA && inputIsPressed(BUTTON_Y)) {
            while(platformIsRunning()) {
                gpuClearScreens();

                RemoteFile file = uiAcceptRemoteFile(TOP_SCREEN, [&](std::stringstream& infoStream) {
                    if(inputIsPressed(BUTTON_A)) {
                        showNetworkPrompts = !showNetworkPrompts;
                    }

                    infoStream << "\n";
                    infoStream << "Prompts: " << (showNetworkPrompts ? "Enabled" : "Disabled") << "\n";
                    infoStream << "Press A to toggle prompts.";
                });

                if(file.fd == NULL) {
                    break;
                }

                std::stringstream confirmStream;
                confirmStream << "Install the received application?" << "\n";
                confirmStream << "Size: " << file.fileSize << " bytes (" << std::fixed << std::setprecision(2) << file.fileSize / 1024.0f / 1024.0f << "MB)";
                if(!showNetworkPrompts || uiPrompt(TOP_SCREEN, confirmStream.str(), true)) {
                    AppResult ret = appInstall(destination, file.fd, file.fileSize, onProgress);
                    prevProgress = -1;
                    if(showNetworkPrompts || ret != APP_SUCCESS) {
                        std::stringstream resultMsg;
                        resultMsg << "Install ";
                        if(ret == APP_SUCCESS) {
                            resultMsg << "succeeded!";
                        } else {
                            resultMsg << "failed!" << "\n";
                            resultMsg << appGetResultString(ret);
                        }

                        uiPrompt(TOP_SCREEN, resultMsg.str(), false);
                    }
                }

                fclose(file.fd);
            }
        }

        if(inputIsPressed(BUTTON_SELECT)) {
            u32 selected = 0;
            bool dirty = true;
            while(platformIsRunning()) {
                inputPoll();
                if(inputIsPressed(BUTTON_B)) {
                    break;
                }

                if(inputIsPressed(BUTTON_A)) {
                    std::stringstream stream;
                    stream << "Install the selected ROP?" << "\n";
                    stream << ropNames[selected];

                    if(uiPrompt(TOP_SCREEN, stream.str(), true)) {
                        u16 userSettingsOffset = 0;
                        bool result = norRead(0x20, &userSettingsOffset, 2) && norWrite(userSettingsOffset << 3, rops[selected], ROP_SIZE);

                        std::stringstream resultMsg;
                        resultMsg << "ROP installation ";
                        if(result) {
                            resultMsg << "succeeded!";
                        } else {
                            resultMsg << "failed!" << "\n";
                            resultMsg << platformGetErrorString(platformGetError());
                        }

                        uiPrompt(TOP_SCREEN, resultMsg.str(), false);
                    }

                    dirty = true;
                }

                if(inputIsPressed(BUTTON_LEFT)) {
                    if(selected == 0) {
                        selected = ROP_COUNT - 1;
                    } else {
                        selected--;
                    }

                    dirty = true;
                }

                if(inputIsPressed(BUTTON_RIGHT)) {
                    if(selected >= ROP_COUNT - 1) {
                        selected = 0;
                    } else {
                        selected++;
                    }

                    dirty = true;
                }

                if(dirty) {
                    std::stringstream stream;
                    stream << "Select a ROP to install." << "\n";
                    stream << "< " << ropNames[selected] << " >" << "\n";
                    stream << "Press A to install, B to cancel.";
                    uiDisplayMessage(TOP_SCREEN, stream.str());
                }
            }
		}

        std::stringstream stream;
        stream << "Battery: ";
        if(platformIsBatteryCharging()) {
            stream << "Charging";
        } else {
            for(u32 i = 0; i < platformGetBatteryLevel(); i++) {
                stream << "|";
            }
        }

        stream << ", WiFi: ";
        if(!platformIsWifiConnected()) {
            stream << "Disconnected";
        } else {
            for(u32 i = 0; i < platformGetWifiLevel(); i++) {
                stream << "|";
            }
        }

        stream << "\n";

        stream << "Free Space: " << freeSpace << " bytes (" << std::fixed << std::setprecision(2) << freeSpace / 1024.0f / 1024.0f << "MB)" << "\n";
        stream << "Destination: " << (destination == NAND ? "NAND" : "SD") << ", Mode: " << (mode == INSTALL_CIA ? "Install CIA" : mode == DELETE_CIA ? "Delete CIA" : mode == DELETE_TITLE ? "Delete Title" : "Launch Title") << "\n";
        stream << "L - Switch Destination, R - Switch Mode" << "\n";
        if(mode == INSTALL_CIA) {
            stream << "X - Install all CIAs in the current directory" << "\n";
            stream << "Y - Receive an app over the network" << "\n";
        } else if(mode == DELETE_CIA) {
            stream << "X - Delete all CIAs in the current directory" << "\n";
        }

        stream << "SELECT - Install MSET ROP";

        if(ninjhax) {
            stream << "\n" << "START - Exit to launcher";
        }

        std::string str = stream.str();
        const std::string title = "FBI v1.4.2";
        gputDrawString(title, (gpuGetViewportWidth() - gputGetStringWidth(title, 16)) / 2, (gpuGetViewportHeight() - gputGetStringHeight(title, 16) + gputGetStringHeight(str, 8)) / 2, 16, 16);
        gputDrawString(str, (gpuGetViewportWidth() - gputGetStringWidth(str, 8)) / 2, 4, 8, 8);

        return breakLoop;
    };

    while(platformIsRunning()) {
        if(mode == INSTALL_CIA || mode == DELETE_CIA) {
            uiDisplayMessage(BOTTOM_SCREEN, "Loading file list...");

            std::string fileTarget;
            uiSelectFile(&fileTarget, "/", extensions, [&](const std::string currDirectory, bool inRoot, bool &updateList) {
                if(inputIsPressed(BUTTON_X)) {
                    std::stringstream confirmMsg;
                    if(mode == INSTALL_CIA) {
                        confirmMsg << "Install ";
                    } else {
                        confirmMsg << "Delete ";
                    }

                    confirmMsg << "all CIAs in the current directory?";
                    if(uiPrompt(TOP_SCREEN, confirmMsg.str(), true)) {
                        bool failed = false;
                        std::vector<FileInfo> contents = fsGetDirectoryContents(currDirectory);
                        u32 currItem = 0;
                        for(std::vector<FileInfo>::iterator it = contents.begin(); it != contents.end(); it++) {
                            std::string path = (*it).path;
                            if(!fsIsDirectory(path) && fsHasExtensions(path, extensions)) {
                                std::string displayFileName = (*it).name;
                                if(displayFileName.length() > 40) {
                                    displayFileName.resize(40);
                                    displayFileName += "...";
                                }

                                if(mode == INSTALL_CIA) {
                                    App app = appGetCiaInfo(path, destination);
                                    if(appIsInstalled(app)) {
                                        std::stringstream overwriteMsg;
                                        overwriteMsg << "Title already installed, overwrite?" << "\n";
                                        overwriteMsg << displayFileName;
                                        if(uiPrompt(TOP_SCREEN, overwriteMsg.str(), true)) {
                                            uiDisplayMessage(TOP_SCREEN, "Deleting title...");
                                            AppResult ret = appDelete(app);
                                            if(ret != APP_SUCCESS) {
                                                std::stringstream resultMsg;
                                                resultMsg << "Delete failed!" << "\n";
                                                resultMsg << appGetResultString(ret);
                                                uiPrompt(TOP_SCREEN, resultMsg.str(), false);

                                                failed = true;
                                                break;
                                            }
                                        } else {
                                            continue;
                                        }
                                    }

                                    std::stringstream batchInstallStream;
                                    batchInstallStream << displayFileName << " (" << currItem << ")" << "\n";

                                    batchInfo = batchInstallStream.str();
                                    AppResult ret = appInstallFile(destination, path, onProgress);
                                    prevProgress = -1;
                                    batchInfo = "";
                                    if(ret != APP_SUCCESS) {
                                        Error error = platformGetError();
                                        platformSetError(error);

                                        std::stringstream resultMsg;
                                        resultMsg << "Install failed!" << "\n";
                                        resultMsg << displayFileName << "\n";
                                        resultMsg << appGetResultString(ret);
                                        uiPrompt(TOP_SCREEN, resultMsg.str(), false);
                                        if(error.module != MODULE_NN_AM || error.description != DESCRIPTION_ALREADY_EXISTS) {
                                            failed = true;
                                            break;
                                        }
                                    }
                                } else {
                                    std::stringstream deleteStream;
                                    deleteStream << "Deleting CIA..." << "\n";
                                    deleteStream << displayFileName << " (" << currItem << ")";

                                    uiDisplayMessage(TOP_SCREEN, deleteStream.str());
                                    if(remove(path.c_str()) != 0) {
                                        std::stringstream resultMsg;
                                        resultMsg << "Delete failed!" << "\n";
                                        resultMsg << displayFileName << "\n";
                                        resultMsg << strerror(errno);
                                        uiPrompt(TOP_SCREEN, resultMsg.str(), false);
                                        failed = true;
                                        break;
                                    } else {
                                        updateList = true;
                                    }
                                }
                            }

                            currItem++;
                        }

                        if(!failed) {
                            uiPrompt(TOP_SCREEN, "Install succeeded!\n", false);
                        }

                        freeSpace = fsGetFreeSpace(destination);
                    }
                }

                return onLoop();
            }, [&](const std::string path, bool &updateList) {
                std::stringstream confirmMsg;
                if(mode == INSTALL_CIA) {
                    confirmMsg << "Install ";
                } else {
                    confirmMsg << "Delete ";
                }

                confirmMsg << "the selected CIA?";
                if(uiPrompt(TOP_SCREEN, confirmMsg.str(), true)) {
                    std::stringstream resultMsg;
                    if(mode == INSTALL_CIA) {
                        resultMsg << "Install ";
                    } else {
                        resultMsg << "Delete ";
                    }

                    if(mode == INSTALL_CIA) {
                        App app = appGetCiaInfo(path, destination);
                        if(appIsInstalled(app)) {
                            std::stringstream overwriteMsg;
                            overwriteMsg << "Title already installed, overwrite?";
                            if(uiPrompt(TOP_SCREEN, overwriteMsg.str(), true)) {
                                uiDisplayMessage(TOP_SCREEN, "Deleting title...");
                                AppResult ret = appDelete(app);
                                if(ret != APP_SUCCESS) {
                                    std::stringstream deleteResultMsg;
                                    deleteResultMsg << "Delete failed!" << "\n";
                                    deleteResultMsg << appGetResultString(ret);
                                    uiPrompt(TOP_SCREEN, deleteResultMsg.str(), false);

                                    return false;
                                }
                            } else {
                                return false;
                            }
                        }

                        AppResult ret = appInstallFile(destination, path, onProgress);
                        prevProgress = -1;
                        if(ret == APP_SUCCESS) {
                            resultMsg << "succeeded!";
                        } else {
                            resultMsg << "failed!" << "\n";
                            resultMsg << appGetResultString(ret);
                        }
                    } else {
                        uiDisplayMessage(TOP_SCREEN, "Deleting CIA...");
                        if(remove(path.c_str()) != 0) {
                            updateList = true;
                            resultMsg << "succeeded!";
                        } else {
                            resultMsg << "failed!" << "\n";
                            resultMsg << strerror(errno);
                        }
                    }

                    uiPrompt(TOP_SCREEN, resultMsg.str(), false);

                    freeSpace = fsGetFreeSpace(destination);
                }

                return false;
            });
        } else if(mode == DELETE_TITLE || mode == LAUNCH_TITLE) {
            uiDisplayMessage(BOTTOM_SCREEN, "Loading title list...");

            App appTarget;
            uiSelectApp(&appTarget, destination, [&](bool &updateList) {
                return onLoop();
            }, [&](App app, bool &updateList) {
                if(mode == DELETE_TITLE) {
                    if(uiPrompt(TOP_SCREEN, "Delete the selected title?", true) && (destination != NAND || uiPrompt(TOP_SCREEN, "You are about to delete a title from the NAND.\nTHIS HAS THE POTENTIAL TO BRICK YOUR 3DS!\nAre you sure you wish to continue?", true))) {
                        updateList = true;
                        uiDisplayMessage(TOP_SCREEN, "Deleting title...");
                        AppResult ret = appDelete(app);

                        std::stringstream resultMsg;
                        resultMsg << "Delete ";
                        if(ret == APP_SUCCESS) {
                            resultMsg << "succeeded!";
                        } else {
                            resultMsg << "failed!" << "\n";
                            resultMsg << appGetResultString(ret);
                        }

                        uiPrompt(TOP_SCREEN, resultMsg.str(), false);

                        freeSpace = fsGetFreeSpace(destination);
                    }
                } else if(mode == LAUNCH_TITLE) {
                    if(uiPrompt(TOP_SCREEN, "Launch the selected title?", true)) {
                        updateList = true;
                        uiDisplayMessage(TOP_SCREEN, "Launching title...");
                        AppResult ret = appLaunch(app);

                        if(ret != APP_SUCCESS) {
                            std::stringstream resultMsg;
                            resultMsg << "Launch failed!" << "\n";
                            resultMsg << appGetResultString(ret);
                            uiPrompt(TOP_SCREEN, resultMsg.str(), false);
                        } else {
                            while(true) {
                            }
                        }
                    }
                }

                return false;
            });
        }

        if(exit) {
            break;
        }
    }

    platformCleanup();
    return 0;
}
<commit_msg>Don't ignore already exists errors.<commit_after>#include <ctrcommon/app.hpp>
#include <ctrcommon/gpu.hpp>
#include <ctrcommon/input.hpp>
#include <ctrcommon/nor.hpp>
#include <ctrcommon/platform.hpp>
#include <ctrcommon/ui.hpp>

#include "rop.h"

#include <sys/errno.h>
#include <stdio.h>
#include <string.h>

#include <sstream>
#include <iomanip>

typedef enum {
    INSTALL_CIA,
    DELETE_CIA,
    DELETE_TITLE,
    LAUNCH_TITLE
} Mode;

int main(int argc, char **argv) {
    if(!platformInit()) {
        return 0;
    }

    bool ninjhax = platformIsNinjhax();

    std::vector<std::string> extensions;
    extensions.push_back("cia");

    MediaType destination = SD;
    Mode mode = INSTALL_CIA;
    bool exit = false;
    bool showNetworkPrompts = true;
    u64 freeSpace = fsGetFreeSpace(destination);

    std::string batchInfo = "";
    int prevProgress = -1;
    auto onProgress = [&](u64 pos, u64 totalSize) {
        u32 progress = (u32) ((pos * 100) / totalSize);
        if(prevProgress != (int) progress) {
            prevProgress = (int) progress;

            std::stringstream details;
            details << batchInfo;
            details << "Press B to cancel.";

            uiDisplayProgress(TOP_SCREEN, "Installing", details.str(), true, progress);
        }

        inputPoll();
        return !inputIsPressed(BUTTON_B);
    };

    auto onLoop = [&]() {
        if(ninjhax && inputIsPressed(BUTTON_START)) {
            exit = true;
            return true;
        }

        bool breakLoop = false;

        if(inputIsPressed(BUTTON_L)) {
            if(destination == SD) {
                destination = NAND;
            } else {
                destination = SD;
            }

            freeSpace = fsGetFreeSpace(destination);
            if(mode == DELETE_TITLE || mode == LAUNCH_TITLE) {
                breakLoop = true;
            }
        }

        if(inputIsPressed(BUTTON_R)) {
            if(mode == INSTALL_CIA) {
                mode = DELETE_CIA;
            } else if(mode == DELETE_CIA) {
                mode = DELETE_TITLE;
                breakLoop = true;
            } else if(mode == DELETE_TITLE) {
                mode = LAUNCH_TITLE;
            } else if(mode == LAUNCH_TITLE) {
                mode = INSTALL_CIA;
                breakLoop = true;
            }
        }

        if(mode == INSTALL_CIA && inputIsPressed(BUTTON_Y)) {
            while(platformIsRunning()) {
                gpuClearScreens();

                RemoteFile file = uiAcceptRemoteFile(TOP_SCREEN, [&](std::stringstream& infoStream) {
                    if(inputIsPressed(BUTTON_A)) {
                        showNetworkPrompts = !showNetworkPrompts;
                    }

                    infoStream << "\n";
                    infoStream << "Prompts: " << (showNetworkPrompts ? "Enabled" : "Disabled") << "\n";
                    infoStream << "Press A to toggle prompts.";
                });

                if(file.fd == NULL) {
                    break;
                }

                std::stringstream confirmStream;
                confirmStream << "Install the received application?" << "\n";
                confirmStream << "Size: " << file.fileSize << " bytes (" << std::fixed << std::setprecision(2) << file.fileSize / 1024.0f / 1024.0f << "MB)";
                if(!showNetworkPrompts || uiPrompt(TOP_SCREEN, confirmStream.str(), true)) {
                    AppResult ret = appInstall(destination, file.fd, file.fileSize, onProgress);
                    prevProgress = -1;
                    if(showNetworkPrompts || ret != APP_SUCCESS) {
                        std::stringstream resultMsg;
                        resultMsg << "Install ";
                        if(ret == APP_SUCCESS) {
                            resultMsg << "succeeded!";
                        } else {
                            resultMsg << "failed!" << "\n";
                            resultMsg << appGetResultString(ret);
                        }

                        uiPrompt(TOP_SCREEN, resultMsg.str(), false);
                    }
                }

                fclose(file.fd);
            }
        }

        if(inputIsPressed(BUTTON_SELECT)) {
            u32 selected = 0;
            bool dirty = true;
            while(platformIsRunning()) {
                inputPoll();
                if(inputIsPressed(BUTTON_B)) {
                    break;
                }

                if(inputIsPressed(BUTTON_A)) {
                    std::stringstream stream;
                    stream << "Install the selected ROP?" << "\n";
                    stream << ropNames[selected];

                    if(uiPrompt(TOP_SCREEN, stream.str(), true)) {
                        u16 userSettingsOffset = 0;
                        bool result = norRead(0x20, &userSettingsOffset, 2) && norWrite(userSettingsOffset << 3, rops[selected], ROP_SIZE);

                        std::stringstream resultMsg;
                        resultMsg << "ROP installation ";
                        if(result) {
                            resultMsg << "succeeded!";
                        } else {
                            resultMsg << "failed!" << "\n";
                            resultMsg << platformGetErrorString(platformGetError());
                        }

                        uiPrompt(TOP_SCREEN, resultMsg.str(), false);
                    }

                    dirty = true;
                }

                if(inputIsPressed(BUTTON_LEFT)) {
                    if(selected == 0) {
                        selected = ROP_COUNT - 1;
                    } else {
                        selected--;
                    }

                    dirty = true;
                }

                if(inputIsPressed(BUTTON_RIGHT)) {
                    if(selected >= ROP_COUNT - 1) {
                        selected = 0;
                    } else {
                        selected++;
                    }

                    dirty = true;
                }

                if(dirty) {
                    std::stringstream stream;
                    stream << "Select a ROP to install." << "\n";
                    stream << "< " << ropNames[selected] << " >" << "\n";
                    stream << "Press A to install, B to cancel.";
                    uiDisplayMessage(TOP_SCREEN, stream.str());
                }
            }
		}

        std::stringstream stream;
        stream << "Battery: ";
        if(platformIsBatteryCharging()) {
            stream << "Charging";
        } else {
            for(u32 i = 0; i < platformGetBatteryLevel(); i++) {
                stream << "|";
            }
        }

        stream << ", WiFi: ";
        if(!platformIsWifiConnected()) {
            stream << "Disconnected";
        } else {
            for(u32 i = 0; i < platformGetWifiLevel(); i++) {
                stream << "|";
            }
        }

        stream << "\n";

        stream << "Free Space: " << freeSpace << " bytes (" << std::fixed << std::setprecision(2) << freeSpace / 1024.0f / 1024.0f << "MB)" << "\n";
        stream << "Destination: " << (destination == NAND ? "NAND" : "SD") << ", Mode: " << (mode == INSTALL_CIA ? "Install CIA" : mode == DELETE_CIA ? "Delete CIA" : mode == DELETE_TITLE ? "Delete Title" : "Launch Title") << "\n";
        stream << "L - Switch Destination, R - Switch Mode" << "\n";
        if(mode == INSTALL_CIA) {
            stream << "X - Install all CIAs in the current directory" << "\n";
            stream << "Y - Receive an app over the network" << "\n";
        } else if(mode == DELETE_CIA) {
            stream << "X - Delete all CIAs in the current directory" << "\n";
        }

        stream << "SELECT - Install MSET ROP";

        if(ninjhax) {
            stream << "\n" << "START - Exit to launcher";
        }

        std::string str = stream.str();
        const std::string title = "FBI v1.4.2";
        gputDrawString(title, (gpuGetViewportWidth() - gputGetStringWidth(title, 16)) / 2, (gpuGetViewportHeight() - gputGetStringHeight(title, 16) + gputGetStringHeight(str, 8)) / 2, 16, 16);
        gputDrawString(str, (gpuGetViewportWidth() - gputGetStringWidth(str, 8)) / 2, 4, 8, 8);

        return breakLoop;
    };

    while(platformIsRunning()) {
        if(mode == INSTALL_CIA || mode == DELETE_CIA) {
            uiDisplayMessage(BOTTOM_SCREEN, "Loading file list...");

            std::string fileTarget;
            uiSelectFile(&fileTarget, "/", extensions, [&](const std::string currDirectory, bool inRoot, bool &updateList) {
                if(inputIsPressed(BUTTON_X)) {
                    std::stringstream confirmMsg;
                    if(mode == INSTALL_CIA) {
                        confirmMsg << "Install ";
                    } else {
                        confirmMsg << "Delete ";
                    }

                    confirmMsg << "all CIAs in the current directory?";
                    if(uiPrompt(TOP_SCREEN, confirmMsg.str(), true)) {
                        bool failed = false;
                        std::vector<FileInfo> contents = fsGetDirectoryContents(currDirectory);
                        u32 currItem = 0;
                        for(std::vector<FileInfo>::iterator it = contents.begin(); it != contents.end(); it++) {
                            std::string path = (*it).path;
                            if(!fsIsDirectory(path) && fsHasExtensions(path, extensions)) {
                                std::string displayFileName = (*it).name;
                                if(displayFileName.length() > 40) {
                                    displayFileName.resize(40);
                                    displayFileName += "...";
                                }

                                if(mode == INSTALL_CIA) {
                                    App app = appGetCiaInfo(path, destination);
                                    if(appIsInstalled(app)) {
                                        std::stringstream overwriteMsg;
                                        overwriteMsg << "Title already installed, overwrite?" << "\n";
                                        overwriteMsg << displayFileName;
                                        if(uiPrompt(TOP_SCREEN, overwriteMsg.str(), true)) {
                                            uiDisplayMessage(TOP_SCREEN, "Deleting title...");
                                            AppResult ret = appDelete(app);
                                            if(ret != APP_SUCCESS) {
                                                std::stringstream resultMsg;
                                                resultMsg << "Delete failed!" << "\n";
                                                resultMsg << displayFileName << "\n";
                                                resultMsg << appGetResultString(ret);
                                                uiPrompt(TOP_SCREEN, resultMsg.str(), false);

                                                failed = true;
                                                break;
                                            }
                                        } else {
                                            continue;
                                        }
                                    }

                                    std::stringstream batchInstallStream;
                                    batchInstallStream << displayFileName << " (" << currItem << ")" << "\n";

                                    batchInfo = batchInstallStream.str();
                                    AppResult ret = appInstallFile(destination, path, onProgress);
                                    prevProgress = -1;
                                    batchInfo = "";
                                    if(ret != APP_SUCCESS) {
                                        std::stringstream resultMsg;
                                        resultMsg << "Install failed!" << "\n";
                                        resultMsg << displayFileName << "\n";
                                        resultMsg << appGetResultString(ret);
                                        uiPrompt(TOP_SCREEN, resultMsg.str(), false);

                                        failed = true;
                                        break;
                                    }
                                } else {
                                    std::stringstream deleteStream;
                                    deleteStream << "Deleting CIA..." << "\n";
                                    deleteStream << displayFileName << " (" << currItem << ")";

                                    uiDisplayMessage(TOP_SCREEN, deleteStream.str());
                                    if(remove(path.c_str()) != 0) {
                                        std::stringstream resultMsg;
                                        resultMsg << "Delete failed!" << "\n";
                                        resultMsg << displayFileName << "\n";
                                        resultMsg << strerror(errno);
                                        uiPrompt(TOP_SCREEN, resultMsg.str(), false);
                                        failed = true;
                                        break;
                                    } else {
                                        updateList = true;
                                    }
                                }
                            }

                            currItem++;
                        }

                        if(!failed) {
                            uiPrompt(TOP_SCREEN, "Install succeeded!\n", false);
                        }

                        freeSpace = fsGetFreeSpace(destination);
                    }
                }

                return onLoop();
            }, [&](const std::string path, bool &updateList) {
                std::stringstream confirmMsg;
                if(mode == INSTALL_CIA) {
                    confirmMsg << "Install ";
                } else {
                    confirmMsg << "Delete ";
                }

                confirmMsg << "the selected CIA?";
                if(uiPrompt(TOP_SCREEN, confirmMsg.str(), true)) {
                    std::stringstream resultMsg;
                    if(mode == INSTALL_CIA) {
                        resultMsg << "Install ";
                    } else {
                        resultMsg << "Delete ";
                    }

                    if(mode == INSTALL_CIA) {
                        App app = appGetCiaInfo(path, destination);
                        if(appIsInstalled(app)) {
                            std::stringstream overwriteMsg;
                            overwriteMsg << "Title already installed, overwrite?";
                            if(uiPrompt(TOP_SCREEN, overwriteMsg.str(), true)) {
                                uiDisplayMessage(TOP_SCREEN, "Deleting title...");
                                AppResult ret = appDelete(app);
                                if(ret != APP_SUCCESS) {
                                    std::stringstream deleteResultMsg;
                                    deleteResultMsg << "Delete failed!" << "\n";
                                    deleteResultMsg << appGetResultString(ret);
                                    uiPrompt(TOP_SCREEN, deleteResultMsg.str(), false);

                                    return false;
                                }
                            } else {
                                return false;
                            }
                        }

                        AppResult ret = appInstallFile(destination, path, onProgress);
                        prevProgress = -1;
                        if(ret == APP_SUCCESS) {
                            resultMsg << "succeeded!";
                        } else {
                            resultMsg << "failed!" << "\n";
                            resultMsg << appGetResultString(ret);
                        }
                    } else {
                        uiDisplayMessage(TOP_SCREEN, "Deleting CIA...");
                        if(remove(path.c_str()) != 0) {
                            updateList = true;
                            resultMsg << "succeeded!";
                        } else {
                            resultMsg << "failed!" << "\n";
                            resultMsg << strerror(errno);
                        }
                    }

                    uiPrompt(TOP_SCREEN, resultMsg.str(), false);

                    freeSpace = fsGetFreeSpace(destination);
                }

                return false;
            });
        } else if(mode == DELETE_TITLE || mode == LAUNCH_TITLE) {
            uiDisplayMessage(BOTTOM_SCREEN, "Loading title list...");

            App appTarget;
            uiSelectApp(&appTarget, destination, [&](bool &updateList) {
                return onLoop();
            }, [&](App app, bool &updateList) {
                if(mode == DELETE_TITLE) {
                    if(uiPrompt(TOP_SCREEN, "Delete the selected title?", true) && (destination != NAND || uiPrompt(TOP_SCREEN, "You are about to delete a title from the NAND.\nTHIS HAS THE POTENTIAL TO BRICK YOUR 3DS!\nAre you sure you wish to continue?", true))) {
                        updateList = true;
                        uiDisplayMessage(TOP_SCREEN, "Deleting title...");
                        AppResult ret = appDelete(app);

                        std::stringstream resultMsg;
                        resultMsg << "Delete ";
                        if(ret == APP_SUCCESS) {
                            resultMsg << "succeeded!";
                        } else {
                            resultMsg << "failed!" << "\n";
                            resultMsg << appGetResultString(ret);
                        }

                        uiPrompt(TOP_SCREEN, resultMsg.str(), false);

                        freeSpace = fsGetFreeSpace(destination);
                    }
                } else if(mode == LAUNCH_TITLE) {
                    if(uiPrompt(TOP_SCREEN, "Launch the selected title?", true)) {
                        updateList = true;
                        uiDisplayMessage(TOP_SCREEN, "Launching title...");
                        AppResult ret = appLaunch(app);

                        if(ret != APP_SUCCESS) {
                            std::stringstream resultMsg;
                            resultMsg << "Launch failed!" << "\n";
                            resultMsg << appGetResultString(ret);
                            uiPrompt(TOP_SCREEN, resultMsg.str(), false);
                        } else {
                            while(true) {
                            }
                        }
                    }
                }

                return false;
            });
        }

        if(exit) {
            break;
        }
    }

    platformCleanup();
    return 0;
}
<|endoftext|>


<commit_before>/** ==========================================================================
* 2012 by KjellKod.cc. This is PUBLIC DOMAIN to use at your own risk and comes
* with no warranties. This code is yours to share, use and modify with no
* strings attached and no restrictions or obligations.
*
* For more information see g3log/LICENSE or refer refer to http://unlicense.org
* ============================================================================*/

#include "g3log/time.hpp"

#include <sstream>
#include <string>
#include <cstring>
#include <cmath>
#include <chrono>
#include <cassert>
#include <iomanip>
#ifdef __MACH__
#include <sys/time.h>
#endif

namespace g3 {
   namespace internal {
      const std::string kFractionalIdentier   = "%f";
      const size_t kFractionalIdentierSize = 2;

      Fractional getFractional(const std::string& format_buffer, size_t pos) {
         char  ch  = (format_buffer.size() > pos + kFractionalIdentierSize ? format_buffer.at(pos + kFractionalIdentierSize) : '\0');
         Fractional type = Fractional::NanosecondDefault;
         switch (ch) {
            case '3': type = Fractional::Millisecond; break;
            case '6': type = Fractional::Microsecond; break;
            case '9': type = Fractional::Nanosecond; break;
            default: type = Fractional::NanosecondDefault; break;
         }
         return type;
      }

      // Returns the fractional as a string with padded zeroes
      // 1 ms --> 001
      // 1 us --> 000001
      // 1 ns --> 000000001
      std::string to_string(const timespec& time_snapshot, Fractional fractional) {
         auto ns = time_snapshot.tv_nsec;
         auto zeroes = 9; // default ns
         auto digitsToCut = 1; // default ns, divide by 1 makes no change
         switch (fractional) {
            case Fractional::Millisecond : {
               zeroes = 3;
               digitsToCut = 1000000;
               break;
            }
            case Fractional::Microsecond : {
               zeroes = 6;
               digitsToCut = 1000;
               break;
            }
            case Fractional::Nanosecond :
            case Fractional::NanosecondDefault:
            default:
               zeroes = 9;
               digitsToCut = 1;

         }

         ns /= digitsToCut;
         // auto value = std::to_string(typeAdjustedValue);
         // return value; // std::string(fractional_digit, '0') + value;
         auto value = std::string(std::to_string(ns));
         return std::string(zeroes - value.size(), '0') + value;
      }
   } // internal
} // g3

namespace g3 {
   struct timespec systemtime_now() {
      struct timespec ts;
      timespec_get(&ts);
      return ts;
   }

   // std::timespec_get or posix clock_gettime)(...) are not
   // implemented on OSX and ubuntu gcc5 has no support for std::timespec_get(...) as of yet
   // so instead we roll our own.
   int timespec_get(struct timespec* ts/*, int base*/) {
      using namespace std::chrono;

      // thanks @AndreasSchoenle for the implementation and the explanation:
      // The time since epoch for the steady_clock is not necessarily really the time since 1970.
      // It usually is the time since program start. Thus, here is calculated the offset between
      // the starting point and the real start of the epoch as reported by the system clock
      // with the precision of the system clock.
      //
      // Time stamps will later have system clock accuracy but relative times will have the precision
      // of the high resolution clock.
      thread_local const auto os =
         time_point_cast<nanoseconds>(system_clock::now()).time_since_epoch() -
         time_point_cast<nanoseconds>(high_resolution_clock::now()).time_since_epoch();

      auto now_ns = (time_point_cast<nanoseconds>(high_resolution_clock::now()).time_since_epoch() + os).count();
      const auto kNanos = 1000000000;
      ts ->tv_sec = now_ns / kNanos;
      ts ->tv_nsec = now_ns % kNanos;
      return TIME_UTC;
   }

   // This mimics the original "std::put_time(const std::tm* tmb, const charT* fmt)"
   // This is needed since latest version (at time of writing) of gcc4.7 does not implement this library function yet.
   // return value is SIMPLIFIED to only return a std::string
   std::string put_time(const struct tm* tmb, const char* c_time_format) {
#if (defined(WIN32) || defined(_WIN32) || defined(__WIN32__)) && !defined(__MINGW32__)
      std::ostringstream oss;
      oss.fill('0');
      // BOGUS hack done for VS2012: C++11 non-conformant since it SHOULD take a "const struct tm*  "
      oss << std::put_time(const_cast<struct tm*> (tmb), c_time_format);
      return oss.str();
#else    // LINUX
      const size_t size = 1024;
      char buffer[size]; // IMPORTANT: check now and then for when gcc will implement std::put_time.
      //                    ... also ... This is way more buffer space then we need

      auto success = std::strftime(buffer, size, c_time_format, tmb);
      // In DEBUG the assert will trigger a process exit. Once inside the if-statement
      // the 'always true' expression will be displayed as reason for the exit
      //
      // In Production mode
      // the assert will do nothing but the format string will instead be returned
      if (0 == success) {
         assert((0 != success) && "strftime fails with illegal formatting");
         return c_time_format;
      }

      return buffer;
#endif
   }

   tm localtime(const std::time_t& time) {
      struct tm tm_snapshot;
#if (defined(WIN32) || defined(_WIN32) || defined(__WIN32__) && !defined(__GNUC__))
      localtime_s(&tm_snapshot, &time); // windsows
#else
      localtime_r(&time, &tm_snapshot); // POSIX
#endif
      return tm_snapshot;
   }

   std::string localtime_formatted(const timespec& time_snapshot, const std::string& time_format) {
      auto format_buffer = time_format;  // copying format string to a separate buffer

      // iterating through every "%f" instance in the format string
      auto identifierExtraSize = 0;
      for (size_t pos = 0; (pos = format_buffer.find(g3::internal::kFractionalIdentier, pos)) != std::string::npos; pos += g3::internal::kFractionalIdentierSize + identifierExtraSize) {
         // figuring out whether this is nano, micro or milli identifier
         auto type = g3::internal::getFractional(format_buffer, pos);
         auto value = g3::internal::to_string(time_snapshot, type);
         auto padding = 0;
         if (type != g3::internal::Fractional::NanosecondDefault) {
            padding = 1;
         }

         // replacing "%f[3|6|9]" with sec fractional part value
         format_buffer.replace(pos, g3::internal::kFractionalIdentier.size() + padding, value);
      }
      std::tm t = localtime(time_snapshot.tv_sec);
      return g3::put_time(&t, format_buffer.c_str()); // format example: //"%Y/%m/%d %H:%M:%S");
   }
} // g3
<commit_msg>Update time.cpp<commit_after>/** ==========================================================================
* 2012 by KjellKod.cc. This is PUBLIC DOMAIN to use at your own risk and comes
* with no warranties. This code is yours to share, use and modify with no
* strings attached and no restrictions or obligations.
*
* For more information see g3log/LICENSE or refer refer to http://unlicense.org
* ============================================================================*/

#include "g3log/time.hpp"

#include <sstream>
#include <string>
#include <cstring>
#include <cmath>
#include <chrono>
#include <cassert>
#include <iomanip>
#ifdef __MACH__
#include <sys/time.h>
#endif

namespace g3 {
   namespace internal {
      const std::string kFractionalIdentier   = "%f";
      const size_t kFractionalIdentierSize = 2;

      Fractional getFractional(const std::string& format_buffer, size_t pos) {
         char  ch  = (format_buffer.size() > pos + kFractionalIdentierSize ? format_buffer.at(pos + kFractionalIdentierSize) : '\0');
         Fractional type = Fractional::NanosecondDefault;
         switch (ch) {
            case '3': type = Fractional::Millisecond; break;
            case '6': type = Fractional::Microsecond; break;
            case '9': type = Fractional::Nanosecond; break;
            default: type = Fractional::NanosecondDefault; break;
         }
         return type;
      }

      // Returns the fractional as a string with padded zeroes
      // 1 ms --> 001
      // 1 us --> 000001
      // 1 ns --> 000000001
      std::string to_string(const timespec& time_snapshot, Fractional fractional) {
         auto ns = time_snapshot.tv_nsec;
         auto zeroes = 9; // default ns
         auto digitsToCut = 1; // default ns, divide by 1 makes no change
         switch (fractional) {
            case Fractional::Millisecond : {
               zeroes = 3;
               digitsToCut = 1000000;
               break;
            }
            case Fractional::Microsecond : {
               zeroes = 6;
               digitsToCut = 1000;
               break;
            }
            case Fractional::Nanosecond :
            case Fractional::NanosecondDefault:
            default:
               zeroes = 9;
               digitsToCut = 1;

         }

         ns /= digitsToCut;
         // auto value = std::to_string(typeAdjustedValue);
         // return value; // std::string(fractional_digit, '0') + value;
         auto value = std::string(std::to_string(ns));
         return std::string(zeroes - value.size(), '0') + value;
      }
   } // internal
} // g3

namespace g3 {
   struct timespec systemtime_now() {
      struct timespec ts;
      timespec_get(&ts);
      return ts;
   }

   // std::timespec_get or posix clock_gettime)(...) are not
   // implemented on OSX and ubuntu gcc5 has no support for std::timespec_get(...) as of yet
   // so instead we roll our own.
   int timespec_get(struct timespec* ts/*, int base*/) {
      using namespace std::chrono;

      // thanks @AndreasSchoenle for the implementation and the explanation:
      // The time since epoch for the steady_clock is not necessarily really the time since 1970.
      // It usually is the time since program start. Thus, here is calculated the offset between
      // the starting point and the real start of the epoch as reported by the system clock
      // with the precision of the system clock.
      //
      // Time stamps will later have system clock accuracy but relative times will have the precision
      // of the high resolution clock.
      thread_local const auto os =
         time_point_cast<nanoseconds>(system_clock::now()).time_since_epoch() -
         time_point_cast<nanoseconds>(high_resolution_clock::now()).time_since_epoch();

      auto now_ns = (time_point_cast<nanoseconds>(high_resolution_clock::now()).time_since_epoch() + os).count();
      const auto kNanos = 1000000000;
      ts ->tv_sec = now_ns / kNanos;
      ts ->tv_nsec = now_ns % kNanos;
      #ifdef TIME_UTC
         return TIME_UTC;
      #endif
      return 1;
   }

   // This mimics the original "std::put_time(const std::tm* tmb, const charT* fmt)"
   // This is needed since latest version (at time of writing) of gcc4.7 does not implement this library function yet.
   // return value is SIMPLIFIED to only return a std::string
   std::string put_time(const struct tm* tmb, const char* c_time_format) {
#if (defined(WIN32) || defined(_WIN32) || defined(__WIN32__)) && !defined(__MINGW32__)
      std::ostringstream oss;
      oss.fill('0');
      // BOGUS hack done for VS2012: C++11 non-conformant since it SHOULD take a "const struct tm*  "
      oss << std::put_time(const_cast<struct tm*> (tmb), c_time_format);
      return oss.str();
#else    // LINUX
      const size_t size = 1024;
      char buffer[size]; // IMPORTANT: check now and then for when gcc will implement std::put_time.
      //                    ... also ... This is way more buffer space then we need

      auto success = std::strftime(buffer, size, c_time_format, tmb);
      // In DEBUG the assert will trigger a process exit. Once inside the if-statement
      // the 'always true' expression will be displayed as reason for the exit
      //
      // In Production mode
      // the assert will do nothing but the format string will instead be returned
      if (0 == success) {
         assert((0 != success) && "strftime fails with illegal formatting");
         return c_time_format;
      }

      return buffer;
#endif
   }

   tm localtime(const std::time_t& time) {
      struct tm tm_snapshot;
#if (defined(WIN32) || defined(_WIN32) || defined(__WIN32__) && !defined(__GNUC__))
      localtime_s(&tm_snapshot, &time); // windsows
#else
      localtime_r(&time, &tm_snapshot); // POSIX
#endif
      return tm_snapshot;
   }

   std::string localtime_formatted(const timespec& time_snapshot, const std::string& time_format) {
      auto format_buffer = time_format;  // copying format string to a separate buffer

      // iterating through every "%f" instance in the format string
      auto identifierExtraSize = 0;
      for (size_t pos = 0; (pos = format_buffer.find(g3::internal::kFractionalIdentier, pos)) != std::string::npos; pos += g3::internal::kFractionalIdentierSize + identifierExtraSize) {
         // figuring out whether this is nano, micro or milli identifier
         auto type = g3::internal::getFractional(format_buffer, pos);
         auto value = g3::internal::to_string(time_snapshot, type);
         auto padding = 0;
         if (type != g3::internal::Fractional::NanosecondDefault) {
            padding = 1;
         }

         // replacing "%f[3|6|9]" with sec fractional part value
         format_buffer.replace(pos, g3::internal::kFractionalIdentier.size() + padding, value);
      }
      std::tm t = localtime(time_snapshot.tv_sec);
      return g3::put_time(&t, format_buffer.c_str()); // format example: //"%Y/%m/%d %H:%M:%S");
   }
} // g3
<|endoftext|>


<commit_before>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/ui/startup/bad_flags_prompt.h"

#include "base/command_line.h"
#include "base/utf_string_conversions.h"
#include "chrome/browser/api/infobars/simple_alert_infobar_delegate.h"
#include "chrome/browser/infobars/infobar_tab_helper.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_tabstrip.h"
#include "chrome/browser/ui/tab_contents/tab_contents.h"
#include "chrome/common/chrome_switches.h"
#include "grit/generated_resources.h"
#include "ui/base/l10n/l10n_util.h"

namespace chrome {

void ShowBadFlagsPrompt(Browser* browser) {
  // Unsupported flags for which to display a warning that "stability and
  // security will suffer".
  static const char* kBadFlags[] = {
    // These imply disabling the sandbox.
    switches::kSingleProcess,
    switches::kNoSandbox,
    switches::kInProcessWebGL,
    switches::kDisableWebSecurity,
    NULL
  };

  const char* bad_flag = NULL;
  for (const char** flag = kBadFlags; *flag; ++flag) {
    if (CommandLine::ForCurrentProcess()->HasSwitch(*flag)) {
      bad_flag = *flag;
      break;
    }
  }

  if (bad_flag) {
    TabContents* tab = chrome::GetActiveTabContents(browser);
    if (!tab)
      return;
    tab->infobar_tab_helper()->AddInfoBar(
        new SimpleAlertInfoBarDelegate(
            tab->infobar_tab_helper(), NULL,
            l10n_util::GetStringFUTF16(
            IDS_BAD_FLAGS_WARNING_MESSAGE,
            UTF8ToUTF16(std::string("--") + bad_flag)),
            false));
  }
}

}  // namespace chrome
<commit_msg><browser> Display a warning that "stability and security will suffer" when browser plugin is enabled for all view types via flags. We don't want to allow browser plugin to be enabled for regular pages since it breaks same origin policy, the flag to force it exists solely for debugging purposes.<commit_after>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/ui/startup/bad_flags_prompt.h"

#include "base/command_line.h"
#include "base/utf_string_conversions.h"
#include "chrome/browser/api/infobars/simple_alert_infobar_delegate.h"
#include "chrome/browser/infobars/infobar_tab_helper.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_tabstrip.h"
#include "chrome/browser/ui/tab_contents/tab_contents.h"
#include "chrome/common/chrome_switches.h"
#include "grit/generated_resources.h"
#include "ui/base/l10n/l10n_util.h"

namespace chrome {

void ShowBadFlagsPrompt(Browser* browser) {
  // Unsupported flags for which to display a warning that "stability and
  // security will suffer".
  static const char* kBadFlags[] = {
    // These imply disabling the sandbox.
    switches::kSingleProcess,
    switches::kNoSandbox,
    switches::kInProcessWebGL,
    switches::kDisableWebSecurity,
    // Browser plugin is dangerous on regular pages because it breaks the Same
    // Origin Policy.
    switches::kEnableBrowserPluginForAllViewTypes,
    NULL
  };

  const char* bad_flag = NULL;
  for (const char** flag = kBadFlags; *flag; ++flag) {
    if (CommandLine::ForCurrentProcess()->HasSwitch(*flag)) {
      bad_flag = *flag;
      break;
    }
  }

  if (bad_flag) {
    TabContents* tab = chrome::GetActiveTabContents(browser);
    if (!tab)
      return;
    tab->infobar_tab_helper()->AddInfoBar(
        new SimpleAlertInfoBarDelegate(
            tab->infobar_tab_helper(), NULL,
            l10n_util::GetStringFUTF16(
            IDS_BAD_FLAGS_WARNING_MESSAGE,
            UTF8ToUTF16(std::string("--") + bad_flag)),
            false));
  }
}

}  // namespace chrome
<|endoftext|>


<commit_before>// Copyright (c) 2006-2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// This test is POSIX only.

#include "base/basictypes.h"
#include "chrome/common/file_descriptor_set_posix.h"
#include "testing/gtest/include/gtest/gtest.h"

// The FileDescriptorSet will try and close some of the descriptor numbers
// which we given it. This is the base descriptor value. It's great enough such
// that no real descriptor will accidently be closed.
static const int kFDBase = 50000;

TEST(FileDescriptorSet, BasicAdd) {
  scoped_refptr<FileDescriptorSet> set = new FileDescriptorSet;

  ASSERT_EQ(set->size(), 0u);
  ASSERT_TRUE(set->empty());
  ASSERT_TRUE(set->Add(kFDBase));
  ASSERT_EQ(set->size(), 1u);
  ASSERT_TRUE(!set->empty());

  // Empties the set and stops a warning about deleting a set with unconsumed
  // descriptors
  set->CommitAll();
}

TEST(FileDescriptorSet, BasicAddAndClose) {
  scoped_refptr<FileDescriptorSet> set = new FileDescriptorSet;

  ASSERT_EQ(set->size(), 0u);
  ASSERT_TRUE(set->empty());
  ASSERT_TRUE(set->AddAndAutoClose(kFDBase));
  ASSERT_EQ(set->size(), 1u);
  ASSERT_TRUE(!set->empty());

  set->CommitAll();
}

TEST(FileDescriptorSet, MaxSize) {
  scoped_refptr<FileDescriptorSet> set = new FileDescriptorSet;

  for (unsigned i = 0;
       i < FileDescriptorSet::MAX_DESCRIPTORS_PER_MESSAGE; ++i) {
    ASSERT_TRUE(set->Add(kFDBase + 1 + i));
  }

  ASSERT_TRUE(!set->Add(kFDBase));

  set->CommitAll();
}

TEST(FileDescriptorSet, SetDescriptors) {
  scoped_refptr<FileDescriptorSet> set = new FileDescriptorSet;

  ASSERT_TRUE(set->empty());
  set->SetDescriptors(NULL, 0);
  ASSERT_TRUE(set->empty());

  static const int fds[] = {kFDBase};
  set->SetDescriptors(fds, 1);
  ASSERT_TRUE(!set->empty());
  ASSERT_EQ(set->size(), 1u);

  set->CommitAll();
}

TEST(FileDescriptorSet, GetDescriptors) {
  scoped_refptr<FileDescriptorSet> set = new FileDescriptorSet;

  set->GetDescriptors(NULL);
  ASSERT_TRUE(set->Add(kFDBase));

  int fds[1];
  fds[0] = 0;
  set->GetDescriptors(fds);
  ASSERT_EQ(fds[0], kFDBase);
  set->CommitAll();
  ASSERT_TRUE(set->empty());
}

TEST(FileDescriptorSet, WalkInOrder) {
  scoped_refptr<FileDescriptorSet> set = new FileDescriptorSet;

  ASSERT_TRUE(set->Add(kFDBase));
  ASSERT_TRUE(set->Add(kFDBase + 1));
  ASSERT_TRUE(set->Add(kFDBase + 2));

  ASSERT_EQ(set->GetDescriptorAt(0), kFDBase);
  ASSERT_EQ(set->GetDescriptorAt(1), kFDBase + 1);
  ASSERT_EQ(set->GetDescriptorAt(2), kFDBase + 2);

  set->CommitAll();
}

TEST(FileDescriptorSet, WalkWrongOrder) {
  scoped_refptr<FileDescriptorSet> set = new FileDescriptorSet;

  ASSERT_TRUE(set->Add(kFDBase));
  ASSERT_TRUE(set->Add(kFDBase + 1));
  ASSERT_TRUE(set->Add(kFDBase + 2));

  ASSERT_EQ(set->GetDescriptorAt(0), kFDBase);
  ASSERT_EQ(set->GetDescriptorAt(2), -1);

  set->CommitAll();
}

TEST(FileDescriptorSet, WalkCycle) {
  scoped_refptr<FileDescriptorSet> set = new FileDescriptorSet;

  ASSERT_TRUE(set->Add(kFDBase));
  ASSERT_TRUE(set->Add(kFDBase + 1));
  ASSERT_TRUE(set->Add(kFDBase + 2));

  ASSERT_EQ(set->GetDescriptorAt(0), kFDBase);
  ASSERT_EQ(set->GetDescriptorAt(1), kFDBase + 1);
  ASSERT_EQ(set->GetDescriptorAt(2), kFDBase + 2);
  ASSERT_EQ(set->GetDescriptorAt(0), kFDBase);
  ASSERT_EQ(set->GetDescriptorAt(1), kFDBase + 1);
  ASSERT_EQ(set->GetDescriptorAt(2), kFDBase + 2);
  ASSERT_EQ(set->GetDescriptorAt(0), kFDBase);
  ASSERT_EQ(set->GetDescriptorAt(1), kFDBase + 1);
  ASSERT_EQ(set->GetDescriptorAt(2), kFDBase + 2);

  set->CommitAll();
}

TEST(FileDescriptorSet, DontClose) {
  scoped_refptr<FileDescriptorSet> set = new FileDescriptorSet;

  const int fd = open("/dev/null", O_RDONLY);
  ASSERT_TRUE(set->Add(fd));
  set->CommitAll();

  const int duped = dup(fd);
  ASSERT_GE(duped, 0);
  close(duped);
  close(fd);
}

TEST(FileDescriptorSet, DoClose) {
  scoped_refptr<FileDescriptorSet> set = new FileDescriptorSet;

  const int fd = open("/dev/null", O_RDONLY);
  ASSERT_TRUE(set->AddAndAutoClose(fd));
  set->CommitAll();

  const int duped = dup(fd);
  ASSERT_EQ(duped, -1);
  close(fd);
}
<commit_msg>POSIX: fix Mac build<commit_after>// Copyright (c) 2006-2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// This test is POSIX only.

#include <unistd.h>
#include <stdio.h>

#include "base/basictypes.h"
#include "chrome/common/file_descriptor_set_posix.h"
#include "testing/gtest/include/gtest/gtest.h"

// The FileDescriptorSet will try and close some of the descriptor numbers
// which we given it. This is the base descriptor value. It's great enough such
// that no real descriptor will accidently be closed.
static const int kFDBase = 50000;

TEST(FileDescriptorSet, BasicAdd) {
  scoped_refptr<FileDescriptorSet> set = new FileDescriptorSet;

  ASSERT_EQ(set->size(), 0u);
  ASSERT_TRUE(set->empty());
  ASSERT_TRUE(set->Add(kFDBase));
  ASSERT_EQ(set->size(), 1u);
  ASSERT_TRUE(!set->empty());

  // Empties the set and stops a warning about deleting a set with unconsumed
  // descriptors
  set->CommitAll();
}

TEST(FileDescriptorSet, BasicAddAndClose) {
  scoped_refptr<FileDescriptorSet> set = new FileDescriptorSet;

  ASSERT_EQ(set->size(), 0u);
  ASSERT_TRUE(set->empty());
  ASSERT_TRUE(set->AddAndAutoClose(kFDBase));
  ASSERT_EQ(set->size(), 1u);
  ASSERT_TRUE(!set->empty());

  set->CommitAll();
}

TEST(FileDescriptorSet, MaxSize) {
  scoped_refptr<FileDescriptorSet> set = new FileDescriptorSet;

  for (unsigned i = 0;
       i < FileDescriptorSet::MAX_DESCRIPTORS_PER_MESSAGE; ++i) {
    ASSERT_TRUE(set->Add(kFDBase + 1 + i));
  }

  ASSERT_TRUE(!set->Add(kFDBase));

  set->CommitAll();
}

TEST(FileDescriptorSet, SetDescriptors) {
  scoped_refptr<FileDescriptorSet> set = new FileDescriptorSet;

  ASSERT_TRUE(set->empty());
  set->SetDescriptors(NULL, 0);
  ASSERT_TRUE(set->empty());

  static const int fds[] = {kFDBase};
  set->SetDescriptors(fds, 1);
  ASSERT_TRUE(!set->empty());
  ASSERT_EQ(set->size(), 1u);

  set->CommitAll();
}

TEST(FileDescriptorSet, GetDescriptors) {
  scoped_refptr<FileDescriptorSet> set = new FileDescriptorSet;

  set->GetDescriptors(NULL);
  ASSERT_TRUE(set->Add(kFDBase));

  int fds[1];
  fds[0] = 0;
  set->GetDescriptors(fds);
  ASSERT_EQ(fds[0], kFDBase);
  set->CommitAll();
  ASSERT_TRUE(set->empty());
}

TEST(FileDescriptorSet, WalkInOrder) {
  scoped_refptr<FileDescriptorSet> set = new FileDescriptorSet;

  ASSERT_TRUE(set->Add(kFDBase));
  ASSERT_TRUE(set->Add(kFDBase + 1));
  ASSERT_TRUE(set->Add(kFDBase + 2));

  ASSERT_EQ(set->GetDescriptorAt(0), kFDBase);
  ASSERT_EQ(set->GetDescriptorAt(1), kFDBase + 1);
  ASSERT_EQ(set->GetDescriptorAt(2), kFDBase + 2);

  set->CommitAll();
}

TEST(FileDescriptorSet, WalkWrongOrder) {
  scoped_refptr<FileDescriptorSet> set = new FileDescriptorSet;

  ASSERT_TRUE(set->Add(kFDBase));
  ASSERT_TRUE(set->Add(kFDBase + 1));
  ASSERT_TRUE(set->Add(kFDBase + 2));

  ASSERT_EQ(set->GetDescriptorAt(0), kFDBase);
  ASSERT_EQ(set->GetDescriptorAt(2), -1);

  set->CommitAll();
}

TEST(FileDescriptorSet, WalkCycle) {
  scoped_refptr<FileDescriptorSet> set = new FileDescriptorSet;

  ASSERT_TRUE(set->Add(kFDBase));
  ASSERT_TRUE(set->Add(kFDBase + 1));
  ASSERT_TRUE(set->Add(kFDBase + 2));

  ASSERT_EQ(set->GetDescriptorAt(0), kFDBase);
  ASSERT_EQ(set->GetDescriptorAt(1), kFDBase + 1);
  ASSERT_EQ(set->GetDescriptorAt(2), kFDBase + 2);
  ASSERT_EQ(set->GetDescriptorAt(0), kFDBase);
  ASSERT_EQ(set->GetDescriptorAt(1), kFDBase + 1);
  ASSERT_EQ(set->GetDescriptorAt(2), kFDBase + 2);
  ASSERT_EQ(set->GetDescriptorAt(0), kFDBase);
  ASSERT_EQ(set->GetDescriptorAt(1), kFDBase + 1);
  ASSERT_EQ(set->GetDescriptorAt(2), kFDBase + 2);

  set->CommitAll();
}

TEST(FileDescriptorSet, DontClose) {
  scoped_refptr<FileDescriptorSet> set = new FileDescriptorSet;

  const int fd = open("/dev/null", O_RDONLY);
  ASSERT_TRUE(set->Add(fd));
  set->CommitAll();

  const int duped = dup(fd);
  ASSERT_GE(duped, 0);
  close(duped);
  close(fd);
}

TEST(FileDescriptorSet, DoClose) {
  scoped_refptr<FileDescriptorSet> set = new FileDescriptorSet;

  const int fd = open("/dev/null", O_RDONLY);
  ASSERT_TRUE(set->AddAndAutoClose(fd));
  set->CommitAll();

  const int duped = dup(fd);
  ASSERT_EQ(duped, -1);
  close(fd);
}
<|endoftext|>


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

#include "boost/python.hpp"

#include "IECorePython/ToCoreConverterBinding.h"

#include "IECorePython/RunTimeTypedBinding.h"

#include "IECore/Object.h"
#include "IECore/ToCoreConverter.h"

using namespace boost::python;
using namespace std;
using namespace IECore;

namespace IECorePython
{

void bindToCoreConverter()
{
	RunTimeTypedClass<ToCoreConverter>()
		.def( "convert", &ToCoreConverter::convert )
	;
}

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

#include "boost/python.hpp"

#include "IECorePython/ToCoreConverterBinding.h"

#include "IECorePython/RunTimeTypedBinding.h"

#include "IECorePython/ScopedGILRelease.h"

#include "IECore/Object.h"
#include "IECore/ToCoreConverter.h"

using namespace boost::python;
using namespace std;
using namespace IECore;

namespace
{
	IECore::ObjectPtr convert(const IECore::ToCoreConverter* self )
	{
		IECorePython::ScopedGILRelease scopedGilRelease;
		return self->convert();
	}
} // namepsace

namespace IECorePython
{

void bindToCoreConverter()
{
	RunTimeTypedClass<ToCoreConverter>()
		.def( "convert", &::convert )
	;
}

}
<|endoftext|>


<commit_before>#include "ArchetypesEditorManager.hpp"
#include <Threads/MainThread.hpp>
#include <Threads/ThreadManager.hpp>
#include <Entities/EntitySerializationInfos.hpp>
#include <Components/EntityRepresentation.hpp>
#include <EntityHelpers/EntityImgui.hpp>
#include <Utils/Age_Imgui.hpp>
#include <Entities\ArchetypeScenes.hpp>
#include <Utils/Directory.hpp>
#include <Utils/FileSystemHelpers.hpp>
#include <Entities/ReadableEntityPack.hpp>
#include <Entities/EntityReadablePacker.hpp>
#include <Systems\AssetsAndComponentRelationsSystem.hpp>
#include <Entities\BinaryEntityPack.hpp>

namespace AGE
{
	namespace WE
	{
		ArchetypeEditorManager::ArchetypeEditorManager()
		{
		}

		ArchetypeEditorManager::~ArchetypeEditorManager()
		{

		}

		void ArchetypeEditorManager::load()
		{
			Directory dir;
			const bool success = dir.open(_libraryFolder.c_str());
			AGE_ASSERT(success);
			for (auto it = dir.recursive_begin(); it != dir.recursive_end(); ++it)
			{
				if (Directory::IsFile(*it))
				{
					auto extension = AGE::FileSystemHelpers::GetExtension(*it);

					if (extension != "raw_archetype")
					{
						continue;
					}
					loadOne(AGE::FileSystemHelpers::RemoveExtension(AGE::FileSystemHelpers::GetName(*it)));
				}
			}
			dir.close();
		}

		void ArchetypeEditorManager::save()
		{
			for (auto &arch : _archetypesCollection)
			{
				ReadableEntityPack pack;
				CreateReadableEntityPack(pack, arch.second->root);
				auto path = _libraryFolder + "/" + arch.second->name + ".raw_archetype";
				pack.saveToFile(path);

				BinaryEntityPack binPack = pack.toBinary();
				binPack.saveToFile(_libraryFolder + "/" + arch.second->name + ".archetype");
			}
		}

		void ArchetypeEditorManager::loadOne(const std::string &name)
		{
			if (_archetypesCollection.find(name) != std::end(_archetypesCollection))
			{
				return;
			}

			auto currentScene = GetMainThread()->getActiveScene();
			GetMainThread()->setSceneAsActive(getScene().get());

			auto representation = std::make_shared<ArchetypeEditorRepresentation>();
			representation->name = name;

			auto path = _libraryFolder + "/" + name + ".raw_archetype";
			ReadableEntityPack pack;
			pack.scene = getScene().get();
			pack.loadFromFile(path);

			representation->root = pack.entities.front().entity;
			_archetypesCollection.insert(std::make_pair(name, representation));
			_regenerateImGuiNamesList();

			if (currentScene)
			{
				GetMainThread()->setSceneAsActive(currentScene);
			}
		}

		void ArchetypeEditorManager::addOne(const std::string &name, Entity &entity)
		{
			if (_archetypesCollection.find(name) != std::end(_archetypesCollection))
			{
				return;
			}
			auto scene = entity.getScene();
			auto representation = std::make_shared<ArchetypeEditorRepresentation>();
			representation->name = name;

			//we copy the original entity into the archetype entity
			//for that we set the ArchetypeScene as the current scene
			//so that messages will be not passed to the renderScene of the WE's scene
			//but to the ArchetypeScene.
			GetMainThread()->setSceneAsActive(getScene().get());
			bool success = getScene()->copyEntity(entity, representation->root, true, false);

			GetMainThread()->setSceneAsActive(scene);
			AGE_ASSERT(success);

			representation->root.getComponent<EntityRepresentation>()->editorOnly = true;

			auto componentsCopy = entity.getComponentList();

			auto entityRepresentationComponent = entity.getComponent<EntityRepresentation>();
			AGE_ASSERT(entityRepresentationComponent != nullptr);

			//we remove original entity's components
			//replacing them by archetypes ones
			for (auto &e : componentsCopy)
			{
				if (e != nullptr && e != entityRepresentationComponent)
				{
					entity.copyComponent(representation->root.getComponent(e->getType()));
				}
			}

			std::vector<Entity*> tmpEntitiesList;
			std::vector<const char*> tmpEntitiesNameList;
			listEntityTree(entity, tmpEntitiesNameList, tmpEntitiesList);

			for (auto &e : tmpEntitiesList)
			{
				auto er = e->getComponent<EntityRepresentation>();
				e->addComponent<ArchetypeComponent>(name);
				e->getComponent<ArchetypeComponent>()->parentIsAnArchetype = false;
				if (er != entityRepresentationComponent)
				{
					e->getComponent<ArchetypeComponent>()->parentIsAnArchetype = true;
				}
			}

			tmpEntitiesList.clear(); tmpEntitiesNameList.clear();
			listEntityTree(representation->root, tmpEntitiesNameList, tmpEntitiesList);

			for (auto &e : tmpEntitiesList)
			{
				auto er = e->getComponent<EntityRepresentation>();
				er->_isArchetype = true;
			}

			entityRepresentationComponent->_archetypeLinked = representation;

			representation->entities.insert(entity);

			_archetypesCollection.insert(std::make_pair(name, representation));

			_regenerateImGuiNamesList();
		}

		void ArchetypeEditorManager::spawn(Entity &entity, const std::string &name)
		{
			auto it = _archetypesCollection.find(name);
			AGE_ASSERT(it != std::end(_archetypesCollection));

			entity.getScene()->copyEntity(it->second->root, entity, true, false);

			auto representation = entity.getComponent<EntityRepresentation>();

			representation->editorOnly = false;
			representation->_archetypeLinked = it->second;

			std::vector<Entity*> tmpEntitiesList;
			std::vector<const char*> tmpEntitiesNameList;
			listEntityTree(entity, tmpEntitiesNameList, tmpEntitiesList);

			for (auto &e : tmpEntitiesList)
			{
				e->addComponent<ArchetypeComponent>(name);
				if (*e != entity)
				{
					e->getComponent<ArchetypeComponent>()->parentIsAnArchetype = true;
				}
			}

			it->second->entities.insert(entity);
		}

		void ArchetypeEditorManager::update(AScene *scene)
		{
			ImGui::SameLine();
			ImGui::BeginChild("Archetypes", ImVec2(ImGui::GetWindowWidth() * 0.35f, 0));

			if (ImGui::TreeNode("Archetypes") && !_archetypesImGuiNamesList.empty()
				&& ImGui::Combo("", &_selectedArchetypeIndex, &_archetypesImGuiNamesList[0], static_cast<int>(_archetypesImGuiNamesList.size())))
			{
				if (_selectedArchetypeIndex < _archetypesImGuiNamesList.size())
				{
					auto name = _archetypesImGuiNamesList[_selectedArchetypeIndex];
					auto find = _archetypesCollection.find(name);
					if (find == std::end(_archetypesCollection))
					{
						_selectedArchetype = nullptr;
					}
					else
					{
						_selectedArchetype = find->second;
					}
				}
				ImGui::TreePop();
			}

			if (_selectedArchetype != nullptr)
			{
				if (_selectedEntity == nullptr)
				{
					_selectedEntity = &_selectedArchetype->root;
				}

				ImGui::Checkbox("Graphnode display", &_graphNodeDisplay);

				auto entity = _selectedArchetype->root;
				auto modified = false;

				GetMainThread()->setSceneAsActive(getScene().get());
				if (_graphNodeDisplay)
				{
					modified |= recursiveDisplayList(entity, _selectedEntity, _selectParent, false);
					if (_selectedEntity)
					{
						modified |= displayEntity(*_selectedEntity, scene);
					}
				}
				else
				{
					_entitiesNames.clear();
					std::vector<Entity*> tmpEntitiesList;
					listEntityTree(_selectedArchetype->root, _entitiesNames, tmpEntitiesList);

					if (tmpEntitiesList.size() > 0)
					{

						if (_selectedEntityIndex > tmpEntitiesList.size())
						{
							_selectedEntityIndex = static_cast<int>(tmpEntitiesList.size() - 1);
						}

						ImGui::PushItemWidth(-1);
						//ImGui::ListBoxHeader("##empty");
						if (ImGui::ListBox("##empty", &_selectedEntityIndex, &(_entitiesNames.front()), (int)(_entitiesNames.size())))
						{
							if (tmpEntitiesList.size() > 0 && _selectedEntityIndex < tmpEntitiesList.size())
							{
								_selectedEntity = tmpEntitiesList[_selectedEntityIndex];
							}
							else
							{
								_selectedEntity = nullptr;
							}
						}
						//ImGui::ListBoxFooter();
						ImGui::PopItemWidth();
						if (_selectedEntity)
						{
							modified |= displayEntity(*_selectedEntity, scene);
						}
					}
				}

				if (_selectedEntity)
				{
					auto &types = ComponentRegistrationManager::getInstance().getExposedType();
					auto &creationFn = ComponentRegistrationManager::getInstance().getCreationFunctions();

					for (auto &t : types)
					{
						if (!_selectedEntity->haveComponent(t.second)
							&& t.second != Component<ArchetypeComponent>::getTypeId())
						{
							if (ImGui::SmallButton(std::string("Add : " + ComponentRegistrationManager::getInstance().getComponentName(t.second)).c_str()))
							{
								creationFn.at(t.first)(_selectedEntity);
								modified = true;
							}
						}
					}
				}
				ImGui::Separator();

				GetMainThread()->setSceneAsActive(scene);

				if (modified)
				{
					for (auto e : _selectedArchetype->entities)
					{
						_copyArchetypeToInstanciedEntity(_selectedArchetype->root, e);
					}
				}

				if (ImGui::SmallButton("Create an instance"))
				{
						auto &name = _archetypesImGuiNamesList[_selectedArchetypeIndex];
						Entity duplicate = scene->createEntity();
						spawn(duplicate, name);
				}
			}

			ImGui::EndChild();
		}

		void ArchetypeEditorManager::_copyArchetypeToInstanciedEntity(Entity &archetype, Entity &entity)
		{
			auto &componentList = archetype.getComponentList();

			auto representation = entity.getComponent<EntityRepresentation>();
			auto archetypeCpt = entity.getComponent<ArchetypeComponent>();

			auto &copyComponentList = entity.getComponentList();

			if (archetypeCpt->synchronizePosition)
			{
				entity.getLink().setPosition(archetype.getLink().getPosition());
			}
			if (archetypeCpt->synchronizeRotation)
			{
				entity.getLink().setOrientation(archetype.getLink().getOrientation());
			}
			if (archetypeCpt->synchronizeScale)
			{
				entity.getLink().setScale(archetype.getLink().getScale());
			}

			// we delete all existing components
			for (auto c : copyComponentList)
			{
				if (c != nullptr && c != representation && c != archetypeCpt)
				{
					entity.removeComponent(c->getType());
				}
			}

			// and replace them by fresh copy
			representation = archetype.getComponent<EntityRepresentation>();
			for (auto c : componentList)
			{
				if (c != nullptr && c != representation && c != archetypeCpt)
				{
					entity.copyComponent(c);
				}
			}

			const auto &archetypesChild = archetype.getLink().getChildren();
			const auto &entityChild = entity.getLink().getChildren();

			AGE_ASSERT(archetypesChild.size() == entityChild.size());

			for (std::size_t i = 0; i < archetypesChild.size(); ++i)
			{
				_copyArchetypeToInstanciedEntity(archetypesChild[i]->getEntity()->getEntity(), entityChild[i]->getEntity()->getEntity());
			}
		}

		void ArchetypeEditorManager::_regenerateImGuiNamesList()
		{
			_archetypesImGuiNamesList.clear();
			for (auto &e : _archetypesCollection)
			{
				_archetypesImGuiNamesList.push_back(e.first.c_str());
			}
		}

		std::shared_ptr<AScene> ArchetypeEditorManager::getScene()
		{
			if (_archetypesScene == nullptr)
			{
				_archetypesScene = std::make_shared<ArchetypeScene>(GetEngine());
				GetEngine()->addScene(_archetypesScene, "EDITOR_ARCHETYPES_SCENE");
				_archetypesScene->addSystem<WE::AssetsAndComponentRelationsSystem>(0);
				GetEngine()->initScene("EDITOR_ARCHETYPES_SCENE");
				GetEngine()->enableScene("EDITOR_ARCHETYPES_SCENE", 0);
			}
			return _archetypesScene;
		}

		void ArchetypeEditorManager::enableScene()
		{
			GetEngine()->enableScene("EDITOR_ARCHETYPES_SCENE", 0);
		}

		void ArchetypeEditorManager::disableScene()
		{
			GetEngine()->enableScene("EDITOR_ARCHETYPES_SCENE", 0);
		}

	}
}<commit_msg>Avoid selection archetype display if the tree Archetype node is not open<commit_after>#include "ArchetypesEditorManager.hpp"
#include <Threads/MainThread.hpp>
#include <Threads/ThreadManager.hpp>
#include <Entities/EntitySerializationInfos.hpp>
#include <Components/EntityRepresentation.hpp>
#include <EntityHelpers/EntityImgui.hpp>
#include <Utils/Age_Imgui.hpp>
#include <Entities\ArchetypeScenes.hpp>
#include <Utils/Directory.hpp>
#include <Utils/FileSystemHelpers.hpp>
#include <Entities/ReadableEntityPack.hpp>
#include <Entities/EntityReadablePacker.hpp>
#include <Systems\AssetsAndComponentRelationsSystem.hpp>
#include <Entities\BinaryEntityPack.hpp>

namespace AGE
{
	namespace WE
	{
		ArchetypeEditorManager::ArchetypeEditorManager()
		{
		}

		ArchetypeEditorManager::~ArchetypeEditorManager()
		{

		}

		void ArchetypeEditorManager::load()
		{
			Directory dir;
			const bool success = dir.open(_libraryFolder.c_str());
			AGE_ASSERT(success);
			for (auto it = dir.recursive_begin(); it != dir.recursive_end(); ++it)
			{
				if (Directory::IsFile(*it))
				{
					auto extension = AGE::FileSystemHelpers::GetExtension(*it);

					if (extension != "raw_archetype")
					{
						continue;
					}
					loadOne(AGE::FileSystemHelpers::RemoveExtension(AGE::FileSystemHelpers::GetName(*it)));
				}
			}
			dir.close();
		}

		void ArchetypeEditorManager::save()
		{
			for (auto &arch : _archetypesCollection)
			{
				ReadableEntityPack pack;
				CreateReadableEntityPack(pack, arch.second->root);
				auto path = _libraryFolder + "/" + arch.second->name + ".raw_archetype";
				pack.saveToFile(path);

				BinaryEntityPack binPack = pack.toBinary();
				binPack.saveToFile(_libraryFolder + "/" + arch.second->name + ".archetype");
			}
		}

		void ArchetypeEditorManager::loadOne(const std::string &name)
		{
			if (_archetypesCollection.find(name) != std::end(_archetypesCollection))
			{
				return;
			}

			auto currentScene = GetMainThread()->getActiveScene();
			GetMainThread()->setSceneAsActive(getScene().get());

			auto representation = std::make_shared<ArchetypeEditorRepresentation>();
			representation->name = name;

			auto path = _libraryFolder + "/" + name + ".raw_archetype";
			ReadableEntityPack pack;
			pack.scene = getScene().get();
			pack.loadFromFile(path);

			representation->root = pack.entities.front().entity;
			_archetypesCollection.insert(std::make_pair(name, representation));
			_regenerateImGuiNamesList();

			if (currentScene)
			{
				GetMainThread()->setSceneAsActive(currentScene);
			}
		}

		void ArchetypeEditorManager::addOne(const std::string &name, Entity &entity)
		{
			if (_archetypesCollection.find(name) != std::end(_archetypesCollection))
			{
				return;
			}
			auto scene = entity.getScene();
			auto representation = std::make_shared<ArchetypeEditorRepresentation>();
			representation->name = name;

			//we copy the original entity into the archetype entity
			//for that we set the ArchetypeScene as the current scene
			//so that messages will be not passed to the renderScene of the WE's scene
			//but to the ArchetypeScene.
			GetMainThread()->setSceneAsActive(getScene().get());
			bool success = getScene()->copyEntity(entity, representation->root, true, false);

			GetMainThread()->setSceneAsActive(scene);
			AGE_ASSERT(success);

			representation->root.getComponent<EntityRepresentation>()->editorOnly = true;

			auto componentsCopy = entity.getComponentList();

			auto entityRepresentationComponent = entity.getComponent<EntityRepresentation>();
			AGE_ASSERT(entityRepresentationComponent != nullptr);

			//we remove original entity's components
			//replacing them by archetypes ones
			for (auto &e : componentsCopy)
			{
				if (e != nullptr && e != entityRepresentationComponent)
				{
					entity.copyComponent(representation->root.getComponent(e->getType()));
				}
			}

			std::vector<Entity*> tmpEntitiesList;
			std::vector<const char*> tmpEntitiesNameList;
			listEntityTree(entity, tmpEntitiesNameList, tmpEntitiesList);

			for (auto &e : tmpEntitiesList)
			{
				auto er = e->getComponent<EntityRepresentation>();
				e->addComponent<ArchetypeComponent>(name);
				e->getComponent<ArchetypeComponent>()->parentIsAnArchetype = false;
				if (er != entityRepresentationComponent)
				{
					e->getComponent<ArchetypeComponent>()->parentIsAnArchetype = true;
				}
			}

			tmpEntitiesList.clear(); tmpEntitiesNameList.clear();
			listEntityTree(representation->root, tmpEntitiesNameList, tmpEntitiesList);

			for (auto &e : tmpEntitiesList)
			{
				auto er = e->getComponent<EntityRepresentation>();
				er->_isArchetype = true;
			}

			entityRepresentationComponent->_archetypeLinked = representation;

			representation->entities.insert(entity);

			_archetypesCollection.insert(std::make_pair(name, representation));

			_regenerateImGuiNamesList();
		}

		void ArchetypeEditorManager::spawn(Entity &entity, const std::string &name)
		{
			auto it = _archetypesCollection.find(name);
			AGE_ASSERT(it != std::end(_archetypesCollection));

			entity.getScene()->copyEntity(it->second->root, entity, true, false);

			auto representation = entity.getComponent<EntityRepresentation>();

			representation->editorOnly = false;
			representation->_archetypeLinked = it->second;

			std::vector<Entity*> tmpEntitiesList;
			std::vector<const char*> tmpEntitiesNameList;
			listEntityTree(entity, tmpEntitiesNameList, tmpEntitiesList);

			for (auto &e : tmpEntitiesList)
			{
				e->addComponent<ArchetypeComponent>(name);
				if (*e != entity)
				{
					e->getComponent<ArchetypeComponent>()->parentIsAnArchetype = true;
				}
			}

			it->second->entities.insert(entity);
		}

		void ArchetypeEditorManager::update(AScene *scene)
		{
			ImGui::SameLine();
			ImGui::BeginChild("Archetypes", ImVec2(ImGui::GetWindowWidth() * 0.35f, 0));
			bool treeNodeOpen;

			if ((treeNodeOpen = ImGui::TreeNode("Archetypes") && !_archetypesImGuiNamesList.empty())
				&& ImGui::Combo("", &_selectedArchetypeIndex, &_archetypesImGuiNamesList[0], static_cast<int>(_archetypesImGuiNamesList.size())))
			{
				treeNodeOpen = true;
				if (_selectedArchetypeIndex < _archetypesImGuiNamesList.size())
				{
					auto name = _archetypesImGuiNamesList[_selectedArchetypeIndex];
					auto find = _archetypesCollection.find(name);
					if (find == std::end(_archetypesCollection))
					{
						_selectedArchetype = nullptr;
					}
					else
					{
						_selectedArchetype = find->second;
					}
				}
				ImGui::TreePop();
			}

			if (treeNodeOpen && _selectedArchetype != nullptr)
			{
				if (_selectedEntity == nullptr)
				{
					_selectedEntity = &_selectedArchetype->root;
				}

				ImGui::Checkbox("Graphnode display", &_graphNodeDisplay);

				auto entity = _selectedArchetype->root;
				auto modified = false;

				GetMainThread()->setSceneAsActive(getScene().get());
				if (_graphNodeDisplay)
				{
					modified |= recursiveDisplayList(entity, _selectedEntity, _selectParent, false);
					if (_selectedEntity)
					{
						modified |= displayEntity(*_selectedEntity, scene);
					}
				}
				else
				{
					_entitiesNames.clear();
					std::vector<Entity*> tmpEntitiesList;
					listEntityTree(_selectedArchetype->root, _entitiesNames, tmpEntitiesList);

					if (tmpEntitiesList.size() > 0)
					{

						if (_selectedEntityIndex > tmpEntitiesList.size())
						{
							_selectedEntityIndex = static_cast<int>(tmpEntitiesList.size() - 1);
						}

						ImGui::PushItemWidth(-1);
						//ImGui::ListBoxHeader("##empty");
						if (ImGui::ListBox("##empty", &_selectedEntityIndex, &(_entitiesNames.front()), (int)(_entitiesNames.size())))
						{
							if (tmpEntitiesList.size() > 0 && _selectedEntityIndex < tmpEntitiesList.size())
							{
								_selectedEntity = tmpEntitiesList[_selectedEntityIndex];
							}
							else
							{
								_selectedEntity = nullptr;
							}
						}
						//ImGui::ListBoxFooter();
						ImGui::PopItemWidth();
						if (_selectedEntity)
						{
							modified |= displayEntity(*_selectedEntity, scene);
						}
					}
				}

				if (_selectedEntity)
				{
					auto &types = ComponentRegistrationManager::getInstance().getExposedType();
					auto &creationFn = ComponentRegistrationManager::getInstance().getCreationFunctions();

					for (auto &t : types)
					{
						if (!_selectedEntity->haveComponent(t.second)
							&& t.second != Component<ArchetypeComponent>::getTypeId())
						{
							if (ImGui::SmallButton(std::string("Add : " + ComponentRegistrationManager::getInstance().getComponentName(t.second)).c_str()))
							{
								creationFn.at(t.first)(_selectedEntity);
								modified = true;
							}
						}
					}
				}
				ImGui::Separator();

				GetMainThread()->setSceneAsActive(scene);

				if (modified)
				{
					for (auto e : _selectedArchetype->entities)
					{
						_copyArchetypeToInstanciedEntity(_selectedArchetype->root, e);
					}
				}

				if (ImGui::SmallButton("Create an instance"))
				{
						auto &name = _archetypesImGuiNamesList[_selectedArchetypeIndex];
						Entity duplicate = scene->createEntity();
						spawn(duplicate, name);
				}
			}

			ImGui::EndChild();
		}

		void ArchetypeEditorManager::_copyArchetypeToInstanciedEntity(Entity &archetype, Entity &entity)
		{
			auto &componentList = archetype.getComponentList();

			auto representation = entity.getComponent<EntityRepresentation>();
			auto archetypeCpt = entity.getComponent<ArchetypeComponent>();

			auto &copyComponentList = entity.getComponentList();

			if (archetypeCpt->synchronizePosition)
			{
				entity.getLink().setPosition(archetype.getLink().getPosition());
			}
			if (archetypeCpt->synchronizeRotation)
			{
				entity.getLink().setOrientation(archetype.getLink().getOrientation());
			}
			if (archetypeCpt->synchronizeScale)
			{
				entity.getLink().setScale(archetype.getLink().getScale());
			}

			// we delete all existing components
			for (auto c : copyComponentList)
			{
				if (c != nullptr && c != representation && c != archetypeCpt)
				{
					entity.removeComponent(c->getType());
				}
			}

			// and replace them by fresh copy
			representation = archetype.getComponent<EntityRepresentation>();
			for (auto c : componentList)
			{
				if (c != nullptr && c != representation && c != archetypeCpt)
				{
					entity.copyComponent(c);
				}
			}

			const auto &archetypesChild = archetype.getLink().getChildren();
			const auto &entityChild = entity.getLink().getChildren();

			AGE_ASSERT(archetypesChild.size() == entityChild.size());

			for (std::size_t i = 0; i < archetypesChild.size(); ++i)
			{
				_copyArchetypeToInstanciedEntity(archetypesChild[i]->getEntity()->getEntity(), entityChild[i]->getEntity()->getEntity());
			}
		}

		void ArchetypeEditorManager::_regenerateImGuiNamesList()
		{
			_archetypesImGuiNamesList.clear();
			for (auto &e : _archetypesCollection)
			{
				_archetypesImGuiNamesList.push_back(e.first.c_str());
			}
		}

		std::shared_ptr<AScene> ArchetypeEditorManager::getScene()
		{
			if (_archetypesScene == nullptr)
			{
				_archetypesScene = std::make_shared<ArchetypeScene>(GetEngine());
				GetEngine()->addScene(_archetypesScene, "EDITOR_ARCHETYPES_SCENE");
				_archetypesScene->addSystem<WE::AssetsAndComponentRelationsSystem>(0);
				GetEngine()->initScene("EDITOR_ARCHETYPES_SCENE");
				GetEngine()->enableScene("EDITOR_ARCHETYPES_SCENE", 0);
			}
			return _archetypesScene;
		}

		void ArchetypeEditorManager::enableScene()
		{
			GetEngine()->enableScene("EDITOR_ARCHETYPES_SCENE", 0);
		}

		void ArchetypeEditorManager::disableScene()
		{
			GetEngine()->enableScene("EDITOR_ARCHETYPES_SCENE", 0);
		}

	}
}<|endoftext|>