<commit_before>// Copyright 2015-2019 Elviss Strazdins. All rights reserved.

#include "core/Setup.h"

#if OUZEL_COMPILE_DIRECTSOUND

#include <system_error>
#include "DSAudioDevice.hpp"
#include "core/Engine.hpp"
#include "core/Window.hpp"

#ifndef WAVE_FORMAT_IEEE_FLOAT
#  define WAVE_FORMAT_IEEE_FLOAT 0x0003
#endif

namespace
{
    BOOL CALLBACK enumCallback(LPGUID, LPCWSTR description, LPCWSTR, LPVOID)
    {
        int bufferSize = WideCharToMultiByte(CP_UTF8, 0, description, -1, nullptr, 0, nullptr, nullptr);
        if (bufferSize != 0)
        {
            std::vector<char> buffer(bufferSize);
            if (WideCharToMultiByte(CP_UTF8, 0, description, -1, buffer.data(), bufferSize, nullptr, nullptr) != 0)
                ouzel::engine->log(ouzel::Log::Level::Info) << "Using " << buffer.data() << " for audio";
        }
        return FALSE;
    }
}

namespace ouzel
{
    namespace audio
    {
        namespace directsound
        {
            namespace
            {
                class ErrorCategory final: public std::error_category
                {
                public:
                    const char* name() const noexcept final
                    {
                        return "DirectSound";
                    }

                    std::string message(int condition) const final
                    {
                        switch (condition)
                        {
                            case DSERR_ACCESSDENIED: return "DSERR_ACCESSDENIED";
                            case DSERR_ALLOCATED: return "DSERR_ALLOCATED";
                            case DSERR_ALREADYINITIALIZED: return "DSERR_ALREADYINITIALIZED";
                            case DSERR_BADFORMAT: return "DSERR_BADFORMAT";
                            case DSERR_BADSENDBUFFERGUID: return "DSERR_BADSENDBUFFERGUID";
                            case DSERR_BUFFERLOST: return "DSERR_BUFFERLOST";
                            case DSERR_BUFFERTOOSMALL: return "DSERR_BUFFERTOOSMALL";
                            case DSERR_CONTROLUNAVAIL: return "DSERR_CONTROLUNAVAIL";
                            case DSERR_DS8_REQUIRED: return "DSERR_DS8_REQUIRED";
                            case DSERR_FXUNAVAILABLE: return "DSERR_FXUNAVAILABLE";
                            case DSERR_GENERIC: return "DSERR_GENERIC";
                            case DSERR_INVALIDCALL: return "DSERR_INVALIDCALL";
                            case DSERR_INVALIDPARAM: return "DSERR_INVALIDPARAM";
                            case DSERR_NOAGGREGATION: return "DSERR_NOAGGREGATION";
                            case DSERR_NODRIVER: return "DSERR_NODRIVER";
                            case DSERR_NOINTERFACE: return "DSERR_NOINTERFACE";
                            case DSERR_OBJECTNOTFOUND: return "DSERR_OBJECTNOTFOUND";
                            case DSERR_OTHERAPPHASPRIO: return "DSERR_OTHERAPPHASPRIO";
                            case DSERR_OUTOFMEMORY: return "DSERR_OUTOFMEMORY";
                            case DSERR_PRIOLEVELNEEDED: return "DSERR_PRIOLEVELNEEDED";
                            case DSERR_SENDLOOP: return "DSERR_SENDLOOP";
                            case DSERR_UNINITIALIZED: return "DSERR_UNINITIALIZED";
                            case DSERR_UNSUPPORTED: return "DSERR_UNSUPPORTED";
                            default: return "Unknown error (" + std::to_string(condition) + ")";
                        }
                    }
                };

                const ErrorCategory errorCategory {};
            }

            AudioDevice::AudioDevice(uint32_t initBufferSize,
                                     uint32_t initSampleRate,
                                     uint32_t initChannels,
                                     const std::function<void(uint32_t frames,
                                                              uint32_t channels,
                                                              uint32_t sampleRate,
                                                              std::vector<float>& samples)>& initDataGetter):
                audio::AudioDevice(Driver::DirectSound, initBufferSize, initSampleRate, initChannels, initDataGetter)
            {
                HRESULT hr;
                if (FAILED(hr = DirectSoundEnumerateW(enumCallback, this)))
                    throw std::system_error(hr, errorCategory, "Failed to enumerate DirectSound 8 devices");

                IDirectSound8* directSoundPointer;
                if (FAILED(hr = DirectSoundCreate8(&DSDEVID_DefaultPlayback, &directSoundPointer, nullptr)))
                    throw std::system_error(hr, errorCategory, "Failed to create DirectSound 8 instance");

                directSound = directSoundPointer;

                if (FAILED(hr = directSound->SetCooperativeLevel(GetDesktopWindow(), DSSCL_PRIORITY)))
                    throw std::system_error(hr, errorCategory, "Failed to set cooperative level for DirectSound 8");

                DSBUFFERDESC primaryBufferDesc;
                primaryBufferDesc.dwSize = sizeof(primaryBufferDesc);
                primaryBufferDesc.dwFlags = DSBCAPS_PRIMARYBUFFER | DSBCAPS_CTRLVOLUME;
                primaryBufferDesc.dwBufferBytes = 0;
                primaryBufferDesc.dwReserved = 0;
                primaryBufferDesc.lpwfxFormat = nullptr;
                primaryBufferDesc.guid3DAlgorithm = GUID_NULL;

                IDirectSoundBuffer* primaryBufferPointer;
                if (FAILED(hr = directSound->CreateSoundBuffer(&primaryBufferDesc, &primaryBufferPointer, nullptr)))
                    throw std::system_error(hr, errorCategory, "Failed to create DirectSound buffer");

                primaryBuffer = primaryBufferPointer;

                WAVEFORMATEX waveFormat;
                waveFormat.wFormatTag = WAVE_FORMAT_IEEE_FLOAT;
                waveFormat.nChannels = static_cast<WORD>(channels);
                waveFormat.nSamplesPerSec = sampleRate;
                waveFormat.wBitsPerSample = sizeof(float) * 8;
                waveFormat.nBlockAlign = waveFormat.nChannels * (waveFormat.wBitsPerSample / 8);
                waveFormat.nAvgBytesPerSec = waveFormat.nSamplesPerSec * waveFormat.nBlockAlign;
                waveFormat.cbSize = 0;

                sampleFormat = SampleFormat::Float32;
                sampleSize = sizeof(float);

                if (FAILED(hr = primaryBuffer->SetFormat(&waveFormat)))
                {
                    waveFormat.wFormatTag = WAVE_FORMAT_PCM;
                    waveFormat.wBitsPerSample = sizeof(int16_t) * 8;
                    waveFormat.nBlockAlign = waveFormat.nChannels * (waveFormat.wBitsPerSample / 8);
                    waveFormat.nAvgBytesPerSec = waveFormat.nSamplesPerSec * waveFormat.nBlockAlign;

                    if (FAILED(hr = primaryBuffer->SetFormat(&waveFormat)))
                        throw std::system_error(hr, errorCategory, "Failed to set DirectSound buffer format");

                    sampleFormat = SampleFormat::SignedInt16;
                    sampleSize = sizeof(int16_t);
                }

                DSBUFFERDESC bufferDesc;
                bufferDesc.dwSize = sizeof(bufferDesc);
                bufferDesc.dwFlags = DSBCAPS_CTRLVOLUME | DSBCAPS_CTRLPOSITIONNOTIFY;
                bufferDesc.dwBufferBytes = 2 * bufferSize;
                bufferDesc.dwReserved = 0;
                bufferDesc.lpwfxFormat = &waveFormat;
                bufferDesc.guid3DAlgorithm = GUID_NULL;

                IDirectSoundBuffer* tempBufferPointer;
                if (FAILED(hr = directSound->CreateSoundBuffer(&bufferDesc, &tempBufferPointer, nullptr)))
                    throw std::system_error(hr, errorCategory, "Failed to create DirectSound buffer");

                Pointer<IDirectSoundBuffer> tempBuffer = tempBufferPointer;

                void* bufferPointer;
                if (FAILED(hr = tempBuffer->QueryInterface(IID_IDirectSoundBuffer8, &bufferPointer)))
                    throw std::system_error(hr, errorCategory, "Failed to create DirectSound buffer");

                buffer = static_cast<IDirectSoundBuffer8*>(bufferPointer);

                void* notifyPointer;
                if (FAILED(hr = tempBuffer->QueryInterface(IID_IDirectSoundNotify, &notifyPointer)))
                    throw std::system_error(hr, errorCategory, "Failed to get DirectSound notify interface");

                notify = static_cast<IDirectSoundNotify*>(notifyPointer);

                uint8_t* bufferDataPointer;
                DWORD lockedBufferSize;
                if (FAILED(hr = buffer->Lock(0, bufferDesc.dwBufferBytes, reinterpret_cast<void**>(&bufferDataPointer), &lockedBufferSize, nullptr, 0, 0)))
                    throw std::system_error(hr, errorCategory, "Failed to lock DirectSound buffer");

                getData(lockedBufferSize / (channels * sizeof(int16_t)), data);
                std::copy(data.begin(), data.end(), bufferDataPointer);

                if (FAILED(hr = buffer->Unlock(bufferDataPointer, lockedBufferSize, nullptr, 0)))
                    throw std::system_error(hr, errorCategory, "Failed to unlock DirectSound buffer");

                nextBuffer = 0;

                notifyEvents[0] = CreateEvent(nullptr, false, false, nullptr);
                if (!notifyEvents[0])
                    throw std::system_error(GetLastError(), std::system_category(), "Failed to create event");

                notifyEvents[1] = CreateEvent(nullptr, false, false, nullptr);
                if (!notifyEvents[1])
                    throw std::system_error(GetLastError(), std::system_category(), "Failed to create event");

                DSBPOSITIONNOTIFY positionNotifyEvents[2];
                positionNotifyEvents[0].dwOffset = bufferSize - 1;
                positionNotifyEvents[0].hEventNotify = notifyEvents[0];

                positionNotifyEvents[1].dwOffset = 2 * bufferSize - 1;
                positionNotifyEvents[1].hEventNotify = notifyEvents[1];

                if (FAILED(hr = notify->SetNotificationPositions(2, positionNotifyEvents)))
                    throw std::system_error(hr, errorCategory, "Failed to set DirectSound notification positions");
            }

            AudioDevice::~AudioDevice()
            {
                running = false;
                for (HANDLE notifyEvent : notifyEvents)
                    if (notifyEvent) SetEvent(notifyEvent);

                if (audioThread.isJoinable()) audioThread.join();

                for (HANDLE notifyEvent : notifyEvents)
                    if (notifyEvent) CloseHandle(notifyEvent);
            }

            void AudioDevice::start()
            {
                HRESULT hr;
                if (FAILED(hr = buffer->Play(0, 0, DSBPLAY_LOOPING)))
                    throw std::system_error(hr, errorCategory, "Failed to play DirectSound buffer");

                running = true;
                audioThread = Thread(&AudioDevice::run, this);
            }

            void AudioDevice::stop()
            {
                running = false;
                if (audioThread.isJoinable()) audioThread.join();

                HRESULT hr;
                if (FAILED(hr = buffer->Stop()))
                    throw std::system_error(hr, errorCategory, "Failed to stop DirectSound buffer");
            }

            void AudioDevice::run()
            {
                Thread::setCurrentThreadName("Audio");

                while (running)
                {
                    try
                    {
                        DWORD result;
                        if ((result = WaitForSingleObject(notifyEvents[nextBuffer], INFINITE)) == WAIT_FAILED)
                            throw std::system_error(GetLastError(), std::system_category(), "Failed to wait for event");

                        if (result == WAIT_OBJECT_0)
                        {
                            if (!running) break;

                            uint8_t* bufferDataPointer;
                            DWORD lockedBufferSize;
                            HRESULT hr;
                            if (FAILED(hr = buffer->Lock(nextBuffer * bufferSize, bufferSize, reinterpret_cast<void**>(&bufferDataPointer), &lockedBufferSize, nullptr, 0, 0)))
                                throw std::system_error(hr, errorCategory, "Failed to lock DirectSound buffer");

                            getData(lockedBufferSize / (sampleSize * channels), data);

                            std::copy(data.begin(), data.end(), bufferDataPointer);

                            if (FAILED(hr = buffer->Unlock(bufferDataPointer, lockedBufferSize, nullptr, 0)))
                                throw std::system_error(hr, errorCategory, "Failed to unlock DirectSound buffer");

                            nextBuffer = (nextBuffer + 1) % 2;
                        }
                    }
                    catch (const std::exception& e)
                    {
                        engine->log(Log::Level::Error) << e.what();
                    }
                }
            }
        } // namespace directsound
    } // namespace audio
} // namespace ouzel

