<commit_before>#include "DNSMusic.h"

DNSMusic::DNSMusic (const std::string& appname,
const std::string& clientname,
const std::string& clientid)
: mosqpp::mosquittopp{ (clientid).c_str () }
, _appname{ appname }
, _clientname{ clientname }
, _topicRoot{ "ESEiot" }
, _mtx{}
, _client_id (clientid)
, _cache_path (".cache/")
, _master_volume (0)
, _sources ()
, _rwf_volumes ()
, _players ()
, _speaker_data ()
, _data_parser ()

{
    will_set (MQTT_TOPIC_INFO_CLIENTS_OFFLINE.c_str (), _client_id.size (),
    _client_id.c_str (), MQTT_QoS_0);

    connect (MQTT_BROKER.c_str (), MQTT_BROKER_PORT, MQTT_KEEP_ALIVE);
}

DNSMusic::~DNSMusic () {
    std::cerr << "---- ** disconnecting DNSMusic" << std::endl;
    publish (nullptr, MQTT_TOPIC_INFO_CLIENTS_OFFLINE.c_str (),
    _client_id.size (), _client_id.c_str (), MQTT_QoS_0);
    disconnect ();
}

void DNSMusic::on_connect (int rc) {
    if (rc == 0) {
        publish (nullptr, MQTT_TOPIC_INFO_CLIENTS_ONLINE.c_str (),
        _client_id.size (), _client_id.c_str (), MQTT_QoS_0);
        subscribe (nullptr, MQTT_TOPIC_REQUEST_ONLINE.c_str (), MQTT_QoS_0);
        subscribe (nullptr, MQTT_TOPIC_REQUEST_INFO_CLIENTS.c_str (), MQTT_QoS_0);
        subscribe (nullptr, MQTT_TOPIC_INFO_CLIENTS_DATA_WILDCARD.c_str (), MQTT_QoS_0);
        subscribe (nullptr, MQTT_TOPIC_INFO_MUSIC_VOLUME.c_str (), MQTT_QoS_0);
        subscribe (nullptr, MQTT_TOPIC_INFO_MUSIC_STATUS.c_str (), MQTT_QoS_0);
        subscribe (nullptr, MQTT_TOPIC_INFO_MUSIC_SOURCES.c_str (), MQTT_QoS_0);
    }
}

void DNSMusic::on_disconnect (int rc) {
    if (!(rc == 0)) {
        publish (nullptr, MQTT_TOPIC_INFO_CLIENTS_OFFLINE.c_str (),
        _client_id.size (), _client_id.c_str (), MQTT_QoS_0);
    }
    std::cerr << "---- DNSMusic disconnected with rc = " << rc << std::endl;
}

void DNSMusic::on_message (const mosquitto_message* message) {
    std::unique_lock<std::mutex> lk{ _mtx };
    std::string topic{ message->topic };

    D (std::cerr << "DATA received by a topic + message: " << topic << " "
                 << (char*)message->payload << std::endl;);

    D (std::cerr << "Value of the struct mosquitto_message" << std::endl
                 << "Mid: " << message->mid << std::endl
                 << "topic: " << message->topic << std::endl
                 << "payload: " << (char*)message->payload
                 << " lengte: " << message->payloadlen << std::endl
                 << "QOS: " << message->qos << std::endl
                 << "Retian" << message->retain << std::endl
                 << std::endl;);

    if (topic == MQTT_TOPIC_REQUEST_ONLINE) {
        publish (nullptr, MQTT_TOPIC_INFO_CLIENTS_ONLINE.c_str (),
        _client_id.size (), _client_id.c_str (), MQTT_QoS_0);
    }

    if (topic == MQTT_TOPIC_REQUEST_INFO_CLIENTS) {
        const std::string str_payload = _data_parser.composeClientData (_speaker_data);
        publish (nullptr, (char*)message->payload, str_payload.size (),
        str_payload.c_str (), MQTT_QoS_0);
    }

    if (topic == MQTT_TOPIC_INFO_MUSIC_VOLUME) {
        setMasterVolume (std::string{ (char*)message->payload });
    }

    if (topic == MQTT_TOPIC_INFO_MUSIC_STATUS) {
        setPPS (std::string{ (char*)message->payload });
    }

    if (topic == MQTT_TOPIC_INFO_MUSIC_SOURCES) {
        processMusicSourceData (std::string{ (char*)message->payload });
    }

    if (topic.find (MQTT_TOPIC_INFO_CLIENTS_DATA) == 0) {
        processClientData (std::string{ (char*)message->payload });
    }
}

void DNSMusic::on_subscribe (int mid, int qos_count, const int* granted_qos) {
    std::cerr << "---- DNSMusic subscription succeeded mid = " << mid << std::endl
              << " qos_count = " << qos_count << std::endl
              << " granted_qos = " << *granted_qos << std::endl;
}

void DNSMusic::on_log (int level, const char* str) {
    std::cerr << "---- # log DNSMusic " << level << std::endl
              << ": " << str << std::endl;
}

void DNSMusic::on_error () {
    std::cerr << "**** DNSMusic ERROR" << std::endl;
}

void DNSMusic::setMasterVolume (std::string volume) {
    try {
        size_t size{ 0 };
        _master_volume = stoi (volume, &size);
        if (volume.size () != size) {
            D (std::cerr << "wrong volume value" << std::endl;);
        }
    } catch (std::invalid_argument& e) {
        D (std::cerr << std::endl
                     << "## EXCEPTION s40 invalid_argument: " << e.what () << std::endl;);
    } catch (std::out_of_range& e) {
        D (std::cerr << std::endl
                     << "## EXCEPTION s40 out_of_range: " << e.what () << std::endl;);
    }

    for (auto& object : _players) {
        int rwf_volume, adjusted_volume;

        rwf_volume      = _rwf_volumes[object.first];
        adjusted_volume = (100 * rwf_volume) / _master_volume;

        object.second.set_volume (adjusted_volume);
    }
}

void DNSMusic::setPPS (std::string status_str) {
    enum play_status { play, pause, stop } status;
    if (status_str == "p" || status_str == "play") {
        status = play;
    }
    if (status_str == "pa" || status_str == "pause") {
        status = pause;
    }
    if (status_str == "s" || status_str == "stop") {
        status = stop;
    }

    for (auto& player : _players) {
        switch (status) {
            case play: player.second.play (); break;
            case pause: // simply stop playing
            case stop: player.second.stop (); break;
        }
    }
}

/*
new sources come in

check if new sources are in old sources map (by name)
    if so, compare uri
        if uri is same, do nothing
        if uri is different
            if object has a player
                stop player
                download file
                if was playing before stopped
                    start playing
            else
                download file

if source is new
    add to sources
    download
beepboop
*/
void DNSMusic::processMusicSourceData (std::string json_str) {
    std::map<std::string, std::string> new_sources;
    new_sources = _data_parser.parseAudioSourceData (json_str);

    for (auto new_source : new_sources) {
        std::string local_name = new_source.first;

        if (_sources[local_name] != new_source.second) {
            // only interact with player if it already exists
            if (_players.find (local_name) != _players.end ()) {
                int status = _players[local_name].stop ();

                download::download (new_source.second, _cache_path + local_name);

                // only start playing if it was previously playing
                if (status == 0) {
                    _players[local_name].set_file (_cache_path + local_name);
                    _players[local_name].play ();
                }
            } else {
                download::download (new_source.second, _cache_path + local_name);
            }
        }
    }
    _sources = new_sources;
}

/*
new objects come in
parse into map of vectors of speaker distances
parse local speaker objects

for every local speaker object
    get vector of speaker distances to said object
    append vector with personal distance
    calculate rwf from vector
    get local object volume from rwf returns
    adjust local object volume to master volume
    if audio player exists for object
        set player local object volume
    else
        if a source file is known for the object
            create player and set file
            set player local object volume
*/

void DNSMusic::processClientData (std::string json_str) {
    std::map<std::string, std::vector<float>> objects;
    float rwf_volume, adjusted_volume;
    rwf::rwf<float> rwf ({ 0 });
    _speaker_data = _data_parser.parseClientData (json_str, _client_id, objects);

    for (auto audio_object : _speaker_data.objects) {
        std::string object_name      = audio_object.first;
        std::vector<float> distances = objects[object_name];
        distances.push_back (audio_object.second.distance);

        rwf.set_factors (distances);
        rwf_volume = rwf.get_relative_weight_factor ().back ();

        _rwf_volumes[object_name] = rwf_volume;
        adjusted_volume           = (rwf_volume * _master_volume) / 100;

        if (_players.find (object_name) != _players.end ()) {
            _players[object_name].set_volume (adjusted_volume);
        } else {
            if (_sources.find (object_name) != _sources.end ()) {
                _players[object_name].set_file (_cache_path + object_name);
                _players[object_name].set_volume (adjusted_volume);
            } else {
                ; // TODO LOG this somehow: no file known for this object
            }
        }
    }

    // remove all unneeded players
    for (auto it = _players.cbegin (); it != _players.cend ();) {
        if (_speaker_data.objects.find (it->first) == _speaker_data.objects.end ()) {
            _players.erase (it++);
        } else {
            ++it;
        }
    }
}
<commit_msg>fix volume calculation in client<commit_after>#include "DNSMusic.h"

DNSMusic::DNSMusic (const std::string& appname,
const std::string& clientname,
const std::string& clientid)
: mosqpp::mosquittopp{ (clientid).c_str () }
, _appname{ appname }
, _clientname{ clientname }
, _topicRoot{ "ESEiot" }
, _mtx{}
, _client_id (clientid)
, _cache_path (".cache/")
, _master_volume (0)
, _sources ()
, _rwf_volumes ()
, _players ()
, _speaker_data ()
, _data_parser ()

{
    will_set (MQTT_TOPIC_INFO_CLIENTS_OFFLINE.c_str (), _client_id.size (),
    _client_id.c_str (), MQTT_QoS_0);

    connect (MQTT_BROKER.c_str (), MQTT_BROKER_PORT, MQTT_KEEP_ALIVE);
}

DNSMusic::~DNSMusic () {
    std::cerr << "---- ** disconnecting DNSMusic" << std::endl;
    publish (nullptr, MQTT_TOPIC_INFO_CLIENTS_OFFLINE.c_str (),
    _client_id.size (), _client_id.c_str (), MQTT_QoS_0);
    disconnect ();
}

void DNSMusic::on_connect (int rc) {
    if (rc == 0) {
        publish (nullptr, MQTT_TOPIC_INFO_CLIENTS_ONLINE.c_str (),
        _client_id.size (), _client_id.c_str (), MQTT_QoS_0);
        subscribe (nullptr, MQTT_TOPIC_REQUEST_ONLINE.c_str (), MQTT_QoS_0);
        subscribe (nullptr, MQTT_TOPIC_REQUEST_INFO_CLIENTS.c_str (), MQTT_QoS_0);
        subscribe (nullptr, MQTT_TOPIC_INFO_CLIENTS_DATA_WILDCARD.c_str (), MQTT_QoS_0);
        subscribe (nullptr, MQTT_TOPIC_INFO_MUSIC_VOLUME.c_str (), MQTT_QoS_0);
        subscribe (nullptr, MQTT_TOPIC_INFO_MUSIC_STATUS.c_str (), MQTT_QoS_0);
        subscribe (nullptr, MQTT_TOPIC_INFO_MUSIC_SOURCES.c_str (), MQTT_QoS_0);
    }
}

void DNSMusic::on_disconnect (int rc) {
    if (!(rc == 0)) {
        publish (nullptr, MQTT_TOPIC_INFO_CLIENTS_OFFLINE.c_str (),
        _client_id.size (), _client_id.c_str (), MQTT_QoS_0);
    }
    std::cerr << "---- DNSMusic disconnected with rc = " << rc << std::endl;
}

