<commit_before>/*
* UsbDk filter/redirector driver
*
* Copyright (c) 2013  Red Hat, Inc.
*
* Authors:
*  Dmitry Fleytman  <dfleytma@redhat.com>
*
*/

#include "driver.h"
#include "Filter.h"
#include "device.tmh"

// {C0F2DADE-8235-4065-89A8-58DB74DDC9AC}
DEFINE_GUID(GUID_USBDK_CLONE_PDO,
    0xc0f2dade, 0x8235, 0x4065, 0x89, 0xa8, 0x58, 0xdb, 0x74, 0xdd, 0xc9, 0xac);

typedef struct _CONTROL_DEVICE_EXTENSION {
} PDO_CLONE_EXTENSION, *PPDO_CLONE_EXTENSION;

WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(PDO_CLONE_EXTENSION, PdoCloneGetData)

static WDFDEVICE
UsbDkClonePdo(WDFDEVICE ParentDevice)
{
    WDFDEVICE              ClonePdo;
    NTSTATUS               status;
    PWDFDEVICE_INIT        DevInit;
    WDF_OBJECT_ATTRIBUTES  DevAttr;

    PAGED_CODE();

    DevInit = WdfPdoInitAllocate(ParentDevice);

    if (DevInit == NULL) {
        TraceEvents(TRACE_LEVEL_ERROR, TRACE_DEVICE, "%!FUNC! WdfPdoInitAllocate returned NULL");
        return WDF_NO_HANDLE;
    }

    WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&DevAttr, PDO_CLONE_EXTENSION);

#define CLONE_HARDWARE_IDS      L"USB\\Vid_FEED&Pid_CAFE&Rev_0001\0USB\\Vid_FEED&Pid_CAFE\0"
#define CLONE_COMPATIBLE_IDS    L"USB\\Class_FF&SubClass_FF&Prot_FF\0USB\\Class_FF&SubClass_FF\0USB\\Class_FF\0"
#define CLONE_INSTANCE_ID       L"111222333"

    DECLARE_CONST_UNICODE_STRING(CloneHwId, CLONE_HARDWARE_IDS);
    DECLARE_CONST_UNICODE_STRING(CloneCompatId, CLONE_COMPATIBLE_IDS);
    DECLARE_CONST_UNICODE_STRING(CloneInstanceId, CLONE_INSTANCE_ID);

    //TODO: Check error codes
    WdfPdoInitAssignDeviceID(DevInit, &CloneHwId);
    WdfPdoInitAddCompatibleID(DevInit, &CloneCompatId);
    WdfPdoInitAddHardwareID(DevInit, &CloneCompatId);
    WdfPdoInitAssignInstanceID(DevInit, &CloneInstanceId);

    status = WdfDeviceCreate(&DevInit, &DevAttr, &ClonePdo);
    if (!NT_SUCCESS(status))
    {
        TraceEvents(TRACE_LEVEL_ERROR, TRACE_DEVICE, "%!FUNC! WdfDeviceCreate returned %!STATUS!", status);
        WdfDeviceInitFree(DevInit);
        return WDF_NO_HANDLE;
    }

    return ClonePdo;
}

VOID UsbDkQDRPostProcessWi(_In_ PVOID WdfDevice)
{
    WDFDEVICE Device = (WDFDEVICE) WdfDevice;
    PDEVICE_CONTEXT Ctx = DeviceGetContext(WdfDevice);

    ASSERT(Ctx->QDRIrp != NULL);

    TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DEVICE, "%!FUNC! Entry");

    PDEVICE_RELATIONS Relations = (PDEVICE_RELATIONS) Ctx->QDRIrp->IoStatus.Information;

    if (Relations)
    {
        if (Relations->Count > 0)
        {
            Ctx->ClonedPdo = Relations->Objects[0];

            WDFDEVICE PdoClone = UsbDkClonePdo(Device);

            if (PdoClone != WDF_NO_HANDLE)
            {
                Relations->Objects[0] = WdfDeviceWdmGetDeviceObject(PdoClone);
                ObReferenceObject(Relations->Objects[0]);

                TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DEVICE, "%!FUNC! Replaced PDO 0x%p with 0x%p",
                    Ctx->ClonedPdo, Relations->Objects[0]);

                //TODO: Temporary to allow normal USB hub driver unload
                ObDereferenceObject(Ctx->ClonedPdo);
            }
            else
            {
                TraceEvents(TRACE_LEVEL_ERROR, TRACE_DEVICE, "%!FUNC! Failed to create clone PDO");
            }
        }
    }

    PIRP QDRIrp = Ctx->QDRIrp;
    Ctx->QDRIrp = NULL;

    IoCompleteRequest(QDRIrp, IO_NO_INCREMENT);
}

NTSTATUS UsbDkQDRPostProcess(_In_  PDEVICE_OBJECT DeviceObject, _In_  PIRP Irp, _In_  PVOID WdfDevice)
{
    PDEVICE_CONTEXT Ctx = DeviceGetContext(WdfDevice);

    UNREFERENCED_PARAMETER(DeviceObject);

    if (Irp->PendingReturned)
    {
        IoMarkIrpPending(Irp);
    }

    ASSERT(Ctx->QDRIrp == NULL);

    TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DEVICE, "%!FUNC! Queuing work item");

    Ctx->QDRIrp = Irp;
    Ctx->QDRCompletionWorkItem.Enqueue();

    return STATUS_MORE_PROCESSING_REQUIRED;
}

static NTSTATUS UsbDkQDRPreProcess(_In_ WDFDEVICE Device, _Inout_  PIRP Irp)
{
     PDEVICE_OBJECT wdmDevice = WdfDeviceWdmGetDeviceObject(Device);

    PIO_STACK_LOCATION  irpStack = IoGetCurrentIrpStackLocation(Irp);

    if (BusRelations != irpStack->Parameters.QueryDeviceRelations.Type)
    {
        IoSkipCurrentIrpStackLocation(Irp);
    }
    else
    {
        IoCopyCurrentIrpStackLocationToNext(Irp);
        IoSetCompletionRoutineEx(wdmDevice, Irp, UsbDkQDRPostProcess, Device, TRUE, FALSE, FALSE);
    }

    return WdfDeviceWdmDispatchPreprocessedIrp(Device, Irp);
}

static NTSTATUS
UsbDkSetupFiltering(_In_ PWDFDEVICE_INIT DeviceInit)
{
    UCHAR minorCode = IRP_MN_QUERY_DEVICE_RELATIONS;

    PAGED_CODE();

    WdfFdoInitSetFilter(DeviceInit);

    NTSTATUS status = WdfDeviceInitAssignWdmIrpPreprocessCallback(DeviceInit,
                                                                  UsbDkQDRPreProcess,
                                                                  IRP_MJ_PNP, &minorCode, 1);

    if (!NT_SUCCESS(status))
    {
        TraceEvents(TRACE_LEVEL_ERROR, TRACE_DEVICE, "%!FUNC! status: %!STATUS!", status);
    }

    return status;
}

VOID
UsbDkEvtDeviceContextCleanup(_In_ WDFOBJECT DeviceObject)
{
    PAGED_CODE();

    TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DEVICE, "%!FUNC! Entry");

    auto deviceContext = DeviceGetContext(DeviceObject);
    if (deviceContext->Initialized)
    {
        deviceContext->QDRCompletionWorkItem.~CWdfWorkitem();
    }
}

NTSTATUS
UsbDkCreateDevice(_Inout_ PWDFDEVICE_INIT DeviceInit)
{
    WDF_OBJECT_ATTRIBUTES deviceAttributes;
    WDFDEVICE device;

    PAGED_CODE();

    TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DEVICE, "%!FUNC! Entry");

    auto status = UsbDkSetupFiltering(DeviceInit);
    if (!NT_SUCCESS(status))
    {
        return status;
    }

    WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&deviceAttributes, DEVICE_CONTEXT);
    deviceAttributes.EvtCleanupCallback = UsbDkEvtDeviceContextCleanup;

    status = WdfDeviceCreate(&DeviceInit, &deviceAttributes, &device);

    if (!NT_SUCCESS(status))
    {
        TraceEvents(TRACE_LEVEL_ERROR, TRACE_DEVICE, "%!FUNC! WdfDeviceCreate status: %!STATUS!", status);
        return status;
    }

    if (UsbDkShouldAttach(device))
    {
        auto deviceContext = DeviceGetContext(device);
        deviceContext->IOTarget = WdfDeviceGetIoTarget(device);
        deviceContext->QDRIrp = NULL;
        deviceContext->ClonedPdo = NULL;

        new (&deviceContext->QDRCompletionWorkItem) CWdfWorkitem(device, UsbDkQDRPostProcessWi, device);
        status = deviceContext->QDRCompletionWorkItem.Create();

        deviceContext->Initialized = TRUE;

        ULONG traceLevel = NT_SUCCESS(status) ? TRACE_LEVEL_INFORMATION : TRACE_LEVEL_ERROR;
        TraceEvents(traceLevel, TRACE_DEVICE, "%!FUNC! Attachment status: %!STATUS!", status);
    }
    else
    {
        status = STATUS_NOT_SUPPORTED;
        TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DEVICE, "%!FUNC! Not attached");
    }

    return status;
}
<commit_msg>UsbDk: Introduce redirected device IDs dumps<commit_after>/*
* UsbDk filter/redirector driver
*
* Copyright (c) 2013  Red Hat, Inc.
*
* Authors:
*  Dmitry Fleytman  <dfleytma@redhat.com>
*
*/

#include "driver.h"
#include "Filter.h"
#include "DeviceAccess.h"
#include "device.tmh"

extern "C"
{
#include <ntstrsafe.h>
}

// {C0F2DADE-8235-4065-89A8-58DB74DDC9AC}
DEFINE_GUID(GUID_USBDK_CLONE_PDO,
    0xc0f2dade, 0x8235, 0x4065, 0x89, 0xa8, 0x58, 0xdb, 0x74, 0xdd, 0xc9, 0xac);

typedef struct _CONTROL_DEVICE_EXTENSION {
} PDO_CLONE_EXTENSION, *PPDO_CLONE_EXTENSION;

WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(PDO_CLONE_EXTENSION, PdoCloneGetData)

static WDFDEVICE
UsbDkClonePdo(WDFDEVICE ParentDevice)
{
    WDFDEVICE              ClonePdo;
    NTSTATUS               status;
    PWDFDEVICE_INIT        DevInit;
    WDF_OBJECT_ATTRIBUTES  DevAttr;

    PAGED_CODE();

    DevInit = WdfPdoInitAllocate(ParentDevice);

    if (DevInit == NULL) {
        TraceEvents(TRACE_LEVEL_ERROR, TRACE_DEVICE, "%!FUNC! WdfPdoInitAllocate returned NULL");
        return WDF_NO_HANDLE;
    }

    WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&DevAttr, PDO_CLONE_EXTENSION);

#define CLONE_HARDWARE_IDS      L"USB\\Vid_FEED&Pid_CAFE&Rev_0001\0USB\\Vid_FEED&Pid_CAFE\0"
#define CLONE_COMPATIBLE_IDS    L"USB\\Class_FF&SubClass_FF&Prot_FF\0USB\\Class_FF&SubClass_FF\0USB\\Class_FF\0"
#define CLONE_INSTANCE_ID       L"111222333"

    DECLARE_CONST_UNICODE_STRING(CloneHwId, CLONE_HARDWARE_IDS);
    DECLARE_CONST_UNICODE_STRING(CloneCompatId, CLONE_COMPATIBLE_IDS);
    DECLARE_CONST_UNICODE_STRING(CloneInstanceId, CLONE_INSTANCE_ID);

    //TODO: Check error codes
    WdfPdoInitAssignDeviceID(DevInit, &CloneHwId);
    WdfPdoInitAddCompatibleID(DevInit, &CloneCompatId);
    WdfPdoInitAddHardwareID(DevInit, &CloneCompatId);
    WdfPdoInitAssignInstanceID(DevInit, &CloneInstanceId);

    status = WdfDeviceCreate(&DevInit, &DevAttr, &ClonePdo);
    if (!NT_SUCCESS(status))
    {
        TraceEvents(TRACE_LEVEL_ERROR, TRACE_DEVICE, "%!FUNC! WdfDeviceCreate returned %!STATUS!", status);
        WdfDeviceInitFree(DevInit);
        return WDF_NO_HANDLE;
    }

    return ClonePdo;
}

//TODO: Temporary function, printouts only
VOID UsbDkDumpHWIds(CDeviceAccess* devAcc)
{
    CObjHolder<CRegText> IDs(devAcc->GetHardwareIDs());

    if (!IDs || IDs->empty())
    {
        TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DEVICE, "%!FUNC! No HW IDs read");
    }
    else
    {
        TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DEVICE, "%!FUNC! HW IDs read");
        IDs->Dump();
    }

    CObjHolder<CRegText> DevIDs(devAcc->GetDeviceID());

    if (!DevIDs || DevIDs->empty())
    {
        TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DEVICE, "%!FUNC! No Device IDs read");
    }
    else
    {
        TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DEVICE, "%!FUNC! Device IDs read");
        DevIDs->Dump();
    }
}