#endif
<commit_msg>Get rid of reinterpret_cast in DSAudioDevice<commit_after>// Copyright 2015-2019 Elviss Strazdins. All rights reserved.

#include "core/Setup.h"

#if OUZEL_COMPILE_DIRECTSOUND

#include <system_error>
#include "DSAudioDevice.hpp"
#include "core/Engine.hpp"
#include "core/Window.hpp"

#ifndef WAVE_FORMAT_IEEE_FLOAT
#  define WAVE_FORMAT_IEEE_FLOAT 0x0003
#endif

namespace
{
    BOOL CALLBACK enumCallback(LPGUID, LPCWSTR description, LPCWSTR, LPVOID)
    {
        int bufferSize = WideCharToMultiByte(CP_UTF8, 0, description, -1, nullptr, 0, nullptr, nullptr);
        if (bufferSize != 0)
        {
            std::vector<char> buffer(bufferSize);
            if (WideCharToMultiByte(CP_UTF8, 0, description, -1, buffer.data(), bufferSize, nullptr, nullptr) != 0)
                ouzel::engine->log(ouzel::Log::Level::Info) << "Using " << buffer.data() << " for audio";
        }
        return FALSE;
    }
}

namespace ouzel
{
    namespace audio
    {
        namespace directsound
        {
            namespace
            {
                class ErrorCategory final: public std::error_category
                {
                public:
                    const char* name() const noexcept final
                    {
                        return "DirectSound";
                    }

                    std::string message(int condition) const final
                    {
                        switch (condition)
                        {
                            case DSERR_ACCESSDENIED: return "DSERR_ACCESSDENIED";
                            case DSERR_ALLOCATED: return "DSERR_ALLOCATED";
                            case DSERR_ALREADYINITIALIZED: return "DSERR_ALREADYINITIALIZED";
                            case DSERR_BADFORMAT: return "DSERR_BADFORMAT";
                            case DSERR_BADSENDBUFFERGUID: return "DSERR_BADSENDBUFFERGUID";
                            case DSERR_BUFFERLOST: return "DSERR_BUFFERLOST";
                            case DSERR_BUFFERTOOSMALL: return "DSERR_BUFFERTOOSMALL";
                            case DSERR_CONTROLUNAVAIL: return "DSERR_CONTROLUNAVAIL";
                            case DSERR_DS8_REQUIRED: return "DSERR_DS8_REQUIRED";
                            case DSERR_FXUNAVAILABLE: return "DSERR_FXUNAVAILABLE";
                            case DSERR_GENERIC: return "DSERR_GENERIC";
                            case DSERR_INVALIDCALL: return "DSERR_INVALIDCALL";
                            case DSERR_INVALIDPARAM: return "DSERR_INVALIDPARAM";
                            case DSERR_NOAGGREGATION: return "DSERR_NOAGGREGATION";
                            case DSERR_NODRIVER: return "DSERR_NODRIVER";
                            case DSERR_NOINTERFACE: return "DSERR_NOINTERFACE";
                            case DSERR_OBJECTNOTFOUND: return "DSERR_OBJECTNOTFOUND";
                            case DSERR_OTHERAPPHASPRIO: return "DSERR_OTHERAPPHASPRIO";
                            case DSERR_OUTOFMEMORY: return "DSERR_OUTOFMEMORY";
                            case DSERR_PRIOLEVELNEEDED: return "DSERR_PRIOLEVELNEEDED";
                            case DSERR_SENDLOOP: return "DSERR_SENDLOOP";
                            case DSERR_UNINITIALIZED: return "DSERR_UNINITIALIZED";
                            case DSERR_UNSUPPORTED: return "DSERR_UNSUPPORTED";
                            default: return "Unknown error (" + std::to_string(condition) + ")";
                        }
                    }
                };

                const ErrorCategory errorCategory {};
            }

            AudioDevice::AudioDevice(uint32_t initBufferSize,
                                     uint32_t initSampleRate,
                                     uint32_t initChannels,
                                     const std::function<void(uint32_t frames,
                                                              uint32_t channels,
                                                              uint32_t sampleRate,
                                                              std::vector<float>& samples)>& initDataGetter):
                audio::AudioDevice(Driver::DirectSound, initBufferSize, initSampleRate, initChannels, initDataGetter)
            {
                HRESULT hr;
                if (FAILED(hr = DirectSoundEnumerateW(enumCallback, this)))
                    throw std::system_error(hr, errorCategory, "Failed to enumerate DirectSound 8 devices");

                IDirectSound8* directSoundPointer;
                if (FAILED(hr = DirectSoundCreate8(&DSDEVID_DefaultPlayback, &directSoundPointer, nullptr)))
                    throw std::system_error(hr, errorCategory, "Failed to create DirectSound 8 instance");

                directSound = directSoundPointer;

                if (FAILED(hr = directSound->SetCooperativeLevel(GetDesktopWindow(), DSSCL_PRIORITY)))
                    throw std::system_error(hr, errorCategory, "Failed to set cooperative level for DirectSound 8");

                DSBUFFERDESC primaryBufferDesc;
                primaryBufferDesc.dwSize = sizeof(primaryBufferDesc);
                primaryBufferDesc.dwFlags = DSBCAPS_PRIMARYBUFFER | DSBCAPS_CTRLVOLUME;
                primaryBufferDesc.dwBufferBytes = 0;
                primaryBufferDesc.dwReserved = 0;
                primaryBufferDesc.lpwfxFormat = nullptr;
                primaryBufferDesc.guid3DAlgorithm = GUID_NULL;

                IDirectSoundBuffer* primaryBufferPointer;
                if (FAILED(hr = directSound->CreateSoundBuffer(&primaryBufferDesc, &primaryBufferPointer, nullptr)))
                    throw std::system_error(hr, errorCategory, "Failed to create DirectSound buffer");

                primaryBuffer = primaryBufferPointer;

                WAVEFORMATEX waveFormat;
                waveFormat.wFormatTag = WAVE_FORMAT_IEEE_FLOAT;
                waveFormat.nChannels = static_cast<WORD>(channels);
                waveFormat.nSamplesPerSec = sampleRate;
                waveFormat.wBitsPerSample = sizeof(float) * 8;
                waveFormat.nBlockAlign = waveFormat.nChannels * (waveFormat.wBitsPerSample / 8);
                waveFormat.nAvgBytesPerSec = waveFormat.nSamplesPerSec * waveFormat.nBlockAlign;
                waveFormat.cbSize = 0;

                sampleFormat = SampleFormat::Float32;
                sampleSize = sizeof(float);

                if (FAILED(hr = primaryBuffer->SetFormat(&waveFormat)))
                {
                    waveFormat.wFormatTag = WAVE_FORMAT_PCM;
                    waveFormat.wBitsPerSample = sizeof(int16_t) * 8;
                    waveFormat.nBlockAlign = waveFormat.nChannels * (waveFormat.wBitsPerSample / 8);
                    waveFormat.nAvgBytesPerSec = waveFormat.nSamplesPerSec * waveFormat.nBlockAlign;

                    if (FAILED(hr = primaryBuffer->SetFormat(&waveFormat)))
                        throw std::system_error(hr, errorCategory, "Failed to set DirectSound buffer format");

                    sampleFormat = SampleFormat::SignedInt16;
                    sampleSize = sizeof(int16_t);
                }

                DSBUFFERDESC bufferDesc;
                bufferDesc.dwSize = sizeof(bufferDesc);
                bufferDesc.dwFlags = DSBCAPS_CTRLVOLUME | DSBCAPS_CTRLPOSITIONNOTIFY;
                bufferDesc.dwBufferBytes = 2 * bufferSize;
                bufferDesc.dwReserved = 0;
                bufferDesc.lpwfxFormat = &waveFormat;
                bufferDesc.guid3DAlgorithm = GUID_NULL;

                IDirectSoundBuffer* tempBufferPointer;
                if (FAILED(hr = directSound->CreateSoundBuffer(&bufferDesc, &tempBufferPointer, nullptr)))
                    throw std::system_error(hr, errorCategory, "Failed to create DirectSound buffer");

                Pointer<IDirectSoundBuffer> tempBuffer = tempBufferPointer;

                void* bufferPointer;
                if (FAILED(hr = tempBuffer->QueryInterface(IID_IDirectSoundBuffer8, &bufferPointer)))
                    throw std::system_error(hr, errorCategory, "Failed to create DirectSound buffer");

                buffer = static_cast<IDirectSoundBuffer8*>(bufferPointer);

                void* notifyPointer;
                if (FAILED(hr = tempBuffer->QueryInterface(IID_IDirectSoundNotify, &notifyPointer)))
                    throw std::system_error(hr, errorCategory, "Failed to get DirectSound notify interface");

                notify = static_cast<IDirectSoundNotify*>(notifyPointer);

                void* bufferDataPointer;
                DWORD lockedBufferSize;
                if (FAILED(hr = buffer->Lock(0, bufferDesc.dwBufferBytes, &bufferDataPointer, &lockedBufferSize, nullptr, 0, 0)))
                    throw std::system_error(hr, errorCategory, "Failed to lock DirectSound buffer");

                uint8_t* bufferData = static_cast<uint8_t*>(bufferDataPointer);

                getData(lockedBufferSize / (channels * sizeof(int16_t)), data);
                std::copy(data.begin(), data.end(), bufferData);

                if (FAILED(hr = buffer->Unlock(bufferDataPointer, lockedBufferSize, nullptr, 0)))
                    throw std::system_error(hr, errorCategory, "Failed to unlock DirectSound buffer");

                nextBuffer = 0;

                notifyEvents[0] = CreateEvent(nullptr, false, false, nullptr);
                if (!notifyEvents[0])
                    throw std::system_error(GetLastError(), std::system_category(), "Failed to create event");

                notifyEvents[1] = CreateEvent(nullptr, false, false, nullptr);
                if (!notifyEvents[1])
                    throw std::system_error(GetLastError(), std::system_category(), "Failed to create event");

                DSBPOSITIONNOTIFY positionNotifyEvents[2];
                positionNotifyEvents[0].dwOffset = bufferSize - 1;
                positionNotifyEvents[0].hEventNotify = notifyEvents[0];

                positionNotifyEvents[1].dwOffset = 2 * bufferSize - 1;
                positionNotifyEvents[1].hEventNotify = notifyEvents[1];

                if (FAILED(hr = notify->SetNotificationPositions(2, positionNotifyEvents)))
                    throw std::system_error(hr, errorCategory, "Failed to set DirectSound notification positions");
            }

            AudioDevice::~AudioDevice()
            {
                running = false;
                for (HANDLE notifyEvent : notifyEvents)
                    if (notifyEvent) SetEvent(notifyEvent);

                if (audioThread.isJoinable()) audioThread.join();

                for (HANDLE notifyEvent : notifyEvents)
                    if (notifyEvent) CloseHandle(notifyEvent);
            }

            void AudioDevice::start()
            {
                HRESULT hr;
                if (FAILED(hr = buffer->Play(0, 0, DSBPLAY_LOOPING)))
                    throw std::system_error(hr, errorCategory, "Failed to play DirectSound buffer");

                running = true;
                audioThread = Thread(&AudioDevice::run, this);
            }

            void AudioDevice::stop()
            {
                running = false;
                if (audioThread.isJoinable()) audioThread.join();

                HRESULT hr;
                if (FAILED(hr = buffer->Stop()))
                    throw std::system_error(hr, errorCategory, "Failed to stop DirectSound buffer");
            }

            void AudioDevice::run()
            {
                Thread::setCurrentThreadName("Audio");

                while (running)
                {
                    try
                    {
                        DWORD result;
                        if ((result = WaitForSingleObject(notifyEvents[nextBuffer], INFINITE)) == WAIT_FAILED)
                            throw std::system_error(GetLastError(), std::system_category(), "Failed to wait for event");

                        if (result == WAIT_OBJECT_0)
                        {
                            if (!running) break;

                            void* bufferDataPointer;
                            DWORD lockedBufferSize;
                            HRESULT hr;
                            if (FAILED(hr = buffer->Lock(nextBuffer * bufferSize, bufferSize, &bufferDataPointer, &lockedBufferSize, nullptr, 0, 0)))
                                throw std::system_error(hr, errorCategory, "Failed to lock DirectSound buffer");

                            uint8_t* bufferData = static_cast<uint8_t*>(bufferDataPointer);

                            getData(lockedBufferSize / (sampleSize * channels), data);

                            std::copy(data.begin(), data.end(), bufferData);

                            if (FAILED(hr = buffer->Unlock(bufferDataPointer, lockedBufferSize, nullptr, 0)))
                                throw std::system_error(hr, errorCategory, "Failed to unlock DirectSound buffer");

                            nextBuffer = (nextBuffer + 1) % 2;
                        }
                    }
                    catch (const std::exception& e)
                    {
                        engine->log(Log::Level::Error) << e.what();
                    }
                }
            }
        } // namespace directsound
    } // namespace audio
} // namespace ouzel