void DNSMusic::on_message (const mosquitto_message* message) {
    std::unique_lock<std::mutex> lk{ _mtx };
    std::string topic{ message->topic };

    D (std::cerr << "DATA received by a topic + message: " << topic << " "
                 << (char*)message->payload << std::endl;);

    D (std::cerr << "Value of the struct mosquitto_message" << std::endl
                 << "Mid: " << message->mid << std::endl
                 << "topic: " << message->topic << std::endl
                 << "payload: " << (char*)message->payload
                 << " lengte: " << message->payloadlen << std::endl
                 << "QOS: " << message->qos << std::endl
                 << "Retian" << message->retain << std::endl
                 << std::endl;);

    if (topic == MQTT_TOPIC_REQUEST_ONLINE) {
        publish (nullptr, MQTT_TOPIC_INFO_CLIENTS_ONLINE.c_str (),
        _client_id.size (), _client_id.c_str (), MQTT_QoS_0);
    }

    if (topic == MQTT_TOPIC_REQUEST_INFO_CLIENTS) {
        const std::string str_payload = _data_parser.composeClientData (_speaker_data);
        publish (nullptr, (char*)message->payload, str_payload.size (),
        str_payload.c_str (), MQTT_QoS_0);
    }

    if (topic == MQTT_TOPIC_INFO_MUSIC_VOLUME) {
        setMasterVolume (std::string{ (char*)message->payload });
    }

    if (topic == MQTT_TOPIC_INFO_MUSIC_STATUS) {
        setPPS (std::string{ (char*)message->payload });
    }

    if (topic == MQTT_TOPIC_INFO_MUSIC_SOURCES) {
        processMusicSourceData (std::string{ (char*)message->payload });
    }

    if (topic.find (MQTT_TOPIC_INFO_CLIENTS_DATA) == 0) {
        processClientData (std::string{ (char*)message->payload });
    }
}

void DNSMusic::on_subscribe (int mid, int qos_count, const int* granted_qos) {
    std::cerr << "---- DNSMusic subscription succeeded mid = " << mid << std::endl
              << " qos_count = " << qos_count << std::endl
              << " granted_qos = " << *granted_qos << std::endl;
}

void DNSMusic::on_log (int level, const char* str) {
    std::cerr << "---- # log DNSMusic " << level << std::endl
              << ": " << str << std::endl;
}

void DNSMusic::on_error () {
    std::cerr << "**** DNSMusic ERROR" << std::endl;
}

void DNSMusic::setMasterVolume (std::string volume) {
    try {
        size_t size{ 0 };
        _master_volume = stoi (volume, &size);
        if (volume.size () != size) {
            D (std::cerr << "wrong volume value" << std::endl;);
        }
    } catch (std::invalid_argument& e) {
        D (std::cerr << std::endl
                     << "## EXCEPTION s40 invalid_argument: " << e.what () << std::endl;);
    } catch (std::out_of_range& e) {
        D (std::cerr << std::endl
                     << "## EXCEPTION s40 out_of_range: " << e.what () << std::endl;);
    }

    for (auto& object : _players) {
        int rwf_volume, adjusted_volume;

        rwf_volume      = _rwf_volumes[object.first];
        adjusted_volume = (rwf_volume * _master_volume) / 100;

        object.second.set_volume (adjusted_volume);
    }
}

void DNSMusic::setPPS (std::string status_str) {
    enum play_status { play, pause, stop } status;
    if (status_str == "p" || status_str == "play") {
        status = play;
    }
    if (status_str == "pa" || status_str == "pause") {
        status = pause;
    }
    if (status_str == "s" || status_str == "stop") {
        status = stop;
    }

    for (auto& player : _players) {
        switch (status) {
            case play: player.second.play (); break;
            case pause: // simply stop playing
            case stop: player.second.stop (); break;
        }
    }
}

/*
new sources come in

check if new sources are in old sources map (by name)
    if so, compare uri
        if uri is same, do nothing
        if uri is different
            if object has a player
                stop player
                download file
                if was playing before stopped
                    start playing
            else
                download file

if source is new
    add to sources
    download
beepboop
*/
void DNSMusic::processMusicSourceData (std::string json_str) {
    std::map<std::string, std::string> new_sources;
    new_sources = _data_parser.parseAudioSourceData (json_str);

    for (auto new_source : new_sources) {
        std::string local_name = new_source.first;

        if (_sources[local_name] != new_source.second) {
            // only interact with player if it already exists
            if (_players.find (local_name) != _players.end ()) {
                int status = _players[local_name].stop ();

                download::download (new_source.second, _cache_path + local_name);

                // only start playing if it was previously playing
                if (status == 0) {
                    _players[local_name].set_file (_cache_path + local_name);
                    _players[local_name].play ();
                }
            } else {
                download::download (new_source.second, _cache_path + local_name);
            }
        }
    }
    _sources = new_sources;
}

/*
new objects come in
parse into map of vectors of speaker distances
parse local speaker objects

for every local speaker object
    get vector of speaker distances to said object
    append vector with personal distance
    calculate rwf from vector
    get local object volume from rwf returns
    adjust local object volume to master volume
    if audio player exists for object
        set player local object volume
    else
        if a source file is known for the object
            create player and set file
            set player local object volume
*/

void DNSMusic::processClientData (std::string json_str) {
    std::map<std::string, std::vector<float>> objects;
    float rwf_volume, adjusted_volume;
    rwf::rwf<float> rwf ({ 0 });
    _speaker_data = _data_parser.parseClientData (json_str, _client_id, objects);

    for (auto audio_object : _speaker_data.objects) {
        std::string object_name      = audio_object.first;
        std::vector<float> distances = objects[object_name];
        distances.push_back (audio_object.second.distance);

        rwf.set_factors (distances);
        rwf_volume = rwf.get_relative_weight_factor ().back ();

        _rwf_volumes[object_name] = rwf_volume;
        adjusted_volume           = (rwf_volume * _master_volume) / 100;

        if (_players.find (object_name) != _players.end ()) {
            _players[object_name].set_volume (adjusted_volume);
        } else {
            if (_sources.find (object_name) != _sources.end ()) {
                _players[object_name].set_file (_cache_path + object_name);
                _players[object_name].set_volume (adjusted_volume);
            } else {
                ; // TODO LOG this somehow: no file known for this object
            }
        }
    }

    // remove all unneeded players
    for (auto it = _players.cbegin (); it != _players.cend ();) {
        if (_speaker_data.objects.find (it->first) == _speaker_data.objects.end ()) {
            _players.erase (it++);
        } else {
            ++it;
        }
    }
}
<|endoftext|>


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

#include "../query.h"

#include <windows.h>
#include <wingdi.h>
#include <GL/gl.h>

namespace {

static const char* wndClassName = TEXT("opengl-dummy-window");

WNDCLASS registerWindowClass() {
    WNDCLASS wc;
    memset(&wc, 0, sizeof(wc));
    wc.style         = 0;
    wc.lpfnWndProc   = DefWindowProc;
    wc.hInstance     = GetModuleHandle(0);
    wc.hCursor       = LoadCursor(0, IDC_ARROW);
    wc.lpszMenuName  = TEXT("");
    wc.lpszClassName = wndClassName;
    RegisterClass(&wc);
    return wc;
}

} // anonymous namespace

namespace query {

struct Context {
    char mError[512];
    HWND mWnd;
    HDC mHDC;
    HGLRC mCtx;
    int mNumCores;
    char mHostName[MAX_COMPUTERNAME_LENGTH*4+1]; // Stored as UTF-8
    OSVERSIONINFOEX mOsVersion;
    const char* mOsName;
};

static Context gContext;
static int gContextRefCount = 0;

void destroyContext() {
    if (--gContextRefCount > 0) {
        return;
    }

    if (gContext.mWnd != nullptr) {
        DestroyWindow(gContext.mWnd);
    }
    if (gContext.mCtx != nullptr) {
        wglMakeCurrent(gContext.mHDC, 0);
        wglDeleteContext(gContext.mCtx);
    }
}

bool createContext(void* platform_data) {
    if (gContextRefCount++ > 0) {
        return true;
    }

    WNDCLASS wc = registerWindowClass();
    gContext.mWnd = CreateWindow(wndClassName, TEXT(""), WS_POPUP, 0, 0, 8, 8, 0, 0, GetModuleHandle(0), 0);
    if (gContext.mWnd == nullptr) {
        snprintf(gContext.mError, sizeof(gContext.mError),
                 "CreateWindow returned error: %d", GetLastError());
        return false;
    }
    PIXELFORMATDESCRIPTOR pfd;
    memset(&pfd, 0, sizeof(pfd));
    pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
    pfd.nVersion = 1;
    pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
    pfd.iPixelType = PFD_TYPE_RGBA;
    pfd.cRedBits = 8;
    pfd.cGreenBits = 8;
    pfd.cBlueBits = 8;
    pfd.cAlphaBits = 8;
    pfd.cDepthBits = 24;
    pfd.cStencilBits = 8;
    pfd.cColorBits = 32;
    pfd.iLayerType = PFD_MAIN_PLANE;
    gContext.mHDC = GetDC(gContext.mWnd);
    SetPixelFormat(gContext.mHDC, ChoosePixelFormat(gContext.mHDC, &pfd), &pfd);
    gContext.mCtx = wglCreateContext(gContext.mHDC);
    if (gContext.mCtx == nullptr) {
        snprintf(gContext.mError, sizeof(gContext.mError),
                 "wglCreateContext returned error: %d", GetLastError());
        destroyContext();
        return false;
    }
    wglMakeCurrent(gContext.mHDC, gContext.mCtx);

    gContext.mOsVersion.dwOSVersionInfoSize = sizeof(gContext.mOsVersion);
    GetVersionEx((OSVERSIONINFO*)(&gContext.mOsVersion));
    int major = gContext.mOsVersion.dwMajorVersion;
    int minor = gContext.mOsVersion.dwMinorVersion;
    int point = gContext.mOsVersion.dwBuildNumber;
    bool isNTWorkstation = (gContext.mOsVersion.wProductType == VER_NT_WORKSTATION);

    if (major == 10 && isNTWorkstation) {
        gContext.mOsName = "Windows 10";
    } else if (major == 10 && !isNTWorkstation) {
        gContext.mOsName = "Windows Server 2016 Technical Preview";
    } else if (major == 6 && minor == 3 && isNTWorkstation) {
        gContext.mOsName = "Windows 8.1";
    } else if (major == 6 && minor == 3 && !isNTWorkstation) {
        gContext.mOsName = "Windows Server 2012 R2";
    } else if (major == 6 && minor == 2 && isNTWorkstation) {
        gContext.mOsName = "Windows 8";
    } else if (major == 6 && minor == 2 && !isNTWorkstation) {
        gContext.mOsName = "Windows Server 2012";
    } else if (major == 6 && minor == 1 && isNTWorkstation) {
        gContext.mOsName = "Windows 7";
    } else if (major == 6 && minor == 1 && !isNTWorkstation) {
        gContext.mOsName = "Windows Server 2008 R2";
    } else if (major == 6 && minor == 0 && isNTWorkstation) {
        gContext.mOsName = "Windows Vista";
    } else if (major == 6 && minor == 0 && !isNTWorkstation) {
        gContext.mOsName = "Windows Server 2008";
    } else if (major == 5 && minor == 1) {
        gContext.mOsName = "Windows XP";
    } else if (major == 5 && minor == 0) {
        gContext.mOsName = "Windows 2000";
    } else {
        gContext.mOsName = "<unknown>";
    }

    SYSTEM_INFO sysInfo;
    GetSystemInfo(&sysInfo);
    gContext.mNumCores = sysInfo.dwNumberOfProcessors;

    DWORD size = MAX_COMPUTERNAME_LENGTH + 1;
    WCHAR host_wide[MAX_COMPUTERNAME_LENGTH + 1];
    if (!GetComputerNameW(host_wide, &size)) {
        snprintf(gContext.mError, sizeof(gContext.mError),
                 "Couldn't get host name: %d", GetLastError());
    }
    WideCharToMultiByte(
        CP_UTF8,                    // CodePage
        0,                          // dwFlags
        host_wide,                  // lpWideCharStr
        -1,                         // cchWideChar
        gContext.mHostName,         // lpMultiByteStr
        sizeof(gContext.mHostName), // cbMultiByte
        nullptr,                    // lpDefaultChar
        nullptr                     // lpUsedDefaultChar
    );

    return true;
}

const char* contextError() {
    return gContext.mError;
}

int numABIs() { return 1; }

void abi(int idx, device::ABI* abi) {
    abi->set_name("X86_64");
    abi->set_os(device::OSX);
    abi->set_architecture(device::X86_64);
    abi->set_allocated_memorylayout(currentMemoryLayout());
}

device::ABI* currentABI() {
    auto out = new device::ABI();
    abi(0, out);
    return out;
}

int cpuNumCores() { return gContext.mNumCores; }

const char* gpuName() { return "<unknown>"; }

const char* gpuVendor() { return "<unknown>"; }

const char* instanceName() { return gContext.mHostName; }

const char* instanceSerial()  { return gContext.mHostName; }

const char* hardwareName() { return "<unknown>"; }

device::OSKind osKind() { return device::Windows; }

const char* osName() { return gContext.mOsName; }

const char* osBuild() { return "<unknown>"; }

int osMajor() { return gContext.mOsVersion.dwMajorVersion; }

int osMinor() { return gContext.mOsVersion.dwMinorVersion; }

int osPoint() { return gContext.mOsVersion.dwBuildNumber; }

} // namespace query<commit_msg>Fix missing return from previous CL.<commit_after>/*
 * Copyright (C) 2017 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "../query.h"