VOID UsbDkQDRPostProcessWi(_In_ PVOID WdfDevice)
{
    WDFDEVICE Device = (WDFDEVICE) WdfDevice;
    PDEVICE_CONTEXT Ctx = DeviceGetContext(WdfDevice);

    ASSERT(Ctx->QDRIrp != NULL);

    TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DEVICE, "%!FUNC! Entry");

    PDEVICE_RELATIONS Relations = (PDEVICE_RELATIONS) Ctx->QDRIrp->IoStatus.Information;

    if (Relations)
    {
        if (Relations->Count > 0)
        {
            Ctx->ClonedPdo = Relations->Objects[0];

            {
                //TEMPORARY: To verify we see HW ids of PDO to be cloned
                CObjHolder<CDeviceAccess> pdoAccess(CDeviceAccess::GetDeviceAccess(Ctx->ClonedPdo));
                if (pdoAccess)
                {
                    UsbDkDumpHWIds(pdoAccess);
                }
            }

            WDFDEVICE PdoClone = UsbDkClonePdo(Device);

            if (PdoClone != WDF_NO_HANDLE)
            {
                Relations->Objects[0] = WdfDeviceWdmGetDeviceObject(PdoClone);
                ObReferenceObject(Relations->Objects[0]);

                TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DEVICE, "%!FUNC! Replaced PDO 0x%p with 0x%p",
                    Ctx->ClonedPdo, Relations->Objects[0]);

                //TODO: Temporary to allow normal USB hub driver unload
                ObDereferenceObject(Ctx->ClonedPdo);
            }
            else
            {
                TraceEvents(TRACE_LEVEL_ERROR, TRACE_DEVICE, "%!FUNC! Failed to create clone PDO");
            }
        }
    }

    PIRP QDRIrp = Ctx->QDRIrp;
    Ctx->QDRIrp = NULL;

    IoCompleteRequest(QDRIrp, IO_NO_INCREMENT);
}

NTSTATUS UsbDkQDRPostProcess(_In_  PDEVICE_OBJECT DeviceObject, _In_  PIRP Irp, _In_  PVOID WdfDevice)
{
    PDEVICE_CONTEXT Ctx = DeviceGetContext(WdfDevice);

    UNREFERENCED_PARAMETER(DeviceObject);

    if (Irp->PendingReturned)
    {
        IoMarkIrpPending(Irp);
    }

    ASSERT(Ctx->QDRIrp == NULL);

    TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DEVICE, "%!FUNC! Queuing work item");

    Ctx->QDRIrp = Irp;
    Ctx->QDRCompletionWorkItem.Enqueue();

    return STATUS_MORE_PROCESSING_REQUIRED;
}

static NTSTATUS UsbDkQDRPreProcess(_In_ WDFDEVICE Device, _Inout_  PIRP Irp)
{
     PDEVICE_OBJECT wdmDevice = WdfDeviceWdmGetDeviceObject(Device);

    PIO_STACK_LOCATION  irpStack = IoGetCurrentIrpStackLocation(Irp);

    if (BusRelations != irpStack->Parameters.QueryDeviceRelations.Type)
    {
        IoSkipCurrentIrpStackLocation(Irp);
    }
    else
    {
        IoCopyCurrentIrpStackLocationToNext(Irp);
        IoSetCompletionRoutineEx(wdmDevice, Irp, UsbDkQDRPostProcess, Device, TRUE, FALSE, FALSE);
    }

    return WdfDeviceWdmDispatchPreprocessedIrp(Device, Irp);
}

static NTSTATUS
UsbDkSetupFiltering(_In_ PWDFDEVICE_INIT DeviceInit)
{
    UCHAR minorCode = IRP_MN_QUERY_DEVICE_RELATIONS;

    PAGED_CODE();

    WdfFdoInitSetFilter(DeviceInit);

    NTSTATUS status = WdfDeviceInitAssignWdmIrpPreprocessCallback(DeviceInit,
                                                                  UsbDkQDRPreProcess,
                                                                  IRP_MJ_PNP, &minorCode, 1);

    if (!NT_SUCCESS(status))
    {
        TraceEvents(TRACE_LEVEL_ERROR, TRACE_DEVICE, "%!FUNC! status: %!STATUS!", status);
    }

    return status;
}

VOID
UsbDkEvtDeviceContextCleanup(_In_ WDFOBJECT DeviceObject)
{
    PAGED_CODE();

    TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DEVICE, "%!FUNC! Entry");

    auto deviceContext = DeviceGetContext(DeviceObject);
    if (deviceContext->Initialized)
    {
        deviceContext->QDRCompletionWorkItem.~CWdfWorkitem();
    }
}

NTSTATUS
UsbDkCreateDevice(_Inout_ PWDFDEVICE_INIT DeviceInit)
{
    WDF_OBJECT_ATTRIBUTES deviceAttributes;
    WDFDEVICE device;

    PAGED_CODE();

    TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DEVICE, "%!FUNC! Entry");

    auto status = UsbDkSetupFiltering(DeviceInit);
    if (!NT_SUCCESS(status))
    {
        return status;
    }

    WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&deviceAttributes, DEVICE_CONTEXT);
    deviceAttributes.EvtCleanupCallback = UsbDkEvtDeviceContextCleanup;

    status = WdfDeviceCreate(&DeviceInit, &deviceAttributes, &device);

    if (!NT_SUCCESS(status))
    {
        TraceEvents(TRACE_LEVEL_ERROR, TRACE_DEVICE, "%!FUNC! WdfDeviceCreate status: %!STATUS!", status);
        return status;
    }

    if (UsbDkShouldAttach(device))
    {
        auto deviceContext = DeviceGetContext(device);
        deviceContext->IOTarget = WdfDeviceGetIoTarget(device);
        deviceContext->QDRIrp = NULL;
        deviceContext->ClonedPdo = NULL;

        new (&deviceContext->QDRCompletionWorkItem) CWdfWorkitem(device, UsbDkQDRPostProcessWi, device);
        status = deviceContext->QDRCompletionWorkItem.Create();

        deviceContext->Initialized = TRUE;

        ULONG traceLevel = NT_SUCCESS(status) ? TRACE_LEVEL_INFORMATION : TRACE_LEVEL_ERROR;
        TraceEvents(traceLevel, TRACE_DEVICE, "%!FUNC! Attachment status: %!STATUS!", status);
    }
    else
    {
        status = STATUS_NOT_SUPPORTED;
        TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DEVICE, "%!FUNC! Not attached");
    }

    return status;
}
<|endoftext|>


<commit_before>/***************************************************************************
*  @file       The code is for the exercises in C++ Primmer 5th Edition
*  @author     Yue Wang
*  @date       22  DEC 2013
*              Jun 2015
*  @remark
***************************************************************************/
//
// Exercise 12.6:
// Write a function that returns a dynamically allocated vector of ints.
// Pass that vector to another function that reads the standard input to
// give values to the elements. Pass the vector to another function to print
// the values that were read.
// Remember to delete the vector at the appropriate time.
//

#include <iostream>
#include <vector>

using Ptr = std::vector<int>*;

auto make_dynamically() -> Ptr
{
    return new std::vector < int > { };
}

auto populate(Ptr vec) -> Ptr
{
    for (int i; std::cout << "Pls Enter:\n", std::cin >> i; vec->push_back(i));
    return vec;
}

auto print(Ptr vec) -> std::ostream&
{
    for (auto i : *vec) std::cout << i << " ";
    return std::cout;
}

int main()
{
    auto vec = populate(make_dynamically());
    print(vec) << std::endl;
    delete vec;

    return 0;
}
<commit_msg>Update ex12_06.cpp<commit_after>/***************************************************************************
*  @file       The code is for the exercises in C++ Primmer 5th Edition
*  @author     Yue Wang
*  @date       22  DEC 2013
*              Jun 2015
*              Oct 2015
*  @remark
***************************************************************************/
//
// Exercise 12.6:
// Write a function that returns a dynamically allocated vector of ints.
// Pass that vector to another function that reads the standard input to
// give values to the elements. Pass the vector to another function to print
// the values that were read.
// Remember to delete the vector at the appropriate time.
//

#include <iostream>
#include <vector>

using Ptr = std::vector<int>*;

auto make_dynamically()
{
    return new std::vector < int > { };
}

auto populate(Ptr vec)
{
    for (int i; std::cout << "Pls Enter:\n", std::cin >> i; vec->push_back(i));
    return vec;
}

auto print(Ptr vec) -> std::ostream&
{
    for (auto i : *vec) std::cout << i << " ";
    return std::cout;
}

int main()
{
    auto vec = populate(make_dynamically());
    print(vec) << std::endl;
    delete vec;

    return 0;
}
<|endoftext|>


<commit_before>#include "LedStripController.h"

#include "Layer.h"
#include <cstdio>
#include <QTimer>
#include <QString>
#include <ws2811.h>
#include <wiringPi.h>

Q_LOGGING_CATEGORY(CONTROLLER, "ledify.controller", QtWarningMsg)

#define NUM_LEDS        300
#define GPIO_PIN        18
#define DMA             10
#define TARGET_FREQ     WS2811_TARGET_FREQ
#define STRIP_TYPE      SK6812_STRIP_GRBW
#define FPS             40

ws2811_t ledStrip {
    .render_wait_time = 0,
    .device = nullptr,
    .rpi_hw = nullptr,
    .freq = TARGET_FREQ,
    .dmanum = DMA,
    .channel =
    {
        {
            .gpionum = GPIO_PIN,
            .invert = 0,
            .count = NUM_LEDS,
            .strip_type = STRIP_TYPE,
            .leds = nullptr,
            .brightness = 255,
            .wshift = 0,
            .rshift = 0,
            .gshift = 0,
            .bshift = 0,
            .gamma = 0
        }
    },
};

LedStripController::LedStripController() {
    connect(this, &LedStripController::terminated, this, &LedStripController::deinitialize);

    m_layerController.addColorLayer(0, 0, 0, 0, 0);
    m_layerController.setAsRootLayer(0);
    m_executor.reset(new CommandExecutor(&m_layerController, &m_fpsCalculator));

    m_loopTimer = new QTimer(this);
    m_loopTimer->setSingleShot(true);
    m_loopTimer->setInterval(5000);
    connect(m_loopTimer, &QTimer::timeout, this, &LedStripController::drawLoop);
}

void LedStripController::initialize() {
    initializeWiringPi();
    initializeLedStrip();
    restServer.registerCallback([this] (QString &command) -> QString {
        auto result = parseReceivedString(command);
        if (!m_relayController.isOn()) {
            m_relayController.turnOn();
            m_loopTimer->start(2000);
        } else {
            m_loopTimer->start(0);
        }
        return result;
    });
}

bool LedStripController::writeChar(char c) {
    if (m_commandReader.receivedChar(c)) {
        return parseReceivedString(m_commandReader.command()).isEmpty();
    }
    return false;
}

bool LedStripController::animationFinished() {
    return m_layerController.rootLayer()->animationFinished();
}

void LedStripController::draw(uint32_t *ledsRgbw, int numLeds) {
    m_fpsCalculator.tick();
    auto *rootLayer = m_layerController.rootLayer();

    rootLayer->startDraw();
    auto child = rootLayer->child();
    if (child.isNull()) {
        return;
    }
    for (uint16_t i = 0; i < numLeds; i++) {
        ledsRgbw[i] = child->pixel(i);
    }
    rootLayer->endDraw();
}

bool LedStripController::isAnyLedOn() {
    for (int i = 0; i < NUM_LEDS; i++) {
        if (ledStrip.channel[0].leds[i] != 0) {
             return true;
        }
    }
    return false;
}

QString LedStripController::parseReceivedString(const QString &string) {
    qCDebug(CONTROLLER) << "Recv:" << string;
    auto commandAndArgs = string.split("=");
    if (commandAndArgs.empty()) {
        qCDebug(CONTROLLER) << "Empty command";
        return "Empty command";
    }
    auto command = commandAndArgs.first();
    QStringList args;
    if (commandAndArgs.count() >= 2) {
        args = commandAndArgs[1].split(",");
    }

    QString response;
    m_executor->parseCommand(command, args, response);
    return response;
}

void LedStripController::commandOff() {
    QString str;
    m_executor->cOff(QStringList(), str);
}

void LedStripController::commandOnIfNight() {
    QString str;
    m_executor->cOnIfNight(QStringList(), str);
}

void LedStripController::startDrawLoop() {
    m_loopTimer->start(0);
}

void LedStripController::terminate() {
    qCDebug(CONTROLLER) << "Terminating...";

    connect(&m_relayController, &RelayController::relayStateChanged,
            this, [this] (int, bool state) {
        if (!state) {
            emit terminated();
        }
    });
    commandOff();
    QTimer::singleShot(3000, this, [this] { //force
        m_relayController.turnOff(0);
        emit terminated();
    });
    //    m_terminating = true;
}

void LedStripController::initializeWiringPi() {
    if (wiringPiSetup() == -1) {
        qCritical(CONTROLLER) << "Unable to start wiringPi:"
                    << strerror (errno);
        emit terminated();
    }
}

void LedStripController::initializeLedStrip() {
    ws2811_return_t errCode;
    if ((errCode = ws2811_init(&ledStrip)) != WS2811_SUCCESS) {
        fprintf(stderr, "ws2811_init failed: %s\n", ws2811_get_return_t_str(errCode));
        emit terminated();
    }

}

void LedStripController::deinitialize() {
    deinitializeLedStrip();
}

void LedStripController::deinitializeLedStrip() {
    ws2811_fini(&ledStrip);
}

void LedStripController::drawLoop() {
    auto startMs = millis();
    if (!m_relayController.isOn()) {
        return;
    }

    draw(static_cast<uint32_t *>(ledStrip.channel[0].leds), NUM_LEDS);

    ws2811_return_t errCode;
    if ((errCode = ws2811_render(&ledStrip)) != WS2811_SUCCESS) {
        fprintf(stderr, "ws2811_render failed: %s\n", ws2811_get_return_t_str(errCode));
        terminate();
    }

    if (animationFinished()) {
        if (isAnyLedOn()) {
            m_loopTimer->start(5000);
        } else {
            m_relayController.turnOff();
        }
    } else {
        const auto sleepMs = 1000 / FPS;
        auto diffProcessingMs = static_cast<int>(millis() - startMs);
        m_loopTimer->start(qMax(sleepMs - diffProcessingMs, 1));
    }
}