#endif
<|endoftext|>


<commit_before>#include "catch.hpp"

#include <lua.hpp>
#include <luwra.hpp>

#include <memory>

struct A {
	int a;

	A() {}
};

TEST_CASE("usertypes_local_state") {
	lua_State* state = luaL_newstate();

	REQUIRE(luwra::internal::user_type_id<A> == (void*) INTPTR_MAX);

	luwra::register_user_type<A>(state, {});
	REQUIRE(luwra::internal::user_type_id<A> != (void*) INTPTR_MAX);

	A* instance = new A;
	luwra::Value<A*>::push(state, instance);

	REQUIRE(luwra::internal::get_user_type_id(state, -1) == luwra::internal::user_type_id<A>);
	REQUIRE(luwra::internal::check_user_type<A>(state, -1) == instance);

	lua_close(state);
}

struct B {
	int prop;

	int increment(int x) {
		return prop += x;
	}

	B* add(const B* other) {
		return new B {prop + other->prop};
	}
};

TEST_CASE("usertypes_lua_usage") {
	lua_State* state = luaL_newstate();
	luwra::register_user_type<B>(
		state,
		{
			{"increment", luwra::wrap_method<B, int(int), &B::increment>},
			{"prop", luwra::wrap_property<B, int, &B::prop>}
		},
		{
			{"__add", luwra::wrap_method<B, B*(const B*), &B::add>}
		}
	);

	B* value = new B {1337};
	luwra::register_global(state, "value", value);

	REQUIRE(luaL_dostring(state, "return value:prop()") == 0);
	REQUIRE(luwra::Value<int>::read(state, -1) == value->prop);

	REQUIRE(luaL_dostring(state, "value:prop(7331)") == 0);
	REQUIRE(value->prop == 7331);

	REQUIRE(luaL_dostring(state, "value:increment(-7329)") == 0);
	REQUIRE(value->prop == 2);

	REQUIRE(luaL_dostring(state, "return value + value") == 0);
	REQUIRE(luwra::Value<B*>::read(state, -1)->prop == 4);

	lua_close(state);
}

TEST_CASE("usertypes_gchook_tref") {
	lua_State* state = luaL_newstate();
	luwra::register_user_type<std::shared_ptr<int>>(state, {});

	std::shared_ptr<int> shared_var = std::make_shared<int>(1337);
	REQUIRE(shared_var.use_count() == 1);

	luwra::Value<std::shared_ptr<int>&>::push(state, shared_var);
	REQUIRE(shared_var.use_count() == 2);

	lua_close(state);
	REQUIRE(shared_var.use_count() == 1);
}

TEST_CASE("usertypes_gchook_tptr") {
	lua_State* state = luaL_newstate();
	luwra::register_user_type<std::shared_ptr<int>>(state, {});

	std::shared_ptr<int> shared_var = std::make_shared<int>(1337);
	REQUIRE(shared_var.use_count() == 1);

	luwra::Value<std::shared_ptr<int>*>::push(state, &shared_var);
	REQUIRE(shared_var.use_count() == 1);

	lua_close(state);
	REQUIRE(shared_var.use_count() == 1);
}
<commit_msg>tests: Use const qualifier in tests<commit_after>#include "catch.hpp"

#include <lua.hpp>
#include <luwra.hpp>

#include <memory>

struct A {
	int a;

	A() {}
};

TEST_CASE("usertypes_local_state") {
	lua_State* state = luaL_newstate();

	REQUIRE(luwra::internal::user_type_id<A> == (void*) INTPTR_MAX);

	luwra::register_user_type<A>(state, {});
	REQUIRE(luwra::internal::user_type_id<A> != (void*) INTPTR_MAX);

	A* instance = new A;
	luwra::Value<A*>::push(state, instance);

	REQUIRE(luwra::internal::get_user_type_id(state, -1) == luwra::internal::user_type_id<A>);
	REQUIRE(luwra::internal::check_user_type<A>(state, -1) == instance);

	lua_close(state);
}

struct B {
	int prop;

	int increment(int x) {
		return prop += x;
	}

	B* add(const B* other) const {
		return new B {prop + other->prop};
	}
};

TEST_CASE("usertypes_lua_usage") {
	lua_State* state = luaL_newstate();
	luwra::register_user_type<B>(
		state,
		{
			{"increment", luwra::wrap_method<B, int(int), &B::increment>},
			{"prop", luwra::wrap_property<B, int, &B::prop>}
		},
		{
			{"__add", luwra::wrap_method<const B, B*(const B*), &B::add>}
		}
	);

	B* value = new B {1337};
	luwra::register_global(state, "value", value);

	REQUIRE(luaL_dostring(state, "return value:prop()") == 0);
	REQUIRE(luwra::Value<int>::read(state, -1) == value->prop);

	REQUIRE(luaL_dostring(state, "value:prop(7331)") == 0);
	REQUIRE(value->prop == 7331);

	REQUIRE(luaL_dostring(state, "value:increment(-7329)") == 0);
	REQUIRE(value->prop == 2);

	REQUIRE(luaL_dostring(state, "return value + value") == 0);
	REQUIRE(luwra::Value<B*>::read(state, -1)->prop == 4);

	lua_close(state);
}

TEST_CASE("usertypes_gchook_tref") {
	lua_State* state = luaL_newstate();
	luwra::register_user_type<std::shared_ptr<int>>(state, {});

	std::shared_ptr<int> shared_var = std::make_shared<int>(1337);
	REQUIRE(shared_var.use_count() == 1);

	luwra::Value<std::shared_ptr<int>&>::push(state, shared_var);
	REQUIRE(shared_var.use_count() == 2);

	lua_close(state);
	REQUIRE(shared_var.use_count() == 1);
}

TEST_CASE("usertypes_gchook_tptr") {
	lua_State* state = luaL_newstate();
	luwra::register_user_type<std::shared_ptr<int>>(state, {});

	std::shared_ptr<int> shared_var = std::make_shared<int>(1337);
	REQUIRE(shared_var.use_count() == 1);

	luwra::Value<std::shared_ptr<int>*>::push(state, &shared_var);
	REQUIRE(shared_var.use_count() == 1);

	lua_close(state);
	REQUIRE(shared_var.use_count() == 1);
}
<|endoftext|>


<commit_before>#include <iostream>
#include <string>
#include <cstdint>
#include <cstdlib>
#include <vector>
#include <algorithm>
using namespace std;
static const string kStub =
  "/* O_O Generator by Hugh Wang. http://github.com/hghwng/O_O */\n"
  "#include \"stdio.h\"\n"
  "#define o_O +\n"
  "#define O_o <<\n"
  "#define o (\n"
  "#define O )\n"
  "#define oo if\n"
  "#define oO int\n"
  "#define Oo char\n"
  "#define OO return\n"
  "#define _ 1\n"
  "#define __ o _ O_o _ O\n"
  "#define ___ o __ O_o _ O\n"
  "#define ooo oo (OoO == -_) OO 0; }\n"
  "#define o_o oO main o oO OoO, Oo **Ooo O {\n"
  "#define O_O(OOO, OOOO, OOOOO) oo o OOO == OoO O fputc o OOOO, stdout O , main o OOOOO , 0 O ;\n";

int encode_by_sum(size_t v, string &ret) {
  if (v == 0) {
    ret = "0";
    return 0;
  }
  int num_parts = 0;

  string s;
  while (v) {
    if (num_parts++) s += " o_O ";

    for (;;) {
      auto r = rand() % 3;
      switch (r) {
        case 0: // 1
          s += "_";
          v -= 1;
          goto exit;
        case 1: // 2
          if (v < 2) break;
          s += "__";
          v -= 2;
          goto exit;
        case 2: // 4
          if (v < 4) break;
          s += "___";
          v -= 4;
          goto exit;
      }
    }
  }

exit:
  if (num_parts == 1) {
    ret = s;
  } else {
    ret = "o " + s + " O";
  }

  return num_parts;
}

void encode_part(size_t lhs_val, size_t rhs_val, string &part_str) {
  string lhs_str, rhs_str;
  int lhs_part = encode_by_sum(lhs_val, lhs_str);
  int rhs_part = encode_by_sum(rhs_val, rhs_str);

  if (lhs_part == 0) {
    // 0 << x -> nothing, ""
    part_str.clear();
  }

  if (rhs_part == 0) {
    // lhs << 0 -> "lhs"
    part_str = lhs_str;
  } else {
    // lhs << rhs -> "lhs << rhs"
    part_str = "o " + lhs_str + " O_o " + rhs_str + " O";
  }
}

string encode_num(size_t v) {
  // x = ((a + b + c + d) << (e + f)) + (x << y)
  size_t prev_bits = 0;
  size_t cur_bits;
  int part_num = 0;
  string s;

  for (auto t = v; t; prev_bits += cur_bits) {
    int r = rand();
    cur_bits = r % 3 + 1; // 1 to 4
    size_t mask = (1 << cur_bits) - 1;

    string part_str;
    encode_part(t & mask, prev_bits, part_str);
    if (part_num++) s += " o_O ";
    s += part_str;

    t >>= cur_bits;
  }

  return s;
}

string encode_string(string s) {
  string ret;
  size_t size = s.size();

  // random cond value
  vector<size_t> cond_vals;
  cond_vals.resize(size);
  cond_vals[0] = rand() % 10 + 2; // >= 2
  for (size_t i = 1; i < size; ++i) {
    cond_vals[i] = cond_vals[i - 1] + rand() % 10 + 1;
  }
  random_shuffle(cond_vals.begin(), cond_vals.end());
  cond_vals[0] = 1;

  // random output sequences
  vector<size_t> out_seqs;
  out_seqs.resize(size);
  for (size_t i = 0; i < size; ++i) {
    out_seqs[i] = i;
  }
  random_shuffle(out_seqs.begin(), out_seqs.end());

  for (size_t n = 0; n < size; ++n) {
    size_t i = out_seqs[n];
    string val_str = encode_num(s[i]);
    string cond_str = encode_num(cond_vals[i]);
    string goto_str;
    if (i == size - 1) {
      // last one, goto -1
      goto_str = "-_";
    } else {
      goto_str = encode_num(cond_vals[i + 1]);
    }

    ret += "O_O(" + cond_str + ", "
                 + val_str + ", "
                 + goto_str + ")\n";
  }
  return ret;
}

int main(int argc, char *argv[]) {
  if (argc != 2) {
    cerr << "Usage:" << argv[0] << "string_to_encode" << endl;
    return -1;
  }

  srand(time(0));
  string src = argv[1];
  string dst = encode_string(src);
  cout << kStub;
  cout << "o_o" << endl;
  cout << dst;
  cout << "ooo" << endl;

  return 0;
}
<commit_msg>Fix bug caused by 41cd6b652d4f704bbdd9d5fcf72b24e03558be8d<commit_after>#include <iostream>
#include <string>
#include <cstdint>
#include <cstdlib>
#include <vector>
#include <algorithm>
using namespace std;
static const string kStub =
  "/* O_O Generator by Hugh Wang. http://github.com/hghwng/O_O */\n"
  "#include \"stdio.h\"\n"
  "#define o_O +\n"
  "#define O_o <<\n"
  "#define o (\n"
  "#define O )\n"
  "#define oo if\n"
  "#define oO int\n"
  "#define Oo char\n"
  "#define OO return\n"
  "#define _ 1\n"
  "#define __ o _ O_o _ O\n"
  "#define ___ o __ O_o _ O\n"
  "#define ooo oo (OoO == -_) OO 0; }\n"
  "#define o_o oO main o oO OoO, Oo **Ooo O {\n"
  "#define O_O(OOO, OOOO, OOOOO) oo o OOO == OoO O fputc o OOOO, stdout O , main o OOOOO , 0 O ;\n";

int encode_by_sum(size_t v, string &ret) {
  if (v == 0) {
    ret = "0";
    return 0;
  }
  int num_parts = 0;

  string s;
  while (v) {
    if (num_parts++) s += " o_O ";

    for (;;) {
      auto r = rand() % 3;
      switch (r) {
        case 0: // 1
          s += "_";
          v -= 1;
          goto exit;
        case 1: // 2
          if (v < 2) break;
          s += "__";
          v -= 2;
          goto exit;
        case 2: // 4
          if (v < 4) break;
          s += "___";
          v -= 4;
          goto exit;
      }
    }
exit:
      continue;
  }

  if (num_parts == 1) {
    ret = s;
  } else {
    ret = "o " + s + " O";
  }

  return num_parts;
}