#include <windows.h>
#include <wingdi.h>
#include <GL/gl.h>

namespace {

static const char* wndClassName = TEXT("opengl-dummy-window");

WNDCLASS registerWindowClass() {
    WNDCLASS wc;
    memset(&wc, 0, sizeof(wc));
    wc.style         = 0;
    wc.lpfnWndProc   = DefWindowProc;
    wc.hInstance     = GetModuleHandle(0);
    wc.hCursor       = LoadCursor(0, IDC_ARROW);
    wc.lpszMenuName  = TEXT("");
    wc.lpszClassName = wndClassName;
    RegisterClass(&wc);
    return wc;
}

} // anonymous namespace

namespace query {

struct Context {
    char mError[512];
    HWND mWnd;
    HDC mHDC;
    HGLRC mCtx;
    int mNumCores;
    char mHostName[MAX_COMPUTERNAME_LENGTH*4+1]; // Stored as UTF-8
    OSVERSIONINFOEX mOsVersion;
    const char* mOsName;
};

static Context gContext;
static int gContextRefCount = 0;

void destroyContext() {
    if (--gContextRefCount > 0) {
        return;
    }

    if (gContext.mWnd != nullptr) {
        DestroyWindow(gContext.mWnd);
    }
    if (gContext.mCtx != nullptr) {
        wglMakeCurrent(gContext.mHDC, 0);
        wglDeleteContext(gContext.mCtx);
    }
}

bool createContext(void* platform_data) {
    if (gContextRefCount++ > 0) {
        return true;
    }

    WNDCLASS wc = registerWindowClass();
    gContext.mWnd = CreateWindow(wndClassName, TEXT(""), WS_POPUP, 0, 0, 8, 8, 0, 0, GetModuleHandle(0), 0);
    if (gContext.mWnd == nullptr) {
        snprintf(gContext.mError, sizeof(gContext.mError),
                 "CreateWindow returned error: %d", GetLastError());
        return false;
    }
    PIXELFORMATDESCRIPTOR pfd;
    memset(&pfd, 0, sizeof(pfd));
    pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
    pfd.nVersion = 1;
    pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
    pfd.iPixelType = PFD_TYPE_RGBA;
    pfd.cRedBits = 8;
    pfd.cGreenBits = 8;
    pfd.cBlueBits = 8;
    pfd.cAlphaBits = 8;
    pfd.cDepthBits = 24;
    pfd.cStencilBits = 8;
    pfd.cColorBits = 32;
    pfd.iLayerType = PFD_MAIN_PLANE;
    gContext.mHDC = GetDC(gContext.mWnd);
    SetPixelFormat(gContext.mHDC, ChoosePixelFormat(gContext.mHDC, &pfd), &pfd);
    gContext.mCtx = wglCreateContext(gContext.mHDC);
    if (gContext.mCtx == nullptr) {
        snprintf(gContext.mError, sizeof(gContext.mError),
                 "wglCreateContext returned error: %d", GetLastError());
        destroyContext();
        return false;
    }
    wglMakeCurrent(gContext.mHDC, gContext.mCtx);

    gContext.mOsVersion.dwOSVersionInfoSize = sizeof(gContext.mOsVersion);
    GetVersionEx((OSVERSIONINFO*)(&gContext.mOsVersion));
    int major = gContext.mOsVersion.dwMajorVersion;
    int minor = gContext.mOsVersion.dwMinorVersion;
    int point = gContext.mOsVersion.dwBuildNumber;
    bool isNTWorkstation = (gContext.mOsVersion.wProductType == VER_NT_WORKSTATION);

    if (major == 10 && isNTWorkstation) {
        gContext.mOsName = "Windows 10";
    } else if (major == 10 && !isNTWorkstation) {
        gContext.mOsName = "Windows Server 2016 Technical Preview";
    } else if (major == 6 && minor == 3 && isNTWorkstation) {
        gContext.mOsName = "Windows 8.1";
    } else if (major == 6 && minor == 3 && !isNTWorkstation) {
        gContext.mOsName = "Windows Server 2012 R2";
    } else if (major == 6 && minor == 2 && isNTWorkstation) {
        gContext.mOsName = "Windows 8";
    } else if (major == 6 && minor == 2 && !isNTWorkstation) {
        gContext.mOsName = "Windows Server 2012";
    } else if (major == 6 && minor == 1 && isNTWorkstation) {
        gContext.mOsName = "Windows 7";
    } else if (major == 6 && minor == 1 && !isNTWorkstation) {
        gContext.mOsName = "Windows Server 2008 R2";
    } else if (major == 6 && minor == 0 && isNTWorkstation) {
        gContext.mOsName = "Windows Vista";
    } else if (major == 6 && minor == 0 && !isNTWorkstation) {
        gContext.mOsName = "Windows Server 2008";
    } else if (major == 5 && minor == 1) {
        gContext.mOsName = "Windows XP";
    } else if (major == 5 && minor == 0) {
        gContext.mOsName = "Windows 2000";
    } else {
        gContext.mOsName = "<unknown>";
    }

    SYSTEM_INFO sysInfo;
    GetSystemInfo(&sysInfo);
    gContext.mNumCores = sysInfo.dwNumberOfProcessors;

    DWORD size = MAX_COMPUTERNAME_LENGTH + 1;
    WCHAR host_wide[MAX_COMPUTERNAME_LENGTH + 1];
    if (!GetComputerNameW(host_wide, &size)) {
        snprintf(gContext.mError, sizeof(gContext.mError),
                 "Couldn't get host name: %d", GetLastError());
        return false;
    }
    WideCharToMultiByte(
        CP_UTF8,                    // CodePage
        0,                          // dwFlags
        host_wide,                  // lpWideCharStr
        -1,                         // cchWideChar
        gContext.mHostName,         // lpMultiByteStr
        sizeof(gContext.mHostName), // cbMultiByte
        nullptr,                    // lpDefaultChar
        nullptr                     // lpUsedDefaultChar
    );

    return true;
}

const char* contextError() {
    return gContext.mError;
}

int numABIs() { return 1; }

void abi(int idx, device::ABI* abi) {
    abi->set_name("X86_64");
    abi->set_os(device::OSX);
    abi->set_architecture(device::X86_64);
    abi->set_allocated_memorylayout(currentMemoryLayout());
}

device::ABI* currentABI() {
    auto out = new device::ABI();
    abi(0, out);
    return out;
}

int cpuNumCores() { return gContext.mNumCores; }

const char* gpuName() { return "<unknown>"; }

const char* gpuVendor() { return "<unknown>"; }

const char* instanceName() { return gContext.mHostName; }

const char* instanceSerial()  { return gContext.mHostName; }

const char* hardwareName() { return "<unknown>"; }

device::OSKind osKind() { return device::Windows; }

const char* osName() { return gContext.mOsName; }

const char* osBuild() { return "<unknown>"; }

int osMajor() { return gContext.mOsVersion.dwMajorVersion; }

int osMinor() { return gContext.mOsVersion.dwMinorVersion; }

int osPoint() { return gContext.mOsVersion.dwBuildNumber; }

} // namespace query
<|endoftext|>


<commit_before>//cci_stack_trace.cpp     william k. johnson 2016

#include <cci_stack_trace.h>

using namespace cci_daemon_impl;

//demangled stack backtrace of the caller function to out stream
void cci_daemon_impl::print_stacktrace( FILE *out , unsigned max_frames )
{
        fprintf(out, "stack trace:\n");

        // storage array for stack trace address data
        void* addrlist[max_frames+1];

        // retrieve current stack addresses
        int addrlen = backtrace(addrlist, sizeof(addrlist) / sizeof(void*));

        if (addrlen == 0) {
        fprintf(out, "  <empty, possibly corrupt>\n");
        return;
        }

        // resolve addresses into strings containing "filename(function+address)",
        // this array must be free()-ed
        char** symbollist = backtrace_symbols(addrlist, addrlen);

        // allocate string which will be filled with the demangled function name
        size_t funcnamesize = 256;
        char* funcname = (char*)malloc(funcnamesize);

        // iterate over the returned symbol lines. skip the first, it is the
        // address of this function.
        for (int i = 1; i < addrlen; i++)
        {
            char *begin_name = 0, *begin_offset = 0, *end_offset = 0;

            // find parentheses and +address offset surrounding the mangled name:
            // ./module(function+0x15c) [0x8048a6d]
            for (char *p = symbollist[i]; *p; ++p)
            {
                if (*p == '(')
                begin_name = p;
                else if (*p == '+')
                begin_offset = p;
                else if (*p == ')' && begin_offset) {
                end_offset = p;
                break;
                }
            }

            if (begin_name && begin_offset && end_offset
                && begin_name < begin_offset)
            {
                *begin_name++ = '\0';
                *begin_offset++ = '\0';
                *end_offset = '\0';

                // mangled name is now in [begin_name, begin_offset) and caller
                // offset in [begin_offset, end_offset). now apply
                // __cxa_demangle():

                int status;
                char* ret = abi::__cxa_demangle(begin_name,
                                funcname, &funcnamesize, &status);
                if (status == 0) {
                funcname = ret; // use possibly realloc()-ed string
                fprintf(out, "  %s : %s+%s\n",
                    symbollist[i], funcname, begin_offset);
                }
                else {
                // demangling failed. Output function name as a C function with
                // no arguments.
                fprintf(out, "  %s : %s()+%s\n",

                    symbollist[i], begin_name, begin_offset);
                }
            }
            else
            {
                // couldn't parse the line? print the whole line.
                fprintf(out, "  %s\n", symbollist[i]);
            }
        }

        free(funcname);
        free(symbollist);
}

//--------------------------------------------------------------------------------------
//shift ptr
void** cci_daemon_impl::get_ebp( int dummy )
{
    void** ebp = (void** )&dummy - 2;

    return( ebp );
}

//--------------------------------------------------------------------------------------
//print trace back
void cci_daemon_impl::print_walk_backtrace( FILE *out )
{
        int dummy  = 0;
        int frame = 0;
        Dl_info dlip;

        void** ebp = get_ebp( dummy );
        void** ret = NULL;

        //instruction pointer
        fprintf( out , "stack backtrace walk: \n" );

        while( *ebp )
        {
            ret = ebp + 1;
            dladdr( *ret, &dlip );
            fprintf(  out ,
                     "frame %d: [ebp=0x%08x] [ret=0x%08x] %s\n" ,
                     frame++ ,
                     *ebp ,
                     *ret ,
                     dlip.dli_sname );
            //next frame pointer
            ebp = (void**)(*ebp);
        }

}

<commit_msg>-afternoon<commit_after>//cci_stack_trace.cpp     william k. johnson 2016-2021 chromatic universe

#include <cci_stack_trace.h>

using namespace cci_daemon_impl;