LayerController &LedStripController::layerController() {
    return m_layerController;
}
<commit_msg>Refactor and turn off/on leds depending on if any LED is on<commit_after>#include "LedStripController.h"

#include "Layer.h"
#include <cstdio>
#include <QTimer>
#include <QString>
#include <ws2811.h>
#include <wiringPi.h>

Q_LOGGING_CATEGORY(CONTROLLER, "ledify.controller", QtWarningMsg)

#define NUM_LEDS        300
#define GPIO_PIN        18
#define DMA             10
#define TARGET_FREQ     WS2811_TARGET_FREQ
#define STRIP_TYPE      SK6812_STRIP_GRBW
#define FPS             40

ws2811_t ledStrip {
    .render_wait_time = 0,
    .device = nullptr,
    .rpi_hw = nullptr,
    .freq = TARGET_FREQ,
    .dmanum = DMA,
    .channel =
    {
        {
            .gpionum = GPIO_PIN,
            .invert = 0,
            .count = NUM_LEDS,
            .strip_type = STRIP_TYPE,
            .leds = nullptr,
            .brightness = 255,
            .wshift = 0,
            .rshift = 0,
            .gshift = 0,
            .bshift = 0,
            .gamma = 0
        }
    },
};

LedStripController::LedStripController() {
    connect(this, &LedStripController::terminated, this, &LedStripController::deinitialize);

    m_layerController.addColorLayer(0, 0, 0, 0, 0);
    m_layerController.setAsRootLayer(0);
    m_executor.reset(new CommandExecutor(&m_layerController, &m_fpsCalculator));

    m_loopTimer = new QTimer(this);
    m_loopTimer->setSingleShot(true);
    m_loopTimer->setInterval(5000);
    connect(m_loopTimer, &QTimer::timeout, this, &LedStripController::drawLoop);
}

void LedStripController::initialize() {
    initializeWiringPi();
    initializeLedStrip();
    restServer.registerCallback([this] (QString &command) -> QString {
        auto result = parseReceivedString(command);
        m_relayController.turnOn();
        if (!m_relayController.isOn()) {
            m_loopTimer->start(2000);
        } else {
            m_loopTimer->start(0);
        }
        return result;
    });
}

bool LedStripController::writeChar(char c) {
    if (m_commandReader.receivedChar(c)) {
        return parseReceivedString(m_commandReader.command()).isEmpty();
    }
    return false;
}

bool LedStripController::animationFinished() {
    return m_layerController.rootLayer()->animationFinished();
}

void LedStripController::draw(uint32_t *ledsRgbw, int numLeds) {
    m_fpsCalculator.tick();
    auto *rootLayer = m_layerController.rootLayer();

    rootLayer->startDraw();
    auto child = rootLayer->child();
    if (child.isNull()) {
        return;
    }
    for (uint16_t i = 0; i < numLeds; i++) {
        ledsRgbw[i] = child->pixel(i);
    }
    rootLayer->endDraw();
}

bool LedStripController::isAnyLedOn() {
    for (int i = 0; i < NUM_LEDS; i++) {
        if (ledStrip.channel[0].leds[i] != 0) {
             return true;
        }
    }
    return false;
}

QString LedStripController::parseReceivedString(const QString &string) {
    qCDebug(CONTROLLER) << "Recv:" << string;
    auto commandAndArgs = string.split("=");
    if (commandAndArgs.empty()) {
        qCDebug(CONTROLLER) << "Empty command";
        return "Empty command";
    }
    auto command = commandAndArgs.first();
    QStringList args;
    if (commandAndArgs.count() >= 2) {
        args = commandAndArgs[1].split(",");
    }

    QString response;
    m_executor->parseCommand(command, args, response);
    return response;
}

void LedStripController::commandOff() {
    QString str;
    m_executor->cOff(QStringList(), str);
}

void LedStripController::commandOnIfNight() {
    QString str;
    m_executor->cOnIfNight(QStringList(), str);
}

void LedStripController::startDrawLoop() {
    m_loopTimer->start(0);
}

void LedStripController::terminate() {
    qCDebug(CONTROLLER) << "Terminating...";

    connect(&m_relayController, &RelayController::relayStateChanged,
            this, [this] (int, bool state) {
        if (!state) {
            emit terminated();
        }
    });
    commandOff();
    QTimer::singleShot(3000, this, [this] { //force
        m_relayController.turnOff(0);
        emit terminated();
    });
    //    m_terminating = true;
}

void LedStripController::initializeWiringPi() {
    if (wiringPiSetup() == -1) {
        qCritical(CONTROLLER) << "Unable to start wiringPi:"
                    << strerror (errno);
        emit terminated();
    }
}

void LedStripController::initializeLedStrip() {
    ws2811_return_t errCode;
    if ((errCode = ws2811_init(&ledStrip)) != WS2811_SUCCESS) {
        fprintf(stderr, "ws2811_init failed: %s\n", ws2811_get_return_t_str(errCode));
        emit terminated();
    }

}

void LedStripController::deinitialize() {
    deinitializeLedStrip();
}

void LedStripController::deinitializeLedStrip() {
    ws2811_fini(&ledStrip);
}

void LedStripController::drawLoop() {
    auto startMs = millis();
    if (!m_relayController.isOn()) {
        return;
    }

    draw(static_cast<uint32_t *>(ledStrip.channel[0].leds), NUM_LEDS);

    ws2811_return_t errCode;
    if ((errCode = ws2811_render(&ledStrip)) != WS2811_SUCCESS) {
        fprintf(stderr, "ws2811_render failed: %s\n", ws2811_get_return_t_str(errCode));
        terminate();
    }

    if (animationFinished()) {
        if (isAnyLedOn()) {
            m_loopTimer->start(5000);
        } else {
            m_relayController.turnOff();
        }
    } else {
        const auto sleepMs = 1000 / FPS;
        auto diffProcessingMs = static_cast<int>(millis() - startMs);
        m_loopTimer->start(qMax(sleepMs - diffProcessingMs, 1));
    }
}

LayerController &LedStripController::layerController() {
    return m_layerController;
}
<|endoftext|>


<commit_before>#include "get-drvs.hh"
#include "util.hh"
#include "eval-inline.hh"

#include <cstring>

namespace nix {

string DrvInfo::queryDrvPath()
{
    if (drvPath == "" && attrs) {
        Bindings::iterator i = attrs->find(state->sDrvPath);
        PathSet context;
        drvPath = i != attrs->end() ? state->coerceToPath(*i->pos, *i->value, context) : "";
    }
    return drvPath;
}

string DrvInfo::queryOutPath()
{
    if (outPath == "" && attrs) {
        Bindings::iterator i = attrs->find(state->sOutPath);
        PathSet context;
        outPath = i != attrs->end() ? state->coerceToPath(*i->pos, *i->value, context) : "";
    }
    return outPath;
}

DrvInfo::Outputs DrvInfo::queryOutputs(bool onlyOutputsToInstall)
{
    if (outputs.empty()) {
        /* Get the ‘outputs’ list. */
        Bindings::iterator i;
        if (attrs && (i = attrs->find(state->sOutputs)) != attrs->end()) {
            state->forceList(*i->value, *i->pos);

            /* For each output... */
            for (unsigned int j = 0; j < i->value->listSize(); ++j) {
                /* Evaluate the corresponding set. */
                string name = state->forceStringNoCtx(*i->value->listElems()[j], *i->pos);
                Bindings::iterator out = attrs->find(state->symbols.create(name));
                if (out == attrs->end()) continue; // FIXME: throw error?
                state->forceAttrs(*out->value);

                /* And evaluate its ‘outPath’ attribute. */
                Bindings::iterator outPath = out->value->attrs->find(state->sOutPath);
                if (outPath == out->value->attrs->end()) continue; // FIXME: throw error?
                PathSet context;
                outputs[name] = state->coerceToPath(*outPath->pos, *outPath->value, context);
            }
        } else
            outputs["out"] = queryOutPath();
    }
    if (!onlyOutputsToInstall || !attrs)
        return outputs;

    /* Check for `meta.outputsToInstall` and return `outputs` reduced to that. */
    const Value * outTI = queryMeta("outputsToInstall");
    if (!outTI) return outputs;
    const auto errMsg = Error("this derivation has bad ‘meta.outputsToInstall’");
        /* ^ this shows during `nix-env -i` right under the bad derivation */
    if (!outTI->isList()) throw errMsg;
    Outputs result;
    for (auto i = outTI->listElems(); i != outTI->listElems() + outTI->listSize(); ++i) {
        if ((*i)->type != tString) throw errMsg;
        auto out = outputs.find((*i)->string.s);
        if (out == outputs.end()) throw errMsg;
        result.insert(*out);
    }
    return result;
}

string DrvInfo::queryOutputName()
{
    if (outputName == "" && attrs) {
        Bindings::iterator i = attrs->find(state->sOutputName);
        outputName = i != attrs->end() ? state->forceStringNoCtx(*i->value) : "";
    }
    return outputName;
}

Bindings * DrvInfo::getMeta()
{
    if (meta) return meta;
    if (!attrs) return 0;
    Bindings::iterator a = attrs->find(state->sMeta);
    if (a == attrs->end()) return 0;
    state->forceAttrs(*a->value, *a->pos);
    meta = a->value->attrs;
    return meta;
}

StringSet DrvInfo::queryMetaNames()
{
    StringSet res;
    if (!getMeta()) return res;
    for (auto & i : *meta)
        res.insert(i.name);
    return res;
}

bool DrvInfo::checkMeta(Value & v)
{
    state->forceValue(v);
    if (v.isList()) {
        for (unsigned int n = 0; n < v.listSize(); ++n)
            if (!checkMeta(*v.listElems()[n])) return false;
        return true;
    }
    else if (v.type == tAttrs) {
        Bindings::iterator i = v.attrs->find(state->sOutPath);
        if (i != v.attrs->end()) return false;
        for (auto & i : *v.attrs)
            if (!checkMeta(*i.value)) return false;
        return true;
    }
    else return v.type == tInt || v.type == tBool || v.type == tString ||
                v.type == tFloat;
}

Value * DrvInfo::queryMeta(const string & name)
{
    if (!getMeta()) return 0;
    Bindings::iterator a = meta->find(state->symbols.create(name));
    if (a == meta->end() || !checkMeta(*a->value)) return 0;
    return a->value;
}

string DrvInfo::queryMetaString(const string & name)
{
    Value * v = queryMeta(name);
    if (!v || v->type != tString) return "";
    return v->string.s;
}

NixInt DrvInfo::queryMetaInt(const string & name, NixInt def)
{
    Value * v = queryMeta(name);
    if (!v) return def;
    if (v->type == tInt) return v->integer;
    if (v->type == tString) {
        /* Backwards compatibility with before we had support for
           integer meta fields. */
        NixInt n;
        if (string2Int(v->string.s, n)) return n;
    }
    return def;
}

NixFloat DrvInfo::queryMetaFloat(const string & name, NixFloat def)
{
    Value * v = queryMeta(name);
    if (!v) return def;
    if (v->type == tFloat) return v->fpoint;
    if (v->type == tString) {
        /* Backwards compatibility with before we had support for
           float meta fields. */
        NixFloat n;
        if (string2Float(v->string.s, n)) return n;
    }
    return def;
}

bool DrvInfo::queryMetaBool(const string & name, bool def)
{
    Value * v = queryMeta(name);
    if (!v) return def;
    if (v->type == tBool) return v->boolean;
    if (v->type == tString) {
        /* Backwards compatibility with before we had support for
           Boolean meta fields. */
        if (strcmp(v->string.s, "true") == 0) return true;
        if (strcmp(v->string.s, "false") == 0) return false;
    }
    return def;
}

void DrvInfo::setMeta(const string & name, Value * v)
{
    getMeta();
    Bindings * old = meta;
    meta = state->allocBindings(1 + (old ? old->size() : 0));
    Symbol sym = state->symbols.create(name);
    if (old)
        for (auto i : *old)
            if (i.name != sym)
                meta->push_back(i);
    if (v) meta->push_back(Attr(sym, v));
    meta->sort();
}

/* Cache for already considered attrsets. */
typedef set<Bindings *> Done;

/* Evaluate value `v'.  If it evaluates to a set of type `derivation',
   then put information about it in `drvs' (unless it's already in `done').
   The result boolean indicates whether it makes sense
   for the caller to recursively search for derivations in `v'. */
static bool getDerivation(EvalState & state, Value & v,
    const string & attrPath, DrvInfos & drvs, Done & done,
    bool ignoreAssertionFailures)
{
    try {
        state.forceValue(v);
        if (!state.isDerivation(v)) return true;

        /* Remove spurious duplicates (e.g., a set like `rec { x =
           derivation {...}; y = x;}'. */
        if (done.find(v.attrs) != done.end()) return false;
        done.insert(v.attrs);

        Bindings::iterator i = v.attrs->find(state.sName);
        /* !!! We really would like to have a decent back trace here. */
        if (i == v.attrs->end()) throw TypeError("derivation name missing");

        Bindings::iterator i2 = v.attrs->find(state.sSystem);

        DrvInfo drv(state, state.forceStringNoCtx(*i->value), attrPath,
            i2 == v.attrs->end() ? "unknown" : state.forceStringNoCtx(*i2->value, *i2->pos),
            v.attrs);

        drvs.push_back(drv);
        return false;

    } catch (AssertionError & e) {
        if (ignoreAssertionFailures) return false;
        throw;
    }
}

bool getDerivation(EvalState & state, Value & v, DrvInfo & drv,
    bool ignoreAssertionFailures)
{
    Done done;
    DrvInfos drvs;
    getDerivation(state, v, "", drvs, done, ignoreAssertionFailures);
    if (drvs.size() != 1) return false;
    drv = drvs.front();
    return true;
}

static string addToPath(const string & s1, const string & s2)
{
    return s1.empty() ? s2 : s1 + "." + s2;
}

static void getDerivations(EvalState & state, Value & vIn,
    const string & pathPrefix, Bindings & autoArgs,
    DrvInfos & drvs, Done & done,
    bool ignoreAssertionFailures)
{
    Value v;
    state.autoCallFunction(autoArgs, vIn, v);

    /* Process the expression. */
    if (!getDerivation(state, v, pathPrefix, drvs, done, ignoreAssertionFailures)) ;

    else if (v.type == tAttrs) {

        /* !!! undocumented hackery to support combining channels in
           nix-env.cc. */
        bool combineChannels = v.attrs->find(state.symbols.create("_combineChannels")) != v.attrs->end();

        /* Consider the attributes in sorted order to get more
           deterministic behaviour in nix-env operations (e.g. when
           there are names clashes between derivations, the derivation
           bound to the attribute with the "lower" name should take
           precedence). */
        for (auto & i : v.attrs->lexicographicOrder()) {
            Activity act(*logger, lvlDebug, format("evaluating attribute ‘%1%’") % i->name);
            string pathPrefix2 = addToPath(pathPrefix, i->name);
            if (combineChannels)
                getDerivations(state, *i->value, pathPrefix2, autoArgs, drvs, done, ignoreAssertionFailures);
            else if (getDerivation(state, *i->value, pathPrefix2, drvs, done, ignoreAssertionFailures)) {
                /* If the value of this attribute is itself a set,
                   should we recurse into it?  => Only if it has a
                   `recurseForDerivations = true' attribute. */
                if (i->value->type == tAttrs) {
                    Bindings::iterator j = i->value->attrs->find(state.symbols.create("recurseForDerivations"));
                    if (j != i->value->attrs->end() && state.forceBool(*j->value, *j->pos))
                        getDerivations(state, *i->value, pathPrefix2, autoArgs, drvs, done, ignoreAssertionFailures);
                }
            }
        }
    }

    else if (v.isList()) {
        for (unsigned int n = 0; n < v.listSize(); ++n) {
            Activity act(*logger, lvlDebug, "evaluating list element");
            string pathPrefix2 = addToPath(pathPrefix, (format("%1%") % n).str());
            if (getDerivation(state, *v.listElems()[n], pathPrefix2, drvs, done, ignoreAssertionFailures))
                getDerivations(state, *v.listElems()[n], pathPrefix2, autoArgs, drvs, done, ignoreAssertionFailures);
        }
    }

    else throw TypeError("expression does not evaluate to a derivation (or a set or list of those)");
}

void getDerivations(EvalState & state, Value & v, const string & pathPrefix,
    Bindings & autoArgs, DrvInfos & drvs, bool ignoreAssertionFailures)
{
    Done done;
    getDerivations(state, v, pathPrefix, autoArgs, drvs, done, ignoreAssertionFailures);
}

}
<commit_msg>getDerivations(): Filter out packages with bad derivation names<commit_after>#include "get-drvs.hh"
#include "util.hh"
#include "eval-inline.hh"