void encode_part(size_t lhs_val, size_t rhs_val, string &part_str) {
  string lhs_str, rhs_str;
  int lhs_part = encode_by_sum(lhs_val, lhs_str);
  int rhs_part = encode_by_sum(rhs_val, rhs_str);

  if (lhs_part == 0) {
    // 0 << x -> nothing, ""
    part_str.clear();
  }

  if (rhs_part == 0) {
    // lhs << 0 -> "lhs"
    part_str = lhs_str;
  } else {
    // lhs << rhs -> "lhs << rhs"
    part_str = "o " + lhs_str + " O_o " + rhs_str + " O";
  }
}

string encode_num(size_t v) {
  // x = ((a + b + c + d) << (e + f)) + (x << y)
  size_t prev_bits = 0;
  size_t cur_bits;
  int part_num = 0;
  string s;

  for (auto t = v; t; prev_bits += cur_bits) {
    int r = rand();
    cur_bits = r % 3 + 1; // 1 to 4
    size_t mask = (1 << cur_bits) - 1;

    string part_str;
    encode_part(t & mask, prev_bits, part_str);
    if (part_num++) s += " o_O ";
    s += part_str;

    t >>= cur_bits;
  }

  return s;
}

string encode_string(string s) {
  string ret;
  size_t size = s.size();

  // random cond value
  vector<size_t> cond_vals;
  cond_vals.resize(size);
  cond_vals[0] = rand() % 10 + 2; // >= 2
  for (size_t i = 1; i < size; ++i) {
    cond_vals[i] = cond_vals[i - 1] + rand() % 10 + 1;
  }
  random_shuffle(cond_vals.begin(), cond_vals.end());
  cond_vals[0] = 1;

  // random output sequences
  vector<size_t> out_seqs;
  out_seqs.resize(size);
  for (size_t i = 0; i < size; ++i) {
    out_seqs[i] = i;
  }
  random_shuffle(out_seqs.begin(), out_seqs.end());

  for (size_t n = 0; n < size; ++n) {
    size_t i = out_seqs[n];
    string val_str = encode_num(s[i]);
    string cond_str = encode_num(cond_vals[i]);
    string goto_str;
    if (i == size - 1) {
      // last one, goto -1
      goto_str = "-_";
    } else {
      goto_str = encode_num(cond_vals[i + 1]);
    }

    ret += "O_O(" + cond_str + ", "
                 + val_str + ", "
                 + goto_str + ")\n";
  }
  return ret;
}

int main(int argc, char *argv[]) {
  if (argc != 2) {
    cerr << "Usage:" << argv[0] << "string_to_encode" << endl;
    return -1;
  }

  srand(time(0));
  string src = argv[1];
  string dst = encode_string(src);
  cout << kStub;
  cout << "o_o" << endl;
  cout << dst;
  cout << "ooo" << endl;

  return 0;
}
<|endoftext|>


<commit_before>//===-- DumpValueObjectOptions.cpp -----------------------------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "lldb/DataFormatters/DumpValueObjectOptions.h"

// C Includes
// C++ Includes
// Other libraries and framework includes
// Project includes
#include "lldb/Core/ValueObject.h"

using namespace lldb;
using namespace lldb_private;

DumpValueObjectOptions::DumpValueObjectOptions() :
m_summary_sp(),
m_root_valobj_name(),
m_max_ptr_depth(PointerDepth{PointerDepth::Mode::Default,0}),
m_decl_printing_helper(),
m_use_synthetic(true),
m_scope_already_checked(false),
m_flat_output(false),
m_ignore_cap(false),
m_show_types(false),
m_show_location(false),
m_use_objc(false),
m_hide_root_type(false),
m_hide_name(false),
m_hide_value(false),
m_run_validator(false),
m_use_type_display_name(true),
m_allow_oneliner_mode(true),
m_hide_pointer_value(false),
m_reveal_empty_aggregates(true)
{}

DumpValueObjectOptions::DumpValueObjectOptions (ValueObject& valobj) :
DumpValueObjectOptions()
{
    m_use_dynamic = valobj.GetDynamicValueType();
    m_use_synthetic = valobj.IsSynthetic();
    m_varformat_language = valobj.GetPreferredDisplayLanguage();
}

DumpValueObjectOptions&
DumpValueObjectOptions::SetMaximumPointerDepth(PointerDepth depth)
{
    m_max_ptr_depth = depth;
    return *this;
}

DumpValueObjectOptions&
DumpValueObjectOptions::SetMaximumDepth(uint32_t depth)
{
    m_max_depth = depth;
    return *this;
}

DumpValueObjectOptions&
DumpValueObjectOptions::SetDeclPrintingHelper(DeclPrintingHelper helper)
{
    m_decl_printing_helper = helper;
    return *this;
}

DumpValueObjectOptions&
DumpValueObjectOptions::SetShowTypes(bool show)
{
    m_show_types = show;
    return *this;
}

DumpValueObjectOptions&
DumpValueObjectOptions::SetShowLocation(bool show)
{
    m_show_location = show;
    return *this;
}

DumpValueObjectOptions&
DumpValueObjectOptions::SetUseObjectiveC(bool use)
{
    m_use_objc = use;
    return *this;
}

DumpValueObjectOptions&
DumpValueObjectOptions::SetShowSummary(bool show)
{
    if (show == false)
        SetOmitSummaryDepth(UINT32_MAX);
    else
        SetOmitSummaryDepth(0);
    return *this;
}

DumpValueObjectOptions&
DumpValueObjectOptions::SetUseDynamicType(lldb::DynamicValueType dyn)
{
    m_use_dynamic = dyn;
    return *this;
}

DumpValueObjectOptions&
DumpValueObjectOptions::SetUseSyntheticValue(bool use_synthetic)
{
    m_use_synthetic = use_synthetic;
    return *this;
}

DumpValueObjectOptions&
DumpValueObjectOptions::SetScopeChecked(bool check)
{
    m_scope_already_checked = check;
    return *this;
}

DumpValueObjectOptions&
DumpValueObjectOptions::SetFlatOutput(bool flat)
{
    m_flat_output = flat;
    return *this;
}

DumpValueObjectOptions&
DumpValueObjectOptions::SetOmitSummaryDepth(uint32_t depth)
{
    m_omit_summary_depth = depth;
    return *this;
}

DumpValueObjectOptions&
DumpValueObjectOptions::SetIgnoreCap(bool ignore)
{
    m_ignore_cap = ignore;
    return *this;
}

DumpValueObjectOptions&
DumpValueObjectOptions::SetRawDisplay()
{
    SetUseSyntheticValue(false);
    SetOmitSummaryDepth(UINT32_MAX);
    SetIgnoreCap(true);
    SetHideName(false);
    SetHideValue(false);
    SetUseTypeDisplayName(false);
    SetAllowOnelinerMode(false);
    return *this;
}

DumpValueObjectOptions&
DumpValueObjectOptions::SetFormat (lldb::Format format)
{
    m_format = format;
    return *this;
}

DumpValueObjectOptions&
DumpValueObjectOptions::SetSummary (lldb::TypeSummaryImplSP summary)
{
    m_summary_sp = summary;
    return *this;
}

DumpValueObjectOptions&
DumpValueObjectOptions::SetRootValueObjectName (const char* name)
{
    if (name)
        m_root_valobj_name.assign(name);
    else
        m_root_valobj_name.clear();
    return *this;
}

DumpValueObjectOptions&
DumpValueObjectOptions::SetHideRootType (bool hide_root_type)
{
    m_hide_root_type = hide_root_type;
    return *this;
}

DumpValueObjectOptions&
DumpValueObjectOptions::SetHideName (bool hide_name)
{
    m_hide_name = hide_name;
    return *this;
}

DumpValueObjectOptions&
DumpValueObjectOptions::SetHideValue (bool hide_value)
{
    m_hide_value = hide_value;
    return *this;
}

DumpValueObjectOptions&
DumpValueObjectOptions::SetHidePointerValue (bool hide)
{
    m_hide_pointer_value = hide;
    return *this;
}

DumpValueObjectOptions&
DumpValueObjectOptions::SetVariableFormatDisplayLanguage (lldb::LanguageType lang)
{
    m_varformat_language = lang;
    return *this;
}

DumpValueObjectOptions&
DumpValueObjectOptions::SetRunValidator (bool run)
{
    m_run_validator = run;
    return *this;
}

DumpValueObjectOptions&
DumpValueObjectOptions::SetUseTypeDisplayName (bool dis)
{
    m_use_type_display_name = dis;
    return *this;
}

DumpValueObjectOptions&
DumpValueObjectOptions::SetAllowOnelinerMode (bool oneliner)
{
    m_allow_oneliner_mode = oneliner;
    return *this;
}

DumpValueObjectOptions&
DumpValueObjectOptions::SetRevealEmptyAggregates (bool reveal)
{
    m_reveal_empty_aggregates = reveal;
    return *this;
}

<commit_msg>Fix indentation<commit_after>//===-- DumpValueObjectOptions.cpp -----------------------------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "lldb/DataFormatters/DumpValueObjectOptions.h"

// C Includes
// C++ Includes
// Other libraries and framework includes
// Project includes
#include "lldb/Core/ValueObject.h"

using namespace lldb;
using namespace lldb_private;

DumpValueObjectOptions::DumpValueObjectOptions() :
    m_summary_sp(),
    m_root_valobj_name(),
    m_max_ptr_depth(PointerDepth{PointerDepth::Mode::Default,0}),
    m_decl_printing_helper(),
    m_use_synthetic(true),
    m_scope_already_checked(false),
    m_flat_output(false),
    m_ignore_cap(false),
    m_show_types(false),
    m_show_location(false),
    m_use_objc(false),
    m_hide_root_type(false),
    m_hide_name(false),
    m_hide_value(false),
    m_run_validator(false),
    m_use_type_display_name(true),
    m_allow_oneliner_mode(true),
    m_hide_pointer_value(false),
    m_reveal_empty_aggregates(true)
{}

DumpValueObjectOptions::DumpValueObjectOptions (ValueObject& valobj) :
    DumpValueObjectOptions()
{
    m_use_dynamic = valobj.GetDynamicValueType();
    m_use_synthetic = valobj.IsSynthetic();
    m_varformat_language = valobj.GetPreferredDisplayLanguage();
}

DumpValueObjectOptions&
DumpValueObjectOptions::SetMaximumPointerDepth(PointerDepth depth)
{
    m_max_ptr_depth = depth;
    return *this;
}

DumpValueObjectOptions&
DumpValueObjectOptions::SetMaximumDepth(uint32_t depth)
{
    m_max_depth = depth;
    return *this;
}

DumpValueObjectOptions&
DumpValueObjectOptions::SetDeclPrintingHelper(DeclPrintingHelper helper)
{
    m_decl_printing_helper = helper;
    return *this;
}

DumpValueObjectOptions&
DumpValueObjectOptions::SetShowTypes(bool show)
{
    m_show_types = show;
    return *this;
}

DumpValueObjectOptions&
DumpValueObjectOptions::SetShowLocation(bool show)
{
    m_show_location = show;
    return *this;
}

DumpValueObjectOptions&
DumpValueObjectOptions::SetUseObjectiveC(bool use)
{
    m_use_objc = use;
    return *this;
}

DumpValueObjectOptions&
DumpValueObjectOptions::SetShowSummary(bool show)
{
    if (show == false)
        SetOmitSummaryDepth(UINT32_MAX);
    else
        SetOmitSummaryDepth(0);
    return *this;
}

DumpValueObjectOptions&
DumpValueObjectOptions::SetUseDynamicType(lldb::DynamicValueType dyn)
{
    m_use_dynamic = dyn;
    return *this;
}

DumpValueObjectOptions&
DumpValueObjectOptions::SetUseSyntheticValue(bool use_synthetic)
{
    m_use_synthetic = use_synthetic;
    return *this;
}

DumpValueObjectOptions&
DumpValueObjectOptions::SetScopeChecked(bool check)
{
    m_scope_already_checked = check;
    return *this;
}

DumpValueObjectOptions&
DumpValueObjectOptions::SetFlatOutput(bool flat)
{
    m_flat_output = flat;
    return *this;
}

DumpValueObjectOptions&
DumpValueObjectOptions::SetOmitSummaryDepth(uint32_t depth)
{
    m_omit_summary_depth = depth;
    return *this;
}