//demangled stack backtrace of the caller function to out stream
void cci_daemon_impl::print_stacktrace( FILE *out , unsigned max_frames )
{
        fprintf(out, "stack trace:\n");

        // storage array for stack trace address data
        void* addrlist[max_frames+1];

        // retrieve current stack addresses
        int addrlen = backtrace(addrlist, sizeof(addrlist) / sizeof(void*));

        if (addrlen == 0) {
        fprintf(out, "  <empty, possibly corrupt>\n");
        return;
        }

        // resolve addresses into strings containing "filename(function+address)",
        // this array must be free()-ed
        char** symbollist = backtrace_symbols(addrlist, addrlen);

        // allocate string which will be filled with the demangled function name
        size_t funcnamesize = 256;
        char* funcname = (char*)malloc(funcnamesize);

        // iterate over the returned symbol lines. skip the first, it is the
        // address of this function.
        for (int i = 1; i < addrlen; i++)
        {
            char *begin_name = 0, *begin_offset = 0, *end_offset = 0;

            // find parentheses and +address offset surrounding the mangled name:
            // ./module(function+0x15c) [0x8048a6d]
            for (char *p = symbollist[i]; *p; ++p)
            {
                if (*p == '(')
                begin_name = p;
                else if (*p == '+')
                begin_offset = p;
                else if (*p == ')' && begin_offset) {
                end_offset = p;
                break;
                }
            }

            if (begin_name && begin_offset && end_offset
                && begin_name < begin_offset)
            {
                *begin_name++ = '\0';
                *begin_offset++ = '\0';
                *end_offset = '\0';

                // mangled name is now in [begin_name, begin_offset) and caller
                // offset in [begin_offset, end_offset). now apply
                // __cxa_demangle():

                int status;
                char* ret = abi::__cxa_demangle(begin_name,
                                funcname, &funcnamesize, &status);
                if (status == 0) {
                funcname = ret; // use possibly realloc()-ed string
                fprintf(out, "  %s : %s+%s\n",
                    symbollist[i], funcname, begin_offset);
                }
                else {
                // demangling failed. Output function name as a C function with
                // no arguments.
                fprintf(out, "  %s : %s()+%s\n",

                    symbollist[i], begin_name, begin_offset);
                }
            }
            else
            {
                // couldn't parse the line? print the whole line.
                fprintf(out, "  %s\n", symbollist[i]);
            }
        }

        free(funcname);
        free(symbollist);
}

//--------------------------------------------------------------------------------------
//shift ptr
void** cci_daemon_impl::get_ebp( int dummy )
{
    void** ebp = (void** )&dummy - 2;

    return( ebp );
}

//--------------------------------------------------------------------------------------
//print trace back
void cci_daemon_impl::print_walk_backtrace( FILE *out )
{
        int dummy  = 0;
        int frame = 0;
        Dl_info dlip;

        void** ebp = get_ebp( dummy );
        void** ret = NULL;

        //instruction pointer
        fprintf( out , "stack backtrace walk: \n" );

        while( *ebp )
        {
            ret = ebp + 1;
            dladdr( *ret, &dlip );
            fprintf(  out ,
                     "frame %d: [ebp=0x%08x] [ret=0x%08x] %s\n" ,
                     frame++ ,
                     *ebp ,
                     *ret ,
                     dlip.dli_sname );
            //next frame pointer
            ebp = (void**)(*ebp);
        }

}

<|endoftext|>


<commit_before>/// \file ROOT/RNTupleOptions.hxx
/// \ingroup NTuple ROOT7
/// \author Jakob Blomer <jblomer@cern.ch>
/// \date 2019-08-25
/// \warning This is part of the ROOT 7 prototype! It will change without notice. It might trigger earthquakes. Feedback
/// is welcome!

/*************************************************************************
 * Copyright (C) 1995-2019, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

#ifndef ROOT7_RNTupleOptions
#define ROOT7_RNTupleOptions

#include <Compression.h>
#include <ROOT/RError.hxx>
#include <ROOT/RNTupleUtil.hxx>

namespace ROOT {
namespace Experimental {

// clang-format off
/**
\class ROOT::Experimental::ENTupleContainerFormat
\ingroup NTuple
\brief Describes the options for wrapping RNTuple data in files
*/
// clang-format on
enum class ENTupleContainerFormat {
   kTFile, // ROOT TFile
   kBare, // A thin envelope supporting a single RNTuple only
};

// clang-format off
/**
\class ROOT::Experimental::RNTupleWriteOptions
\ingroup NTuple
\brief Common user-tunable settings for storing ntuples

All page sink classes need to support the common options.
*/
// clang-format on
class RNTupleWriteOptions {
   int fCompression{RCompressionSetting::EDefaults::kUseAnalysis};
   ENTupleContainerFormat fContainerFormat{ENTupleContainerFormat::kTFile};
   /// Approximation of the target compressed cluster size
   std::size_t fApproxZippedClusterSize = 64 * 1000 * 1000;
   /// Memory limit for committing a cluster: with very high compression ratio, we need a limit
   /// on how large the I/O buffer can grow during writing.
   std::size_t fMaxUnzippedClusterSize = 512 * 1000 * 1000;
   /// Should be just large enough so that the compression ratio does not benefit much more from larger pages
   std::size_t fMaxUnzippedPageSize = 64 * 1024;
   bool fUseBufferedWrite = true;

public:
   virtual ~RNTupleWriteOptions() = default;
   virtual std::unique_ptr<RNTupleWriteOptions> Clone() const
   { return std::make_unique<RNTupleWriteOptions>(*this); }

   int GetCompression() const { return fCompression; }
   void SetCompression(int val) { fCompression = val; }
   void SetCompression(RCompressionSetting::EAlgorithm algorithm, int compressionLevel) {
     fCompression = CompressionSettings(algorithm, compressionLevel);
   }

   ENTupleContainerFormat GetContainerFormat() const { return fContainerFormat; }
   void SetContainerFormat(ENTupleContainerFormat val) { fContainerFormat = val; }

   std::size_t GetApproxZippedClusterSize() const { return fApproxZippedClusterSize; }
   void SetApproxZippedClusterSize(std::size_t val) { fApproxZippedClusterSize = val; }

   std::size_t GetMaxUnzippedClusterSize() const { return fMaxUnzippedClusterSize; }
   void SetMaxUnzippedClusterSize(std::size_t val) { fMaxUnzippedClusterSize = val; }

   std::size_t GetMaxUnzippedPageSize() const { return fMaxUnzippedPageSize; }
   void SetMaxUnzippedPageSize(std::size_t val) {
      if (val < 64)
         throw RException(R__FAIL("page size too small"));
      fMaxUnzippedPageSize = val;
   }

   bool GetUseBufferedWrite() const { return fUseBufferedWrite; }
   void SetUseBufferedWrite(bool val) { fUseBufferedWrite = val; }
};

// clang-format off
/**
\class ROOT::Experimental::RNTupleWriteOptionsDaos
\ingroup NTuple
\brief DAOS-specific user-tunable settings for storing ntuples
*/
// clang-format on
class RNTupleWriteOptionsDaos : public RNTupleWriteOptions {
  std::string fObjectClass{"SX"};

public:
   virtual ~RNTupleWriteOptionsDaos() = default;
   std::unique_ptr<RNTupleWriteOptions> Clone() const override
   { return std::make_unique<RNTupleWriteOptionsDaos>(*this); }

   const std::string &GetObjectClass() const { return fObjectClass; }
   /// Set the object class used to generate OIDs that relate to user data. Any
   /// `OC_xxx` constant defined in `daos_obj_class.h` may be used here without
   /// the OC_ prefix.
   void SetObjectClass(const std::string &val) { fObjectClass = val; }
};

// clang-format off
/**
\class ROOT::Experimental::RNTupleReadOptions
\ingroup NTuple
\brief Common user-tunable settings for reading ntuples

All page source classes need to support the common options.
*/
// clang-format on
class RNTupleReadOptions {
public:
   enum EClusterCache {
      kOff,
      kOn,
      kDefault = kOn,
   };

private:
   EClusterCache fClusterCache = EClusterCache::kDefault;

public:
   EClusterCache GetClusterCache() const { return fClusterCache; }
   void SetClusterCache(EClusterCache val) { fClusterCache = val; }
};

} // namespace Experimental
} // namespace ROOT

#endif
<commit_msg>[ntuple] Adjust cluster size tunables<commit_after>/// \file ROOT/RNTupleOptions.hxx
/// \ingroup NTuple ROOT7
/// \author Jakob Blomer <jblomer@cern.ch>
/// \date 2019-08-25
/// \warning This is part of the ROOT 7 prototype! It will change without notice. It might trigger earthquakes. Feedback
/// is welcome!

/*************************************************************************
 * Copyright (C) 1995-2019, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

#ifndef ROOT7_RNTupleOptions
#define ROOT7_RNTupleOptions

#include <Compression.h>
#include <ROOT/RError.hxx>
#include <ROOT/RNTupleUtil.hxx>

namespace ROOT {
namespace Experimental {

// clang-format off
/**
\class ROOT::Experimental::ENTupleContainerFormat
\ingroup NTuple
\brief Describes the options for wrapping RNTuple data in files
*/
// clang-format on
enum class ENTupleContainerFormat {
   kTFile, // ROOT TFile
   kBare, // A thin envelope supporting a single RNTuple only
};

// clang-format off
/**
\class ROOT::Experimental::RNTupleWriteOptions
\ingroup NTuple
\brief Common user-tunable settings for storing ntuples

All page sink classes need to support the common options.
*/
// clang-format on
class RNTupleWriteOptions {
   int fCompression{RCompressionSetting::EDefaults::kUseAnalysis};
   ENTupleContainerFormat fContainerFormat{ENTupleContainerFormat::kTFile};
   /// Approximation of the target compressed cluster size
   std::size_t fApproxZippedClusterSize = 50 * 1000 * 1000;
   /// Memory limit for committing a cluster: with very high compression ratio, we need a limit
   /// on how large the I/O buffer can grow during writing.
   std::size_t fMaxUnzippedClusterSize = 512 * 1024 * 1024;
   /// Should be just large enough so that the compression ratio does not benefit much more from larger pages
   std::size_t fMaxUnzippedPageSize = 64 * 1024;
   bool fUseBufferedWrite = true;

public:
   virtual ~RNTupleWriteOptions() = default;
   virtual std::unique_ptr<RNTupleWriteOptions> Clone() const
   { return std::make_unique<RNTupleWriteOptions>(*this); }

   int GetCompression() const { return fCompression; }
   void SetCompression(int val) { fCompression = val; }
   void SetCompression(RCompressionSetting::EAlgorithm algorithm, int compressionLevel) {
     fCompression = CompressionSettings(algorithm, compressionLevel);
   }

   ENTupleContainerFormat GetContainerFormat() const { return fContainerFormat; }
   void SetContainerFormat(ENTupleContainerFormat val) { fContainerFormat = val; }

   std::size_t GetApproxZippedClusterSize() const { return fApproxZippedClusterSize; }
   void SetApproxZippedClusterSize(std::size_t val) { fApproxZippedClusterSize = val; }

   std::size_t GetMaxUnzippedClusterSize() const { return fMaxUnzippedClusterSize; }
   void SetMaxUnzippedClusterSize(std::size_t val) { fMaxUnzippedClusterSize = val; }

   std::size_t GetMaxUnzippedPageSize() const { return fMaxUnzippedPageSize; }
   void SetMaxUnzippedPageSize(std::size_t val) {
      if (val < 64)
         throw RException(R__FAIL("page size too small"));
      fMaxUnzippedPageSize = val;
   }

   bool GetUseBufferedWrite() const { return fUseBufferedWrite; }
   void SetUseBufferedWrite(bool val) { fUseBufferedWrite = val; }
};

// clang-format off
/**
\class ROOT::Experimental::RNTupleWriteOptionsDaos
\ingroup NTuple
\brief DAOS-specific user-tunable settings for storing ntuples
*/
// clang-format on
class RNTupleWriteOptionsDaos : public RNTupleWriteOptions {
  std::string fObjectClass{"SX"};

public:
   virtual ~RNTupleWriteOptionsDaos() = default;
   std::unique_ptr<RNTupleWriteOptions> Clone() const override
   { return std::make_unique<RNTupleWriteOptionsDaos>(*this); }