#include <cstring>
#include <regex>

namespace nix {

string DrvInfo::queryDrvPath()
{
    if (drvPath == "" && attrs) {
        Bindings::iterator i = attrs->find(state->sDrvPath);
        PathSet context;
        drvPath = i != attrs->end() ? state->coerceToPath(*i->pos, *i->value, context) : "";
    }
    return drvPath;
}

string DrvInfo::queryOutPath()
{
    if (outPath == "" && attrs) {
        Bindings::iterator i = attrs->find(state->sOutPath);
        PathSet context;
        outPath = i != attrs->end() ? state->coerceToPath(*i->pos, *i->value, context) : "";
    }
    return outPath;
}

DrvInfo::Outputs DrvInfo::queryOutputs(bool onlyOutputsToInstall)
{
    if (outputs.empty()) {
        /* Get the ‘outputs’ list. */
        Bindings::iterator i;
        if (attrs && (i = attrs->find(state->sOutputs)) != attrs->end()) {
            state->forceList(*i->value, *i->pos);

            /* For each output... */
            for (unsigned int j = 0; j < i->value->listSize(); ++j) {
                /* Evaluate the corresponding set. */
                string name = state->forceStringNoCtx(*i->value->listElems()[j], *i->pos);
                Bindings::iterator out = attrs->find(state->symbols.create(name));
                if (out == attrs->end()) continue; // FIXME: throw error?
                state->forceAttrs(*out->value);

                /* And evaluate its ‘outPath’ attribute. */
                Bindings::iterator outPath = out->value->attrs->find(state->sOutPath);
                if (outPath == out->value->attrs->end()) continue; // FIXME: throw error?
                PathSet context;
                outputs[name] = state->coerceToPath(*outPath->pos, *outPath->value, context);
            }
        } else
            outputs["out"] = queryOutPath();
    }
    if (!onlyOutputsToInstall || !attrs)
        return outputs;

    /* Check for `meta.outputsToInstall` and return `outputs` reduced to that. */
    const Value * outTI = queryMeta("outputsToInstall");
    if (!outTI) return outputs;
    const auto errMsg = Error("this derivation has bad ‘meta.outputsToInstall’");
        /* ^ this shows during `nix-env -i` right under the bad derivation */
    if (!outTI->isList()) throw errMsg;
    Outputs result;
    for (auto i = outTI->listElems(); i != outTI->listElems() + outTI->listSize(); ++i) {
        if ((*i)->type != tString) throw errMsg;
        auto out = outputs.find((*i)->string.s);
        if (out == outputs.end()) throw errMsg;
        result.insert(*out);
    }
    return result;
}

string DrvInfo::queryOutputName()
{
    if (outputName == "" && attrs) {
        Bindings::iterator i = attrs->find(state->sOutputName);
        outputName = i != attrs->end() ? state->forceStringNoCtx(*i->value) : "";
    }
    return outputName;
}

Bindings * DrvInfo::getMeta()
{
    if (meta) return meta;
    if (!attrs) return 0;
    Bindings::iterator a = attrs->find(state->sMeta);
    if (a == attrs->end()) return 0;
    state->forceAttrs(*a->value, *a->pos);
    meta = a->value->attrs;
    return meta;
}

StringSet DrvInfo::queryMetaNames()
{
    StringSet res;
    if (!getMeta()) return res;
    for (auto & i : *meta)
        res.insert(i.name);
    return res;
}

bool DrvInfo::checkMeta(Value & v)
{
    state->forceValue(v);
    if (v.isList()) {
        for (unsigned int n = 0; n < v.listSize(); ++n)
            if (!checkMeta(*v.listElems()[n])) return false;
        return true;
    }
    else if (v.type == tAttrs) {
        Bindings::iterator i = v.attrs->find(state->sOutPath);
        if (i != v.attrs->end()) return false;
        for (auto & i : *v.attrs)
            if (!checkMeta(*i.value)) return false;
        return true;
    }
    else return v.type == tInt || v.type == tBool || v.type == tString ||
                v.type == tFloat;
}

Value * DrvInfo::queryMeta(const string & name)
{
    if (!getMeta()) return 0;
    Bindings::iterator a = meta->find(state->symbols.create(name));
    if (a == meta->end() || !checkMeta(*a->value)) return 0;
    return a->value;
}

string DrvInfo::queryMetaString(const string & name)
{
    Value * v = queryMeta(name);
    if (!v || v->type != tString) return "";
    return v->string.s;
}

NixInt DrvInfo::queryMetaInt(const string & name, NixInt def)
{
    Value * v = queryMeta(name);
    if (!v) return def;
    if (v->type == tInt) return v->integer;
    if (v->type == tString) {
        /* Backwards compatibility with before we had support for
           integer meta fields. */
        NixInt n;
        if (string2Int(v->string.s, n)) return n;
    }
    return def;
}

NixFloat DrvInfo::queryMetaFloat(const string & name, NixFloat def)
{
    Value * v = queryMeta(name);
    if (!v) return def;
    if (v->type == tFloat) return v->fpoint;
    if (v->type == tString) {
        /* Backwards compatibility with before we had support for
           float meta fields. */
        NixFloat n;
        if (string2Float(v->string.s, n)) return n;
    }
    return def;
}

bool DrvInfo::queryMetaBool(const string & name, bool def)
{
    Value * v = queryMeta(name);
    if (!v) return def;
    if (v->type == tBool) return v->boolean;
    if (v->type == tString) {
        /* Backwards compatibility with before we had support for
           Boolean meta fields. */
        if (strcmp(v->string.s, "true") == 0) return true;
        if (strcmp(v->string.s, "false") == 0) return false;
    }
    return def;
}

void DrvInfo::setMeta(const string & name, Value * v)
{
    getMeta();
    Bindings * old = meta;
    meta = state->allocBindings(1 + (old ? old->size() : 0));
    Symbol sym = state->symbols.create(name);
    if (old)
        for (auto i : *old)
            if (i.name != sym)
                meta->push_back(i);
    if (v) meta->push_back(Attr(sym, v));
    meta->sort();
}

/* Cache for already considered attrsets. */
typedef set<Bindings *> Done;

/* Evaluate value `v'.  If it evaluates to a set of type `derivation',
   then put information about it in `drvs' (unless it's already in `done').
   The result boolean indicates whether it makes sense
   for the caller to recursively search for derivations in `v'. */
static bool getDerivation(EvalState & state, Value & v,
    const string & attrPath, DrvInfos & drvs, Done & done,
    bool ignoreAssertionFailures)
{
    try {
        state.forceValue(v);
        if (!state.isDerivation(v)) return true;

        /* Remove spurious duplicates (e.g., a set like `rec { x =
           derivation {...}; y = x;}'. */
        if (done.find(v.attrs) != done.end()) return false;
        done.insert(v.attrs);

        Bindings::iterator i = v.attrs->find(state.sName);
        /* !!! We really would like to have a decent back trace here. */
        if (i == v.attrs->end()) throw TypeError("derivation name missing");

        Bindings::iterator i2 = v.attrs->find(state.sSystem);

        DrvInfo drv(state, state.forceStringNoCtx(*i->value), attrPath,
            i2 == v.attrs->end() ? "unknown" : state.forceStringNoCtx(*i2->value, *i2->pos),
            v.attrs);

        drvs.push_back(drv);
        return false;

    } catch (AssertionError & e) {
        if (ignoreAssertionFailures) return false;
        throw;
    }
}

bool getDerivation(EvalState & state, Value & v, DrvInfo & drv,
    bool ignoreAssertionFailures)
{
    Done done;
    DrvInfos drvs;
    getDerivation(state, v, "", drvs, done, ignoreAssertionFailures);
    if (drvs.size() != 1) return false;
    drv = drvs.front();
    return true;
}

static string addToPath(const string & s1, const string & s2)
{
    return s1.empty() ? s2 : s1 + "." + s2;
}

static std::regex attrRegex("[A-Za-z_][A-Za-z0-9-_+]*");

static void getDerivations(EvalState & state, Value & vIn,
    const string & pathPrefix, Bindings & autoArgs,
    DrvInfos & drvs, Done & done,
    bool ignoreAssertionFailures)
{
    Value v;
    state.autoCallFunction(autoArgs, vIn, v);

    /* Process the expression. */
    if (!getDerivation(state, v, pathPrefix, drvs, done, ignoreAssertionFailures)) ;

    else if (v.type == tAttrs) {

        /* !!! undocumented hackery to support combining channels in
           nix-env.cc. */
        bool combineChannels = v.attrs->find(state.symbols.create("_combineChannels")) != v.attrs->end();

        /* Consider the attributes in sorted order to get more
           deterministic behaviour in nix-env operations (e.g. when
           there are names clashes between derivations, the derivation
           bound to the attribute with the "lower" name should take
           precedence). */
        for (auto & i : v.attrs->lexicographicOrder()) {
            Activity act(*logger, lvlDebug, format("evaluating attribute ‘%1%’") % i->name);
            if (!std::regex_match(std::string(i->name), attrRegex))
                continue;
            string pathPrefix2 = addToPath(pathPrefix, i->name);
            if (combineChannels)
                getDerivations(state, *i->value, pathPrefix2, autoArgs, drvs, done, ignoreAssertionFailures);
            else if (getDerivation(state, *i->value, pathPrefix2, drvs, done, ignoreAssertionFailures)) {
                /* If the value of this attribute is itself a set,
                   should we recurse into it?  => Only if it has a
                   `recurseForDerivations = true' attribute. */
                if (i->value->type == tAttrs) {
                    Bindings::iterator j = i->value->attrs->find(state.symbols.create("recurseForDerivations"));
                    if (j != i->value->attrs->end() && state.forceBool(*j->value, *j->pos))
                        getDerivations(state, *i->value, pathPrefix2, autoArgs, drvs, done, ignoreAssertionFailures);
                }
            }
        }
    }

    else if (v.isList()) {
        for (unsigned int n = 0; n < v.listSize(); ++n) {
            Activity act(*logger, lvlDebug, "evaluating list element");
            string pathPrefix2 = addToPath(pathPrefix, (format("%1%") % n).str());
            if (getDerivation(state, *v.listElems()[n], pathPrefix2, drvs, done, ignoreAssertionFailures))
                getDerivations(state, *v.listElems()[n], pathPrefix2, autoArgs, drvs, done, ignoreAssertionFailures);
        }
    }

    else throw TypeError("expression does not evaluate to a derivation (or a set or list of those)");
}

void getDerivations(EvalState & state, Value & v, const string & pathPrefix,
    Bindings & autoArgs, DrvInfos & drvs, bool ignoreAssertionFailures)
{
    Done done;
    getDerivations(state, v, pathPrefix, autoArgs, drvs, done, ignoreAssertionFailures);
}

}
<|endoftext|>