DumpValueObjectOptions&
DumpValueObjectOptions::SetIgnoreCap(bool ignore)
{
    m_ignore_cap = ignore;
    return *this;
}

DumpValueObjectOptions&
DumpValueObjectOptions::SetRawDisplay()
{
    SetUseSyntheticValue(false);
    SetOmitSummaryDepth(UINT32_MAX);
    SetIgnoreCap(true);
    SetHideName(false);
    SetHideValue(false);
    SetUseTypeDisplayName(false);
    SetAllowOnelinerMode(false);
    return *this;
}

DumpValueObjectOptions&
DumpValueObjectOptions::SetFormat (lldb::Format format)
{
    m_format = format;
    return *this;
}

DumpValueObjectOptions&
DumpValueObjectOptions::SetSummary (lldb::TypeSummaryImplSP summary)
{
    m_summary_sp = summary;
    return *this;
}

DumpValueObjectOptions&
DumpValueObjectOptions::SetRootValueObjectName (const char* name)
{
    if (name)
        m_root_valobj_name.assign(name);
    else
        m_root_valobj_name.clear();
    return *this;
}

DumpValueObjectOptions&
DumpValueObjectOptions::SetHideRootType (bool hide_root_type)
{
    m_hide_root_type = hide_root_type;
    return *this;
}

DumpValueObjectOptions&
DumpValueObjectOptions::SetHideName (bool hide_name)
{
    m_hide_name = hide_name;
    return *this;
}

DumpValueObjectOptions&
DumpValueObjectOptions::SetHideValue (bool hide_value)
{
    m_hide_value = hide_value;
    return *this;
}

DumpValueObjectOptions&
DumpValueObjectOptions::SetHidePointerValue (bool hide)
{
    m_hide_pointer_value = hide;
    return *this;
}

DumpValueObjectOptions&
DumpValueObjectOptions::SetVariableFormatDisplayLanguage (lldb::LanguageType lang)
{
    m_varformat_language = lang;
    return *this;
}

DumpValueObjectOptions&
DumpValueObjectOptions::SetRunValidator (bool run)
{
    m_run_validator = run;
    return *this;
}

DumpValueObjectOptions&
DumpValueObjectOptions::SetUseTypeDisplayName (bool dis)
{
    m_use_type_display_name = dis;
    return *this;
}

DumpValueObjectOptions&
DumpValueObjectOptions::SetAllowOnelinerMode (bool oneliner)
{
    m_allow_oneliner_mode = oneliner;
    return *this;
}

DumpValueObjectOptions&
DumpValueObjectOptions::SetRevealEmptyAggregates (bool reveal)
{
    m_reveal_empty_aggregates = reveal;
    return *this;
}

<|endoftext|>


<commit_before>//===-- ProcessLauncherWindows.cpp ------------------------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "lldb/Core/Error.h"
#include "lldb/Core/Log.h"
#include "lldb/Core/Module.h"
#include "lldb/Host/HostProcess.h"
#include "lldb/Host/MonitoringProcessLauncher.h"
#include "lldb/Target/Platform.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/ProcessLaunchInfo.h"

using namespace lldb;
using namespace lldb_private;

MonitoringProcessLauncher::MonitoringProcessLauncher(std::unique_ptr<ProcessLauncher> delegate_launcher)
    : m_delegate_launcher(std::move(delegate_launcher))
{
}

HostProcess
MonitoringProcessLauncher::LaunchProcess(const ProcessLaunchInfo &launch_info, Error &error)
{
    ProcessLaunchInfo resolved_info(launch_info);

    error.Clear();
    char exe_path[PATH_MAX];

    PlatformSP host_platform_sp(Platform::GetHostPlatform());

    const ArchSpec &arch_spec = resolved_info.GetArchitecture();

    FileSpec exe_spec(resolved_info.GetExecutableFile());

    FileSpec::FileType file_type = exe_spec.GetFileType();
    if (file_type != FileSpec::eFileTypeRegular)
    {
        lldb::ModuleSP exe_module_sp;
        error = host_platform_sp->ResolveExecutable(exe_spec, arch_spec, exe_module_sp, NULL);

        if (error.Fail())
            return HostProcess();

        if (exe_module_sp)
            exe_spec = exe_module_sp->GetFileSpec();
    }

    if (exe_spec.Exists())
    {
        exe_spec.GetPath(exe_path, sizeof(exe_path));
    }
    else
    {
        resolved_info.GetExecutableFile().GetPath(exe_path, sizeof(exe_path));
        error.SetErrorStringWithFormat("executable doesn't exist: '%s'", exe_path);
        return HostProcess();
    }

    resolved_info.SetExecutableFile(exe_spec, false);
    assert(!resolved_info.GetFlags().Test(eLaunchFlagLaunchInTTY));

    HostProcess process = m_delegate_launcher->LaunchProcess(resolved_info, error);

    if (process.GetProcessId() != LLDB_INVALID_PROCESS_ID)
    {
        Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));

        Host::MonitorChildProcessCallback callback = launch_info.GetMonitorProcessCallback();

        void *baton = nullptr;
        bool monitor_signals = false;
        if (callback)
        {
            // If the ProcessLaunchInfo specified a callback, use that.
            baton = launch_info.GetMonitorProcessBaton();
            monitor_signals = launch_info.GetMonitorSignals();
        }
        else
        {
            callback = Process::SetProcessExitStatus;
        }

        process.StartMonitoring(callback, baton, monitor_signals);
        if (log)
            log->PutCString("started monitoring child process.");
    }
    else
    {
        // Invalid process ID, something didn't go well
        if (error.Success())
            error.SetErrorString("process launch failed for unknown reasons");
    }
    return process;
}
<commit_msg>Fix broken build after signature change of ResolveExecutable.<commit_after>//===-- ProcessLauncherWindows.cpp ------------------------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "lldb/Core/Error.h"
#include "lldb/Core/Log.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/ModuleSpec.h"
#include "lldb/Host/HostProcess.h"
#include "lldb/Host/MonitoringProcessLauncher.h"
#include "lldb/Target/Platform.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/ProcessLaunchInfo.h"

using namespace lldb;
using namespace lldb_private;

MonitoringProcessLauncher::MonitoringProcessLauncher(std::unique_ptr<ProcessLauncher> delegate_launcher)
    : m_delegate_launcher(std::move(delegate_launcher))
{
}

HostProcess
MonitoringProcessLauncher::LaunchProcess(const ProcessLaunchInfo &launch_info, Error &error)
{
    ProcessLaunchInfo resolved_info(launch_info);

    error.Clear();
    char exe_path[PATH_MAX];

    PlatformSP host_platform_sp(Platform::GetHostPlatform());

    const ArchSpec &arch_spec = resolved_info.GetArchitecture();

    FileSpec exe_spec(resolved_info.GetExecutableFile());

    FileSpec::FileType file_type = exe_spec.GetFileType();
    if (file_type != FileSpec::eFileTypeRegular)
    {
        ModuleSpec module_spec(exe_spec, arch_spec);
        lldb::ModuleSP exe_module_sp;
        error = host_platform_sp->ResolveExecutable(module_spec, exe_module_sp, NULL);

        if (error.Fail())
            return HostProcess();

        if (exe_module_sp)
            exe_spec = exe_module_sp->GetFileSpec();
    }

    if (exe_spec.Exists())
    {
        exe_spec.GetPath(exe_path, sizeof(exe_path));
    }
    else
    {
        resolved_info.GetExecutableFile().GetPath(exe_path, sizeof(exe_path));
        error.SetErrorStringWithFormat("executable doesn't exist: '%s'", exe_path);
        return HostProcess();
    }

    resolved_info.SetExecutableFile(exe_spec, false);
    assert(!resolved_info.GetFlags().Test(eLaunchFlagLaunchInTTY));

    HostProcess process = m_delegate_launcher->LaunchProcess(resolved_info, error);

    if (process.GetProcessId() != LLDB_INVALID_PROCESS_ID)
    {
        Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));

        Host::MonitorChildProcessCallback callback = launch_info.GetMonitorProcessCallback();

        void *baton = nullptr;
        bool monitor_signals = false;
        if (callback)
        {
            // If the ProcessLaunchInfo specified a callback, use that.
            baton = launch_info.GetMonitorProcessBaton();
            monitor_signals = launch_info.GetMonitorSignals();
        }
        else
        {
            callback = Process::SetProcessExitStatus;
        }

        process.StartMonitoring(callback, baton, monitor_signals);
        if (log)
            log->PutCString("started monitoring child process.");
    }
    else
    {
        // Invalid process ID, something didn't go well
        if (error.Success())
            error.SetErrorString("process launch failed for unknown reasons");
    }
    return process;
}
<|endoftext|>


<commit_before>//===-- SerializationTests.cpp - Binary and YAML serialization unit tests -===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "index/Index.h"
#include "index/Serialization.h"
#include "llvm/Support/ScopedPrinter.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"

using testing::_;
using testing::AllOf;
using testing::Pair;
using testing::UnorderedElementsAre;
using testing::UnorderedElementsAreArray;
namespace clang {
namespace clangd {
namespace {

const char *YAML = R"(
---
!Symbol
ID: 057557CEBF6E6B2DD437FBF60CC58F352D1DF856
Name:   'Foo1'
Scope:   'clang::'
SymInfo:
  Kind:            Function
  Lang:            Cpp
CanonicalDeclaration:
  FileURI:        file:///path/foo.h
  Start:
    Line: 1
    Column: 0
  End:
    Line: 1
    Column: 1
Origin:    4
Flags:    1
Documentation:    'Foo doc'
ReturnType:    'int'
IncludeHeaders:
  - Header:    'include1'
    References:    7
  - Header:    'include2'
    References:    3
...
---
!Symbol
ID: 057557CEBF6E6B2DD437FBF60CC58F352D1DF858
Name:   'Foo2'
Scope:   'clang::'
SymInfo:
  Kind:            Function
  Lang:            Cpp
CanonicalDeclaration:
  FileURI:        file:///path/bar.h
  Start:
    Line: 1
    Column: 0
  End:
    Line: 1
    Column: 1
Flags:    2
Signature:    '-sig'
CompletionSnippetSuffix:    '-snippet'
...
!Refs
ID: 057557CEBF6E6B2DD437FBF60CC58F352D1DF856
References:
  - Kind: 4
    Location:
      FileURI:    file:///path/foo.cc
      Start:
        Line: 5
        Column: 3
      End:
        Line: 5
        Column: 8
)";

MATCHER_P(ID, I, "") { return arg.ID == cantFail(SymbolID::fromStr(I)); }
MATCHER_P(QName, Name, "") { return (arg.Scope + arg.Name).str() == Name; }
MATCHER_P2(IncludeHeaderWithRef, IncludeHeader, References, "") {
  return (arg.IncludeHeader == IncludeHeader) && (arg.References == References);
}

TEST(SerializationTest, YAMLConversions) {
  auto In = readIndexFile(YAML);
  EXPECT_TRUE(bool(In)) << In.takeError();

  auto ParsedYAML = readIndexFile(YAML);
  ASSERT_TRUE(bool(ParsedYAML)) << ParsedYAML.takeError();
  ASSERT_TRUE(bool(ParsedYAML->Symbols));
  EXPECT_THAT(
      *ParsedYAML->Symbols,
      UnorderedElementsAre(ID("057557CEBF6E6B2DD437FBF60CC58F352D1DF856"),
                           ID("057557CEBF6E6B2DD437FBF60CC58F352D1DF858")));

  auto Sym1 = *ParsedYAML->Symbols->find(
      cantFail(SymbolID::fromStr("057557CEBF6E6B2DD437FBF60CC58F352D1DF856")));
  auto Sym2 = *ParsedYAML->Symbols->find(
      cantFail(SymbolID::fromStr("057557CEBF6E6B2DD437FBF60CC58F352D1DF858")));

  EXPECT_THAT(Sym1, QName("clang::Foo1"));
  EXPECT_EQ(Sym1.Signature, "");
  EXPECT_EQ(Sym1.Documentation, "Foo doc");
  EXPECT_EQ(Sym1.ReturnType, "int");
  EXPECT_EQ(Sym1.CanonicalDeclaration.FileURI, "file:///path/foo.h");
  EXPECT_EQ(Sym1.Origin, SymbolOrigin::Static);
  EXPECT_TRUE(Sym1.Flags & Symbol::IndexedForCodeCompletion);
  EXPECT_FALSE(Sym1.Flags & Symbol::Deprecated);
  EXPECT_THAT(Sym1.IncludeHeaders,
              UnorderedElementsAre(IncludeHeaderWithRef("include1", 7u),
                                   IncludeHeaderWithRef("include2", 3u)));

  EXPECT_THAT(Sym2, QName("clang::Foo2"));
  EXPECT_EQ(Sym2.Signature, "-sig");
  EXPECT_EQ(Sym2.ReturnType, "");
  EXPECT_EQ(Sym2.CanonicalDeclaration.FileURI, "file:///path/bar.h");
  EXPECT_FALSE(Sym2.Flags & Symbol::IndexedForCodeCompletion);
  EXPECT_TRUE(Sym2.Flags & Symbol::Deprecated);

  ASSERT_TRUE(bool(ParsedYAML->Refs));
  EXPECT_THAT(*ParsedYAML->Refs,
              UnorderedElementsAre(
                  Pair(cantFail(SymbolID::fromStr(
                           "057557CEBF6E6B2DD437FBF60CC58F352D1DF856")),
                       testing::SizeIs(1))));
  auto Ref1 = ParsedYAML->Refs->begin()->second.front();
  EXPECT_EQ(Ref1.Kind, RefKind::Reference);
  EXPECT_EQ(Ref1.Location.FileURI, "file:///path/foo.cc");
}

std::vector<std::string> YAMLFromSymbols(const SymbolSlab &Slab) {
  std::vector<std::string> Result;
  for (const auto &Sym : Slab)
    Result.push_back(toYAML(Sym));
  return Result;
}
std::vector<std::string> YAMLFromRefs(const RefSlab &Slab) {
  std::vector<std::string> Result;
  for (const auto &Sym : Slab)
    Result.push_back(toYAML(Sym));
  return Result;
}

TEST(SerializationTest, BinaryConversions) {
  auto In = readIndexFile(YAML);
  EXPECT_TRUE(bool(In)) << In.takeError();

  // Write to binary format, and parse again.
  IndexFileOut Out(*In);
  Out.Format = IndexFileFormat::RIFF;
  std::string Serialized = llvm::to_string(Out);
  {
    std::error_code EC;
    llvm::raw_fd_ostream F("/tmp/foo", EC);
    F << Serialized;
  }

  auto In2 = readIndexFile(Serialized);
  ASSERT_TRUE(bool(In2)) << In.takeError();
  ASSERT_TRUE(In2->Symbols);
  ASSERT_TRUE(In2->Refs);

  // Assert the YAML serializations match, for nice comparisons and diffs.
  EXPECT_THAT(YAMLFromSymbols(*In2->Symbols),
              UnorderedElementsAreArray(YAMLFromSymbols(*In->Symbols)));
  EXPECT_THAT(YAMLFromRefs(*In2->Refs),
              UnorderedElementsAreArray(YAMLFromRefs(*In->Refs)));
}

} // namespace
} // namespace clangd
} // namespace clang
<commit_msg>[clangd] Remove debugging output in test<commit_after>//===-- SerializationTests.cpp - Binary and YAML serialization unit tests -===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "index/Index.h"
#include "index/Serialization.h"
#include "llvm/Support/ScopedPrinter.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"