   const std::string &GetObjectClass() const { return fObjectClass; }
   /// Set the object class used to generate OIDs that relate to user data. Any
   /// `OC_xxx` constant defined in `daos_obj_class.h` may be used here without
   /// the OC_ prefix.
   void SetObjectClass(const std::string &val) { fObjectClass = val; }
};

// clang-format off
/**
\class ROOT::Experimental::RNTupleReadOptions
\ingroup NTuple
\brief Common user-tunable settings for reading ntuples

All page source classes need to support the common options.
*/
// clang-format on
class RNTupleReadOptions {
public:
   enum EClusterCache {
      kOff,
      kOn,
      kDefault = kOn,
   };

private:
   EClusterCache fClusterCache = EClusterCache::kDefault;

public:
   EClusterCache GetClusterCache() const { return fClusterCache; }
   void SetClusterCache(EClusterCache val) { fClusterCache = val; }
};

} // namespace Experimental
} // namespace ROOT

#endif
<|endoftext|>


<commit_before>#ifndef ALPINO_CORPUSREADER_HH
#define ALPINO_CORPUSREADER_HH

#include <QSharedPointer>
#include <QString>
#include <QVector>

#include <AlpinoCorpus/DLLDefines.hh>

namespace alpinocorpus {

/**
 * Abstract base class for corpus readers.
 *
 * A corpus is conceptually a mapping of names to XML documents.
 * Both are represented as QStrings.
 */
class CorpusReader
{
  protected:
    // Iterator body. We need handle-body/proxy/pimpl for polymorphic copy.
    struct IterImpl {
        virtual QString const &current() const = 0;
        virtual bool equals(IterImpl const *) const = 0;
        virtual void next() = 0;
    };

  public:
    /** Iterator over entry names */
    class EntryIterator
        : public std::iterator<std::input_iterator_tag, QString>
    {
        QSharedPointer<IterImpl> impl;

      public:
        EntryIterator(IterImpl *p) : impl(p) { }
        EntryIterator(EntryIterator const &other) : impl(other.impl) { }
        EntryIterator &operator++() { impl->next(); return *this; }
        EntryIterator operator++(int)
        {
            EntryIterator r(*this);
            operator++();
            return r;
        }
        bool operator==(EntryIterator const &other)
        { return impl->equals(other.impl.data()); }
        bool operator!=(EntryIterator const &other)
        { return !operator==(other); }
        value_type const &operator*() const { return impl->current(); }
        //value_type const *operator->() const { return impl->current(); }
    };

    virtual ~CorpusReader() {}

    /** Return canonical name of corpus */
    virtual QString name() const = 0;

    /** Retrieve the names of all treebank entries. */
    virtual QVector<QString> entries() const = 0;

    /** Iterator to begin of entry names */
    virtual EntryIterator begin() const = 0;

    /** Iterator to end of entry names */
    virtual EntryIterator end() const = 0;

    /** Return content of a single treebank entry. */
    virtual QString read(QString const &entry) = 0;

    /** The number of entries in the corpus. */
    virtual size_t size() const = 0;

    /**
     * Factory method: open a corpus, determining its type automatically.
     * The caller is responsible for deleting the object returned.
     */
    static INDEXED_CORPUS_EXPORT CorpusReader *open(QString const &corpusPath);
};

}

#endif  // ALPINO_CORPUSREADER_HH
<commit_msg>Deprecate CorpusReader::entries()<commit_after>#ifndef ALPINO_CORPUSREADER_HH
#define ALPINO_CORPUSREADER_HH

#include <QSharedPointer>
#include <QString>
#include <QVector>

#include <AlpinoCorpus/DLLDefines.hh>

namespace alpinocorpus {

/**
 * Abstract base class for corpus readers.
 *
 * A corpus is conceptually a mapping of names to XML documents.
 * Both are represented as QStrings.
 */
class CorpusReader
{
  protected:
    // Iterator body. We need handle-body/proxy/pimpl for polymorphic copy.
    struct IterImpl {
        virtual QString const &current() const = 0;
        virtual bool equals(IterImpl const *) const = 0;
        virtual void next() = 0;
    };

  public:
    /** Iterator over entry names */
    class EntryIterator
        : public std::iterator<std::input_iterator_tag, QString>
    {
        QSharedPointer<IterImpl> impl;

      public:
        EntryIterator(IterImpl *p) : impl(p) { }
        EntryIterator(EntryIterator const &other) : impl(other.impl) { }
        EntryIterator &operator++() { impl->next(); return *this; }
        EntryIterator operator++(int)
        {
            EntryIterator r(*this);
            operator++();
            return r;
        }
        bool operator==(EntryIterator const &other)
        { return impl->equals(other.impl.data()); }
        bool operator!=(EntryIterator const &other)
        { return !operator==(other); }
        value_type const &operator*() const { return impl->current(); }
        //value_type const *operator->() const { return impl->current(); }
    };

    virtual ~CorpusReader() {}

    /** Return canonical name of corpus */
    virtual QString name() const = 0;

    /**
     * Retrieve the names of all treebank entries.
     * @deprecated Use the iterator interface instead.
     */
    virtual QVector<QString> entries() const = 0;

    /** Iterator to begin of entry names */
    virtual EntryIterator begin() const = 0;

    /** Iterator to end of entry names */
    virtual EntryIterator end() const = 0;

    /** Return content of a single treebank entry. */
    virtual QString read(QString const &entry) = 0;

    /** The number of entries in the corpus. */
    virtual size_t size() const = 0;

    /**
     * Factory method: open a corpus, determining its type automatically.
     * The caller is responsible for deleting the object returned.
     */
    static INDEXED_CORPUS_EXPORT CorpusReader *open(QString const &corpusPath);
};

}

#endif  // ALPINO_CORPUSREADER_HH
<|endoftext|>


<commit_before>// Copyright (C) 2015 Jérôme Leclercq
// This file is part of the "Nazara Engine - Network module"
// For conditions of distribution and use, see copyright notice in Config.hpp

#pragma once

#ifndef NAZARA_ALGORITHM_NETWORK_HPP
#define NAZARA_ALGORITHM_NETWORK_HPP

#include <Nazara/Prerequesites.hpp>
#include <functional>
#include <tuple>

namespace Nz
{
	bool ParseIPAddress(const char* addressPtr, UInt8 result[16], UInt16* port = nullptr, bool* isIPv6 = nullptr, const char** endOfRead = nullptr);
}

#include <Nazara/Network/Algorithm.inl>

#endif // NAZARA_ALGORITHM_NETWORK_HPP
<commit_msg>Network/Algorithm: Fix external linking<commit_after>// Copyright (C) 2015 Jérôme Leclercq
// This file is part of the "Nazara Engine - Network module"
// For conditions of distribution and use, see copyright notice in Config.hpp

#pragma once

#ifndef NAZARA_ALGORITHM_NETWORK_HPP
#define NAZARA_ALGORITHM_NETWORK_HPP

#include <Nazara/Prerequesites.hpp>
#include <Nazara/Network/Config.hpp>
#include <functional>
#include <tuple>

namespace Nz
{
	NAZARA_NETWORK_API bool ParseIPAddress(const char* addressPtr, UInt8 result[16], UInt16* port = nullptr, bool* isIPv6 = nullptr, const char** endOfRead = nullptr);
}

#include <Nazara/Network/Algorithm.inl>

#endif // NAZARA_ALGORITHM_NETWORK_HPP
<|endoftext|>


<commit_before>/** \file jsonv/detail/string_view.hpp
 *  The JsonVoorhees implementation of string_view. You should not include this directly; instead, prefer including
 *  \c jsonv/string_view.hpp and manipulating \c JSONV_STRING_REF_TYPE and \c JSONV_STRING_REF_INCLUDE.
 *
 *  Copyright (c) 2014 by Travis Gockel. All rights reserved.
 *
 *  This program is free software: you can redistribute it and/or modify it under the terms of the Apache License
 *  as published by the Apache Software Foundation, either version 2 of the License, or (at your option) any later
 *  version.
 *
 *  \author Travis Gockel (travis@gockelhut.com)
**/
#ifndef __JSONV_DETAIL_STRING_VIEW_HPP_INCLUDED__
#define __JSONV_DETAIL_STRING_VIEW_HPP_INCLUDED__

#include <jsonv/config.hpp>

#include <algorithm>
#include <cstddef>
#include <cstring>
#include <iterator>
#include <ostream>
#include <stdexcept>

namespace jsonv
{
namespace detail
{

class string_view
{
public:
    using value_type             = char;
    using pointer                = const value_type*;
    using reference              = const value_type&;
    using const_reference        = const value_type&;
    using iterator               = pointer;
    using const_iterator         = pointer;
    using reverse_iterator       = std::reverse_iterator<iterator>;
    using const_reverse_iterator = std::reverse_iterator<const_iterator>;
    using size_type              = std::size_t;
    using difference_type        = std::ptrdiff_t;

    static constexpr size_type npos = size_type(~0);

public:
    constexpr string_view() noexcept :
            _base(nullptr),
            _length(0)
    { }

    string_view(pointer p) noexcept :
            _base(p),
            _length(std::strlen(p))
    { }

    constexpr string_view(pointer p, size_type len) noexcept :
            _base(p),
            _length(len)
    { }

    template <typename UAllocator>
    string_view(const std::basic_string<value_type, std::char_traits<value_type>, UAllocator>& src)
                noexcept(noexcept(src.data()) && noexcept(src.length())):
            _base(src.data()),
            _length(src.length())
    { }

    string_view(const string_view&) noexcept = default;
    string_view& operator=(const string_view&) noexcept = default;

    template <typename UAllocator>
    explicit operator std::basic_string<value_type, std::char_traits<value_type>, UAllocator>() const
    {
        return std::basic_string<value_type, std::char_traits<value_type>, UAllocator>(_base, _length);
    }

    constexpr size_type size()     const noexcept { return _length; }
    constexpr size_type max_size() const noexcept { return _length; }
    constexpr size_type length()   const noexcept { return _length; }

    constexpr bool empty() const noexcept { return _length == 0; }

    constexpr const_reference operator[](size_type idx) const { return _base[idx]; }
    const_reference at(size_type idx) const
    {
        if (idx < _length)
            return _base[idx];
        else
            throw std::out_of_range("jsonv::string_view::at");
    }

    constexpr const_reference front() const { return _base[0]; }
    constexpr const_reference back()  const { return _base[_length - 1]; }

    constexpr pointer data() const { return _base; }

    constexpr const_iterator begin()  const { return _base; }
    constexpr const_iterator cbegin() const { return _base; }
    constexpr const_iterator end()    const { return _base + _length; }
    constexpr const_iterator cend()   const { return _base + _length; }

    const_reverse_iterator rbegin()  const { return const_reverse_iterator(end()); }
    const_reverse_iterator crbegin() const { return const_reverse_iterator(end()); }
    const_reverse_iterator rend()    const { return const_reverse_iterator(begin()); }
    const_reverse_iterator crend()   const { return const_reverse_iterator(begin()); }

    void clear()
    {
        _base = nullptr;
        _length = 0;
    }

    void remove_prefix(size_type n)
    {
        if (n <= _length)
        {
            _base += n;
            _length -= n;
        }
        else
        {
            throw std::range_error("jsonv::string_view::remove_prefix");
        }
    }

    void remove_suffix(size_type n)
    {
        if (n <= _length)
        {
            _length -= n;
        }
        else
        {
            throw std::range_error("jsonv::string_view::remove_prefix");
        }
    }

    string_view substr(size_type idx, size_type count = npos) const
    {
        count = count == npos ? (_length - idx) : count;
        if (idx + count <= _length)
            return string_view(_base + idx, count);
        else
            throw std::range_error("jsonv::string_view::substr");
    }

    bool starts_with(value_type val) const
    {
        return !empty() && front() == val;
    }

    bool starts_with(const string_view& sub) const
    {
        return sub.length() <= length() && std::equal(sub.begin(), sub.end(), begin());
    }