<commit_before>// Copyright (c) 2012 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <string>

#include "version.h"

// Name of client reported in the 'version' message. Report the same name
// for both bitcoind and bitcoin-qt, to make it harder for attackers to
// target servers or GUI users specifically.
const std::string CLIENT_NAME("GraniteCoin");

// Client version number
#define CLIENT_VERSION_SUFFIX   "-final"

// The following part of the code determines the CLIENT_BUILD variable.
// Several mechanisms are used for this:
// * first, if HAVE_BUILD_INFO is defined, include build.h, a file that is
//   generated by the build environment, possibly containing the output
//   of git-describe in a macro called BUILD_DESC
// * secondly, if this is an exported version of the code, GIT_ARCHIVE will
//   be defined (automatically using the export-subst git attribute), and
//   GIT_COMMIT will contain the commit id.
// * then, three options exist for determining CLIENT_BUILD:
//   * if BUILD_DESC is defined, use that literally (output of git-describe)
//   * if not, but GIT_COMMIT is defined, use v[maj].[min].[rev].[build]-g[commit]
//   * otherwise, use v[maj].[min].[rev].[build]-unk
// finally CLIENT_VERSION_SUFFIX is added

// First, include build.h if requested
#ifdef HAVE_BUILD_INFO
#    include "build.h"
#endif

// git will put "#define GIT_ARCHIVE 1" on the next line inside archives.
#define GIT_ARCHIVE 1
#ifdef GIT_ARCHIVE
#    define GIT_COMMIT_ID " Release"
#    define GIT_COMMIT_DATE "Wed, 21 May 2014"
#endif

#define BUILD_DESC_FROM_COMMIT(maj,min,rev,build,commit) \
    "v" DO_STRINGIZE(maj) "." DO_STRINGIZE(min) "." DO_STRINGIZE(rev) "." DO_STRINGIZE(build) "" commit

#define BUILD_DESC_FROM_UNKNOWN(maj,min,rev,build) \
    "v" DO_STRINGIZE(maj) "." DO_STRINGIZE(min) "." DO_STRINGIZE(rev) "." DO_STRINGIZE(build)

#ifndef BUILD_DESC
#    ifdef GIT_COMMIT_ID
#        define BUILD_DESC BUILD_DESC_FROM_COMMIT(CLIENT_VERSION_MAJOR, CLIENT_VERSION_MINOR, CLIENT_VERSION_REVISION, CLIENT_VERSION_BUILD, GIT_COMMIT_ID)
#    else
#        define BUILD_DESC BUILD_DESC_FROM_UNKNOWN(CLIENT_VERSION_MAJOR, CLIENT_VERSION_MINOR, CLIENT_VERSION_REVISION, CLIENT_VERSION_BUILD)
#    endif
#endif

#ifndef BUILD_DATE
#    ifdef GIT_COMMIT_DATE
#        define BUILD_DATE GIT_COMMIT_DATE
#    else
#        define BUILD_DATE __DATE__ ", " __TIME__
#    endif
#endif

const std::string CLIENT_BUILD(BUILD_DESC CLIENT_VERSION_SUFFIX);
const std::string CLIENT_DATE(BUILD_DATE);
<commit_msg>Update version.cpp<commit_after>// Copyright (c) 2012 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <string>

#include "version.h"

// Name of client reported in the 'version' message. Report the same name
// for both bitcoind and bitcoin-qt, to make it harder for attackers to
// target servers or GUI users specifically.
const std::string CLIENT_NAME("granite");

// Client version number
#define CLIENT_VERSION_SUFFIX   "-final"

// The following part of the code determines the CLIENT_BUILD variable.
// Several mechanisms are used for this:
// * first, if HAVE_BUILD_INFO is defined, include build.h, a file that is
//   generated by the build environment, possibly containing the output
//   of git-describe in a macro called BUILD_DESC
// * secondly, if this is an exported version of the code, GIT_ARCHIVE will
//   be defined (automatically using the export-subst git attribute), and
//   GIT_COMMIT will contain the commit id.
// * then, three options exist for determining CLIENT_BUILD:
//   * if BUILD_DESC is defined, use that literally (output of git-describe)
//   * if not, but GIT_COMMIT is defined, use v[maj].[min].[rev].[build]-g[commit]
//   * otherwise, use v[maj].[min].[rev].[build]-unk
// finally CLIENT_VERSION_SUFFIX is added

// First, include build.h if requested
#ifdef HAVE_BUILD_INFO
#    include "build.h"
#endif

// git will put "#define GIT_ARCHIVE 1" on the next line inside archives.
#define GIT_ARCHIVE 1
#ifdef GIT_ARCHIVE
#    define GIT_COMMIT_ID " Release"
#    define GIT_COMMIT_DATE "Wed, 21 May 2014"
#endif

#define BUILD_DESC_FROM_COMMIT(maj,min,rev,build,commit) \
    "v" DO_STRINGIZE(maj) "." DO_STRINGIZE(min) "." DO_STRINGIZE(rev) "." DO_STRINGIZE(build) "" commit

#define BUILD_DESC_FROM_UNKNOWN(maj,min,rev,build) \
    "v" DO_STRINGIZE(maj) "." DO_STRINGIZE(min) "." DO_STRINGIZE(rev) "." DO_STRINGIZE(build)

#ifndef BUILD_DESC
#    ifdef GIT_COMMIT_ID
#        define BUILD_DESC BUILD_DESC_FROM_COMMIT(CLIENT_VERSION_MAJOR, CLIENT_VERSION_MINOR, CLIENT_VERSION_REVISION, CLIENT_VERSION_BUILD, GIT_COMMIT_ID)
#    else
#        define BUILD_DESC BUILD_DESC_FROM_UNKNOWN(CLIENT_VERSION_MAJOR, CLIENT_VERSION_MINOR, CLIENT_VERSION_REVISION, CLIENT_VERSION_BUILD)
#    endif
#endif

#ifndef BUILD_DATE
#    ifdef GIT_COMMIT_DATE
#        define BUILD_DATE GIT_COMMIT_DATE
#    else
#        define BUILD_DATE __DATE__ ", " __TIME__
#    endif
#endif

const std::string CLIENT_BUILD(BUILD_DESC CLIENT_VERSION_SUFFIX);
const std::string CLIENT_DATE(BUILD_DATE);
<|endoftext|>


<commit_before>/*
 * ThreadSafeStackTrace.cpp
 *
 * Copyright (C) 2006 - 2008 by Universitaet Stuttgart (VIS).
 * Alle Rechte vorbehalten.
 */

#include "vislib/ThreadSafeStackTrace.h"
#include "vislib/assert.h"

/*
 * vislib::sys::ThreadSafeStackTrace::GetStackString
 */
void vislib::sys::ThreadSafeStackTrace::GetStackString(char *outStr,
        unsigned int &strSize) {
    vislib::StackTrace::GetStackString(outStr, strSize);
}

/*
 * vislib::sys::ThreadSafeStackTrace::GetStackString
 */
void vislib::sys::ThreadSafeStackTrace::GetStackString(wchar_t *outStr,
        unsigned int &strSize) {
    vislib::StackTrace::GetStackString(outStr, strSize);
}

/*
 * vislib::sys::ThreadSafeStackTrace::Initialise
 */
bool vislib::sys::ThreadSafeStackTrace::Initialise(
        vislib::SmartPtr<vislib::StackTrace> manager, bool force) {
    if (manager.IsNull()) {
        return vislib::StackTrace::Initialise(new ThreadSafeStackTrace(),
            force);
    }
    return vislib::StackTrace::Initialise(manager, force);
}

/*
 * vislib::sys::ThreadSafeStackTrace::Manager
 */
vislib::SmartPtr<vislib::StackTrace>
vislib::sys::ThreadSafeStackTrace::Manager(void) {
    return vislib::StackTrace::Manager();
}

/*
 * vislib::sys::ThreadSafeStackTrace::~ThreadSafeStackTrace
 */
vislib::sys::ThreadSafeStackTrace::~ThreadSafeStackTrace(void) {
    this->critSect.Lock();
    this->valid = false;
    ThreadStackRoot *r;
    StackElement *e;
    while (this->stacks) {
        r = this->stacks;
        this->stacks = r->next;
        while (r->stack) {
            e = r->stack;
            r->stack = e->next;
            e->func = NULL; // DO NOT DELETE
            e->file = NULL; // DO NOT DELETE
            e->next = NULL;
            delete e;
        }
        delete r;
    }
    this->critSect.Unlock();
}

/*
 * vislib::sys::ThreadSafeStackTrace::ThreadSafeStackTrace
 */
vislib::sys::ThreadSafeStackTrace::ThreadSafeStackTrace(void) : StackTrace(),
        critSect(), stacks(NULL), valid(true) {
    // Intentionally empty
}

/*
 * vislib::sys::ThreadSafeStackTrace::pop
 */
void vislib::sys::ThreadSafeStackTrace::pop(int id) {
    this->critSect.Lock();
    if (!this->valid) return;

    DWORD ctid = vislib::sys::Thread::CurrentID();

    ThreadStackRoot *r = this->stacks;
    while (r != NULL) {
        if (r->id == ctid) {

            this->stack = r->stack;
            StackTrace::pop(id);
            r->stack = this->stack;

            if (r->stack == NULL) {
                if (this->stacks == r) {
                    this->stacks = r->next;
                } else {
                    ThreadStackRoot *p = this->stacks;
                    while ((p->next != NULL) && (p->next != r)) {
                        p = p->next;
                    }
                    ASSERT(p->next == r);
                    p->next = r->next;
                }
                delete r;
            }

            break;
        }
        r = r->next;
    }

    this->critSect.Unlock();
}

/*
 * vislib::sys::ThreadSafeStackTrace::push
 */
int vislib::sys::ThreadSafeStackTrace::push(const char* func, const char* file, const int line) {
    int retval = 0;
    this->critSect.Lock();
    if (!this->valid) return 0;

    DWORD ctid = vislib::sys::Thread::CurrentID();
    ThreadStackRoot *root = NULL;
    ThreadStackRoot *r = this->stacks;
    while (r != NULL) {
        if (r->id == ctid) {
            root = r;
            break;
        }
        r = r->next;
    }
    if (root == NULL) {
        root = new ThreadStackRoot;
        root->id = ctid;
        root->stack = NULL;
        root->next = this->stacks;
        this->stacks = root;
    }

    this->stack = root->stack;
    retval = StackTrace::push(func, file, line);
    root->stack = this->stack;

    this->critSect.Unlock();
    return retval;
}

/*
 * vislib::sys::ThreadSafeStackTrace::startUseStack
 */
vislib::StackTrace::StackElement*
vislib::sys::ThreadSafeStackTrace::startUseStack(void) {
    this->critSect.Lock();
    if (!this->valid) return NULL;

    DWORD ctid = vislib::sys::Thread::CurrentID();
    ThreadStackRoot *r = this->stacks;
    while (r != NULL) {
        if (r->id == ctid) {
            return r->stack;
        }
        r = r->next;
    }

    return NULL;
}

/*
 * vislib::sys::ThreadSafeStackTrace::stopUseStack
 */
void vislib::sys::ThreadSafeStackTrace::stopUseStack(
        vislib::StackTrace::StackElement* stack) {
    // stack could be used for sanity check here
    this->critSect.Unlock();
}
<commit_msg>bigfix: ThreadSafeStackTrace no longer corrupts simple base class member<commit_after>/*
 * ThreadSafeStackTrace.cpp
 *
 * Copyright (C) 2006 - 2008 by Universitaet Stuttgart (VIS).
 * Alle Rechte vorbehalten.
 */

#include "vislib/ThreadSafeStackTrace.h"
#include "vislib/assert.h"

/*
 * vislib::sys::ThreadSafeStackTrace::GetStackString
 */
void vislib::sys::ThreadSafeStackTrace::GetStackString(char *outStr,
        unsigned int &strSize) {
    vislib::StackTrace::GetStackString(outStr, strSize);
}

/*
 * vislib::sys::ThreadSafeStackTrace::GetStackString
 */
void vislib::sys::ThreadSafeStackTrace::GetStackString(wchar_t *outStr,
        unsigned int &strSize) {
    vislib::StackTrace::GetStackString(outStr, strSize);
}

/*
 * vislib::sys::ThreadSafeStackTrace::Initialise
 */
bool vislib::sys::ThreadSafeStackTrace::Initialise(
        vislib::SmartPtr<vislib::StackTrace> manager, bool force) {
    if (manager.IsNull()) {
        return vislib::StackTrace::Initialise(new ThreadSafeStackTrace(),
            force);
    }
    return vislib::StackTrace::Initialise(manager, force);
}

/*
 * vislib::sys::ThreadSafeStackTrace::Manager
 */
vislib::SmartPtr<vislib::StackTrace>
vislib::sys::ThreadSafeStackTrace::Manager(void) {
    return vislib::StackTrace::Manager();
}

/*
 * vislib::sys::ThreadSafeStackTrace::~ThreadSafeStackTrace
 */