using testing::_;
using testing::AllOf;
using testing::Pair;
using testing::UnorderedElementsAre;
using testing::UnorderedElementsAreArray;
namespace clang {
namespace clangd {
namespace {

const char *YAML = R"(
---
!Symbol
ID: 057557CEBF6E6B2DD437FBF60CC58F352D1DF856
Name:   'Foo1'
Scope:   'clang::'
SymInfo:
  Kind:            Function
  Lang:            Cpp
CanonicalDeclaration:
  FileURI:        file:///path/foo.h
  Start:
    Line: 1
    Column: 0
  End:
    Line: 1
    Column: 1
Origin:    4
Flags:    1
Documentation:    'Foo doc'
ReturnType:    'int'
IncludeHeaders:
  - Header:    'include1'
    References:    7
  - Header:    'include2'
    References:    3
...
---
!Symbol
ID: 057557CEBF6E6B2DD437FBF60CC58F352D1DF858
Name:   'Foo2'
Scope:   'clang::'
SymInfo:
  Kind:            Function
  Lang:            Cpp
CanonicalDeclaration:
  FileURI:        file:///path/bar.h
  Start:
    Line: 1
    Column: 0
  End:
    Line: 1
    Column: 1
Flags:    2
Signature:    '-sig'
CompletionSnippetSuffix:    '-snippet'
...
!Refs
ID: 057557CEBF6E6B2DD437FBF60CC58F352D1DF856
References:
  - Kind: 4
    Location:
      FileURI:    file:///path/foo.cc
      Start:
        Line: 5
        Column: 3
      End:
        Line: 5
        Column: 8
)";

MATCHER_P(ID, I, "") { return arg.ID == cantFail(SymbolID::fromStr(I)); }
MATCHER_P(QName, Name, "") { return (arg.Scope + arg.Name).str() == Name; }
MATCHER_P2(IncludeHeaderWithRef, IncludeHeader, References, "") {
  return (arg.IncludeHeader == IncludeHeader) && (arg.References == References);
}

TEST(SerializationTest, YAMLConversions) {
  auto In = readIndexFile(YAML);
  EXPECT_TRUE(bool(In)) << In.takeError();

  auto ParsedYAML = readIndexFile(YAML);
  ASSERT_TRUE(bool(ParsedYAML)) << ParsedYAML.takeError();
  ASSERT_TRUE(bool(ParsedYAML->Symbols));
  EXPECT_THAT(
      *ParsedYAML->Symbols,
      UnorderedElementsAre(ID("057557CEBF6E6B2DD437FBF60CC58F352D1DF856"),
                           ID("057557CEBF6E6B2DD437FBF60CC58F352D1DF858")));

  auto Sym1 = *ParsedYAML->Symbols->find(
      cantFail(SymbolID::fromStr("057557CEBF6E6B2DD437FBF60CC58F352D1DF856")));
  auto Sym2 = *ParsedYAML->Symbols->find(
      cantFail(SymbolID::fromStr("057557CEBF6E6B2DD437FBF60CC58F352D1DF858")));

  EXPECT_THAT(Sym1, QName("clang::Foo1"));
  EXPECT_EQ(Sym1.Signature, "");
  EXPECT_EQ(Sym1.Documentation, "Foo doc");
  EXPECT_EQ(Sym1.ReturnType, "int");
  EXPECT_EQ(Sym1.CanonicalDeclaration.FileURI, "file:///path/foo.h");
  EXPECT_EQ(Sym1.Origin, SymbolOrigin::Static);
  EXPECT_TRUE(Sym1.Flags & Symbol::IndexedForCodeCompletion);
  EXPECT_FALSE(Sym1.Flags & Symbol::Deprecated);
  EXPECT_THAT(Sym1.IncludeHeaders,
              UnorderedElementsAre(IncludeHeaderWithRef("include1", 7u),
                                   IncludeHeaderWithRef("include2", 3u)));

  EXPECT_THAT(Sym2, QName("clang::Foo2"));
  EXPECT_EQ(Sym2.Signature, "-sig");
  EXPECT_EQ(Sym2.ReturnType, "");
  EXPECT_EQ(Sym2.CanonicalDeclaration.FileURI, "file:///path/bar.h");
  EXPECT_FALSE(Sym2.Flags & Symbol::IndexedForCodeCompletion);
  EXPECT_TRUE(Sym2.Flags & Symbol::Deprecated);

  ASSERT_TRUE(bool(ParsedYAML->Refs));
  EXPECT_THAT(*ParsedYAML->Refs,
              UnorderedElementsAre(
                  Pair(cantFail(SymbolID::fromStr(
                           "057557CEBF6E6B2DD437FBF60CC58F352D1DF856")),
                       testing::SizeIs(1))));
  auto Ref1 = ParsedYAML->Refs->begin()->second.front();
  EXPECT_EQ(Ref1.Kind, RefKind::Reference);
  EXPECT_EQ(Ref1.Location.FileURI, "file:///path/foo.cc");
}

std::vector<std::string> YAMLFromSymbols(const SymbolSlab &Slab) {
  std::vector<std::string> Result;
  for (const auto &Sym : Slab)
    Result.push_back(toYAML(Sym));
  return Result;
}
std::vector<std::string> YAMLFromRefs(const RefSlab &Slab) {
  std::vector<std::string> Result;
  for (const auto &Sym : Slab)
    Result.push_back(toYAML(Sym));
  return Result;
}

TEST(SerializationTest, BinaryConversions) {
  auto In = readIndexFile(YAML);
  EXPECT_TRUE(bool(In)) << In.takeError();

  // Write to binary format, and parse again.
  IndexFileOut Out(*In);
  Out.Format = IndexFileFormat::RIFF;
  std::string Serialized = llvm::to_string(Out);

  auto In2 = readIndexFile(Serialized);
  ASSERT_TRUE(bool(In2)) << In.takeError();
  ASSERT_TRUE(In2->Symbols);
  ASSERT_TRUE(In2->Refs);

  // Assert the YAML serializations match, for nice comparisons and diffs.
  EXPECT_THAT(YAMLFromSymbols(*In2->Symbols),
              UnorderedElementsAreArray(YAMLFromSymbols(*In->Symbols)));
  EXPECT_THAT(YAMLFromRefs(*In2->Refs),
              UnorderedElementsAreArray(YAMLFromRefs(*In->Refs)));
}

} // namespace
} // namespace clangd
} // namespace clang
<|endoftext|>


<commit_before>// Copyright 2014 The Crashpad Authors. All rights reserved.
//
// 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 "util/stdlib/string_number_conversion.h"

#include <ctype.h>
#include <errno.h>
#include <inttypes.h>
#include <stdlib.h>
#include <string.h>

#include <limits>

#include "base/logging.h"
#include "util/stdlib/cxx.h"

// CONSTEXPR_STATIC_ASSERT will be a normal static_assert if the C++ library is
// the C++11 library. If using an older C++ library, the
// std::numeric_limits<>::min() and max() functions will not be marked as
// constexpr, and thus won’t be usable with static_assert(). In that case, a
// run-time CHECK() will have to do.
#if CXX_LIBRARY_HAS_CONSTEXPR
#define CONSTEXPR_STATIC_ASSERT(condition, message) \
  static_assert(condition, message)
#else
#define CONSTEXPR_STATIC_ASSERT(condition, message) CHECK(condition) << message
#endif

namespace {

template <typename TIntType, typename TLongType>
struct StringToIntegerTraits {
  using IntType = TIntType;
  using LongType = TLongType;
  static void TypeCheck() {
    static_assert(std::numeric_limits<TIntType>::is_integer &&
                      std::numeric_limits<TLongType>::is_integer,
                  "IntType and LongType must be integer");
    static_assert(std::numeric_limits<TIntType>::is_signed ==
                      std::numeric_limits<TLongType>::is_signed,
                  "IntType and LongType signedness must agree");
    CONSTEXPR_STATIC_ASSERT(std::numeric_limits<TIntType>::min() >=
                                    std::numeric_limits<TLongType>::min() &&
                                std::numeric_limits<TIntType>::min() <
                                    std::numeric_limits<TLongType>::max(),
                            "IntType min must be in LongType range");
    CONSTEXPR_STATIC_ASSERT(std::numeric_limits<TIntType>::max() >
                                    std::numeric_limits<TLongType>::min() &&
                                std::numeric_limits<TIntType>::max() <=
                                    std::numeric_limits<TLongType>::max(),
                            "IntType max must be in LongType range");
  }
};

template <typename TIntType, typename TLongType>
struct StringToSignedIntegerTraits
    : public StringToIntegerTraits<TIntType, TLongType> {
  static void TypeCheck() {
    static_assert(std::numeric_limits<TIntType>::is_signed,
                  "StringToSignedTraits IntType must be signed");
    return super::TypeCheck();
  }
  static bool IsNegativeOverflow(TLongType value) {
    return value < std::numeric_limits<TIntType>::min();
  }

 private:
  using super = StringToIntegerTraits<TIntType, TLongType>;
};

template <typename TIntType, typename TLongType>
struct StringToUnsignedIntegerTraits
    : public StringToIntegerTraits<TIntType, TLongType> {
  static void TypeCheck() {
    static_assert(!std::numeric_limits<TIntType>::is_signed,
                  "StringToUnsignedTraits IntType must be unsigned");
    return super::TypeCheck();
  }
  static bool IsNegativeOverflow(TLongType value) { return false; }

 private:
  using super = StringToIntegerTraits<TIntType, TLongType>;
};

struct StringToIntTraits : public StringToSignedIntegerTraits<int, long> {
  static LongType Convert(const char* str, char** end, int base) {
    return strtol(str, end, base);
  }
};

struct StringToUnsignedIntTraits
    : public StringToUnsignedIntegerTraits<unsigned int, unsigned long> {
  static LongType Convert(const char* str, char** end, int base) {
    if (str[0] == '-') {
      return 0;
    }
    return strtoul(str, end, base);
  }
};

struct StringToUnsignedInt64Traits
    : public StringToUnsignedIntegerTraits<uint64_t, uint64_t> {
  static LongType Convert(const char* str, char** end, int base) {
    if (str[0] == '-') {
      return 0;
    }
    return strtoull(str, end, base);
  }
};

template <typename Traits>
bool StringToIntegerInternal(const base::StringPiece& string,
                             typename Traits::IntType* number) {
  using IntType = typename Traits::IntType;
  using LongType = typename Traits::LongType;

  Traits::TypeCheck();

  if (string.empty() || isspace(string[0])) {
    return false;
  }

  if (string[string.length()] != '\0') {
    // The implementations use the C standard library’s conversion routines,
    // which rely on the strings having a trailing NUL character. std::string
    // will NUL-terminate.
    std::string terminated_string(string.data(), string.length());
    return StringToIntegerInternal<Traits>(terminated_string, number);
  }

  errno = 0;
  char* end;
  LongType result = Traits::Convert(string.data(), &end, 0);
  if (Traits::IsNegativeOverflow(result) ||
      result > std::numeric_limits<IntType>::max() ||
      errno == ERANGE ||
      end != string.data() + string.length()) {
    return false;
  }
  *number = result;
  return true;
}

}  // namespace