    bool ends_with(value_type val) const
    {
        return !empty() && back() == val;
    }

    bool ends_with(const string_view& sub) const
    {
        return sub.length() <= length() && std::equal(sub.rbegin(), sub.rend(), rbegin());
    }

    size_type find(const string_view& sub) const
    {
        auto iter = std::search(begin(), end(), sub.begin(), sub.end());
        return iter == end() ? npos : std::distance(begin(), iter);
    }

    size_type find(value_type val) const
    {
        auto iter = std::find(begin(), end(), val);
        return iter == end() ? npos : std::distance(begin(), iter);
    }

    size_type rfind(const string_view& sub) const
    {
        auto iter = std::search(rbegin(), rend(), sub.rbegin(), sub.rend());
        return iter == rend() ? npos : std::distance(iter, rend());
    }

    size_type rfind(value_type val) const
    {
        auto iter = std::find(rbegin(), rend(), val);
        return iter == rend() ? npos : std::distance(iter, rend());
    }

    size_type find_first_of(value_type val) const
    {
        return find(val);
    }

    size_type find_first_of(const string_view& chars) const
    {
        auto iter = std::find_first_of(begin(), end(), chars.begin(), chars.end());
        return iter == end() ? npos : std::distance(begin(), iter);
    }

    size_type find_first_not_of(value_type val) const
    {
        auto iter = std::find_if(begin(), end(), [val] (value_type x) { return val != x; });
        return iter == end() ? npos : std::distance(begin(), iter);
    }

    size_type find_first_not_of(const string_view& chars) const
    {
        auto iter = std::find_if(begin(), end(),
                                 [&chars] (value_type x)
                                 {
                                     return chars.find(x) == npos;
                                 }
                                );
        return iter == end() ? npos : std::distance(begin(), iter);
    }

    size_type find_last_of(value_type val) const
    {
        return rfind(val);
    }

    size_type find_last_of(const string_view& chars) const
    {
        auto iter = std::find_first_of(rbegin(), rend(), chars.begin(), chars.end());
        return iter == rend() ? npos : std::distance(iter, rend());
    }

    size_type find_last_not_of(value_type val) const
    {
        auto iter = std::find_if(rbegin(), rend(), [val] (value_type x) { return val != x; });
        return iter == rend() ? npos : std::distance(iter, rend());
    }

    size_type find_last_not_of(const string_view& chars) const
    {
        auto iter = std::find_if(rbegin(), rend(),
                                 [&chars] (value_type x)
                                 {
                                     return chars.find(x) == npos;
                                 }
                                );
        return iter == rend() ? npos : std::distance(iter, rend());
    }

    bool operator==(const string_view& other) const
    {
        return _length == other._length
            && (_base == other._base || std::equal(begin(), end(), other.begin()));
    }

    bool operator!=(const string_view& other) const
    {
        return _length != other._length
            || (_base != other._base && std::mismatch(begin(), end(), other.begin()).first == end());
    }

    bool operator<(const string_view& other) const
    {
        return std::lexicographical_compare(begin(), end(), other.begin(), other.end());
    }

    bool operator<=(const string_view& other) const
    {
        return !(other < *this);
    }

    bool operator>(const string_view& other) const
    {
        return other < *this;
    }

    bool operator>=(const string_view& other) const
    {
        return !(*this < other);
    }

    friend std::ostream& operator<<(std::ostream& os, const string_view& self)
    {
        os.write(self.begin(), self.size());
        return os;
    }

private:
    pointer   _base;
    size_type _length;
};

}
}

#endif/*__JSONV_DETAIL_STRING_VIEW_HPP_INCLUDED__*/
<commit_msg>Adds a bit of documentation to string_view.<commit_after>/** \file jsonv/detail/string_view.hpp
 *  The JsonVoorhees implementation of string_view. You should not include this directly; instead, prefer including
 *  \c jsonv/string_view.hpp and manipulating \c JSONV_STRING_REF_TYPE and \c JSONV_STRING_REF_INCLUDE.
 *
 *  Copyright (c) 2014 by Travis Gockel. All rights reserved.
 *
 *  This program is free software: you can redistribute it and/or modify it under the terms of the Apache License
 *  as published by the Apache Software Foundation, either version 2 of the License, or (at your option) any later
 *  version.
 *
 *  \author Travis Gockel (travis@gockelhut.com)
**/
#ifndef __JSONV_DETAIL_STRING_VIEW_HPP_INCLUDED__
#define __JSONV_DETAIL_STRING_VIEW_HPP_INCLUDED__

#include <jsonv/config.hpp>

#include <algorithm>
#include <cstddef>
#include <cstring>
#include <iterator>
#include <ostream>
#include <stdexcept>

namespace jsonv
{
namespace detail
{

/** A non-owning reference to an \c std::string, as proposed to the C++ Standard Committee by Jeffrey Yasskin in N3921
 *  (http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n3921.html). Unlike the one proposed, this is not templated
 *  over the \c char type, as this project only deals with UTF-8 encoded strings.
**/
class string_view
{
public:
    using value_type             = char;
    using pointer                = const value_type*;
    using reference              = const value_type&;
    using const_reference        = const value_type&;
    using iterator               = pointer;
    using const_iterator         = pointer;
    using reverse_iterator       = std::reverse_iterator<iterator>;
    using const_reverse_iterator = std::reverse_iterator<const_iterator>;
    using size_type              = std::size_t;
    using difference_type        = std::ptrdiff_t;

    static constexpr size_type npos = size_type(~0);

public:
    constexpr string_view() noexcept :
            _base(nullptr),
            _length(0)
    { }

    string_view(pointer p) noexcept :
            _base(p),
            _length(std::strlen(p))
    { }

    constexpr string_view(pointer p, size_type len) noexcept :
            _base(p),
            _length(len)
    { }

    template <typename UAllocator>
    string_view(const std::basic_string<value_type, std::char_traits<value_type>, UAllocator>& src)
                noexcept(noexcept(src.data()) && noexcept(src.length())):
            _base(src.data()),
            _length(src.length())
    { }

    string_view(const string_view&) noexcept = default;
    string_view& operator=(const string_view&) noexcept = default;

    template <typename UAllocator>
    explicit operator std::basic_string<value_type, std::char_traits<value_type>, UAllocator>() const
    {
        return std::basic_string<value_type, std::char_traits<value_type>, UAllocator>(_base, _length);
    }

    constexpr size_type size()     const noexcept { return _length; }
    constexpr size_type max_size() const noexcept { return _length; }
    constexpr size_type length()   const noexcept { return _length; }

    constexpr bool empty() const noexcept { return _length == 0; }

    constexpr const_reference operator[](size_type idx) const { return _base[idx]; }
    const_reference at(size_type idx) const
    {
        if (idx < _length)
            return _base[idx];
        else
            throw std::out_of_range("jsonv::string_view::at");
    }

    constexpr const_reference front() const { return _base[0]; }
    constexpr const_reference back()  const { return _base[_length - 1]; }

    constexpr pointer data() const { return _base; }

    constexpr const_iterator begin()  const { return _base; }
    constexpr const_iterator cbegin() const { return _base; }
    constexpr const_iterator end()    const { return _base + _length; }
    constexpr const_iterator cend()   const { return _base + _length; }

    const_reverse_iterator rbegin()  const { return const_reverse_iterator(end()); }
    const_reverse_iterator crbegin() const { return const_reverse_iterator(end()); }
    const_reverse_iterator rend()    const { return const_reverse_iterator(begin()); }
    const_reverse_iterator crend()   const { return const_reverse_iterator(begin()); }

    void clear()
    {
        _base = nullptr;
        _length = 0;
    }

    void remove_prefix(size_type n)
    {
        if (n <= _length)
        {
            _base += n;
            _length -= n;
        }
        else
        {
            throw std::range_error("jsonv::string_view::remove_prefix");
        }
    }

    void remove_suffix(size_type n)
    {
        if (n <= _length)
        {
            _length -= n;
        }
        else
        {
            throw std::range_error("jsonv::string_view::remove_prefix");
        }
    }

    string_view substr(size_type idx, size_type count = npos) const
    {
        count = count == npos ? (_length - idx) : count;
        if (idx + count <= _length)
            return string_view(_base + idx, count);
        else
            throw std::range_error("jsonv::string_view::substr");
    }

    bool starts_with(value_type val) const
    {
        return !empty() && front() == val;
    }

    bool starts_with(const string_view& sub) const
    {
        return sub.length() <= length() && std::equal(sub.begin(), sub.end(), begin());
    }

    bool ends_with(value_type val) const
    {
        return !empty() && back() == val;
    }

    bool ends_with(const string_view& sub) const
    {
        return sub.length() <= length() && std::equal(sub.rbegin(), sub.rend(), rbegin());
    }

    size_type find(const string_view& sub) const
    {
        auto iter = std::search(begin(), end(), sub.begin(), sub.end());
        return iter == end() ? npos : std::distance(begin(), iter);
    }

    size_type find(value_type val) const
    {
        auto iter = std::find(begin(), end(), val);
        return iter == end() ? npos : std::distance(begin(), iter);
    }

    size_type rfind(const string_view& sub) const
    {
        auto iter = std::search(rbegin(), rend(), sub.rbegin(), sub.rend());
        return iter == rend() ? npos : std::distance(iter, rend());
    }

    size_type rfind(value_type val) const
    {
        auto iter = std::find(rbegin(), rend(), val);
        return iter == rend() ? npos : std::distance(iter, rend());
    }

    size_type find_first_of(value_type val) const
    {
        return find(val);
    }

    size_type find_first_of(const string_view& chars) const
    {
        auto iter = std::find_first_of(begin(), end(), chars.begin(), chars.end());
        return iter == end() ? npos : std::distance(begin(), iter);
    }

    size_type find_first_not_of(value_type val) const
    {
        auto iter = std::find_if(begin(), end(), [val] (value_type x) { return val != x; });
        return iter == end() ? npos : std::distance(begin(), iter);
    }

    size_type find_first_not_of(const string_view& chars) const
    {
        auto iter = std::find_if(begin(), end(),
                                 [&chars] (value_type x)
                                 {
                                     return chars.find(x) == npos;
                                 }
                                );
        return iter == end() ? npos : std::distance(begin(), iter);
    }

    size_type find_last_of(value_type val) const
    {
        return rfind(val);
    }

    size_type find_last_of(const string_view& chars) const
    {
        auto iter = std::find_first_of(rbegin(), rend(), chars.begin(), chars.end());
        return iter == rend() ? npos : std::distance(iter, rend());
    }

    size_type find_last_not_of(value_type val) const
    {
        auto iter = std::find_if(rbegin(), rend(), [val] (value_type x) { return val != x; });
        return iter == rend() ? npos : std::distance(iter, rend());
    }

    size_type find_last_not_of(const string_view& chars) const
    {
        auto iter = std::find_if(rbegin(), rend(),
                                 [&chars] (value_type x)
                                 {
                                     return chars.find(x) == npos;
                                 }
                                );
        return iter == rend() ? npos : std::distance(iter, rend());
    }

    bool operator==(const string_view& other) const
    {
        return _length == other._length
            && (_base == other._base || std::equal(begin(), end(), other.begin()));
    }

    bool operator!=(const string_view& other) const
    {
        return _length != other._length
            || (_base != other._base && std::mismatch(begin(), end(), other.begin()).first == end());
    }

    bool operator<(const string_view& other) const
    {
        return std::lexicographical_compare(begin(), end(), other.begin(), other.end());
    }

    bool operator<=(const string_view& other) const
    {
        return !(other < *this);
    }

    bool operator>(const string_view& other) const
    {
        return other < *this;
    }

    bool operator>=(const string_view& other) const
    {
        return !(*this < other);
    }

    friend std::ostream& operator<<(std::ostream& os, const string_view& self)
    {
        os.write(self.begin(), self.size());
        return os;
    }

private:
    pointer   _base;
    size_type _length;
};

}
}

#endif/*__JSONV_DETAIL_STRING_VIEW_HPP_INCLUDED__*/
<|endoftext|>