vislib::sys::ThreadSafeStackTrace::~ThreadSafeStackTrace(void) {
    this->critSect.Lock();
    this->valid = false;
    ThreadStackRoot *r;
    StackElement *e;
    while (this->stacks) {
        r = this->stacks;
        this->stacks = r->next;
        while (r->stack) {
            e = r->stack;
            r->stack = e->next;
            e->func = NULL; // DO NOT DELETE
            e->file = NULL; // DO NOT DELETE
            e->next = NULL;
            delete e;
        }
        delete r;
    }
    this->critSect.Unlock();
}

/*
 * vislib::sys::ThreadSafeStackTrace::ThreadSafeStackTrace
 */
vislib::sys::ThreadSafeStackTrace::ThreadSafeStackTrace(void) : StackTrace(),
        critSect(), stacks(NULL), valid(true) {
    // Intentionally empty
}

/*
 * vislib::sys::ThreadSafeStackTrace::pop
 */
void vislib::sys::ThreadSafeStackTrace::pop(int id) {
    this->critSect.Lock();
    if (!this->valid) return;

    DWORD ctid = vislib::sys::Thread::CurrentID();

    ThreadStackRoot *r = this->stacks;
    while (r != NULL) {
        if (r->id == ctid) {

            this->stack = r->stack;
            StackTrace::pop(id);
            r->stack = this->stack;
            this->stack = NULL;

            if (r->stack == NULL) {
                if (this->stacks == r) {
                    this->stacks = r->next;
                } else {
                    ThreadStackRoot *p = this->stacks;
                    while ((p->next != NULL) && (p->next != r)) {
                        p = p->next;
                    }
                    ASSERT(p->next == r);
                    p->next = r->next;
                }
                delete r;
            }

            break;
        }
        r = r->next;
    }

    this->critSect.Unlock();
}

/*
 * vislib::sys::ThreadSafeStackTrace::push
 */
int vislib::sys::ThreadSafeStackTrace::push(const char* func, const char* file, const int line) {
    int retval = 0;
    this->critSect.Lock();
    if (!this->valid) return 0;

    DWORD ctid = vislib::sys::Thread::CurrentID();
    ThreadStackRoot *root = NULL;
    ThreadStackRoot *r = this->stacks;
    while (r != NULL) {
        if (r->id == ctid) {
            root = r;
            break;
        }
        r = r->next;
    }
    if (root == NULL) {
        root = new ThreadStackRoot;
        root->id = ctid;
        root->stack = NULL;
        root->next = this->stacks;
        this->stacks = root;
    }

    this->stack = root->stack;
    retval = StackTrace::push(func, file, line);
    root->stack = this->stack;
    this->stack = NULL;

    this->critSect.Unlock();
    return retval;
}

/*
 * vislib::sys::ThreadSafeStackTrace::startUseStack
 */
vislib::StackTrace::StackElement*
vislib::sys::ThreadSafeStackTrace::startUseStack(void) {
    this->critSect.Lock();
    if (!this->valid) return NULL;

    DWORD ctid = vislib::sys::Thread::CurrentID();
    ThreadStackRoot *r = this->stacks;
    while (r != NULL) {
        if (r->id == ctid) {
            return r->stack;
        }
        r = r->next;
    }

    return NULL;
}

/*
 * vislib::sys::ThreadSafeStackTrace::stopUseStack
 */
void vislib::sys::ThreadSafeStackTrace::stopUseStack(
        vislib::StackTrace::StackElement* stack) {
    // stack could be used for sanity check here
    this->critSect.Unlock();
}
<|endoftext|>


<commit_before>#include "globals.hh"
#include "util.hh"
#include "archive.hh"
#include "args.hh"
#include "abstract-setting-to-json.hh"
#include "compute-levels.hh"

#include <algorithm>
#include <map>
#include <thread>
#include <dlfcn.h>
#include <sys/utsname.h>

#include <nlohmann/json.hpp>

namespace nix {

/* The default location of the daemon socket, relative to nixStateDir.
   The socket is in a directory to allow you to control access to the
   Nix daemon by setting the mode/ownership of the directory
   appropriately.  (This wouldn't work on the socket itself since it
   must be deleted and recreated on startup.) */
#define DEFAULT_SOCKET_PATH "/daemon-socket/socket"

Settings settings;

static GlobalConfig::Register rSettings(&settings);

Settings::Settings()
    : nixPrefix(NIX_PREFIX)
    , nixStore(canonPath(getEnv("NIX_STORE_DIR").value_or(getEnv("NIX_STORE").value_or(NIX_STORE_DIR))))
    , nixDataDir(canonPath(getEnv("NIX_DATA_DIR").value_or(NIX_DATA_DIR)))
    , nixLogDir(canonPath(getEnv("NIX_LOG_DIR").value_or(NIX_LOG_DIR)))
    , nixStateDir(canonPath(getEnv("NIX_STATE_DIR").value_or(NIX_STATE_DIR)))
    , nixConfDir(canonPath(getEnv("NIX_CONF_DIR").value_or(NIX_CONF_DIR)))
    , nixUserConfFiles(getUserConfigFiles())
    , nixBinDir(canonPath(getEnv("NIX_BIN_DIR").value_or(NIX_BIN_DIR)))
    , nixManDir(canonPath(NIX_MAN_DIR))
    , nixDaemonSocketFile(canonPath(getEnv("NIX_DAEMON_SOCKET_PATH").value_or(nixStateDir + DEFAULT_SOCKET_PATH)))
{
    buildUsersGroup = getuid() == 0 ? "nixbld" : "";
    lockCPU = getEnv("NIX_AFFINITY_HACK") == "1";
    allowSymlinkedStore = getEnv("NIX_IGNORE_SYMLINK_STORE") == "1";

    caFile = getEnv("NIX_SSL_CERT_FILE").value_or(getEnv("SSL_CERT_FILE").value_or(""));
    if (caFile == "") {
        for (auto & fn : {"/etc/ssl/certs/ca-certificates.crt", "/nix/var/nix/profiles/default/etc/ssl/certs/ca-bundle.crt"})
            if (pathExists(fn)) {
                caFile = fn;
                break;
            }
    }

    /* Backwards compatibility. */
    auto s = getEnv("NIX_REMOTE_SYSTEMS");
    if (s) {
        Strings ss;
        for (auto & p : tokenizeString<Strings>(*s, ":"))
            ss.push_back("@" + p);
        builders = concatStringsSep(" ", ss);
    }

#if defined(__linux__) && defined(SANDBOX_SHELL)
    sandboxPaths = tokenizeString<StringSet>("/bin/sh=" SANDBOX_SHELL);
#endif

    /* chroot-like behavior from Apple's sandbox */
#if __APPLE__
    sandboxPaths = tokenizeString<StringSet>("/System/Library/Frameworks /System/Library/PrivateFrameworks /bin/sh /bin/bash /private/tmp /private/var/tmp /usr/lib");
    allowedImpureHostPrefixes = tokenizeString<StringSet>("/System/Library /usr/lib /dev /bin/sh");
#endif

    buildHook = getSelfExe().value_or("nix") + " __build-remote";
}

void loadConfFile()
{
    globalConfig.applyConfigFile(settings.nixConfDir + "/nix.conf");

    /* We only want to send overrides to the daemon, i.e. stuff from
       ~/.nix/nix.conf or the command line. */
    globalConfig.resetOverridden();

    auto files = settings.nixUserConfFiles;
    for (auto file = files.rbegin(); file != files.rend(); file++) {
        globalConfig.applyConfigFile(*file);
    }

    auto nixConfEnv = getEnv("NIX_CONFIG");
    if (nixConfEnv.has_value()) {
        globalConfig.applyConfig(nixConfEnv.value(), "NIX_CONFIG");
    }

}

std::vector<Path> getUserConfigFiles()
{
    // Use the paths specified in NIX_USER_CONF_FILES if it has been defined
    auto nixConfFiles = getEnv("NIX_USER_CONF_FILES");
    if (nixConfFiles.has_value()) {
        return tokenizeString<std::vector<std::string>>(nixConfFiles.value(), ":");
    }

    // Use the paths specified by the XDG spec
    std::vector<Path> files;
    auto dirs = getConfigDirs();
    for (auto & dir : dirs) {
        files.insert(files.end(), dir + "/nix/nix.conf");
    }
    return files;
}

unsigned int Settings::getDefaultCores()
{
    const unsigned int concurrency = std::max(1U, std::thread::hardware_concurrency());
    const unsigned int maxCPU = getMaxCPU();

    if (maxCPU > 0)
      return maxCPU;
    else
      return concurrency;
}

StringSet Settings::getDefaultSystemFeatures()
{
    /* For backwards compatibility, accept some "features" that are
       used in Nixpkgs to route builds to certain machines but don't
       actually require anything special on the machines. */
    StringSet features{"nixos-test", "benchmark", "big-parallel"};

    #if __linux__
    if (access("/dev/kvm", R_OK | W_OK) == 0)
        features.insert("kvm");
    #endif

    return features;
}

StringSet Settings::getDefaultExtraPlatforms()
{
    StringSet extraPlatforms;

    if (std::string{SYSTEM} == "x86_64-linux" && !isWSL1())
        extraPlatforms.insert("i686-linux");

#if __linux__
    StringSet levels = computeLevels();
    for (auto iter = levels.begin(); iter != levels.end(); ++iter)
        extraPlatforms.insert(*iter + "-linux");
#elif __APPLE__
    // Rosetta 2 emulation layer can run x86_64 binaries on aarch64
    // machines. Note that we can’t force processes from executing
    // x86_64 in aarch64 environments or vice versa since they can
    // always exec with their own binary preferences.
    if (std::string{SYSTEM} == "aarch64-darwin") {
        if (runProgram(RunOptions {.program = "arch", .args = {"-arch", "x86_64", "/bin/pwd"}, .mergeStderrToStdout = true}).first == 0) {
            debug("Rosetta detected");
            extraPlatforms.insert("x86_64-darwin");
        } else
            debug("Rosetta not detected");
    }
#endif

    return extraPlatforms;
}

bool Settings::isExperimentalFeatureEnabled(const ExperimentalFeature & feature)
{
    auto & f = experimentalFeatures.get();
    return std::find(f.begin(), f.end(), feature) != f.end();
}

void Settings::requireExperimentalFeature(const ExperimentalFeature & feature)
{
    if (!isExperimentalFeatureEnabled(feature))
        throw MissingExperimentalFeature(feature);
}

bool Settings::isWSL1()
{
    struct utsname utsbuf;
    uname(&utsbuf);
    // WSL1 uses -Microsoft suffix
    // WSL2 uses -microsoft-standard suffix
    return hasSuffix(utsbuf.release, "-Microsoft");
}

const std::string nixVersion = PACKAGE_VERSION;

NLOHMANN_JSON_SERIALIZE_ENUM(SandboxMode, {
    {SandboxMode::smEnabled, true},
    {SandboxMode::smRelaxed, "relaxed"},
    {SandboxMode::smDisabled, false},
});

template<> void BaseSetting<SandboxMode>::set(const std::string & str, bool append)
{
    if (str == "true") value = smEnabled;
    else if (str == "relaxed") value = smRelaxed;
    else if (str == "false") value = smDisabled;
    else throw UsageError("option '%s' has invalid value '%s'", name, str);
}

template<> bool BaseSetting<SandboxMode>::isAppendable()
{
    return false;
}

template<> std::string BaseSetting<SandboxMode>::to_string() const
{
    if (value == smEnabled) return "true";
    else if (value == smRelaxed) return "relaxed";
    else if (value == smDisabled) return "false";
    else abort();
}

template<> void BaseSetting<SandboxMode>::convertToArg(Args & args, const std::string & category)
{
    args.addFlag({
        .longName = name,
        .description = "Enable sandboxing.",
        .category = category,
        .handler = {[=]() { override(smEnabled); }}
    });
    args.addFlag({
        .longName = "no-" + name,
        .description = "Disable sandboxing.",
        .category = category,
        .handler = {[=]() { override(smDisabled); }}
    });
    args.addFlag({
        .longName = "relaxed-" + name,
        .description = "Enable sandboxing, but allow builds to disable it.",
        .category = category,
        .handler = {[=]() { override(smRelaxed); }}
    });
}

void MaxBuildJobsSetting::set(const std::string & str, bool append)
{
    if (str == "auto") value = std::max(1U, std::thread::hardware_concurrency());
    else {
        if (auto n = string2Int<decltype(value)>(str))
            value = *n;
        else
            throw UsageError("configuration setting '%s' should be 'auto' or an integer", name);
    }
}

void PluginFilesSetting::set(const std::string & str, bool append)
{
    if (pluginsLoaded)
        throw UsageError("plugin-files set after plugins were loaded, you may need to move the flag before the subcommand");
    BaseSetting<Paths>::set(str, append);
}

void initPlugins()
{
    assert(!settings.pluginFiles.pluginsLoaded);
    for (const auto & pluginFile : settings.pluginFiles.get()) {
        Paths pluginFiles;
        try {
            auto ents = readDirectory(pluginFile);
            for (const auto & ent : ents)
                pluginFiles.emplace_back(pluginFile + "/" + ent.name);
        } catch (SysError & e) {
            if (e.errNo != ENOTDIR)
                throw;
            pluginFiles.emplace_back(pluginFile);
        }
        for (const auto & file : pluginFiles) {
            /* handle is purposefully leaked as there may be state in the
               DSO needed by the action of the plugin. */
            void *handle =
                dlopen(file.c_str(), RTLD_LAZY | RTLD_LOCAL);
            if (!handle)
                throw Error("could not dynamically open plugin file '%s': %s", file, dlerror());
        }
    }

    /* Since plugins can add settings, try to re-apply previously
       unknown settings. */
    globalConfig.reapplyUnknownSettings();
    globalConfig.warnUnknownSettings();

    /* Tell the user if they try to set plugin-files after we've already loaded */
    settings.pluginFiles.pluginsLoaded = true;
}

}
<commit_msg>Use /usr/bin/true<commit_after>#include "globals.hh"
#include "util.hh"
#include "archive.hh"
#include "args.hh"
#include "abstract-setting-to-json.hh"
#include "compute-levels.hh"