namespace crashpad {

bool StringToNumber(const base::StringPiece& string, int* number) {
  return StringToIntegerInternal<StringToIntTraits>(string, number);
}

bool StringToNumber(const base::StringPiece& string, unsigned int* number) {
  return StringToIntegerInternal<StringToUnsignedIntTraits>(string, number);
}

bool StringToNumber(const base::StringPiece& string, uint64_t* number) {
  return StringToIntegerInternal<StringToUnsignedInt64Traits>(string, number);
}

}  // namespace crashpad
<commit_msg>Correct StringToUnsignedInt[64]()<commit_after>// Copyright 2014 The Crashpad Authors. All rights reserved.
//
// 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 "util/stdlib/string_number_conversion.h"

#include <ctype.h>
#include <errno.h>
#include <inttypes.h>
#include <stdlib.h>
#include <string.h>

#include <limits>

#include "base/logging.h"
#include "util/stdlib/cxx.h"

// CONSTEXPR_STATIC_ASSERT will be a normal static_assert if the C++ library is
// the C++11 library. If using an older C++ library, the
// std::numeric_limits<>::min() and max() functions will not be marked as
// constexpr, and thus won’t be usable with static_assert(). In that case, a
// run-time CHECK() will have to do.
#if CXX_LIBRARY_HAS_CONSTEXPR
#define CONSTEXPR_STATIC_ASSERT(condition, message) \
  static_assert(condition, message)
#else
#define CONSTEXPR_STATIC_ASSERT(condition, message) CHECK(condition) << message
#endif

namespace {

template <typename TIntType, typename TLongType>
struct StringToIntegerTraits {
  using IntType = TIntType;
  using LongType = TLongType;
  static void TypeCheck() {
    static_assert(std::numeric_limits<TIntType>::is_integer &&
                      std::numeric_limits<TLongType>::is_integer,
                  "IntType and LongType must be integer");
    static_assert(std::numeric_limits<TIntType>::is_signed ==
                      std::numeric_limits<TLongType>::is_signed,
                  "IntType and LongType signedness must agree");
    CONSTEXPR_STATIC_ASSERT(std::numeric_limits<TIntType>::min() >=
                                    std::numeric_limits<TLongType>::min() &&
                                std::numeric_limits<TIntType>::min() <
                                    std::numeric_limits<TLongType>::max(),
                            "IntType min must be in LongType range");
    CONSTEXPR_STATIC_ASSERT(std::numeric_limits<TIntType>::max() >
                                    std::numeric_limits<TLongType>::min() &&
                                std::numeric_limits<TIntType>::max() <=
                                    std::numeric_limits<TLongType>::max(),
                            "IntType max must be in LongType range");
  }
};

template <typename TIntType, typename TLongType>
struct StringToSignedIntegerTraits
    : public StringToIntegerTraits<TIntType, TLongType> {
  static void TypeCheck() {
    static_assert(std::numeric_limits<TIntType>::is_signed,
                  "StringToSignedTraits IntType must be signed");
    return super::TypeCheck();
  }
  static bool IsNegativeOverflow(TLongType value) {
    return value < std::numeric_limits<TIntType>::min();
  }

 private:
  using super = StringToIntegerTraits<TIntType, TLongType>;
};

template <typename TIntType, typename TLongType>
struct StringToUnsignedIntegerTraits
    : public StringToIntegerTraits<TIntType, TLongType> {
  static void TypeCheck() {
    static_assert(!std::numeric_limits<TIntType>::is_signed,
                  "StringToUnsignedTraits IntType must be unsigned");
    return super::TypeCheck();
  }
  static bool IsNegativeOverflow(TLongType value) { return false; }

 private:
  using super = StringToIntegerTraits<TIntType, TLongType>;
};

struct StringToIntTraits : public StringToSignedIntegerTraits<int, long> {
  static LongType Convert(const char* str, char** end, int base) {
    return strtol(str, end, base);
  }
};

struct StringToUnsignedIntTraits
    : public StringToUnsignedIntegerTraits<unsigned int, unsigned long> {
  static LongType Convert(const char* str, char** end, int base) {
    if (str[0] == '-') {
      *end = const_cast<char*>(str);
      return 0;
    }
    return strtoul(str, end, base);
  }
};

struct StringToUnsignedInt64Traits
    : public StringToUnsignedIntegerTraits<uint64_t, uint64_t> {
  static LongType Convert(const char* str, char** end, int base) {
    if (str[0] == '-') {
      *end = const_cast<char*>(str);
      return 0;
    }
    return strtoull(str, end, base);
  }
};

template <typename Traits>
bool StringToIntegerInternal(const base::StringPiece& string,
                             typename Traits::IntType* number) {
  using IntType = typename Traits::IntType;
  using LongType = typename Traits::LongType;

  Traits::TypeCheck();

  if (string.empty() || isspace(string[0])) {
    return false;
  }

  if (string[string.length()] != '\0') {
    // The implementations use the C standard library’s conversion routines,
    // which rely on the strings having a trailing NUL character. std::string
    // will NUL-terminate.
    std::string terminated_string(string.data(), string.length());
    return StringToIntegerInternal<Traits>(terminated_string, number);
  }

  errno = 0;
  char* end;
  LongType result = Traits::Convert(string.data(), &end, 0);
  if (Traits::IsNegativeOverflow(result) ||
      result > std::numeric_limits<IntType>::max() ||
      errno == ERANGE ||
      end != string.data() + string.length()) {
    return false;
  }
  *number = result;
  return true;
}

}  // namespace

namespace crashpad {

bool StringToNumber(const base::StringPiece& string, int* number) {
  return StringToIntegerInternal<StringToIntTraits>(string, number);
}

bool StringToNumber(const base::StringPiece& string, unsigned int* number) {
  return StringToIntegerInternal<StringToUnsignedIntTraits>(string, number);
}

bool StringToNumber(const base::StringPiece& string, uint64_t* number) {
  return StringToIntegerInternal<StringToUnsignedInt64Traits>(string, number);
}

}  // namespace crashpad
<|endoftext|>


<commit_before>#include <sstream>
#include <cxxabi.h>
#include <cassert>
#include <iomanip>
#include <algorithm>
#include <map>
#include <stack>
#include <limits>
#include <vector>
#include <string>
#include <iostream>
#include <fstream>
#include <sys/time.h>
#include <signal.h>
#include <execinfo.h>
#include <errno.h>
#include <cstdio>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <ucontext.h>

#include "papi.h"

#ifdef DEBUG
#define print(...) printf(__VA_ARGS__)
#else
#define print(...)
#endif

using namespace std;

namespace{
const unsigned kSleepSecs = 0;
const unsigned kSleepUsecs = 10000;
const double kNanoToBase = 1e-9;
const long long kBaseToNano = 1000000000;
const long long kMicroToNano = 1000;
const long long kCounterMax = numeric_limits<unsigned int>::max();
const int kBufSize = 1024;
const int kReadPipe = 0;
const int kWritePipe = 1;
const char* kBufFileName = "eaudit.out";
const char* kCounterNames[] = {
  (char*) "rapl:::PACKAGE_ENERGY:PACKAGE0",
  (char*) "rapl:::PP0_ENERGY:PACKAGE0",
  (char*) "PAPI_TOT_INS",
  (char*) "PAPI_TOT_CYC",
};
constexpr int kNumCounters = sizeof(kCounterNames) / sizeof(kCounterNames[0]);
}

struct stats_t {
  long long time;
  long long counters[kNumCounters];
  stats_t& operator+=(const stats_t &rhs){
    time += rhs.time;
    for(int i = 0; i < kNumCounters; ++i){
      counters[i] += rhs.counters[i];
    }
    return *this;
  }
};

struct trace_entry{
  void* return_addr;
  stats_t stats;
};

inline stats_t operator+(stats_t lhs, const stats_t& rhs) {
  return lhs += rhs;
}

void overflow(int signum, siginfo_t* info, void* context);
string parse_backtrace_entry(string entry);
stats_t read_rapl();
string demangle_func_name(string mangled_name);

struct EnergyAuditor {
  static map<int, vector<int> > component_events;
  static vector<int> eventsets;
  static int myfd;
  static vector<string> counter_names;

  EnergyAuditor() {
    assert(kSleepSecs > 0 ||
           kSleepUsecs > 1000 && "ERROR: must sleep for more than 1ms");
    print("init\n");
    int retval;
    if ((retval = PAPI_library_init(PAPI_VER_CURRENT)) != PAPI_VER_CURRENT) {
      fprintf(stderr, "Unable to init PAPI library.\n");
      switch (retval) {
        case PAPI_EINVAL:
          fprintf(stderr, "einval\n");
          break;
        case PAPI_ENOMEM:
          fprintf(stderr, "enomem\n");
          break;
        case PAPI_ESBSTR:
          fprintf(stderr, "esbstr\n");
          break;
        case PAPI_ESYS:
          fprintf(stderr, "esys\n");
          break;
      }
      exit(-1);
    }

    for (auto& event_name : kCounterNames) {
      int event_code;
      retval = PAPI_event_name_to_code((char*)event_name, &event_code);
      if (retval != PAPI_OK) {
        PAPI_perror(NULL);
        exit(-1);
      }
      int component = PAPI_get_event_component(event_code);
      component_events[component].push_back(event_code);
    }

    for (auto& component : component_events) {
      int eventset = PAPI_NULL;
      PAPI_create_eventset(&eventset);
      if (retval != PAPI_OK) {
        PAPI_perror(NULL);
        exit(-1);
      }
      for(const auto& event : component.second){
        char name[PAPI_MAX_STR_LEN];
        PAPI_event_code_to_name(event, name);
        counter_names.emplace_back(name);
      }
      PAPI_add_events(eventset, &component.second[0], component.second.size());
      if (retval != PAPI_OK) {
        PAPI_perror(NULL);
        exit(-1);
      }
      eventsets.push_back(eventset);
    }

    for (auto& eventset : eventsets) {
      retval = PAPI_start(eventset);
      if (retval != PAPI_OK) {
        PAPI_perror(NULL);
        exit(-1);
      }
    }

    // set up signal handler
    struct sigaction sa;
    sa.sa_sigaction = overflow;
    sa.sa_flags = SA_SIGINFO | SA_RESTART;
    if (sigaction(SIGALRM, &sa, nullptr) != 0) {
      fprintf(stderr, "Unable to set up signal handler\n");
      exit(-1);
    }

    if ((myfd = open(kBufFileName, O_RDWR | O_CREAT | O_TRUNC,
                     S_IRUSR | S_IWUSR)) == -1) {
      cerr << "Unable to open file" << endl;
      exit(-1);
    }

    struct itimerval work_time;
    work_time.it_value.tv_sec = kSleepSecs;
    work_time.it_value.tv_usec = kSleepUsecs;
    work_time.it_interval.tv_sec = kSleepSecs;
    work_time.it_interval.tv_usec = kSleepUsecs;
    setitimer(ITIMER_REAL, &work_time, nullptr);
  }