<commit_before>/**
 * @author: Jeff Thompson
 * See COPYING for copyright and distribution information.
 */

#include <sstream>
#include "common.hpp"

using namespace std;

namespace ndn {

string toHex(const vector<unsigned char>& array)
{
  ostringstream result;
  result.flags(ios::hex | ios::uppercase);
  for (unsigned int i = 0; i < array.size(); ++i) {
    unsigned char x = array[i];
    if (x < 16)
      result << '0';
    result << (unsigned int)x;
  }

  return result.str();
}

}

<commit_msg>In toHex, if argument is null, return "".<commit_after>/**
 * @author: Jeff Thompson
 * See COPYING for copyright and distribution information.
 */

#include <sstream>
#include "common.hpp"

using namespace std;

namespace ndn {

string toHex(const vector<unsigned char>& array)
{
  if (!&array)
    return "";

  ostringstream result;
  result.flags(ios::hex | ios::uppercase);
  for (unsigned int i = 0; i < array.size(); ++i) {
    unsigned char x = array[i];
    if (x < 16)
      result << '0';
    result << (unsigned int)x;
  }

  return result.str();
}

}

<|endoftext|>


<commit_before>#ifndef MOS_RENDERER_H
#define MOS_RENDERER_H

#include <GL/glew.h>
#include <experimental/optional>
#include <initializer_list>
#include <unordered_map>
#include <array>
#include <mos/render/render_scene.hpp>
#include <mos/render/texture_2d.hpp>
#include <mos/render/texture_cube.hpp>
#include <mos/render/model.hpp>
#include <mos/render/text.hpp>
#include <mos/render/particles.hpp>
#include <mos/render/light.hpp>
#include <mos/render/render_target.hpp>
#include <mos/render/render_camera.hpp>
#include <mos/render/environment_light.hpp>
#include <mos/render/fog.hpp>
#include <mos/render/render_box.hpp>
#include <mos/render/decal.hpp>
#include "texture.hpp"

namespace mos {

/**
 * @brief Render geometry.
 * Talks to OpenGL, and renders Model objects.
 */
class RenderSystem {
public:
  /**
   * @brief Renderer constructor.
   * Inits the renderer, in this implementation also creates a
   * valid OpenGL context with GLEW.
   */
  RenderSystem(const glm::vec4 &color = glm::vec4(.0f));
  /**
   * @brief Renderer destructor.
   * Deletes all allocated GPU memory. Textures, Shaders, Buffers.
   */
  ~RenderSystem();

  /**
   * @brief load a model into renderers own memory.
   * @param model
   */
  void load(const Model &model);

  /**
   * @brief unload a model from renderers own memory.
   * @param model
   */
  void unload(const Model &model);

  /**
   * @brief Load a texture into renderer memory.
   * @param texture The texture.
   */
  void load(const SharedTexture2D &texture);

  void load(const Texture2D &texture);

  /**
   * @brief unload a texture from renderer memory.
   * @param texture The texture.
   */
  void unload(const SharedTexture2D &texture);

  /**
   * @brief unload a texture from renderer memory.
   * @param texture The texture.
   */
  void unload(const SharedTextureCube &texture);

  void render_scenes(const std::initializer_list<RenderScene> &scenes_init,
                     const glm::vec4 &color = glm::vec4(.0f),
                     const glm::ivec2 &resolution = glm::ivec2(128, 128));

  template<class Ts>
  void render_scenes(Ts scenes_begin,
                     Ts scenes_end,
                     const glm::vec4 &color = {.0f, .0f, .0f, 1.0f},
                     const glm::ivec2 &resolution = glm::ivec2(128, 128)) {
    clear(color);
    for (auto it = scenes_begin; it != scenes_end; it++) {
      render_shadow_map(*it);
      //TODO: Render if no data in environment texture.
      render_environment(*it);
      render_scene(it->camera, *it, resolution);
    }
  }

  /**
   * @brief Clear all internal buffers.
   */
  void clear_buffers();

  /*
   * For multisampled render target
  void render_target_reset(unsigned int width, unsigned int height) {
    glBindFramebuffer(GL_READ_FRAMEBUFFER, readFBO);
    glBindFramebuffer(GL_DRAW_FRAMEBUFFER, drawFBO);
    glBlitFramebuffer(0, 0, width, height, 0, 0, width, height,
                      GL_COLOR_BUFFER_BIT, GL_NEAREST);
    glBindFramebuffer(GL_FRAMEBUFFER, 0);
  }
  */

private:
   /**
   * @brief models_batch rendering.
   * @param render_scene
   */
  void render_scene(const RenderCamera &camera, const RenderScene &render_scene, const glm::vec2 &resolution);

  void render_shadow_map(const RenderScene &render_scene);

  void render_environment(const RenderScene &render_scene);

  /**
   * @brief Updates render state of model.
   * @param model
   * @param transform Additional transform matrix.
   * @param view View matrix of the camera
   * @param projection Projection matrix of the camera
   * @param program_name Either "text" or "standard"
   * @param light One dynamic light to use.
   */
  void render(const Model &model,
              const RenderScene::Decals &decals,
              const glm::mat4 &transform,
              const RenderCamera &camera,
              const Light &light,
              const EnvironmentLight &environment,
              const Fog &fog,
              const glm::vec2 &resolution,
              const RenderScene::Shader &shader,
              const RenderScene::Draw &draw);

  /**
   * @brief render_target
   * @param target
   */
  void render_target(const RenderTarget &target);

  /**
   * @brief clear
   * @param color
   */
  void clear(const glm::vec4 &color);

  /**
   * @brief The ParticleProgramData struct, uniforms for the particle shader
   * program.
   */
  struct ParticleProgramData {
    GLuint program;
    GLint mvp;
    GLint mv;
    GLint p;
    GLint texture;
    GLint resolution;
  };

  /**
   * @brief The BoxProgramData struct, uniforms for the bounding box shader
   * program.
   */
  struct BoxProgramData {
    GLuint program;
    GLint mvp;
    GLint mv;
  };

  struct DepthProgramData {
    GLuint program;
    GLint mvp;
  };

  /**
   * @brief The VertexProgramData struct, uniforms for the standard shader.
   */
  class VertexProgramData {
  public:
    //TODO make all const
    VertexProgramData() {};
    VertexProgramData(const GLuint program);
    GLuint program;
    GLint model_view_projection_matrix;
    GLint model_view_matrix;
    GLint model_matrix;
    GLint view_matrix;
    GLint normal_matrix;
    GLint depth_bias_mvp;

    std::array<GLint, 10> decal_mvps;
    std::array<GLint, 10> decal_material_diffuse_maps;
    std::array<GLint, 10> decal_material_normal_maps;

    GLint environment_map;
    GLint environment_position;
    GLint environment_extent;
    GLint environment_strength;

    GLint material_albedo_map;
    GLint material_light_map;
    GLint material_normal_map;
    GLint material_metallic_map;
    GLint material_roughness_map;
    GLint material_ambient_occlusion_map;
    GLint material_albedo;
    GLint material_roughness;
    GLint material_metallic;
    GLint material_opacity;
    GLint material_emission;

    GLint camera_resolution;
    GLint camera_position;

    GLint light_position;
    GLint light_color;
    GLint light_view;
    GLint light_projection;
    GLint light_shadow_map;
    GLint light_angle;
    GLint light_direction;

    GLint fog_color_near;
    GLint fog_color_far;
    GLint fog_attenuation_factor;

    GLint brdf_lut;
  };

  using VertexProgramPair = std::pair<RenderScene::Shader, VertexProgramData>;
  using ParticleProgramPair = std::pair<std::string, ParticleProgramData>;
  using BoxProgramPair = std::pair<std::string, BoxProgramData>;

  void add_vertex_program(const RenderScene::Shader shader,
                          const std::string vertex_shader_source,
                          const std::string fragment_shader_source,
                          const std::string &vert_file_name = "",
                          const std::string &frag_file_name = "");

  void add_particle_program(const std::string name, const std::string vs_source,
                            const std::string fs_source, const std::string &vs_file = "",
                            const std::string &fs_file = "");

  unsigned int create_shader(const std::string &source,
                             const unsigned int type);
  bool check_shader(const unsigned int shader, const std::string &name = "");

  bool check_program(const unsigned int program);

  unsigned int create_texture(const SharedTexture2D &texture);
  unsigned int create_texture(const Texture2D &texture);

  unsigned int create_texture_cube(const TextureCube &texture);

  unsigned int
  create_texture_and_pbo(const SharedTexture2D &texture);
  void add_box_program(const std::string &name, const std::string &vs_source,
                       const std::string &fs_source, const std::string &vs_file,
                       const std::string &fs_file);

  void create_depth_program();

  std::map<RenderScene::Shader, VertexProgramData> vertex_programs_;
  std::unordered_map<std::string, ParticleProgramData> particle_programs_;
  std::unordered_map<std::string, BoxProgramData> box_programs_;
  DepthProgramData depth_program_;

  std::unordered_map<unsigned int, GLuint> frame_buffers_;
  std::unordered_map<unsigned int, GLuint> render_buffers;
  std::unordered_map<unsigned int, GLuint> pixel_buffers_;
  std::unordered_map<unsigned int, GLuint> textures_;
  std::unordered_map<unsigned int, GLuint> texture_cubes_;
  std::unordered_map<unsigned int, GLuint> array_buffers_;
  std::unordered_map<unsigned int, GLuint> element_array_buffers_;
  std::unordered_map<unsigned int, GLuint> vertex_arrays_;

  GLuint black_texture_;
  GLuint white_texture_;
  GLuint brdf_lut_texture_;
  GLuint box_vbo;
  GLuint box_ebo;
  GLuint box_va;

  struct FormatPair{
    GLuint internal_format;
    GLuint format;
  };
  //TODO: Static though, be aware initialization problem.
  std::map<Texture::Wrap, GLuint> wrap_map_;
  std::map<Texture::Format, FormatPair> format_map_;
};

}
#endif /* MOS_RENDERER_H */
<commit_msg>Check<commit_after>#ifndef MOS_RENDERER_H
#define MOS_RENDERER_H

#include <GL/glew.h>
#include <experimental/optional>
#include <initializer_list>
#include <unordered_map>
#include <array>
#include <mos/render/render_scene.hpp>
#include <mos/render/texture_2d.hpp>
#include <mos/render/texture_cube.hpp>
#include <mos/render/model.hpp>
#include <mos/render/text.hpp>
#include <mos/render/particles.hpp>
#include <mos/render/light.hpp>
#include <mos/render/render_target.hpp>
#include <mos/render/render_camera.hpp>
#include <mos/render/environment_light.hpp>
#include <mos/render/fog.hpp>
#include <mos/render/render_box.hpp>
#include <mos/render/decal.hpp>
#include "texture.hpp"

namespace mos {

/**
 * @brief Render geometry.
 * Talks to OpenGL, and renders Model objects.
 */
class RenderSystem {
public:
  /**
   * @brief Renderer constructor.
   * Inits the renderer, in this implementation also creates a
   * valid OpenGL context with GLEW.
   */
  RenderSystem(const glm::vec4 &color = glm::vec4(.0f));
  /**
   * @brief Renderer destructor.
   * Deletes all allocated GPU memory. Textures, Shaders, Buffers.
   */
  ~RenderSystem();

  /**
   * @brief load a model into renderers own memory.
   * @param model
   */
  void load(const Model &model);

  /**
   * @brief unload a model from renderers own memory.
   * @param model
   */
  void unload(const Model &model);

  /**
   * @brief Load a texture into renderer memory.
   * @param texture The texture.
   */
  void load(const SharedTexture2D &texture);

  void load(const Texture2D &texture);

  /**
   * @brief unload a texture from renderer memory.
   * @param texture The texture.
   */
  void unload(const SharedTexture2D &texture);

  /**
   * @brief unload a texture from renderer memory.
   * @param texture The texture.
   */
  void unload(const SharedTextureCube &texture);

  void render_scenes(const std::initializer_list<RenderScene> &scenes_init,
                     const glm::vec4 &color = glm::vec4(.0f),
                     const glm::ivec2 &resolution = glm::ivec2(128, 128));