#include <algorithm>
#include <map>
#include <thread>
#include <dlfcn.h>
#include <sys/utsname.h>

#include <nlohmann/json.hpp>

namespace nix {

/* The default location of the daemon socket, relative to nixStateDir.
   The socket is in a directory to allow you to control access to the
   Nix daemon by setting the mode/ownership of the directory
   appropriately.  (This wouldn't work on the socket itself since it
   must be deleted and recreated on startup.) */
#define DEFAULT_SOCKET_PATH "/daemon-socket/socket"

Settings settings;

static GlobalConfig::Register rSettings(&settings);

Settings::Settings()
    : nixPrefix(NIX_PREFIX)
    , nixStore(canonPath(getEnv("NIX_STORE_DIR").value_or(getEnv("NIX_STORE").value_or(NIX_STORE_DIR))))
    , nixDataDir(canonPath(getEnv("NIX_DATA_DIR").value_or(NIX_DATA_DIR)))
    , nixLogDir(canonPath(getEnv("NIX_LOG_DIR").value_or(NIX_LOG_DIR)))
    , nixStateDir(canonPath(getEnv("NIX_STATE_DIR").value_or(NIX_STATE_DIR)))
    , nixConfDir(canonPath(getEnv("NIX_CONF_DIR").value_or(NIX_CONF_DIR)))
    , nixUserConfFiles(getUserConfigFiles())
    , nixBinDir(canonPath(getEnv("NIX_BIN_DIR").value_or(NIX_BIN_DIR)))
    , nixManDir(canonPath(NIX_MAN_DIR))
    , nixDaemonSocketFile(canonPath(getEnv("NIX_DAEMON_SOCKET_PATH").value_or(nixStateDir + DEFAULT_SOCKET_PATH)))
{
    buildUsersGroup = getuid() == 0 ? "nixbld" : "";
    lockCPU = getEnv("NIX_AFFINITY_HACK") == "1";
    allowSymlinkedStore = getEnv("NIX_IGNORE_SYMLINK_STORE") == "1";

    caFile = getEnv("NIX_SSL_CERT_FILE").value_or(getEnv("SSL_CERT_FILE").value_or(""));
    if (caFile == "") {
        for (auto & fn : {"/etc/ssl/certs/ca-certificates.crt", "/nix/var/nix/profiles/default/etc/ssl/certs/ca-bundle.crt"})
            if (pathExists(fn)) {
                caFile = fn;
                break;
            }
    }

    /* Backwards compatibility. */
    auto s = getEnv("NIX_REMOTE_SYSTEMS");
    if (s) {
        Strings ss;
        for (auto & p : tokenizeString<Strings>(*s, ":"))
            ss.push_back("@" + p);
        builders = concatStringsSep(" ", ss);
    }

#if defined(__linux__) && defined(SANDBOX_SHELL)
    sandboxPaths = tokenizeString<StringSet>("/bin/sh=" SANDBOX_SHELL);
#endif

    /* chroot-like behavior from Apple's sandbox */
#if __APPLE__
    sandboxPaths = tokenizeString<StringSet>("/System/Library/Frameworks /System/Library/PrivateFrameworks /bin/sh /bin/bash /private/tmp /private/var/tmp /usr/lib");
    allowedImpureHostPrefixes = tokenizeString<StringSet>("/System/Library /usr/lib /dev /bin/sh");
#endif

    buildHook = getSelfExe().value_or("nix") + " __build-remote";
}

void loadConfFile()
{
    globalConfig.applyConfigFile(settings.nixConfDir + "/nix.conf");

    /* We only want to send overrides to the daemon, i.e. stuff from
       ~/.nix/nix.conf or the command line. */
    globalConfig.resetOverridden();

    auto files = settings.nixUserConfFiles;
    for (auto file = files.rbegin(); file != files.rend(); file++) {
        globalConfig.applyConfigFile(*file);
    }

    auto nixConfEnv = getEnv("NIX_CONFIG");
    if (nixConfEnv.has_value()) {
        globalConfig.applyConfig(nixConfEnv.value(), "NIX_CONFIG");
    }

}

std::vector<Path> getUserConfigFiles()
{
    // Use the paths specified in NIX_USER_CONF_FILES if it has been defined
    auto nixConfFiles = getEnv("NIX_USER_CONF_FILES");
    if (nixConfFiles.has_value()) {
        return tokenizeString<std::vector<std::string>>(nixConfFiles.value(), ":");
    }

    // Use the paths specified by the XDG spec
    std::vector<Path> files;
    auto dirs = getConfigDirs();
    for (auto & dir : dirs) {
        files.insert(files.end(), dir + "/nix/nix.conf");
    }
    return files;
}

unsigned int Settings::getDefaultCores()
{
    const unsigned int concurrency = std::max(1U, std::thread::hardware_concurrency());
    const unsigned int maxCPU = getMaxCPU();

    if (maxCPU > 0)
      return maxCPU;
    else
      return concurrency;
}

StringSet Settings::getDefaultSystemFeatures()
{
    /* For backwards compatibility, accept some "features" that are
       used in Nixpkgs to route builds to certain machines but don't
       actually require anything special on the machines. */
    StringSet features{"nixos-test", "benchmark", "big-parallel"};

    #if __linux__
    if (access("/dev/kvm", R_OK | W_OK) == 0)
        features.insert("kvm");
    #endif

    return features;
}

StringSet Settings::getDefaultExtraPlatforms()
{
    StringSet extraPlatforms;

    if (std::string{SYSTEM} == "x86_64-linux" && !isWSL1())
        extraPlatforms.insert("i686-linux");

#if __linux__
    StringSet levels = computeLevels();
    for (auto iter = levels.begin(); iter != levels.end(); ++iter)
        extraPlatforms.insert(*iter + "-linux");
#elif __APPLE__
    // Rosetta 2 emulation layer can run x86_64 binaries on aarch64
    // machines. Note that we can’t force processes from executing
    // x86_64 in aarch64 environments or vice versa since they can
    // always exec with their own binary preferences.
    if (std::string{SYSTEM} == "aarch64-darwin") {
        if (runProgram(RunOptions {.program = "arch", .args = {"-arch", "x86_64", "/usr/bin/true"}, .mergeStderrToStdout = true}).first == 0) {
            debug("Rosetta detected");
            extraPlatforms.insert("x86_64-darwin");
        } else
            debug("Rosetta not detected");
    }
#endif

    return extraPlatforms;
}

bool Settings::isExperimentalFeatureEnabled(const ExperimentalFeature & feature)
{
    auto & f = experimentalFeatures.get();
    return std::find(f.begin(), f.end(), feature) != f.end();
}

void Settings::requireExperimentalFeature(const ExperimentalFeature & feature)
{
    if (!isExperimentalFeatureEnabled(feature))
        throw MissingExperimentalFeature(feature);
}

bool Settings::isWSL1()
{
    struct utsname utsbuf;
    uname(&utsbuf);
    // WSL1 uses -Microsoft suffix
    // WSL2 uses -microsoft-standard suffix
    return hasSuffix(utsbuf.release, "-Microsoft");
}

const std::string nixVersion = PACKAGE_VERSION;

NLOHMANN_JSON_SERIALIZE_ENUM(SandboxMode, {
    {SandboxMode::smEnabled, true},
    {SandboxMode::smRelaxed, "relaxed"},
    {SandboxMode::smDisabled, false},
});

template<> void BaseSetting<SandboxMode>::set(const std::string & str, bool append)
{
    if (str == "true") value = smEnabled;
    else if (str == "relaxed") value = smRelaxed;
    else if (str == "false") value = smDisabled;
    else throw UsageError("option '%s' has invalid value '%s'", name, str);
}

template<> bool BaseSetting<SandboxMode>::isAppendable()
{
    return false;
}

template<> std::string BaseSetting<SandboxMode>::to_string() const
{
    if (value == smEnabled) return "true";
    else if (value == smRelaxed) return "relaxed";
    else if (value == smDisabled) return "false";
    else abort();
}

template<> void BaseSetting<SandboxMode>::convertToArg(Args & args, const std::string & category)
{
    args.addFlag({
        .longName = name,
        .description = "Enable sandboxing.",
        .category = category,
        .handler = {[=]() { override(smEnabled); }}
    });
    args.addFlag({
        .longName = "no-" + name,
        .description = "Disable sandboxing.",
        .category = category,
        .handler = {[=]() { override(smDisabled); }}
    });
    args.addFlag({
        .longName = "relaxed-" + name,
        .description = "Enable sandboxing, but allow builds to disable it.",
        .category = category,
        .handler = {[=]() { override(smRelaxed); }}
    });
}

void MaxBuildJobsSetting::set(const std::string & str, bool append)
{
    if (str == "auto") value = std::max(1U, std::thread::hardware_concurrency());
    else {
        if (auto n = string2Int<decltype(value)>(str))
            value = *n;
        else
            throw UsageError("configuration setting '%s' should be 'auto' or an integer", name);
    }
}

void PluginFilesSetting::set(const std::string & str, bool append)
{
    if (pluginsLoaded)
        throw UsageError("plugin-files set after plugins were loaded, you may need to move the flag before the subcommand");
    BaseSetting<Paths>::set(str, append);
}

void initPlugins()
{
    assert(!settings.pluginFiles.pluginsLoaded);
    for (const auto & pluginFile : settings.pluginFiles.get()) {
        Paths pluginFiles;
        try {
            auto ents = readDirectory(pluginFile);
            for (const auto & ent : ents)
                pluginFiles.emplace_back(pluginFile + "/" + ent.name);
        } catch (SysError & e) {
            if (e.errNo != ENOTDIR)
                throw;
            pluginFiles.emplace_back(pluginFile);
        }
        for (const auto & file : pluginFiles) {
            /* handle is purposefully leaked as there may be state in the
               DSO needed by the action of the plugin. */
            void *handle =
                dlopen(file.c_str(), RTLD_LAZY | RTLD_LOCAL);
            if (!handle)
                throw Error("could not dynamically open plugin file '%s': %s", file, dlerror());
        }
    }

    /* Since plugins can add settings, try to re-apply previously
       unknown settings. */
    globalConfig.reapplyUnknownSettings();
    globalConfig.warnUnknownSettings();

    /* Tell the user if they try to set plugin-files after we've already loaded */
    settings.pluginFiles.pluginsLoaded = true;
}

}
<|endoftext|>


<commit_before>#include <cctype>
#include <fstream>
#include <stdio.h>
#include <sstream> // ostringstream
#include "utils/logoutput.h"

#include "settings.h"
#include "settingRegistry.h"