  ~EnergyAuditor() {
    print("shutdown\n");
    struct itimerval work_time;
    work_time.it_value.tv_sec = 0;
    work_time.it_value.tv_usec = 0;
    work_time.it_interval.tv_sec = 0;
    work_time.it_interval.tv_usec = 0;
    setitimer(ITIMER_REAL, &work_time, nullptr);

    ssize_t nread;
    trace_entry entry;
    map<string, stats_t> stat_map;
    lseek(myfd, 0, SEEK_SET);
    while ((nread = read(myfd, (void*)&entry, sizeof(entry))) ==
           sizeof(entry)) {
      auto symbol = backtrace_symbols(&entry.return_addr, 1)[0];
      auto mangled = parse_backtrace_entry(symbol);
      auto name = demangle_func_name(mangled);
      stat_map[name] += entry.stats;
    }

    vector<pair<string, stats_t> > stats;
    for (auto& func : stat_map) {
      stats.emplace_back(func.first, func.second);
    }

    stable_sort(stats.begin(), stats.end(), [](const pair<string, stats_t>& a,
                                               const pair<string, stats_t>& b) {
      return a.second.time > b.second.time;
    });

    ofstream myfile;
    myfile.open("eaudit.tsv");
    myfile << "Func Name"
           << "\t"
           << "Time(s)";
    for(const auto& name : counter_names){
      myfile << "\t" << name;
    }
    myfile << endl;

    for (auto& func : stats) {
      myfile << func.first << "\t" << func.second.time* kNanoToBase;
      for (int i = 0; i < kNumCounters; ++i) {
        myfile << "\t" << func.second.counters[i];
      }
      myfile << endl;
    }
    myfile.close();
  }
};

stats_t read_rapl(){
  const auto& esets = EnergyAuditor::eventsets;
  stats_t res;
  int cntr_offset = 0;
  for(int i = 0; i < esets.size(); ++i){
    int retval=PAPI_stop(esets[i], res.counters + cntr_offset);
    if(retval != PAPI_OK){
      PAPI_perror(NULL);
      exit(-1);
    }
    retval = PAPI_start(esets[i]);
    if(retval != PAPI_OK){
      PAPI_perror(NULL);
      exit(-1);
    }
    cntr_offset += EnergyAuditor::component_events[esets[i]].size();
  }
  res.time = kSleepSecs * kBaseToNano + kSleepUsecs * kMicroToNano;
  return res;
}

void overflow(int signum, siginfo_t* info, void* context){
  if(signum == SIGALRM){
    //print("overflow\n");

    ucontext_t* uc = (ucontext_t*) context;
    void* caller = (void*) uc->uc_mcontext.gregs[REG_RIP];
    trace_entry entry;
    entry.return_addr = (void*) uc->uc_mcontext.gregs[REG_RIP];
    entry.stats = read_rapl();
    auto res = write(EnergyAuditor::myfd, &entry, sizeof(entry));
    if(res == -1){
      cerr << "Unable to write to pipe." << endl;
      exit(-1);
    }
  }
}

string parse_backtrace_entry(string entry){
  char* name_start = nullptr;
  string::size_type name_len = 0;
  for(char* p = (char*) entry.c_str(); *p; ++p){
    if(*p == '('){
      name_start = p + 1;
    }
    if(*p == '+' && name_start){
      name_len = p - name_start;
      break;
    }
  }
  return string{name_start, name_len};
}

string demangle_func_name(string mangled_name) {
  int status;
  char* demangled_name = __cxxabiv1::__cxa_demangle(mangled_name.c_str(), NULL, 0, &status);
  if (status == 0 && demangled_name != 0) {
    string result(demangled_name);
    free(demangled_name);
    return result;
  }
  else
    return string(mangled_name);
}

map<int, vector<int> > EnergyAuditor::component_events;
vector<int> EnergyAuditor::eventsets;
int EnergyAuditor::myfd;
vector<string> EnergyAuditor::counter_names;
static EnergyAuditor auditor;

<commit_msg>ensure sampling rate is at least 2x counter update to satisfy nyquist etc etc<commit_after>#include <sstream>
#include <cxxabi.h>
#include <cassert>
#include <iomanip>
#include <algorithm>
#include <map>
#include <stack>
#include <limits>
#include <vector>
#include <string>
#include <iostream>
#include <fstream>
#include <sys/time.h>
#include <signal.h>
#include <execinfo.h>
#include <errno.h>
#include <cstdio>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <ucontext.h>

#include "papi.h"

#ifdef DEBUG
#define print(...) printf(__VA_ARGS__)
#else
#define print(...)
#endif

using namespace std;

namespace{
const unsigned kSleepSecs = 0;
const unsigned kSleepUsecs = 500;
const double kNanoToBase = 1e-9;
const long long kBaseToNano = 1000000000;
const long long kMicroToNano = 1000;
const long long kCounterMax = numeric_limits<unsigned int>::max();
const int kBufSize = 1024;
const int kReadPipe = 0;
const int kWritePipe = 1;
const char* kBufFileName = "eaudit.out";
const char* kCounterNames[] = {
  (char*) "rapl:::PACKAGE_ENERGY:PACKAGE0",
  (char*) "rapl:::PP0_ENERGY:PACKAGE0",
  (char*) "PAPI_TOT_INS",
  (char*) "PAPI_TOT_CYC",
};
constexpr int kNumCounters = sizeof(kCounterNames) / sizeof(kCounterNames[0]);
}

struct stats_t {
  long long time;
  long long counters[kNumCounters];
  stats_t& operator+=(const stats_t &rhs){
    time += rhs.time;
    for(int i = 0; i < kNumCounters; ++i){
      counters[i] += rhs.counters[i];
    }
    return *this;
  }
};

struct trace_entry{
  void* return_addr;
  stats_t stats;
};

inline stats_t operator+(stats_t lhs, const stats_t& rhs) {
  return lhs += rhs;
}

void overflow(int signum, siginfo_t* info, void* context);
string parse_backtrace_entry(string entry);
stats_t read_rapl();
string demangle_func_name(string mangled_name);

struct EnergyAuditor {
  static map<int, vector<int> > component_events;
  static vector<int> eventsets;
  static int myfd;
  static vector<string> counter_names;

  EnergyAuditor() {
    assert(kSleepSecs == 0 &&
           kSleepUsecs <= 500 && "ERROR: must update for less than .5ms (ie half rapl update rate");
    print("init\n");
    int retval;
    if ((retval = PAPI_library_init(PAPI_VER_CURRENT)) != PAPI_VER_CURRENT) {
      fprintf(stderr, "Unable to init PAPI library.\n");
      switch (retval) {
        case PAPI_EINVAL:
          fprintf(stderr, "einval\n");
          break;
        case PAPI_ENOMEM:
          fprintf(stderr, "enomem\n");
          break;
        case PAPI_ESBSTR:
          fprintf(stderr, "esbstr\n");
          break;
        case PAPI_ESYS:
          fprintf(stderr, "esys\n");
          break;
      }
      exit(-1);
    }

    for (auto& event_name : kCounterNames) {
      int event_code;
      retval = PAPI_event_name_to_code((char*)event_name, &event_code);
      if (retval != PAPI_OK) {
        PAPI_perror(NULL);
        exit(-1);
      }
      int component = PAPI_get_event_component(event_code);
      component_events[component].push_back(event_code);
    }

    for (auto& component : component_events) {
      int eventset = PAPI_NULL;
      PAPI_create_eventset(&eventset);
      if (retval != PAPI_OK) {
        PAPI_perror(NULL);
        exit(-1);
      }
      for(const auto& event : component.second){
        char name[PAPI_MAX_STR_LEN];
        PAPI_event_code_to_name(event, name);
        counter_names.emplace_back(name);
      }
      PAPI_add_events(eventset, &component.second[0], component.second.size());
      if (retval != PAPI_OK) {
        PAPI_perror(NULL);
        exit(-1);
      }
      eventsets.push_back(eventset);
    }

    for (auto& eventset : eventsets) {
      retval = PAPI_start(eventset);
      if (retval != PAPI_OK) {
        PAPI_perror(NULL);
        exit(-1);
      }
    }

    // set up signal handler
    struct sigaction sa;
    sa.sa_sigaction = overflow;
    sa.sa_flags = SA_SIGINFO | SA_RESTART;
    if (sigaction(SIGALRM, &sa, nullptr) != 0) {
      fprintf(stderr, "Unable to set up signal handler\n");
      exit(-1);
    }

    if ((myfd = open(kBufFileName, O_RDWR | O_CREAT | O_TRUNC,
                     S_IRUSR | S_IWUSR)) == -1) {
      cerr << "Unable to open file" << endl;
      exit(-1);
    }

    struct itimerval work_time;
    work_time.it_value.tv_sec = kSleepSecs;
    work_time.it_value.tv_usec = kSleepUsecs;
    work_time.it_interval.tv_sec = kSleepSecs;
    work_time.it_interval.tv_usec = kSleepUsecs;
    setitimer(ITIMER_REAL, &work_time, nullptr);
  }

  ~EnergyAuditor() {
    print("shutdown\n");
    struct itimerval work_time;
    work_time.it_value.tv_sec = 0;
    work_time.it_value.tv_usec = 0;
    work_time.it_interval.tv_sec = 0;
    work_time.it_interval.tv_usec = 0;
    setitimer(ITIMER_REAL, &work_time, nullptr);

    ssize_t nread;
    trace_entry entry;
    map<string, stats_t> stat_map;
    lseek(myfd, 0, SEEK_SET);
    while ((nread = read(myfd, (void*)&entry, sizeof(entry))) ==
           sizeof(entry)) {
      auto symbol = backtrace_symbols(&entry.return_addr, 1)[0];
      auto mangled = parse_backtrace_entry(symbol);
      auto name = demangle_func_name(mangled);
      stat_map[name] += entry.stats;
    }

    vector<pair<string, stats_t> > stats;
    for (auto& func : stat_map) {
      stats.emplace_back(func.first, func.second);
    }

    stable_sort(stats.begin(), stats.end(), [](const pair<string, stats_t>& a,
                                               const pair<string, stats_t>& b) {
      return a.second.time > b.second.time;
    });

    ofstream myfile;
    myfile.open("eaudit.tsv");
    myfile << "Func Name"
           << "\t"
           << "Time(s)";
    for(const auto& name : counter_names){
      myfile << "\t" << name;
    }
    myfile << endl;

    for (auto& func : stats) {
      myfile << func.first << "\t" << func.second.time* kNanoToBase;
      for (int i = 0; i < kNumCounters; ++i) {
        myfile << "\t" << func.second.counters[i];
      }
      myfile << endl;
    }
    myfile.close();
  }
};

stats_t read_rapl(){
  const auto& esets = EnergyAuditor::eventsets;
  stats_t res;
  int cntr_offset = 0;
  for(unsigned i = 0; i < esets.size(); ++i){
    int retval=PAPI_stop(esets[i], res.counters + cntr_offset);
    if(retval != PAPI_OK){
      PAPI_perror(NULL);
      exit(-1);
    }
    retval = PAPI_start(esets[i]);
    if(retval != PAPI_OK){
      PAPI_perror(NULL);
      exit(-1);
    }
    cntr_offset += EnergyAuditor::component_events[esets[i]].size();
  }
  res.time = kSleepSecs * kBaseToNano + kSleepUsecs * kMicroToNano;
  return res;
}

void overflow(int signum, siginfo_t* info, void* context){
  if(signum == SIGALRM){
    //print("overflow\n");

    ucontext_t* uc = (ucontext_t*) context;
    trace_entry entry;
    entry.return_addr = (void*) uc->uc_mcontext.gregs[REG_RIP];
    entry.stats = read_rapl();
    auto res = write(EnergyAuditor::myfd, &entry, sizeof(entry));
    if(res == -1){
      cerr << "Unable to write to pipe." << endl;
      exit(-1);
    }
  }
}

string parse_backtrace_entry(string entry){
  char* name_start = nullptr;
  string::size_type name_len = 0;
  for(char* p = (char*) entry.c_str(); *p; ++p){
    if(*p == '('){
      name_start = p + 1;
    }
    if(*p == '+' && name_start){
      name_len = p - name_start;
      break;
    }
  }
  return string{name_start, name_len};
}

string demangle_func_name(string mangled_name) {
  int status;
  char* demangled_name = __cxxabiv1::__cxa_demangle(mangled_name.c_str(), NULL, 0, &status);
  if (status == 0 && demangled_name != 0) {
    string result(demangled_name);
    free(demangled_name);
    return result;
  }
  else
    return string(mangled_name);
}

map<int, vector<int> > EnergyAuditor::component_events;
vector<int> EnergyAuditor::eventsets;
int EnergyAuditor::myfd;
vector<string> EnergyAuditor::counter_names;
static EnergyAuditor auditor;

<|endoftext|>