  template<class Ts>
  void render_scenes(Ts scenes_begin,
                     Ts scenes_end,
                     const glm::vec4 &color = {.0f, .0f, .0f, 1.0f},
                     const glm::ivec2 &resolution = glm::ivec2(128, 128)) {
    clear(color);
    for (auto it = scenes_begin; it != scenes_end; it++) {
      render_shadow_map(*it);
      render_environment(*it);
      render_scene(it->camera, *it, resolution);
    }
  }

  /**
   * @brief Clear all internal buffers.
   */
  void clear_buffers();

  /*
   * For multisampled render target
  void render_target_reset(unsigned int width, unsigned int height) {
    glBindFramebuffer(GL_READ_FRAMEBUFFER, readFBO);
    glBindFramebuffer(GL_DRAW_FRAMEBUFFER, drawFBO);
    glBlitFramebuffer(0, 0, width, height, 0, 0, width, height,
                      GL_COLOR_BUFFER_BIT, GL_NEAREST);
    glBindFramebuffer(GL_FRAMEBUFFER, 0);
  }
  */

private:
   /**
   * @brief models_batch rendering.
   * @param render_scene
   */
  void render_scene(const RenderCamera &camera, const RenderScene &render_scene, const glm::vec2 &resolution);

  void render_shadow_map(const RenderScene &render_scene);

  void render_environment(const RenderScene &render_scene);

  /**
   * @brief Updates render state of model.
   * @param model
   * @param transform Additional transform matrix.
   * @param view View matrix of the camera
   * @param projection Projection matrix of the camera
   * @param program_name Either "text" or "standard"
   * @param light One dynamic light to use.
   */
  void render(const Model &model,
              const RenderScene::Decals &decals,
              const glm::mat4 &transform,
              const RenderCamera &camera,
              const Light &light,
              const EnvironmentLight &environment,
              const Fog &fog,
              const glm::vec2 &resolution,
              const RenderScene::Shader &shader,
              const RenderScene::Draw &draw);

  /**
   * @brief render_target
   * @param target
   */
  void render_target(const RenderTarget &target);

  /**
   * @brief clear
   * @param color
   */
  void clear(const glm::vec4 &color);

  /**
   * @brief The ParticleProgramData struct, uniforms for the particle shader
   * program.
   */
  struct ParticleProgramData {
    GLuint program;
    GLint mvp;
    GLint mv;
    GLint p;
    GLint texture;
    GLint resolution;
  };

  /**
   * @brief The BoxProgramData struct, uniforms for the bounding box shader
   * program.
   */
  struct BoxProgramData {
    GLuint program;
    GLint mvp;
    GLint mv;
  };

  struct DepthProgramData {
    GLuint program;
    GLint mvp;
  };

  /**
   * @brief The VertexProgramData struct, uniforms for the standard shader.
   */
  class VertexProgramData {
  public:
    //TODO make all const
    VertexProgramData() {};
    VertexProgramData(const GLuint program);
    GLuint program;
    GLint model_view_projection_matrix;
    GLint model_view_matrix;
    GLint model_matrix;
    GLint view_matrix;
    GLint normal_matrix;
    GLint depth_bias_mvp;

    std::array<GLint, 10> decal_mvps;
    std::array<GLint, 10> decal_material_diffuse_maps;
    std::array<GLint, 10> decal_material_normal_maps;

    GLint environment_map;
    GLint environment_position;
    GLint environment_extent;
    GLint environment_strength;

    GLint material_albedo_map;
    GLint material_light_map;
    GLint material_normal_map;
    GLint material_metallic_map;
    GLint material_roughness_map;
    GLint material_ambient_occlusion_map;
    GLint material_albedo;
    GLint material_roughness;
    GLint material_metallic;
    GLint material_opacity;
    GLint material_emission;

    GLint camera_resolution;
    GLint camera_position;

    GLint light_position;
    GLint light_color;
    GLint light_view;
    GLint light_projection;
    GLint light_shadow_map;
    GLint light_angle;
    GLint light_direction;

    GLint fog_color_near;
    GLint fog_color_far;
    GLint fog_attenuation_factor;

    GLint brdf_lut;
  };

  using VertexProgramPair = std::pair<RenderScene::Shader, VertexProgramData>;
  using ParticleProgramPair = std::pair<std::string, ParticleProgramData>;
  using BoxProgramPair = std::pair<std::string, BoxProgramData>;

  void add_vertex_program(const RenderScene::Shader shader,
                          const std::string vertex_shader_source,
                          const std::string fragment_shader_source,
                          const std::string &vert_file_name = "",
                          const std::string &frag_file_name = "");

  void add_particle_program(const std::string name, const std::string vs_source,
                            const std::string fs_source, const std::string &vs_file = "",
                            const std::string &fs_file = "");

  unsigned int create_shader(const std::string &source,
                             const unsigned int type);
  bool check_shader(const unsigned int shader, const std::string &name = "");

  bool check_program(const unsigned int program);

  unsigned int create_texture(const SharedTexture2D &texture);
  unsigned int create_texture(const Texture2D &texture);

  unsigned int create_texture_cube(const TextureCube &texture);

  unsigned int
  create_texture_and_pbo(const SharedTexture2D &texture);
  void add_box_program(const std::string &name, const std::string &vs_source,
                       const std::string &fs_source, const std::string &vs_file,
                       const std::string &fs_file);

  void create_depth_program();

  std::map<RenderScene::Shader, VertexProgramData> vertex_programs_;
  std::unordered_map<std::string, ParticleProgramData> particle_programs_;
  std::unordered_map<std::string, BoxProgramData> box_programs_;
  DepthProgramData depth_program_;

  std::unordered_map<unsigned int, GLuint> frame_buffers_;
  std::unordered_map<unsigned int, GLuint> render_buffers;
  std::unordered_map<unsigned int, GLuint> pixel_buffers_;
  std::unordered_map<unsigned int, GLuint> textures_;
  std::unordered_map<unsigned int, GLuint> texture_cubes_;
  std::unordered_map<unsigned int, GLuint> array_buffers_;
  std::unordered_map<unsigned int, GLuint> element_array_buffers_;
  std::unordered_map<unsigned int, GLuint> vertex_arrays_;

  GLuint black_texture_;
  GLuint white_texture_;
  GLuint brdf_lut_texture_;
  GLuint box_vbo;
  GLuint box_ebo;
  GLuint box_va;

  struct FormatPair{
    GLuint internal_format;
    GLuint format;
  };
  //TODO: Static though, be aware initialization problem.
  std::map<Texture::Wrap, GLuint> wrap_map_;
  std::map<Texture::Format, FormatPair> format_map_;
};

}
#endif /* MOS_RENDERER_H */
<|endoftext|>


<commit_before>#include "../../async/task_queue.hpp"

#include <chrono>

using namespace std::chrono;
using namespace std::chrono_literals;

namespace stx {

// =============================================================
// == task_queue =============================================
// =============================================================

void task_queue::defer(std::function<void()> task, float priority) noexcept {
	std::scoped_lock lock{m_mutex};

	m_tasks.emplace(priority, std::move(task));
}

void task_queue::execute_tasks() noexcept {
	std::multimap<float, std::function<void()>> tasks;
	while(m_tasks.size()) {
		// Get tasks
		{ std::scoped_lock lock{m_mutex};
			std::swap(m_tasks, tasks);
		}

		// Execute tasks
		for(auto& [prio, task] : tasks) {
			// Move task out of queue and execute
			std::function<void()>(std::move(task))();
		}

		// Clear executed tasks
		tasks.clear();
	}
}

void task_queue::start() noexcept {
	// TODO
}

// =============================================================
// == task_queue_mt =============================================
// =============================================================

task_queue_mt::task_queue_mt() noexcept :
	m_finish(false)
{}
task_queue_mt::~task_queue_mt() noexcept {
	stop();
}

void task_queue_mt::defer(std::function<void()> fn, float prio) noexcept {
	{ std::scoped_lock lock{m_mutex};
		m_tasks.emplace(prio, std::move(fn));
	}
	m_sleeping_threads.notify_one();
}
void task_queue_mt::execute_tasks() noexcept {
	++m_num_threads;

	std::function<void()> task;

	while(true) {
		std::unique_lock lock{m_mutex};

		// See if we have a task
		if(m_tasks.empty()) break;

		// Get the task
		task = std::move(m_tasks.begin()->second);
		m_tasks.erase(m_tasks.begin());

		// Execute the task
		task();
	}

	--m_num_threads;
}
void task_queue_mt::start() noexcept {
	m_finish = false;

	++m_num_threads;

	std::function<void()> task;

	while(true) {
		std::unique_lock lock{m_mutex};

		// Wait until we have a task
		if(m_tasks.empty()) {
			m_sleeping_threads.wait(lock, [this]() { return m_finish || !m_tasks.empty(); });
			if(m_tasks.empty() && m_finish) break;
		}

		// Get the task
		task = std::move(m_tasks.begin()->second);
		m_tasks.erase(m_tasks.begin());

		// Execute the task
		task();
	}

	--m_num_threads;
}
void task_queue_mt::stop() noexcept {
	m_finish = true;

	m_sleeping_threads.notify_all(); // Wake up all threads, so they can be joined
	execute_tasks(); // Execute all pending tasks
	while(m_num_threads > 0); // Spin until all threads are finished
}

} // namespace stx
<commit_msg>Fixed missing atomic initialization causing hangups<commit_after>#include "../../async/task_queue.hpp"

#include <chrono>

using namespace std::chrono;
using namespace std::chrono_literals;

namespace stx {

// =============================================================
// == task_queue =============================================
// =============================================================

void task_queue::defer(std::function<void()> task, float priority) noexcept {
	std::scoped_lock lock{m_mutex};

	m_tasks.emplace(priority, std::move(task));
}

void task_queue::execute_tasks() noexcept {
	std::multimap<float, std::function<void()>> tasks;
	while(m_tasks.size()) {
		// Get tasks
		{ std::scoped_lock lock{m_mutex};
			std::swap(m_tasks, tasks);
		}

		// Execute tasks
		for(auto& [prio, task] : tasks) {
			// Move task out of queue and execute
			std::function<void()>(std::move(task))();
		}

		// Clear executed tasks
		tasks.clear();
	}
}

void task_queue::start() noexcept {
	// TODO
}

// =============================================================
// == task_queue_mt =============================================
// =============================================================

task_queue_mt::task_queue_mt() noexcept :
	m_finish(false),
	m_num_threads(0)
{}
task_queue_mt::~task_queue_mt() noexcept {
	stop();
}

void task_queue_mt::defer(std::function<void()> fn, float prio) noexcept {
	{ std::scoped_lock lock{m_mutex};
		m_tasks.emplace(prio, std::move(fn));
	}
	m_sleeping_threads.notify_one();
}
void task_queue_mt::execute_tasks() noexcept {
	++m_num_threads;

	std::function<void()> task;

	while(true) {
		std::unique_lock lock{m_mutex};

		// See if we have a task
		if(m_tasks.empty()) break;

		// Get the task
		task = std::move(m_tasks.begin()->second);
		m_tasks.erase(m_tasks.begin());

		// Execute the task
		task();
	}

	--m_num_threads;
}
void task_queue_mt::start() noexcept {
	m_finish = false;

	++m_num_threads;

	std::function<void()> task;

	while(true) {
		std::unique_lock lock{m_mutex};

		// Wait until we have a task
		if(m_tasks.empty()) {
			m_sleeping_threads.wait(lock, [this]() { return m_finish || !m_tasks.empty(); });
			if(m_tasks.empty() && m_finish) break;
		}

		// Get the task
		task = std::move(m_tasks.begin()->second);
		m_tasks.erase(m_tasks.begin());

		// Execute the task
		task();
	}

	--m_num_threads;
}
void task_queue_mt::stop() noexcept {
	m_finish = true;

	m_sleeping_threads.notify_all(); // Wake up all threads, so they can be joined
	execute_tasks(); // Execute all pending tasks
	while(m_num_threads > 0); // Spin until all threads are finished
}

} // namespace stx
<|endoftext|>