namespace cura
{
//c++11 no longer defines M_PI, so add our own constant.
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif

std::string toString(EGCodeFlavor flavor)
{
    switch (flavor)
    {
        case EGCodeFlavor::BFB:
            return "BFB";
        case EGCodeFlavor::MACH3:
            return "Mach3";
        case EGCodeFlavor::MAKERBOT:
            return "Makerbot";
        case EGCodeFlavor::ULTIGCODE:
            return "UltiGcode";
        case EGCodeFlavor::REPRAP_VOLUMATRIC:
            return "RepRap(Volumentric)";
        case EGCodeFlavor::REPRAP:
        default:
            return "RepRap";
    }
}

SettingsBaseVirtual::SettingsBaseVirtual()
: parent(NULL)
{
}

SettingsBaseVirtual::SettingsBaseVirtual(SettingsBaseVirtual* parent)
: parent(parent)
{
}

SettingsBase::SettingsBase()
: SettingsBaseVirtual(NULL)
{
}

SettingsBase::SettingsBase(SettingsBaseVirtual* parent)
: SettingsBaseVirtual(parent)
{
}

SettingsMessenger::SettingsMessenger(SettingsBaseVirtual* parent)
: SettingsBaseVirtual(parent)
{
}

void SettingsBase::setSetting(std::string key, std::string value)
{
    if (SettingRegistry::getInstance()->settingExists(key))
    {
        setting_values[key] = value;
    }
    else
    {
        cura::logError("Warning: setting an unregistered setting %s\n", key.c_str() );
        setting_values[key] = value; // Handy when programmers are in the process of introducing a new setting
    }
}

std::string SettingsBase::getSettingString(std::string key)
{
    if (setting_values.find(key) != setting_values.end())
    {
        return setting_values[key];
    }
    if (parent)
    {
        return parent->getSettingString(key);
    }

    if (SettingRegistry::getInstance()->settingExists(key))
    {
        setting_values[key] = SettingRegistry::getInstance()->getSettingConfig(key)->getDefaultValue();
    }
    else
    {
        setting_values[key] = "";
        cura::logError("Unregistered setting %s\n", key.c_str());
    }
    return setting_values[key];
}

void SettingsMessenger::setSetting(std::string key, std::string value)
{
    parent->setSetting(key, value);
}

std::string SettingsMessenger::getSettingString(std::string key)
{
    return parent->getSettingString(key);
}

void SettingsBase::setExtruderTrainDefaults(unsigned int extruder_nr)
{
    const SettingContainer* machine_extruder_trains = SettingRegistry::getInstance()->getCategory(std::string("machine_extruder_trains"));

    if (!machine_extruder_trains)
    {
        // no machine_extruder_trains setting present; just use defaults for each train..
        return;
    }

    const SettingConfig* train = machine_extruder_trains->getChild(extruder_nr);

    if (!train)
    {
        logError("Not enough extruder trains specified in JSON: %i\n", extruder_nr);
        return;
    }

    for (const SettingConfig& setting : train->getChildren())
    {
        if (setting_values.find(setting.getKey()) == setting_values.end())
        {
            setSetting(setting.getKey(), setting.getDefaultValue());
        }
    }
}

int SettingsBaseVirtual::getSettingAsIndex(std::string key)
{
    std::string value = getSettingString(key);
    return atoi(value.c_str());
}

int SettingsBaseVirtual::getSettingAsCount(std::string key)
{
    std::string value = getSettingString(key);
    return atoi(value.c_str());
}

int SettingsBaseVirtual::getSettingInMicrons(std::string key)
{
    std::string value = getSettingString(key);
    return atof(value.c_str()) * 1000.0;
}

double SettingsBaseVirtual::getSettingInAngleRadians(std::string key)
{
    std::string value = getSettingString(key);
    return atof(value.c_str()) / 180.0 * M_PI;
}

bool SettingsBaseVirtual::getSettingBoolean(std::string key)
{
    std::string value = getSettingString(key);
    if (value == "on")
        return true;
    if (value == "yes")
        return true;
    if (value == "true" or value == "True") //Python uses "True"
        return true;
    int num = atoi(value.c_str());
    return num != 0;
}

double SettingsBaseVirtual::getSettingInDegreeCelsius(std::string key)
{
    std::string value = getSettingString(key);
    return atof(value.c_str());
}

double SettingsBaseVirtual::getSettingInMillimetersPerSecond(std::string key)
{
    std::string value = getSettingString(key);
    return std::max(1.0, atof(value.c_str()));
}

double SettingsBaseVirtual::getSettingInCubicMillimeters(std::string key)
{
    std::string value = getSettingString(key);
    return std::max(0.0, atof(value.c_str()));
}

double SettingsBaseVirtual::getSettingInPercentage(std::string key)
{
    std::string value = getSettingString(key);
    return std::max(0.0, atof(value.c_str()));
}

double SettingsBaseVirtual::getSettingInSeconds(std::string key)
{
    std::string value = getSettingString(key);
    return std::max(0.0, atof(value.c_str()));
}

EGCodeFlavor SettingsBaseVirtual::getSettingAsGCodeFlavor(std::string key)
{
    std::string value = getSettingString(key);
    if (value == "RepRap")
        return EGCodeFlavor::REPRAP;
    else if (value == "UltiGCode")
        return EGCodeFlavor::ULTIGCODE;
    else if (value == "Makerbot")
        return EGCodeFlavor::MAKERBOT;
    else if (value == "BFB")
        return EGCodeFlavor::BFB;
    else if (value == "MACH3")
        return EGCodeFlavor::MACH3;
    else if (value == "RepRap (Volumatric)")
        return EGCodeFlavor::REPRAP_VOLUMATRIC;
    return EGCodeFlavor::REPRAP;
}

EFillMethod SettingsBaseVirtual::getSettingAsFillMethod(std::string key)
{
    std::string value = getSettingString(key);
    if (value == "lines")
        return EFillMethod::LINES;
    if (value == "grid")
        return EFillMethod::GRID;
    if (value == "triangles")
        return EFillMethod::TRIANGLES;
    if (value == "concentric")
        return EFillMethod::CONCENTRIC;
    if (value == "zigzag")
        return EFillMethod::ZIG_ZAG;
    return EFillMethod::NONE;
}

EPlatformAdhesion SettingsBaseVirtual::getSettingAsPlatformAdhesion(std::string key)
{
    std::string value = getSettingString(key);
    if (value == "brim")
        return EPlatformAdhesion::BRIM;
    if (value == "raft")
        return EPlatformAdhesion::RAFT;
    return EPlatformAdhesion::SKIRT;
}

ESupportType SettingsBaseVirtual::getSettingAsSupportType(std::string key)
{
    std::string value = getSettingString(key);
    if (value == "everywhere")
        return ESupportType::EVERYWHERE;
    if (value == "buildplate")
        return ESupportType::PLATFORM_ONLY;
    return ESupportType::NONE;
}

EZSeamType SettingsBaseVirtual::getSettingAsZSeamType(std::string key)
{
    std::string value = getSettingString(key);
    if (value == "random")
        return EZSeamType::RANDOM;
    if (value == "shortest")
        return EZSeamType::SHORTEST;
    if (value == "back")
        return EZSeamType::BACK;
    return EZSeamType::SHORTEST;
}

ESurfaceMode SettingsBaseVirtual::getSettingAsSurfaceMode(std::string key)
{
    std::string value = getSettingString(key);
    if (value == "normal")
        return ESurfaceMode::NORMAL;
    if (value == "surface")
        return ESurfaceMode::SURFACE;
    if (value == "both")
        return ESurfaceMode::BOTH;
    return ESurfaceMode::NORMAL;
}

FillPerimeterGapMode SettingsBaseVirtual::getSettingAsFillPerimeterGapMode(std::string key)
{
    std::string value = getSettingString(key);
    if (value == "nowhere")
    {
        return FillPerimeterGapMode::NOWHERE;
    }
    if (value == "everywhere")
    {
        return FillPerimeterGapMode::EVERYWHERE;
    }
    if (value == "skin")
    {
        return FillPerimeterGapMode::SKIN;
    }
    return FillPerimeterGapMode::NOWHERE;
}

}//namespace cura
<commit_msg>bugfix: gcode flavor prepended for UM2 was incorrect<commit_after>#include <cctype>
#include <fstream>
#include <stdio.h>
#include <sstream> // ostringstream
#include "utils/logoutput.h"

#include "settings.h"
#include "settingRegistry.h"

namespace cura
{
//c++11 no longer defines M_PI, so add our own constant.
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif

std::string toString(EGCodeFlavor flavor)
{
    switch (flavor)
    {
        case EGCodeFlavor::BFB:
            return "BFB";
        case EGCodeFlavor::MACH3:
            return "Mach3";
        case EGCodeFlavor::MAKERBOT:
            return "Makerbot";
        case EGCodeFlavor::ULTIGCODE:
            return "UltiGCode";
        case EGCodeFlavor::REPRAP_VOLUMATRIC:
            return "RepRap(Volumentric)";
        case EGCodeFlavor::REPRAP:
        default:
            return "RepRap";
    }
}

SettingsBaseVirtual::SettingsBaseVirtual()
: parent(NULL)
{
}

SettingsBaseVirtual::SettingsBaseVirtual(SettingsBaseVirtual* parent)
: parent(parent)
{
}

SettingsBase::SettingsBase()
: SettingsBaseVirtual(NULL)
{
}

SettingsBase::SettingsBase(SettingsBaseVirtual* parent)
: SettingsBaseVirtual(parent)
{
}

SettingsMessenger::SettingsMessenger(SettingsBaseVirtual* parent)
: SettingsBaseVirtual(parent)
{
}

void SettingsBase::setSetting(std::string key, std::string value)
{
    if (SettingRegistry::getInstance()->settingExists(key))
    {
        setting_values[key] = value;
    }
    else
    {
        cura::logError("Warning: setting an unregistered setting %s\n", key.c_str() );
        setting_values[key] = value; // Handy when programmers are in the process of introducing a new setting
    }
}

std::string SettingsBase::getSettingString(std::string key)
{
    if (setting_values.find(key) != setting_values.end())
    {
        return setting_values[key];
    }
    if (parent)
    {
        return parent->getSettingString(key);
    }

    if (SettingRegistry::getInstance()->settingExists(key))
    {
        setting_values[key] = SettingRegistry::getInstance()->getSettingConfig(key)->getDefaultValue();
    }
    else
    {
        setting_values[key] = "";
        cura::logError("Unregistered setting %s\n", key.c_str());
    }
    return setting_values[key];
}

void SettingsMessenger::setSetting(std::string key, std::string value)
{
    parent->setSetting(key, value);
}

std::string SettingsMessenger::getSettingString(std::string key)
{
    return parent->getSettingString(key);
}

void SettingsBase::setExtruderTrainDefaults(unsigned int extruder_nr)
{
    const SettingContainer* machine_extruder_trains = SettingRegistry::getInstance()->getCategory(std::string("machine_extruder_trains"));

    if (!machine_extruder_trains)
    {
        // no machine_extruder_trains setting present; just use defaults for each train..
        return;
    }

    const SettingConfig* train = machine_extruder_trains->getChild(extruder_nr);

    if (!train)
    {
        logError("Not enough extruder trains specified in JSON: %i\n", extruder_nr);
        return;
    }

    for (const SettingConfig& setting : train->getChildren())
    {
        if (setting_values.find(setting.getKey()) == setting_values.end())
        {
            setSetting(setting.getKey(), setting.getDefaultValue());
        }
    }
}

int SettingsBaseVirtual::getSettingAsIndex(std::string key)
{
    std::string value = getSettingString(key);
    return atoi(value.c_str());
}

int SettingsBaseVirtual::getSettingAsCount(std::string key)
{
    std::string value = getSettingString(key);
    return atoi(value.c_str());
}

int SettingsBaseVirtual::getSettingInMicrons(std::string key)
{
    std::string value = getSettingString(key);
    return atof(value.c_str()) * 1000.0;
}

double SettingsBaseVirtual::getSettingInAngleRadians(std::string key)
{
    std::string value = getSettingString(key);
    return atof(value.c_str()) / 180.0 * M_PI;
}

bool SettingsBaseVirtual::getSettingBoolean(std::string key)
{
    std::string value = getSettingString(key);
    if (value == "on")
        return true;
    if (value == "yes")
        return true;
    if (value == "true" or value == "True") //Python uses "True"
        return true;
    int num = atoi(value.c_str());
    return num != 0;
}

double SettingsBaseVirtual::getSettingInDegreeCelsius(std::string key)
{
    std::string value = getSettingString(key);
    return atof(value.c_str());
}

double SettingsBaseVirtual::getSettingInMillimetersPerSecond(std::string key)
{
    std::string value = getSettingString(key);
    return std::max(1.0, atof(value.c_str()));
}

double SettingsBaseVirtual::getSettingInCubicMillimeters(std::string key)
{
    std::string value = getSettingString(key);
    return std::max(0.0, atof(value.c_str()));
}

double SettingsBaseVirtual::getSettingInPercentage(std::string key)
{
    std::string value = getSettingString(key);
    return std::max(0.0, atof(value.c_str()));
}

double SettingsBaseVirtual::getSettingInSeconds(std::string key)
{
    std::string value = getSettingString(key);
    return std::max(0.0, atof(value.c_str()));
}

EGCodeFlavor SettingsBaseVirtual::getSettingAsGCodeFlavor(std::string key)
{
    std::string value = getSettingString(key);
    if (value == "RepRap")
        return EGCodeFlavor::REPRAP;
    else if (value == "UltiGCode")
        return EGCodeFlavor::ULTIGCODE;
    else if (value == "Makerbot")
        return EGCodeFlavor::MAKERBOT;
    else if (value == "BFB")
        return EGCodeFlavor::BFB;
    else if (value == "MACH3")
        return EGCodeFlavor::MACH3;
    else if (value == "RepRap (Volumatric)")
        return EGCodeFlavor::REPRAP_VOLUMATRIC;
    return EGCodeFlavor::REPRAP;
}

EFillMethod SettingsBaseVirtual::getSettingAsFillMethod(std::string key)
{
    std::string value = getSettingString(key);
    if (value == "lines")
        return EFillMethod::LINES;
    if (value == "grid")
        return EFillMethod::GRID;
    if (value == "triangles")
        return EFillMethod::TRIANGLES;
    if (value == "concentric")
        return EFillMethod::CONCENTRIC;
    if (value == "zigzag")
        return EFillMethod::ZIG_ZAG;
    return EFillMethod::NONE;
}

EPlatformAdhesion SettingsBaseVirtual::getSettingAsPlatformAdhesion(std::string key)
{
    std::string value = getSettingString(key);
    if (value == "brim")
        return EPlatformAdhesion::BRIM;
    if (value == "raft")
        return EPlatformAdhesion::RAFT;
    return EPlatformAdhesion::SKIRT;
}

ESupportType SettingsBaseVirtual::getSettingAsSupportType(std::string key)
{
    std::string value = getSettingString(key);
    if (value == "everywhere")
        return ESupportType::EVERYWHERE;
    if (value == "buildplate")
        return ESupportType::PLATFORM_ONLY;
    return ESupportType::NONE;
}

EZSeamType SettingsBaseVirtual::getSettingAsZSeamType(std::string key)
{
    std::string value = getSettingString(key);
    if (value == "random")
        return EZSeamType::RANDOM;
    if (value == "shortest")
        return EZSeamType::SHORTEST;
    if (value == "back")
        return EZSeamType::BACK;
    return EZSeamType::SHORTEST;
}

ESurfaceMode SettingsBaseVirtual::getSettingAsSurfaceMode(std::string key)
{
    std::string value = getSettingString(key);
    if (value == "normal")
        return ESurfaceMode::NORMAL;
    if (value == "surface")
        return ESurfaceMode::SURFACE;
    if (value == "both")
        return ESurfaceMode::BOTH;
    return ESurfaceMode::NORMAL;
}

FillPerimeterGapMode SettingsBaseVirtual::getSettingAsFillPerimeterGapMode(std::string key)
{
    std::string value = getSettingString(key);
    if (value == "nowhere")
    {
        return FillPerimeterGapMode::NOWHERE;
    }
    if (value == "everywhere")
    {
        return FillPerimeterGapMode::EVERYWHERE;
    }
    if (value == "skin")
    {
        return FillPerimeterGapMode::SKIN;
    }
    return FillPerimeterGapMode::NOWHERE;
}

}//namespace cura
<|endoftext|>