<commit_before>// Copyright (C) 2016 Elviss Strazdins
// This file is part of the Ouzel engine.

#define NOMINMAX
#include <windows.h>
#include "InputWin.h"
#include "core/Application.h"
#include "core/Engine.h"
#include "core/windows/WindowWin.h"
#include "events/EventDispatcher.h"
#include "GamepadWin.h"
#include "utils/Log.h"

namespace ouzel
{
    namespace input
    {
        KeyboardKey InputWin::convertKeyCode(WPARAM wParam)
        {
            switch (wParam)
            {
                case VK_CANCEL: return KeyboardKey::CANCEL;
                case VK_BACK: return KeyboardKey::BACKSPACE;
                case VK_TAB: return KeyboardKey::TAB;
                case VK_CLEAR: return KeyboardKey::CLEAR;
                case VK_RETURN: return KeyboardKey::RETURN;
                case VK_SHIFT: return KeyboardKey::SHIFT;
                case VK_CONTROL: return KeyboardKey::CONTROL;
                case VK_MENU: return KeyboardKey::LALT;
                case VK_PAUSE: return KeyboardKey::PAUSE;
                case VK_CAPITAL: return KeyboardKey::CAPITAL;

                    // ... Japanese ...

                case VK_ESCAPE: return KeyboardKey::ESCAPE;

                    // ... IME ...

                case VK_SPACE: return KeyboardKey::SPACE;
                case VK_PRIOR: return KeyboardKey::PRIOR;
                case VK_NEXT: return KeyboardKey::NEXT;
                case VK_END: return KeyboardKey::END;
                case VK_HOME: return KeyboardKey::HOME;
                case VK_LEFT: return KeyboardKey::LEFT;
                case VK_UP: return KeyboardKey::UP;
                case VK_RIGHT: return KeyboardKey::RIGHT;
                case VK_DOWN: return KeyboardKey::DOWN;

                case VK_SELECT: return KeyboardKey::SELECT;
                case VK_PRINT: return KeyboardKey::PRINT;
                case VK_EXECUTE: return KeyboardKey::EXECUTE;

                case VK_SNAPSHOT: return KeyboardKey::SNAPSHOT;
                case VK_INSERT: return KeyboardKey::INSERT;
                case VK_DELETE: return KeyboardKey::DEL;
                case VK_HELP: return KeyboardKey::HELP;

                case '0': return KeyboardKey::KEY_0;
                case '1': return KeyboardKey::KEY_1;
                case '2': return KeyboardKey::KEY_2;
                case '3': return KeyboardKey::KEY_3;
                case '4': return KeyboardKey::KEY_4;
                case '5': return KeyboardKey::KEY_5;
                case '6': return KeyboardKey::KEY_6;
                case '7': return KeyboardKey::KEY_7;
                case '8': return KeyboardKey::KEY_8;
                case '9': return KeyboardKey::KEY_9;

                case 'A': return KeyboardKey::KEY_A;
                case 'B': return KeyboardKey::KEY_B;
                case 'C': return KeyboardKey::KEY_C;
                case 'D': return KeyboardKey::KEY_D;
                case 'E': return KeyboardKey::KEY_E;
                case 'F': return KeyboardKey::KEY_F;
                case 'G': return KeyboardKey::KEY_G;
                case 'H': return KeyboardKey::KEY_H;
                case 'I': return KeyboardKey::KEY_I;
                case 'J': return KeyboardKey::KEY_J;
                case 'K': return KeyboardKey::KEY_K;
                case 'L': return KeyboardKey::KEY_L;
                case 'M': return KeyboardKey::KEY_M;
                case 'N': return KeyboardKey::KEY_N;
                case 'O': return KeyboardKey::KEY_O;
                case 'P': return KeyboardKey::KEY_P;
                case 'Q': return KeyboardKey::KEY_Q;
                case 'R': return KeyboardKey::KEY_R;
                case 'S': return KeyboardKey::KEY_S;
                case 'T': return KeyboardKey::KEY_T;
                case 'U': return KeyboardKey::KEY_U;
                case 'V': return KeyboardKey::KEY_V;
                case 'W': return KeyboardKey::KEY_W;
                case 'X': return KeyboardKey::KEY_X;
                case 'Y': return KeyboardKey::KEY_Y;
                case 'Z': return KeyboardKey::KEY_Z;

                case VK_LWIN: return KeyboardKey::LSUPER;
                case VK_RWIN: return KeyboardKey::RSUPER;
                case VK_APPS: return KeyboardKey::APPS;
                case VK_SLEEP: return KeyboardKey::SLEEP;

                case VK_NUMPAD0: return KeyboardKey::NUMPAD0;
                case VK_NUMPAD1: return KeyboardKey::NUMPAD1;
                case VK_NUMPAD2: return KeyboardKey::NUMPAD2;
                case VK_NUMPAD3: return KeyboardKey::NUMPAD3;
                case VK_NUMPAD4: return KeyboardKey::NUMPAD4;
                case VK_NUMPAD5: return KeyboardKey::NUMPAD5;
                case VK_NUMPAD6: return KeyboardKey::NUMPAD6;
                case VK_NUMPAD7: return KeyboardKey::NUMPAD7;
                case VK_NUMPAD8: return KeyboardKey::NUMPAD8;
                case VK_NUMPAD9: return KeyboardKey::NUMPAD9;

                case VK_MULTIPLY: return KeyboardKey::MULTIPLY;
                case VK_ADD: return KeyboardKey::ADD;
                case VK_SEPARATOR: return KeyboardKey::SEPARATOR;
                case VK_SUBTRACT: return KeyboardKey::SUBTRACT;
                case VK_DECIMAL: return KeyboardKey::DECIMAL;
                case VK_DIVIDE: return KeyboardKey::DIVIDE;

                case VK_F1: return KeyboardKey::F1;
                case VK_F2: return KeyboardKey::F2;
                case VK_F3: return KeyboardKey::F3;
                case VK_F4: return KeyboardKey::F4;
                case VK_F5: return KeyboardKey::F5;
                case VK_F6: return KeyboardKey::F6;
                case VK_F7: return KeyboardKey::F7;
                case VK_F8: return KeyboardKey::F8;
                case VK_F9: return KeyboardKey::F9;
                case VK_F10: return KeyboardKey::F10;
                case VK_F11: return KeyboardKey::F11;
                case VK_F12: return KeyboardKey::F12;
                case VK_F13: return KeyboardKey::F13;
                case VK_F14: return KeyboardKey::F14;
                case VK_F15: return KeyboardKey::F15;
                case VK_F16: return KeyboardKey::F16;
                case VK_F17: return KeyboardKey::F17;
                case VK_F18: return KeyboardKey::F18;
                case VK_F19: return KeyboardKey::F19;
                case VK_F20: return KeyboardKey::F20;
                case VK_F21: return KeyboardKey::F21;
                case VK_F22: return KeyboardKey::F22;
                case VK_F23: return KeyboardKey::F23;
                case VK_F24: return KeyboardKey::F24;

                case VK_NUMLOCK: return KeyboardKey::NUMLOCK;
                case VK_SCROLL: return KeyboardKey::SCROLL;
                case VK_LSHIFT: return KeyboardKey::LSHIFT;
                case VK_RSHIFT: return KeyboardKey::RSHIFT;
                case VK_LCONTROL: return KeyboardKey::LCONTROL;
                case VK_RCONTROL: return KeyboardKey::RCONTROL;
                case VK_LMENU: return KeyboardKey::LALT;
                case VK_RMENU: return KeyboardKey::RALT;

                case VK_OEM_1: return KeyboardKey::SEMICOLON;
                case VK_OEM_PLUS: return KeyboardKey::PLUS;
                case VK_OEM_COMMA: return KeyboardKey::COMMA;
                case VK_OEM_MINUS: return KeyboardKey::MINUS;
                case VK_OEM_PERIOD: return KeyboardKey::PERIOD;
                case VK_OEM_2: return KeyboardKey::SLASH;
                case VK_OEM_3: return KeyboardKey::GRAVE;
                case VK_OEM_4: return KeyboardKey::BRACKET_LEFT;
                case VK_OEM_5: return KeyboardKey::BACKSLASH;
                case VK_OEM_6: return KeyboardKey::BRACKET_RIGHT;
                case VK_OEM_7: return KeyboardKey::QUOTE;
                case VK_OEM_8: return KeyboardKey::GRAVE;
                case VK_OEM_AX: return KeyboardKey::OEM_AX;
                case VK_OEM_102: return KeyboardKey::LESS;
            }
            return KeyboardKey::NONE;
        }

        uint32_t InputWin::getKeyboardModifiers(WPARAM wParam)
        {
            uint32_t modifiers = 0;

            if (wParam & MK_SHIFT) modifiers |= SHIFT_DOWN;
            if (wParam & MK_ALT) modifiers |= ALT_DOWN;
            if (wParam & MK_CONTROL) modifiers |= CONTROL_DOWN;

            return modifiers;
        }

        uint32_t InputWin::getMouseModifiers(WPARAM wParam)
        {
            uint32_t modifiers = 0;

            if (wParam & MK_SHIFT) modifiers |= SHIFT_DOWN;
            if (GetKeyState(VK_MENU) & 0x8000) modifiers |= ALT_DOWN;
            if (wParam & MK_CONTROL) modifiers |= CONTROL_DOWN;
            if (wParam & MK_LBUTTON) modifiers |= LEFT_MOUSE_DOWN;
            if (wParam & MK_RBUTTON) modifiers |= RIGHT_MOUSE_DOWN;
            if (wParam & MK_MBUTTON) modifiers |= MIDDLE_MOUSE_DOWN;

            return modifiers;
        }

        InputWin::InputWin()
        {
        }

        InputWin::~InputWin()
        {
        }

        void InputWin::update()
        {
            for (DWORD i = 0; i < XUSER_MAX_COUNT; ++i)
            {
                XINPUT_STATE state;

                memset(&state, 0, sizeof(XINPUT_STATE));

                DWORD result = XInputGetState(i, &state);

                if (result == ERROR_SUCCESS)
                {
                    if (!gamepads[i])
                    {
                        gamepads[i].reset(new GamepadWin(static_cast<int32_t>(i)));

                        Event event;
                        event.type = Event::Type::GAMEPAD_CONNECT;

                        event.gamepadEvent.gamepad = gamepads[i].get();

                        sharedEngine->getEventDispatcher()->postEvent(event);
                    }

                    gamepads[i]->update(state);
                }
                else if (result == ERROR_DEVICE_NOT_CONNECTED)
                {
                    if (gamepads[i])
                    {
                        Event event;
                        event.type = Event::Type::GAMEPAD_DISCONNECT;

                        event.gamepadEvent.gamepad = gamepads[i].get();

                        sharedEngine->getEventDispatcher()->postEvent(event);

                        gamepads[i].reset();
                    }
                }
                else
                {
                    Log(Log::Level::WARN) << "Failed to get state for gamepad " << i;
                }
            }
        }

        void InputWin::setCursorVisible(bool visible)
        {
            cursorVisible = visible;

            sharedApplication->execute([visible] {
                if (visible)
                {
                    SetCursor(LoadCursor(nullptr, IDC_ARROW));
                }
                else
                {
                    SetCursor(nullptr);
                }
            });
        }

        bool InputWin::isCursorVisible() const
        {
            return cursorVisible;
        }

        void InputApple::setCursorPosition(const Vector2& position)
        {
            Input::setCursorPosition(position);

            sharedApplication->execute([position] {
                POINT pt;
                p.x = static_cast<LONG>(position.x);
                p.y = static_cast<LONG>(position.y);
                ClientToScreen(static_cast<WindowWin*>(sharedEngine->getWindow())->getNativeWindow(), &p);
                SetCursorPos(static_cast<int>(p.x),
                             static_cast<int>(p.y));
            });
        }
    } // namespace input
} // namespace ouzel
<commit_msg>Fix the name of variable<commit_after>// Copyright (C) 2016 Elviss Strazdins
// This file is part of the Ouzel engine.

#define NOMINMAX
#include <windows.h>
#include "InputWin.h"
#include "core/Application.h"
#include "core/Engine.h"
#include "core/windows/WindowWin.h"
#include "events/EventDispatcher.h"
#include "GamepadWin.h"
#include "utils/Log.h"

namespace ouzel
{
    namespace input
    {
        KeyboardKey InputWin::convertKeyCode(WPARAM wParam)
        {
            switch (wParam)
            {
                case VK_CANCEL: return KeyboardKey::CANCEL;
                case VK_BACK: return KeyboardKey::BACKSPACE;
                case VK_TAB: return KeyboardKey::TAB;
                case VK_CLEAR: return KeyboardKey::CLEAR;
                case VK_RETURN: return KeyboardKey::RETURN;
                case VK_SHIFT: return KeyboardKey::SHIFT;
                case VK_CONTROL: return KeyboardKey::CONTROL;
                case VK_MENU: return KeyboardKey::LALT;
                case VK_PAUSE: return KeyboardKey::PAUSE;
                case VK_CAPITAL: return KeyboardKey::CAPITAL;

                    // ... Japanese ...

                case VK_ESCAPE: return KeyboardKey::ESCAPE;

                    // ... IME ...

                case VK_SPACE: return KeyboardKey::SPACE;
                case VK_PRIOR: return KeyboardKey::PRIOR;
                case VK_NEXT: return KeyboardKey::NEXT;
                case VK_END: return KeyboardKey::END;
                case VK_HOME: return KeyboardKey::HOME;
                case VK_LEFT: return KeyboardKey::LEFT;
                case VK_UP: return KeyboardKey::UP;
                case VK_RIGHT: return KeyboardKey::RIGHT;
                case VK_DOWN: return KeyboardKey::DOWN;

                case VK_SELECT: return KeyboardKey::SELECT;
                case VK_PRINT: return KeyboardKey::PRINT;
                case VK_EXECUTE: return KeyboardKey::EXECUTE;

                case VK_SNAPSHOT: return KeyboardKey::SNAPSHOT;
                case VK_INSERT: return KeyboardKey::INSERT;
                case VK_DELETE: return KeyboardKey::DEL;
                case VK_HELP: return KeyboardKey::HELP;

                case '0': return KeyboardKey::KEY_0;
                case '1': return KeyboardKey::KEY_1;
                case '2': return KeyboardKey::KEY_2;
                case '3': return KeyboardKey::KEY_3;
                case '4': return KeyboardKey::KEY_4;
                case '5': return KeyboardKey::KEY_5;
                case '6': return KeyboardKey::KEY_6;
                case '7': return KeyboardKey::KEY_7;
                case '8': return KeyboardKey::KEY_8;
                case '9': return KeyboardKey::KEY_9;

                case 'A': return KeyboardKey::KEY_A;
                case 'B': return KeyboardKey::KEY_B;
                case 'C': return KeyboardKey::KEY_C;
                case 'D': return KeyboardKey::KEY_D;
                case 'E': return KeyboardKey::KEY_E;
                case 'F': return KeyboardKey::KEY_F;
                case 'G': return KeyboardKey::KEY_G;
                case 'H': return KeyboardKey::KEY_H;
                case 'I': return KeyboardKey::KEY_I;
                case 'J': return KeyboardKey::KEY_J;
                case 'K': return KeyboardKey::KEY_K;
                case 'L': return KeyboardKey::KEY_L;
                case 'M': return KeyboardKey::KEY_M;
                case 'N': return KeyboardKey::KEY_N;
                case 'O': return KeyboardKey::KEY_O;
                case 'P': return KeyboardKey::KEY_P;
                case 'Q': return KeyboardKey::KEY_Q;
                case 'R': return KeyboardKey::KEY_R;
                case 'S': return KeyboardKey::KEY_S;
                case 'T': return KeyboardKey::KEY_T;
                case 'U': return KeyboardKey::KEY_U;
                case 'V': return KeyboardKey::KEY_V;
                case 'W': return KeyboardKey::KEY_W;
                case 'X': return KeyboardKey::KEY_X;
                case 'Y': return KeyboardKey::KEY_Y;
                case 'Z': return KeyboardKey::KEY_Z;

                case VK_LWIN: return KeyboardKey::LSUPER;
                case VK_RWIN: return KeyboardKey::RSUPER;
                case VK_APPS: return KeyboardKey::APPS;
                case VK_SLEEP: return KeyboardKey::SLEEP;

                case VK_NUMPAD0: return KeyboardKey::NUMPAD0;
                case VK_NUMPAD1: return KeyboardKey::NUMPAD1;
                case VK_NUMPAD2: return KeyboardKey::NUMPAD2;
                case VK_NUMPAD3: return KeyboardKey::NUMPAD3;
                case VK_NUMPAD4: return KeyboardKey::NUMPAD4;
                case VK_NUMPAD5: return KeyboardKey::NUMPAD5;
                case VK_NUMPAD6: return KeyboardKey::NUMPAD6;
                case VK_NUMPAD7: return KeyboardKey::NUMPAD7;
                case VK_NUMPAD8: return KeyboardKey::NUMPAD8;
                case VK_NUMPAD9: return KeyboardKey::NUMPAD9;

                case VK_MULTIPLY: return KeyboardKey::MULTIPLY;
                case VK_ADD: return KeyboardKey::ADD;
                case VK_SEPARATOR: return KeyboardKey::SEPARATOR;
                case VK_SUBTRACT: return KeyboardKey::SUBTRACT;
                case VK_DECIMAL: return KeyboardKey::DECIMAL;
                case VK_DIVIDE: return KeyboardKey::DIVIDE;

                case VK_F1: return KeyboardKey::F1;
                case VK_F2: return KeyboardKey::F2;
                case VK_F3: return KeyboardKey::F3;
                case VK_F4: return KeyboardKey::F4;
                case VK_F5: return KeyboardKey::F5;
                case VK_F6: return KeyboardKey::F6;
                case VK_F7: return KeyboardKey::F7;
                case VK_F8: return KeyboardKey::F8;
                case VK_F9: return KeyboardKey::F9;
                case VK_F10: return KeyboardKey::F10;
                case VK_F11: return KeyboardKey::F11;
                case VK_F12: return KeyboardKey::F12;
                case VK_F13: return KeyboardKey::F13;
                case VK_F14: return KeyboardKey::F14;
                case VK_F15: return KeyboardKey::F15;
                case VK_F16: return KeyboardKey::F16;
                case VK_F17: return KeyboardKey::F17;
                case VK_F18: return KeyboardKey::F18;
                case VK_F19: return KeyboardKey::F19;
                case VK_F20: return KeyboardKey::F20;
                case VK_F21: return KeyboardKey::F21;
                case VK_F22: return KeyboardKey::F22;
                case VK_F23: return KeyboardKey::F23;
                case VK_F24: return KeyboardKey::F24;

                case VK_NUMLOCK: return KeyboardKey::NUMLOCK;
                case VK_SCROLL: return KeyboardKey::SCROLL;
                case VK_LSHIFT: return KeyboardKey::LSHIFT;
                case VK_RSHIFT: return KeyboardKey::RSHIFT;
                case VK_LCONTROL: return KeyboardKey::LCONTROL;
                case VK_RCONTROL: return KeyboardKey::RCONTROL;
                case VK_LMENU: return KeyboardKey::LALT;
                case VK_RMENU: return KeyboardKey::RALT;

                case VK_OEM_1: return KeyboardKey::SEMICOLON;
                case VK_OEM_PLUS: return KeyboardKey::PLUS;
                case VK_OEM_COMMA: return KeyboardKey::COMMA;
                case VK_OEM_MINUS: return KeyboardKey::MINUS;
                case VK_OEM_PERIOD: return KeyboardKey::PERIOD;
                case VK_OEM_2: return KeyboardKey::SLASH;
                case VK_OEM_3: return KeyboardKey::GRAVE;
                case VK_OEM_4: return KeyboardKey::BRACKET_LEFT;
                case VK_OEM_5: return KeyboardKey::BACKSLASH;
                case VK_OEM_6: return KeyboardKey::BRACKET_RIGHT;
                case VK_OEM_7: return KeyboardKey::QUOTE;
                case VK_OEM_8: return KeyboardKey::GRAVE;
                case VK_OEM_AX: return KeyboardKey::OEM_AX;
                case VK_OEM_102: return KeyboardKey::LESS;
            }
            return KeyboardKey::NONE;
        }

        uint32_t InputWin::getKeyboardModifiers(WPARAM wParam)
        {
            uint32_t modifiers = 0;

            if (wParam & MK_SHIFT) modifiers |= SHIFT_DOWN;
            if (wParam & MK_ALT) modifiers |= ALT_DOWN;
            if (wParam & MK_CONTROL) modifiers |= CONTROL_DOWN;

            return modifiers;
        }

        uint32_t InputWin::getMouseModifiers(WPARAM wParam)
        {
            uint32_t modifiers = 0;

            if (wParam & MK_SHIFT) modifiers |= SHIFT_DOWN;
            if (GetKeyState(VK_MENU) & 0x8000) modifiers |= ALT_DOWN;
            if (wParam & MK_CONTROL) modifiers |= CONTROL_DOWN;
            if (wParam & MK_LBUTTON) modifiers |= LEFT_MOUSE_DOWN;
            if (wParam & MK_RBUTTON) modifiers |= RIGHT_MOUSE_DOWN;
            if (wParam & MK_MBUTTON) modifiers |= MIDDLE_MOUSE_DOWN;

            return modifiers;
        }

        InputWin::InputWin()
        {
        }

        InputWin::~InputWin()
        {
        }

        void InputWin::update()
        {
            for (DWORD i = 0; i < XUSER_MAX_COUNT; ++i)
            {
                XINPUT_STATE state;

                memset(&state, 0, sizeof(XINPUT_STATE));

                DWORD result = XInputGetState(i, &state);

                if (result == ERROR_SUCCESS)
                {
                    if (!gamepads[i])
                    {
                        gamepads[i].reset(new GamepadWin(static_cast<int32_t>(i)));

                        Event event;
                        event.type = Event::Type::GAMEPAD_CONNECT;

                        event.gamepadEvent.gamepad = gamepads[i].get();

                        sharedEngine->getEventDispatcher()->postEvent(event);
                    }

                    gamepads[i]->update(state);
                }
                else if (result == ERROR_DEVICE_NOT_CONNECTED)
                {
                    if (gamepads[i])
                    {
                        Event event;
                        event.type = Event::Type::GAMEPAD_DISCONNECT;

                        event.gamepadEvent.gamepad = gamepads[i].get();

                        sharedEngine->getEventDispatcher()->postEvent(event);

                        gamepads[i].reset();
                    }
                }
                else
                {
                    Log(Log::Level::WARN) << "Failed to get state for gamepad " << i;
                }
            }
        }

        void InputWin::setCursorVisible(bool visible)
        {
            cursorVisible = visible;

            sharedApplication->execute([visible] {
                if (visible)
                {
                    SetCursor(LoadCursor(nullptr, IDC_ARROW));
                }
                else
                {
                    SetCursor(nullptr);
                }
            });
        }

        bool InputWin::isCursorVisible() const
        {
            return cursorVisible;
        }

        void InputApple::setCursorPosition(const Vector2& position)
        {
            Input::setCursorPosition(position);

            sharedApplication->execute([position] {
                POINT p;
                p.x = static_cast<LONG>(position.x);
                p.y = static_cast<LONG>(position.y);
                ClientToScreen(static_cast<WindowWin*>(sharedEngine->getWindow())->getNativeWindow(), &p);
                SetCursorPos(static_cast<int>(p.x),
                             static_cast<int>(p.y));
            });
        }
    } // namespace input
} // namespace ouzel
<|endoftext|>


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

#include <com/sun/star/io/XActiveDataSink.hpp>
#include <com/sun/star/io/XSeekable.hpp>
#include <com/sun/star/beans/NamedValue.hpp>
#include <com/sun/star/packages/XDataSinkEncrSupport.hpp>
#include <com/sun/star/uno/XComponentContext.hpp>
#include <ZipPackageEntry.hxx>
#include <rtl/ref.hxx>
#include <cppuhelper/implbase2.hxx>

#include <EncryptionData.hxx>
#include <mutexholder.hxx>

#define PACKAGE_STREAM_NOTSET           0
#define PACKAGE_STREAM_PACKAGEMEMBER    1
#define PACKAGE_STREAM_DETECT           2
#define PACKAGE_STREAM_DATA             3
#define PACKAGE_STREAM_RAW              4

class ZipPackage;
struct ZipEntry;
class ZipPackageStream : public cppu::ImplInheritanceHelper2
<
    ZipPackageEntry,
    ::com::sun::star::io::XActiveDataSink,
    ::com::sun::star::packages::XDataSinkEncrSupport
>
{
private:
    com::sun::star::uno::Reference < com::sun::star::io::XInputStream > m_xStream;
    ZipPackage          &m_rZipPackage;
    bool            m_bToBeCompressed, m_bToBeEncrypted, m_bHaveOwnKey, m_bIsEncrypted;

    ::rtl::Reference< BaseEncryptionData > m_xBaseEncryptionData;
    ::com::sun::star::uno::Sequence< ::com::sun::star::beans::NamedValue > m_aStorageEncryptionKeys;
    ::com::sun::star::uno::Sequence< sal_Int8 > m_aEncryptionKey;

    sal_Int32 m_nImportedStartKeyAlgorithm;
    sal_Int32 m_nImportedEncryptionAlgorithm;
    sal_Int32 m_nImportedChecksumAlgorithm;
    sal_Int32 m_nImportedDerivedKeySize;

    sal_uInt8   m_nStreamMode;
    sal_uInt32  m_nMagicalHackPos;
    sal_uInt32  m_nMagicalHackSize;
    sal_Int64   m_nOwnStreamOrigSize;

    bool m_bHasSeekable;
    bool m_bCompressedIsSetFromOutside;
    bool m_bFromManifest;
    bool m_bUseWinEncoding;
    bool m_bRawStream;

    ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream > GetOwnSeekStream();

public:
    bool IsEncrypted () const    { return m_bIsEncrypted;}
    bool IsPackageMember () const { return m_nStreamMode == PACKAGE_STREAM_PACKAGEMEMBER;}

    bool IsFromManifest() const { return m_bFromManifest; }
    void SetFromManifest( bool bValue ) { m_bFromManifest = bValue; }

    ::rtl::Reference< EncryptionData > GetEncryptionData( bool bWinEncoding = false );

    ::com::sun::star::uno::Sequence< sal_Int8 > GetEncryptionKey( bool bWinEncoding = false );

    sal_Int32 GetStartKeyGenID();

    sal_Int32 GetEncryptionAlgorithm() const;
    sal_Int32 GetBlockSize() const;

    void SetToBeCompressed (bool bNewValue) { m_bToBeCompressed = bNewValue;}
    void SetIsEncrypted (bool bNewValue) { m_bIsEncrypted = bNewValue;}
    void SetImportedStartKeyAlgorithm( sal_Int32 nAlgorithm ) { m_nImportedStartKeyAlgorithm = nAlgorithm; }
    void SetImportedEncryptionAlgorithm( sal_Int32 nAlgorithm ) { m_nImportedEncryptionAlgorithm = nAlgorithm; }
    void SetImportedChecksumAlgorithm( sal_Int32 nAlgorithm ) { m_nImportedChecksumAlgorithm = nAlgorithm; }
    void SetImportedDerivedKeySize( sal_Int32 nSize ) { m_nImportedDerivedKeySize = nSize; }
    void SetToBeEncrypted (bool bNewValue)
    {
        m_bToBeEncrypted  = bNewValue;
        if ( m_bToBeEncrypted && !m_xBaseEncryptionData.is())
            m_xBaseEncryptionData = new BaseEncryptionData;
        else if ( !m_bToBeEncrypted && m_xBaseEncryptionData.is() )
            m_xBaseEncryptionData.clear();
    }
    void SetPackageMember (bool bNewValue);

    void setInitialisationVector (const com::sun::star::uno::Sequence < sal_Int8 >& rNewVector )
    { m_xBaseEncryptionData->m_aInitVector = rNewVector;}
    void setSalt (const com::sun::star::uno::Sequence < sal_Int8 >& rNewSalt )
    { m_xBaseEncryptionData->m_aSalt = rNewSalt;}
    void setDigest (const com::sun::star::uno::Sequence < sal_Int8 >& rNewDigest )
    { m_xBaseEncryptionData->m_aDigest = rNewDigest;}
    void setIterationCount (const sal_Int32 nNewCount)
    { m_xBaseEncryptionData->m_nIterationCount = nNewCount;}
    void setSize (const sal_Int64 nNewSize);

    void CloseOwnStreamIfAny();

    ZipPackageStream( ZipPackage & rNewPackage,
                      const css::uno::Reference < css::uno::XComponentContext >& xContext,
                      sal_Int32 nFormat,
                      bool bAllowRemoveOnInsert );
    virtual ~ZipPackageStream( void );

    ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream > GetRawEncrStreamNoHeaderCopy();
    ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream > TryToGetRawFromDataStream(
                                                                                bool bAddHeaderForEncr );

    bool ParsePackageRawStream();
    virtual bool saveChild( const OUString &rPath,
                            std::vector < css::uno::Sequence < css::beans::PropertyValue > > &rManList,
                            ZipOutputStream & rZipOut,
                            const css::uno::Sequence < sal_Int8 >& rEncryptionKey,
                            const rtlRandomPool &rRandomPool ) SAL_OVERRIDE;

    void setZipEntryOnLoading( const ZipEntry &rInEntry);
    ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream > SAL_CALL getRawData()
        throw(::com::sun::star::uno::RuntimeException);
    void successfullyWritten( ZipEntry *pEntry );

    static ::com::sun::star::uno::Sequence < sal_Int8 > static_getImplementationId();

    // XActiveDataSink
    virtual void SAL_CALL setInputStream( const ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream >& aStream )
        throw(::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
    virtual ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream > SAL_CALL getInputStream(  )
        throw(::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;

    // XDataSinkEncrSupport
    virtual ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream > SAL_CALL getDataStream()
        throw ( ::com::sun::star::packages::WrongPasswordException, ::com::sun::star::packages::zip::ZipException,
                ::com::sun::star::io::IOException,
                ::com::sun::star::uno::RuntimeException, std::exception ) SAL_OVERRIDE;
    virtual ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream > SAL_CALL getRawStream()
        throw ( ::com::sun::star::packages::NoEncryptionException,
                ::com::sun::star::io::IOException,
                ::com::sun::star::uno::RuntimeException, std::exception ) SAL_OVERRIDE;
    virtual void SAL_CALL setDataStream(
                    const ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream >& aStream )
        throw ( ::com::sun::star::io::IOException,
                ::com::sun::star::uno::RuntimeException, std::exception ) SAL_OVERRIDE;
    virtual void SAL_CALL setRawStream(
                    const ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream >& aStream )
        throw ( ::com::sun::star::packages::EncryptionNotAllowedException,
                ::com::sun::star::packages::NoRawFormatException,
                ::com::sun::star::io::IOException,
                ::com::sun::star::uno::RuntimeException, std::exception ) SAL_OVERRIDE;
    virtual ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream > SAL_CALL getPlainRawStream()
        throw ( ::com::sun::star::io::IOException, ::com::sun::star::packages::NoEncryptionException,
                ::com::sun::star::uno::RuntimeException, std::exception ) SAL_OVERRIDE;

    // XUnoTunnel
    virtual sal_Int64 SAL_CALL getSomething( const ::com::sun::star::uno::Sequence< sal_Int8 >& aIdentifier )
        throw(::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;

    // XPropertySet
    virtual void SAL_CALL setPropertyValue( const OUString& aPropertyName, const ::com::sun::star::uno::Any& aValue )
        throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::beans::PropertyVetoException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
    virtual ::com::sun::star::uno::Any SAL_CALL getPropertyValue( const OUString& PropertyName )
        throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;

    // XServiceInfo
    virtual OUString SAL_CALL getImplementationName(  )
        throw (::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
    virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName )
        throw (::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
    virtual ::com::sun::star::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames(  )
        throw (::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
};
#endif

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

#include <com/sun/star/io/XActiveDataSink.hpp>
#include <com/sun/star/io/XSeekable.hpp>
#include <com/sun/star/beans/NamedValue.hpp>
#include <com/sun/star/packages/XDataSinkEncrSupport.hpp>
#include <com/sun/star/uno/XComponentContext.hpp>
#include <ZipPackageEntry.hxx>
#include <rtl/ref.hxx>
#include <cppuhelper/implbase2.hxx>

#include <EncryptionData.hxx>
#include <mutexholder.hxx>

#define PACKAGE_STREAM_NOTSET           0
#define PACKAGE_STREAM_PACKAGEMEMBER    1
#define PACKAGE_STREAM_DETECT           2
#define PACKAGE_STREAM_DATA             3
#define PACKAGE_STREAM_RAW              4

class ZipPackage;
struct ZipEntry;
class ZipPackageStream : public cppu::ImplInheritanceHelper2
<
    ZipPackageEntry,
    ::com::sun::star::io::XActiveDataSink,
    ::com::sun::star::packages::XDataSinkEncrSupport
>
{
private:
    com::sun::star::uno::Reference < com::sun::star::io::XInputStream > m_xStream;
    ZipPackage          &m_rZipPackage;
    bool            m_bToBeCompressed, m_bToBeEncrypted, m_bHaveOwnKey, m_bIsEncrypted;

    ::rtl::Reference< BaseEncryptionData > m_xBaseEncryptionData;
    ::com::sun::star::uno::Sequence< ::com::sun::star::beans::NamedValue > m_aStorageEncryptionKeys;
    ::com::sun::star::uno::Sequence< sal_Int8 > m_aEncryptionKey;

    sal_Int32 m_nImportedStartKeyAlgorithm;
    sal_Int32 m_nImportedEncryptionAlgorithm;
    sal_Int32 m_nImportedChecksumAlgorithm;
    sal_Int32 m_nImportedDerivedKeySize;

    sal_uInt8   m_nStreamMode;
    sal_uInt32  m_nMagicalHackPos;
    sal_uInt32  m_nMagicalHackSize;
    sal_Int64   m_nOwnStreamOrigSize;

    bool m_bHasSeekable;
    bool m_bCompressedIsSetFromOutside;
    bool m_bFromManifest;
    bool m_bUseWinEncoding;
    bool m_bRawStream;

    /// Check that m_xStream implements io::XSeekable and return it
    ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream > GetOwnSeekStream();
    ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream > SAL_CALL getRawData()
        throw(::com::sun::star::uno::RuntimeException);

public:
    bool IsEncrypted () const    { return m_bIsEncrypted;}
    bool IsPackageMember () const { return m_nStreamMode == PACKAGE_STREAM_PACKAGEMEMBER;}

    bool IsFromManifest() const { return m_bFromManifest; }
    void SetFromManifest( bool bValue ) { m_bFromManifest = bValue; }

    ::rtl::Reference< EncryptionData > GetEncryptionData( bool bWinEncoding = false );

    ::com::sun::star::uno::Sequence< sal_Int8 > GetEncryptionKey( bool bWinEncoding = false );

    sal_Int32 GetStartKeyGenID();

    sal_Int32 GetEncryptionAlgorithm() const;
    sal_Int32 GetBlockSize() const;

    void SetToBeCompressed (bool bNewValue) { m_bToBeCompressed = bNewValue;}
    void SetIsEncrypted (bool bNewValue) { m_bIsEncrypted = bNewValue;}
    void SetImportedStartKeyAlgorithm( sal_Int32 nAlgorithm ) { m_nImportedStartKeyAlgorithm = nAlgorithm; }
    void SetImportedEncryptionAlgorithm( sal_Int32 nAlgorithm ) { m_nImportedEncryptionAlgorithm = nAlgorithm; }
    void SetImportedChecksumAlgorithm( sal_Int32 nAlgorithm ) { m_nImportedChecksumAlgorithm = nAlgorithm; }
    void SetImportedDerivedKeySize( sal_Int32 nSize ) { m_nImportedDerivedKeySize = nSize; }
    void SetToBeEncrypted (bool bNewValue)
    {
        m_bToBeEncrypted  = bNewValue;
        if ( m_bToBeEncrypted && !m_xBaseEncryptionData.is())
            m_xBaseEncryptionData = new BaseEncryptionData;
        else if ( !m_bToBeEncrypted && m_xBaseEncryptionData.is() )
            m_xBaseEncryptionData.clear();
    }
    void SetPackageMember (bool bNewValue);

    void setInitialisationVector (const com::sun::star::uno::Sequence < sal_Int8 >& rNewVector )
    { m_xBaseEncryptionData->m_aInitVector = rNewVector;}
    void setSalt (const com::sun::star::uno::Sequence < sal_Int8 >& rNewSalt )
    { m_xBaseEncryptionData->m_aSalt = rNewSalt;}
    void setDigest (const com::sun::star::uno::Sequence < sal_Int8 >& rNewDigest )
    { m_xBaseEncryptionData->m_aDigest = rNewDigest;}
    void setIterationCount (const sal_Int32 nNewCount)
    { m_xBaseEncryptionData->m_nIterationCount = nNewCount;}
    void setSize (const sal_Int64 nNewSize);

    void CloseOwnStreamIfAny();

    ZipPackageStream( ZipPackage & rNewPackage,
                      const css::uno::Reference < css::uno::XComponentContext >& xContext,
                      sal_Int32 nFormat,
                      bool bAllowRemoveOnInsert );
    virtual ~ZipPackageStream( void );

    ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream > GetRawEncrStreamNoHeaderCopy();
    ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream > TryToGetRawFromDataStream(
                                                                                bool bAddHeaderForEncr );

    bool ParsePackageRawStream();
    virtual bool saveChild( const OUString &rPath,
                            std::vector < css::uno::Sequence < css::beans::PropertyValue > > &rManList,
                            ZipOutputStream & rZipOut,
                            const css::uno::Sequence < sal_Int8 >& rEncryptionKey,
                            const rtlRandomPool &rRandomPool ) SAL_OVERRIDE;

    void setZipEntryOnLoading( const ZipEntry &rInEntry);
    void successfullyWritten( ZipEntry *pEntry );

    static ::com::sun::star::uno::Sequence < sal_Int8 > static_getImplementationId();

    // XActiveDataSink
    virtual void SAL_CALL setInputStream( const ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream >& aStream )
        throw(::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
    virtual ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream > SAL_CALL getInputStream(  )
        throw(::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;

    // XDataSinkEncrSupport
    virtual ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream > SAL_CALL getDataStream()
        throw ( ::com::sun::star::packages::WrongPasswordException, ::com::sun::star::packages::zip::ZipException,
                ::com::sun::star::io::IOException,
                ::com::sun::star::uno::RuntimeException, std::exception ) SAL_OVERRIDE;
    virtual ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream > SAL_CALL getRawStream()
        throw ( ::com::sun::star::packages::NoEncryptionException,
                ::com::sun::star::io::IOException,
                ::com::sun::star::uno::RuntimeException, std::exception ) SAL_OVERRIDE;
    virtual void SAL_CALL setDataStream(
                    const ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream >& aStream )
        throw ( ::com::sun::star::io::IOException,
                ::com::sun::star::uno::RuntimeException, std::exception ) SAL_OVERRIDE;
    virtual void SAL_CALL setRawStream(
                    const ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream >& aStream )
        throw ( ::com::sun::star::packages::EncryptionNotAllowedException,
                ::com::sun::star::packages::NoRawFormatException,
                ::com::sun::star::io::IOException,
                ::com::sun::star::uno::RuntimeException, std::exception ) SAL_OVERRIDE;
    virtual ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream > SAL_CALL getPlainRawStream()
        throw ( ::com::sun::star::io::IOException, ::com::sun::star::packages::NoEncryptionException,
                ::com::sun::star::uno::RuntimeException, std::exception ) SAL_OVERRIDE;

    // XUnoTunnel
    virtual sal_Int64 SAL_CALL getSomething( const ::com::sun::star::uno::Sequence< sal_Int8 >& aIdentifier )
        throw(::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;

    // XPropertySet
    virtual void SAL_CALL setPropertyValue( const OUString& aPropertyName, const ::com::sun::star::uno::Any& aValue )
        throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::beans::PropertyVetoException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
    virtual ::com::sun::star::uno::Any SAL_CALL getPropertyValue( const OUString& PropertyName )
        throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;

    // XServiceInfo
    virtual OUString SAL_CALL getImplementationName(  )
        throw (::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
    virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName )
        throw (::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
    virtual ::com::sun::star::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames(  )
        throw (::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
};
#endif

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


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

#include "bitcoinunits.h"

#include <QStringList>

BitcoinUnits::BitcoinUnits(QObject *parent):
        QAbstractListModel(parent),
        unitlist(availableUnits())
{
}

QList<BitcoinUnits::Unit> BitcoinUnits::availableUnits()
{
    QList<BitcoinUnits::Unit> unitlist;
    unitlist.append(DOGE);
    unitlist.append(mDOGE);
    unitlist.append(uDOGE);
    unitlist.append(Koinu);
    return unitlist;
}

bool BitcoinUnits::valid(int unit)
{
    switch(unit)
    {
    case DOGE:
    case mDOGE:
    case uDOGE:
    case Koinu:
        return true;
    default:
        return false;
    }
}

QString BitcoinUnits::name(int unit)
{
    switch(unit)
    {
    case DOGE: return QString("DOGE");
    case mDOGE: return QString("mDOGE");
    case uDOGE: return QString::fromUtf8("μDOGE");
    case Koinu: return QString("Koinu")
    default: return QString("???");
    }
}

QString BitcoinUnits::description(int unit)
{
    switch(unit)
    {
    case DOGE: return QString("Dogecoin");
    case mDOGE: return QString("Milli-Dogecoin (1 / 1,000)");
    case uDOGE: return QString("Micro-Dogecoin (1 / 1,000,000)");
    case Koinu: return QString("Koinu (1 / 100,000,000")
    default: return QString("???");
    }
}

qint64 BitcoinUnits::factor(int unit)
{
    switch(unit)
    {
    case DOGE:  return 100000000;
    case mDOGE: return 100000;
    case uDOGE: return 100;
    case Koinu: return 1;
    default:   return 100000000;
    }
}

qint64 BitcoinUnits::maxAmount(int unit)
{
    switch(unit)
    {
    case DOGE:  return Q_INT64_C(900000000000);    //less than the coin supply until the year 2170
    case mDOGE: return Q_INT64_C(900000000000000);
    case uDOGE: return Q_INT64_C(900000000000000000);
    case Koinu: return Q_INT64_C(90000000000000000000);
    default:   return 0;
    }
}

int BitcoinUnits::amountDigits(int unit)
{
    switch(unit)
    {
    case DOGE: return 12;  // 900,000,000,000 (# digits, without commas)
    case mDOGE: return 15; // 900,000,000,000,000
    case uDOGE: return 18; // 900,000,000,000,000,000
    case Koinu: return 20; // 90,000,000,000,000,000,000
    default: return 0;
    }
}

int BitcoinUnits::decimals(int unit)
{
    switch(unit)
    {
    case DOGE: return 8;
    case mDOGE: return 5;
    case uDOGE: return 2;
    case Koinu: return 0;
    default: return 0;
    }
}

QString BitcoinUnits::format(int unit, qint64 n, bool fPlus)
{
    // Note: not using straight sprintf here because we do NOT want
    // localized number formatting.
    if(!valid(unit))
        return QString(); // Refuse to format invalid unit
    qint64 coin = factor(unit);
    int num_decimals = decimals(unit);
    qint64 n_abs = (n > 0 ? n : -n);
    qint64 quotient = n_abs / coin;
    qint64 remainder = n_abs % coin;
    QString quotient_str = QString::number(quotient);
    QString remainder_str = QString::number(remainder).rightJustified(num_decimals, '0');

    // Right-trim excess zeros after the decimal point
    int nTrim = 0;
    for (int i = remainder_str.size()-1; i>=2 && (remainder_str.at(i) == '0'); --i)
        ++nTrim;
    remainder_str.chop(nTrim);

    if (n < 0)
        quotient_str.insert(0, '-');
    else if (fPlus && n > 0)
        quotient_str.insert(0, '+');
    return quotient_str + QString(".") + remainder_str;
}

QString BitcoinUnits::formatWithUnit(int unit, qint64 amount, bool plussign)
{
    return format(unit, amount, plussign) + QString(" ") + name(unit);
}

bool BitcoinUnits::parse(int unit, const QString &value, qint64 *val_out)
{
    if(!valid(unit) || value.isEmpty())
        return false; // Refuse to parse invalid unit or empty string
    int num_decimals = decimals(unit);
    QStringList parts = value.split(".");

    if(parts.size() > 2)
    {
        return false; // More than one dot
    }
    QString whole = parts[0];
    QString decimals;

    if(parts.size() > 1)
    {
        decimals = parts[1];
    }
    if(decimals.size() > num_decimals)
    {
        return false; // Exceeds max precision
    }
    bool ok = false;
    QString str = whole + decimals.leftJustified(num_decimals, '0');

    if(str.size() > 18)
    {
        return false; // Longer numbers will exceed 63 bits
    }
    qint64 retvalue = str.toLongLong(&ok);
    if(val_out)
    {
        *val_out = retvalue;
    }
    return ok;
}

int BitcoinUnits::rowCount(const QModelIndex &parent) const
{
    Q_UNUSED(parent);
    return unitlist.size();
}

QVariant BitcoinUnits::data(const QModelIndex &index, int role) const
{
    int row = index.row();
    if(row >= 0 && row < unitlist.size())
    {
        Unit unit = unitlist.at(row);
        switch(role)
        {
        case Qt::EditRole:
        case Qt::DisplayRole:
            return QVariant(name(unit));
        case Qt::ToolTipRole:
            return QVariant(description(unit));
        case UnitRole:
            return QVariant(static_cast<int>(unit));
        }
    }
    return QVariant();
}
<commit_msg>Update bitcoinunits.cpp<commit_after>// Copyright (c) 2011-2013 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "bitcoinunits.h"

#include <QStringList>

BitcoinUnits::BitcoinUnits(QObject *parent):
        QAbstractListModel(parent),
        unitlist(availableUnits())
{
}

QList<BitcoinUnits::Unit> BitcoinUnits::availableUnits()
{
    QList<BitcoinUnits::Unit> unitlist;
    unitlist.append(DOGE);
    unitlist.append(mDOGE);
    unitlist.append(uDOGE);
    unitlist.append(Koinu);
    return unitlist;
}

bool BitcoinUnits::valid(int unit)
{
    switch(unit)
    {
    case DOGE:
    case mDOGE:
    case uDOGE:
    case Koinu:
        return true;
    default:
        return false;
    }
}

QString BitcoinUnits::name(int unit)
{
    switch(unit)
    {
    case DOGE: return QString("DOGE");
    case mDOGE: return QString("mDOGE");
    case uDOGE: return QString::fromUtf8("μDOGE");
    case Koinu: return QString("Koinu");
    default: return QString("???");
    }
}

QString BitcoinUnits::description(int unit)
{
    switch(unit)
    {
    case DOGE: return QString("Dogecoin");
    case mDOGE: return QString("Milli-Dogecoin (1 / 1,000)");
    case uDOGE: return QString("Micro-Dogecoin (1 / 1,000,000)");
    case Koinu: return QString("Koinu (1 / 100,000,000");
    default: return QString("???");
    }
}

qint64 BitcoinUnits::factor(int unit)
{
    switch(unit)
    {
    case DOGE:  return 100000000;
    case mDOGE: return 100000;
    case uDOGE: return 100;
    case Koinu: return 1;
    default:   return 100000000;
    }
}

qint64 BitcoinUnits::maxAmount(int unit)
{
    switch(unit)
    {
    case DOGE:  return Q_INT64_C(900000000000);    //less than the coin supply until the year 2170
    case mDOGE: return Q_INT64_C(900000000000000);
    case uDOGE: return Q_INT64_C(900000000000000000);
    case Koinu: return Q_INT64_C(90000000000000000000);
    default:   return 0;
    }
}

int BitcoinUnits::amountDigits(int unit)
{
    switch(unit)
    {
    case DOGE: return 12;  // 900,000,000,000 (# digits, without commas)
    case mDOGE: return 15; // 900,000,000,000,000
    case uDOGE: return 18; // 900,000,000,000,000,000
    case Koinu: return 20; // 90,000,000,000,000,000,000
    default: return 0;
    }
}

int BitcoinUnits::decimals(int unit)
{
    switch(unit)
    {
    case DOGE: return 8;
    case mDOGE: return 5;
    case uDOGE: return 2;
    case Koinu: return 0;
    default: return 0;
    }
}

QString BitcoinUnits::format(int unit, qint64 n, bool fPlus)
{
    // Note: not using straight sprintf here because we do NOT want
    // localized number formatting.
    if(!valid(unit))
        return QString(); // Refuse to format invalid unit
    qint64 coin = factor(unit);
    int num_decimals = decimals(unit);
    qint64 n_abs = (n > 0 ? n : -n);
    qint64 quotient = n_abs / coin;
    qint64 remainder = n_abs % coin;
    QString quotient_str = QString::number(quotient);
    QString remainder_str = QString::number(remainder).rightJustified(num_decimals, '0');

    // Right-trim excess zeros after the decimal point
    int nTrim = 0;
    for (int i = remainder_str.size()-1; i>=2 && (remainder_str.at(i) == '0'); --i)
        ++nTrim;
    remainder_str.chop(nTrim);

    if (n < 0)
        quotient_str.insert(0, '-');
    else if (fPlus && n > 0)
        quotient_str.insert(0, '+');
    return quotient_str + QString(".") + remainder_str;
}

QString BitcoinUnits::formatWithUnit(int unit, qint64 amount, bool plussign)
{
    return format(unit, amount, plussign) + QString(" ") + name(unit);
}

bool BitcoinUnits::parse(int unit, const QString &value, qint64 *val_out)
{
    if(!valid(unit) || value.isEmpty())
        return false; // Refuse to parse invalid unit or empty string
    int num_decimals = decimals(unit);
    QStringList parts = value.split(".");

    if(parts.size() > 2)
    {
        return false; // More than one dot
    }
    QString whole = parts[0];
    QString decimals;

    if(parts.size() > 1)
    {
        decimals = parts[1];
    }
    if(decimals.size() > num_decimals)
    {
        return false; // Exceeds max precision
    }
    bool ok = false;
    QString str = whole + decimals.leftJustified(num_decimals, '0');

    if(str.size() > 18)
    {
        return false; // Longer numbers will exceed 63 bits
    }
    qint64 retvalue = str.toLongLong(&ok);
    if(val_out)
    {
        *val_out = retvalue;
    }
    return ok;
}

int BitcoinUnits::rowCount(const QModelIndex &parent) const
{
    Q_UNUSED(parent);
    return unitlist.size();
}

QVariant BitcoinUnits::data(const QModelIndex &index, int role) const
{
    int row = index.row();
    if(row >= 0 && row < unitlist.size())
    {
        Unit unit = unitlist.at(row);
        switch(role)
        {
        case Qt::EditRole:
        case Qt::DisplayRole:
            return QVariant(name(unit));
        case Qt::ToolTipRole:
            return QVariant(description(unit));
        case UnitRole:
            return QVariant(static_cast<int>(unit));
        }
    }
    return QVariant();
}
<|endoftext|>


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

#include "bitcoinunits.h"

#include "primitives/transaction.h"

#include <QStringList>

BitcoinUnits::BitcoinUnits(QObject *parent):
        QAbstractListModel(parent),
        unitlist(availableUnits())
{
}

QList<BitcoinUnits::Unit> BitcoinUnits::availableUnits()
{
    QList<BitcoinUnits::Unit> unitlist;
    unitlist.append(BTC);
    unitlist.append(mBTC);
    unitlist.append(uBTC);
    return unitlist;
}

bool BitcoinUnits::valid(int unit)
{
    switch(unit)
    {
    case BTC:
    case mBTC:
    case uBTC:
        return true;
    default:
        return false;
    }
}

QString BitcoinUnits::name(int unit)
{
    switch(unit)
    {
    case BTC: return QString("LTC");
    case mBTC: return QString("mLTC");
    case uBTC: return QString::fromUtf8("μLTC");
    default: return QString("???");
    }
}

QString BitcoinUnits::description(int unit)
{
    switch(unit)
    {
    case BTC: return QString("Litecoins");
    case mBTC: return QString("Milli-Litecoins (1 / 1" THIN_SP_UTF8 "000)");
    case uBTC: return QString("Micro-Litecoins (1 / 1" THIN_SP_UTF8 "000" THIN_SP_UTF8 "000)");
    default: return QString("???");
    }
}

qint64 BitcoinUnits::factor(int unit)
{
    switch(unit)
    {
    case BTC:  return 100000000;
    case mBTC: return 100000;
    case uBTC: return 100;
    default:   return 100000000;
    }
}

int BitcoinUnits::decimals(int unit)
{
    switch(unit)
    {
    case BTC: return 8;
    case mBTC: return 5;
    case uBTC: return 2;
    default: return 0;
    }
}

QString BitcoinUnits::format(int unit, const CAmount& nIn, bool fPlus, SeparatorStyle separators)
{
    // Note: not using straight sprintf here because we do NOT want
    // localized number formatting.
    if(!valid(unit))
        return QString(); // Refuse to format invalid unit
    qint64 n = (qint64)nIn;
    qint64 coin = factor(unit);
    int num_decimals = decimals(unit);
    qint64 n_abs = (n > 0 ? n : -n);
    qint64 quotient = n_abs / coin;
    qint64 remainder = n_abs % coin;
    QString quotient_str = QString::number(quotient);
    QString remainder_str = QString::number(remainder).rightJustified(num_decimals, '0');

    // Use SI-style thin space separators as these are locale independent and can't be
    // confused with the decimal marker.
    QChar thin_sp(THIN_SP_CP);
    int q_size = quotient_str.size();
    if (separators == separatorAlways || (separators == separatorStandard && q_size > 4))
        for (int i = 3; i < q_size; i += 3)
            quotient_str.insert(q_size - i, thin_sp);

    if (n < 0)
        quotient_str.insert(0, '-');
    else if (fPlus && n > 0)
        quotient_str.insert(0, '+');
    return quotient_str + QString(".") + remainder_str;
}

// NOTE: Using formatWithUnit in an HTML context risks wrapping
// quantities at the thousands separator. More subtly, it also results
// in a standard space rather than a thin space, due to a bug in Qt's
// XML whitespace canonicalisation
//
// Please take care to use formatHtmlWithUnit instead, when
// appropriate.

QString BitcoinUnits::formatWithUnit(int unit, const CAmount& amount, bool plussign, SeparatorStyle separators)
{
    return format(unit, amount, plussign, separators) + QString(" ") + name(unit);
}

QString BitcoinUnits::formatHtmlWithUnit(int unit, const CAmount& amount, bool plussign, SeparatorStyle separators)
{
    QString str(formatWithUnit(unit, amount, plussign, separators));
    str.replace(QChar(THIN_SP_CP), QString(THIN_SP_HTML));
    return QString("%1").arg(str);
}

bool BitcoinUnits::parse(int unit, const QString &value, CAmount *val_out)
{
    if(!valid(unit) || value.isEmpty())
        return false; // Refuse to parse invalid unit or empty string
    int num_decimals = decimals(unit);

    // Ignore spaces and thin spaces when parsing
    QStringList parts = removeSpaces(value).split(".");

    if(parts.size() > 2)
    {
        return false; // More than one dot
    }
    QString whole = parts[0];
    QString decimals;

    if(parts.size() > 1)
    {
        decimals = parts[1];
    }
    if(decimals.size() > num_decimals)
    {
        return false; // Exceeds max precision
    }
    bool ok = false;
    QString str = whole + decimals.leftJustified(num_decimals, '0');

    if(str.size() > 18)
    {
        return false; // Longer numbers will exceed 63 bits
    }
    CAmount retvalue(str.toLongLong(&ok));
    if(val_out)
    {
        *val_out = retvalue;
    }
    return ok;
}

QString BitcoinUnits::getAmountColumnTitle(int unit)
{
    QString amountTitle = QObject::tr("Amount");
    if (BitcoinUnits::valid(unit))
    {
        amountTitle += " ("+BitcoinUnits::name(unit) + ")";
    }
    return amountTitle;
}

int BitcoinUnits::rowCount(const QModelIndex &parent) const
{
    Q_UNUSED(parent);
    return unitlist.size();
}

QVariant BitcoinUnits::data(const QModelIndex &index, int role) const
{
    int row = index.row();
    if(row >= 0 && row < unitlist.size())
    {
        Unit unit = unitlist.at(row);
        switch(role)
        {
        case Qt::EditRole:
        case Qt::DisplayRole:
            return QVariant(name(unit));
        case Qt::ToolTipRole:
            return QVariant(description(unit));
        case UnitRole:
            return QVariant(static_cast<int>(unit));
        }
    }
    return QVariant();
}

CAmount BitcoinUnits::maxMoney()
{
    return MAX_MONEY;
}
<commit_msg>Litecoin: Rename mLTC/μLTC to lites/photons. (#375)<commit_after>// Copyright (c) 2011-2016 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "bitcoinunits.h"

#include "primitives/transaction.h"

#include <QStringList>

BitcoinUnits::BitcoinUnits(QObject *parent):
        QAbstractListModel(parent),
        unitlist(availableUnits())
{
}

QList<BitcoinUnits::Unit> BitcoinUnits::availableUnits()
{
    QList<BitcoinUnits::Unit> unitlist;
    unitlist.append(BTC);
    unitlist.append(mBTC);
    unitlist.append(uBTC);
    return unitlist;
}

bool BitcoinUnits::valid(int unit)
{
    switch(unit)
    {
    case BTC:
    case mBTC:
    case uBTC:
        return true;
    default:
        return false;
    }
}

QString BitcoinUnits::name(int unit)
{
    switch(unit)
    {
    case BTC: return QString("LTC");
    case mBTC: return QString("lites");
    case uBTC: return QString("photons");
    default: return QString("???");
    }
}

QString BitcoinUnits::description(int unit)
{
    switch(unit)
    {
    case BTC: return QString("Litecoins");
    case mBTC: return QString("Lites (1 / 1" THIN_SP_UTF8 "000)");
    case uBTC: return QString("Photons (1 / 1" THIN_SP_UTF8 "000" THIN_SP_UTF8 "000)");
    default: return QString("???");
    }
}

qint64 BitcoinUnits::factor(int unit)
{
    switch(unit)
    {
    case BTC:  return 100000000;
    case mBTC: return 100000;
    case uBTC: return 100;
    default:   return 100000000;
    }
}

int BitcoinUnits::decimals(int unit)
{
    switch(unit)
    {
    case BTC: return 8;
    case mBTC: return 5;
    case uBTC: return 2;
    default: return 0;
    }
}

QString BitcoinUnits::format(int unit, const CAmount& nIn, bool fPlus, SeparatorStyle separators)
{
    // Note: not using straight sprintf here because we do NOT want
    // localized number formatting.
    if(!valid(unit))
        return QString(); // Refuse to format invalid unit
    qint64 n = (qint64)nIn;
    qint64 coin = factor(unit);
    int num_decimals = decimals(unit);
    qint64 n_abs = (n > 0 ? n : -n);
    qint64 quotient = n_abs / coin;
    qint64 remainder = n_abs % coin;
    QString quotient_str = QString::number(quotient);
    QString remainder_str = QString::number(remainder).rightJustified(num_decimals, '0');

    // Use SI-style thin space separators as these are locale independent and can't be
    // confused with the decimal marker.
    QChar thin_sp(THIN_SP_CP);
    int q_size = quotient_str.size();
    if (separators == separatorAlways || (separators == separatorStandard && q_size > 4))
        for (int i = 3; i < q_size; i += 3)
            quotient_str.insert(q_size - i, thin_sp);

    if (n < 0)
        quotient_str.insert(0, '-');
    else if (fPlus && n > 0)
        quotient_str.insert(0, '+');
    return quotient_str + QString(".") + remainder_str;
}

// NOTE: Using formatWithUnit in an HTML context risks wrapping
// quantities at the thousands separator. More subtly, it also results
// in a standard space rather than a thin space, due to a bug in Qt's
// XML whitespace canonicalisation
//
// Please take care to use formatHtmlWithUnit instead, when
// appropriate.

QString BitcoinUnits::formatWithUnit(int unit, const CAmount& amount, bool plussign, SeparatorStyle separators)
{
    return format(unit, amount, plussign, separators) + QString(" ") + name(unit);
}

QString BitcoinUnits::formatHtmlWithUnit(int unit, const CAmount& amount, bool plussign, SeparatorStyle separators)
{
    QString str(formatWithUnit(unit, amount, plussign, separators));
    str.replace(QChar(THIN_SP_CP), QString(THIN_SP_HTML));
    return QString("%1").arg(str);
}

bool BitcoinUnits::parse(int unit, const QString &value, CAmount *val_out)
{
    if(!valid(unit) || value.isEmpty())
        return false; // Refuse to parse invalid unit or empty string
    int num_decimals = decimals(unit);

    // Ignore spaces and thin spaces when parsing
    QStringList parts = removeSpaces(value).split(".");

    if(parts.size() > 2)
    {
        return false; // More than one dot
    }
    QString whole = parts[0];
    QString decimals;

    if(parts.size() > 1)
    {
        decimals = parts[1];
    }
    if(decimals.size() > num_decimals)
    {
        return false; // Exceeds max precision
    }
    bool ok = false;
    QString str = whole + decimals.leftJustified(num_decimals, '0');

    if(str.size() > 18)
    {
        return false; // Longer numbers will exceed 63 bits
    }
    CAmount retvalue(str.toLongLong(&ok));
    if(val_out)
    {
        *val_out = retvalue;
    }
    return ok;
}

QString BitcoinUnits::getAmountColumnTitle(int unit)
{
    QString amountTitle = QObject::tr("Amount");
    if (BitcoinUnits::valid(unit))
    {
        amountTitle += " ("+BitcoinUnits::name(unit) + ")";
    }
    return amountTitle;
}

int BitcoinUnits::rowCount(const QModelIndex &parent) const
{
    Q_UNUSED(parent);
    return unitlist.size();
}

QVariant BitcoinUnits::data(const QModelIndex &index, int role) const
{
    int row = index.row();
    if(row >= 0 && row < unitlist.size())
    {
        Unit unit = unitlist.at(row);
        switch(role)
        {
        case Qt::EditRole:
        case Qt::DisplayRole:
            return QVariant(name(unit));
        case Qt::ToolTipRole:
            return QVariant(description(unit));
        case UnitRole:
            return QVariant(static_cast<int>(unit));
        }
    }
    return QVariant();
}

CAmount BitcoinUnits::maxMoney()
{
    return MAX_MONEY;
}
<|endoftext|>


<commit_before>#ifndef DICE_RANDOM_VARIABLE_HPP_
#define DICE_RANDOM_VARIABLE_HPP_

#include <cassert>
#include <limits>
#include <vector>
#include <algorithm>
#include <unordered_map>
#include <map>

namespace dice
{
    class bernoulli_tag{};
    class constant_tag{};

    template<typename ValueType, typename ProbabilityType>
    class random_variable_decomposition;

    // discrete random variable
    template<typename ValueType, typename ProbabilityType>
    class random_variable
    {
        friend class random_variable_decomposition<ValueType, ProbabilityType>;
    public:
        using value_type = ValueType;
        using probability_type = ProbabilityType;
        using freq_list = std::vector<std::pair<value_type, std::size_t>>;

        // create an impossible event
        random_variable() {}

        // create a constant
        random_variable(constant_tag, value_type value) :
            probability_({ std::make_pair(value, 1.0) }) {}

        // create a bernoulli distribution
        random_variable(bernoulli_tag, probability_type success_prob) :
            probability_({
                std::make_pair(0, 1 - success_prob),
                std::make_pair(1, success_prob)
            })
        {
            // make this a constant if the success probability is 1 or 0
            if (success_prob <= 0)
            {
                probability_.erase(probability_.find(1));
            }
            else if (success_prob >= 1)
            {
                probability_.erase(probability_.find(0));
            }
        }

        random_variable(freq_list&& list)
        {
            probability_type sum = 0;
            for (auto&& item : list)
                sum += item.second;

            for (auto&& item : list)
            {
                if (item.second == 0)
                    continue;

                probability_.insert(std::make_pair(
                    item.first,
                    item.second / sum
                ));
            }
        }

        // allow copy
        random_variable(const random_variable&) = default;
        random_variable& operator=(const random_variable&) = default;

        // allow move
        random_variable(random_variable&&) = default;
        random_variable& operator=(random_variable&&) = default;

        // true IFF there is only 1 value in its range
        bool is_constant() const
        {
            return probability_.size() == 1;
        }

        // value of the variable (makes sense for constant variables only)
        value_type value() const
        {
            assert(is_constant());
            return probability_.begin()->first;
        }

        /** Compute expected value of this random variable.
         * @return expected value of this variable
         */
        auto expected_value() const
        {
            probability_type exp = 0;
            for (auto&& pair : probability_)
            {
                exp += pair.first * pair.second;
            }
            return exp;
        }

        /** Compute variance of this random variable.
         * @return variance of this variable
         */
        auto variance() const
        {
            probability_type sum_sq = 0;
            probability_type sum = 0;
            for (auto&& pair : probability_)
            {
                sum_sq += pair.first * pair.first * pair.second;
                sum += pair.first * pair.second;
            }
            return sum_sq - sum * sum;
        }

        /** Calculate indicator that X (this r.v.) is in given interval
         * @param lower bound of the interval
         * @param upper bound of the interval
         * @return r.v. Y with a Bernoulli distribution
         *         Y = 1 <=> X is in the [lower_bound, upper_bound] interval
         *         Y = 0 otherwise
         */
        template<typename T>
        random_variable in(const T& lower_bound, const T& upper_bound) const
        {
            probability_type success_prob = 0;
            for (auto&& pair : probability_)
            {
                if (lower_bound <= static_cast<T>(pair.first) &&
                    upper_bound >= static_cast<T>(pair.first))
                {
                    success_prob += pair.second;
                }
            }
            return random_variable{ bernoulli_tag{}, success_prob };
        }

        /** Compute distribution of X + Y (X is this random variable).
         * X and Y are assumed to be independent.
         * @param other random variable Y (independent of X)
         * @return distribution of X + Y
         */
        auto operator+(const random_variable& other) const
        {
            return combine(other, [](auto&& a, auto&& b)
            {
                return a + b;
            });
        }

        /** Compute distribution of X - Y (X is this random variable).
         * X and Y are assumed to be independent.
         * @param other random variable Y (independent of X)
         * @return distribution of X - Y
         */
        auto operator-(const random_variable& other) const
        {
            return combine(other, [](auto&& a, auto&& b)
            {
                return a - b;
            });
        }

        /** Compute distribution of X * Y (X is this random variable).
         * X and Y are assumed to be independent.
         * @param other random variable Y (independent of X)
         * @return distribution of X * Y
         */
        auto operator*(const random_variable& other) const
        {
            return combine(other, [](auto&& a, auto&& b)
            {
                return a * b;
            });
        }

        /** Compute distribution of integer division X / Y.
         * X is this random variable.
         * X and Y are assumed to be independent.
         * @param other random variable Y (independent of X)
         * @return distribution of X / Y
         */
        auto operator/(const random_variable& other) const
        {
            return combine(other, [](auto&& a, auto&& b)
            {
                return a / b;
            });
        }

        /** Compute indicator of X < Y (X is this random variable).
         * X and Y are assumed to be indepedent.
         * @param other random variable Y (independent of X)
         * @return indicator of X < Y
         *         (i.e. a random variable with a bernoulli distribution)
         */
        auto less_than(const random_variable& other) const
        {
            return combine(other, [](auto&& a, auto&& b)
            {
                return static_cast<value_type>(a < b);
            });
        }

        /** Compute indicator of X <= Y (X is this random variable).
         * X and Y are assumed to be indepedent.
         * @param other random variable Y (independent of X)
         * @return indicator of X <= Y
         *         (i.e. a random variable with a bernoulli distribution)
         */
        auto less_than_or_equal(const random_variable& other) const
        {
            return combine(other, [](auto&& a, auto&& b)
            {
                return static_cast<value_type>(a <= b);
            });
        }

        /** Compute indicator of X = Y (X is this random variable).
         * X and Y are assumed to be indepedent.
         * @param other random variable Y (independent of X)
         * @return indicator of X = Y
         *         (i.e. a random variable with a bernoulli distribution)
         */
        auto equal(const random_variable& other) const
        {
            return combine(other, [](auto&& a, auto&& b)
            {
                return static_cast<value_type>(a == b);
            });
        }

        /** Compute indicator of X != Y (X is this random variable).
         * X and Y are assumed to be indepedent.
         * @param other random variable Y (independent of X)
         * @return indicator of X != Y
         *         (i.e. a random variable with a bernoulli distribution)
         */
        auto not_equal(const random_variable& other) const
        {
            return combine(other, [](auto&& a, auto&& b)
            {
                return static_cast<value_type>(a != b);
            });
        }

        /** Compute indicator of X > Y (X is this random variable).
         * X and Y are assumed to be indepedent.
         * @param other random variable Y (independent of X)
         * @return indicator of X > Y
         *         (i.e. a random variable with a bernoulli distribution)
         */
        auto greater_than(const random_variable& other) const
        {
            return combine(other, [](auto&& a, auto&& b)
            {
                return static_cast<value_type>(a > b);
            });
        }

        /** Compute indicator of X >= Y (X is this random variable).
         * X and Y are assumed to be indepedent.
         * @param other random variable Y (independent of X)
         * @return indicator of X >= Y
         *         (i.e. a random variable with a bernoulli distribution)
         */
        auto greater_than_or_equal(const random_variable& other) const
        {
            return combine(other, [](auto&& a, auto&& b)
            {
                return static_cast<value_type>(a >= b);
            });
        }

        /** Compute negation of this random variable (-X)
         * @return a random variable -X (X is this random variable)
         */
        auto operator-() const
        {
            random_variable result;
            for (auto&& pair : probability_)
            {
                result.probability_.insert(
                    std::make_pair(-pair.first, pair.second));
            }
            return result;
        }

        /** Compute restriction of the range of this random variable.
         * Values for which given predicate returns false won't be included.
         * Probabilities will be modified so that they sum up to 1.
         * @param include predicate
         *        Returns true IFF given element should be included
         * @return a new random variable with restricted range
         */
        template<typename Predicate>
        auto restrict(Predicate include) const
        {
            probability_type prob_sum = 0;
            for (auto&& pair : probability_)
            {
                if (include(pair.first))
                {
                    prob_sum += pair.second;
                }
            }

            random_variable result;
            for (auto&& pair : probability_)
            {
                if (include(pair.first))
                {
                    // make sure probabilities sum up to 1
                    result.probability_.insert(std::make_pair(
                        pair.first,
                        pair.second / prob_sum
                    ));
                }
            }
            return result;
        }

        /**
         * Create a random variable Z = XdY.
         * X times roll a Y sided dice.
         * Assumes X, Y are independent random variables.
         *
         * This funciton implements a simple dynamic programming algorithm.
         * The probability that we roll k with X throws of a Y sided die is
         * the probability that we roll k - n with X - 1 throws of a Y sided
         * die and then roll n on the last die for n = 1 to Y.
         *
         * @param number of dice X (independent of Y)
         *        Each value has to be a positive integer
         * @param number of sides of each dice Y (independent of X)
         *        Each value has to be a positive integer
         * @return distribution of XdY
         */
        friend auto roll(
            const random_variable& num_dice,
            const random_variable& num_sides)
        {
            // If there are no dice or dice sizes,
            // then this is an impossible event
            if (num_dice.probability_.size() <= 0 ||
                num_sides.probability_.size() <= 0)
            {
                return random_variable{};
            }

            // Throw an exception if the number of dice or
            // number of dice sides is not positive.
            // note: Use the restrict method to restrict variable's
            //       range to positive integers.
            for (auto&& pair : num_dice.probability_)
            {
                if (pair.first <= 0)
                {
                    throw std::runtime_error(
                        "Number of dice has to be a positive integer.");
                }
            }

            for (auto&& pair : num_sides.probability_)
            {
                if (pair.first <= 0)
                {
                    throw std::runtime_error(
                        "Number of dice sides has to be a positive integer.");
                }
            }

            // find maximal number of dice
            auto max_dice = num_dice.probability_.rbegin()->first;

            // compute distribution for each possible number of sides
            random_variable dist;
            for (auto&& pair : num_sides.probability_)
            {
                auto sides_count = pair.first;
                auto sides_prob = pair.second;

                // probability P(XdY = k | X = dice_count, Y = sides_count)
                std::vector<probability_type> probability(
                    sides_count * max_dice + 1, 0);
                for (value_type dice_count = 1;
                    dice_count <= max_dice;
                    ++dice_count)
                {
                    // iterate backwards so that we don't override
                    // probability values that will be needed
                    for (value_type i = sides_count * dice_count; i > 0; --i)
                    {
                        // compute the probability of the sum of i
                        auto base_prob =
                            1 / static_cast<probability_type>(sides_count);
                        auto prob_i = dice_count == 1 ? base_prob : 0;
                        value_type j = std::max(i - sides_count, 1);
                        for (; j < i; ++j)
                        {
                            prob_i += probability[j] * base_prob;
                        }
                        probability[i] = prob_i;

                        // save the probability
                        auto num_rolls = num_dice.probability_.find(dice_count);
                        if (num_rolls != num_dice.probability_.end())
                        {
                            auto rolls_prob = num_rolls->second;
                            auto prob = prob_i * sides_prob * rolls_prob;
                            // don't save impossible events
                            if (prob == 0)
                                continue;

                            auto result = dist.probability_.insert(
                                std::make_pair(i, prob));
                            if (!result.second)
                            {
                                result.first->second += prob;
                            }
                        }
                    }
                }
            }
            return dist;
        }

        /** Create a random variable that is a function
         *  of this r.v. (X) and the other r.v. (Y)
         * @param other random variable Y (independent of X)
         * @param combination function of X and Y
         * @return a new random variable that is a function of X and Y
         */
        template<typename Func>
        auto combine(const random_variable& other, Func&& combination) const
        {
            random_variable dist;
            for (auto&& pair_a : probability_)
            {
                for (auto&& pair_b : other.probability_)
                {
                    auto value = combination(pair_a.first, pair_b.first);
                    auto probability = pair_b.second * pair_a.second;
                    auto result = dist.probability_.insert(
                        std::make_pair(value, probability));
                    if (!result.second)
                    {
                        result.first->second += probability;
                    }
                }
            }
            return dist;
        }

        const std::map<value_type, probability_type>& probability() const
        {
            return probability_;
        }
    private:
        std::map<value_type, probability_type> probability_;
    };

    // Calculate max(X, Y) for independent r.v. X and Y
    template<typename T, typename U>
    random_variable<T, U> max(
        const random_variable<T, U>& a,
        const random_variable<T, U>& b)
    {
        return a.combine(b, [](auto&& value_a, auto&& value_b)
        {
            return std::max(value_a, value_b);
        });
    }

    // Calculate min(X, Y) for independent r.v. X and Y
    template<typename T, typename U>
    random_variable<T, U> min(
        const random_variable<T, U>& a,
        const random_variable<T, U>& b)
    {
        return a.combine(b, [](auto&& value_a, auto&& value_b)
        {
            return std::min(value_a, value_b);
        });
    }
}

#endif // DICE_RANDOM_VARIABLE_HPP_<commit_msg>Use unordered map<commit_after>#ifndef DICE_RANDOM_VARIABLE_HPP_
#define DICE_RANDOM_VARIABLE_HPP_

#include <cassert>
#include <limits>
#include <vector>
#include <algorithm>
#include <unordered_map>
#include <map>

namespace dice
{
    class bernoulli_tag{};
    class constant_tag{};

    template<typename ValueType, typename ProbabilityType>
    class random_variable_decomposition;

    // discrete random variable
    template<typename ValueType, typename ProbabilityType>
    class random_variable
    {
        friend class random_variable_decomposition<ValueType, ProbabilityType>;
    public:
        using value_type = ValueType;
        using probability_type = ProbabilityType;
        using freq_list = std::vector<std::pair<value_type, std::size_t>>;

        // create an impossible event
        random_variable() {}

        // create a constant
        random_variable(constant_tag, value_type value) :
            probability_({ std::make_pair(value, 1.0) }) {}

        // create a bernoulli distribution
        random_variable(bernoulli_tag, probability_type success_prob) :
            probability_({
                std::make_pair(0, 1 - success_prob),
                std::make_pair(1, success_prob)
            })
        {
            // make this a constant if the success probability is 1 or 0
            if (success_prob <= 0)
            {
                probability_.erase(probability_.find(1));
            }
            else if (success_prob >= 1)
            {
                probability_.erase(probability_.find(0));
            }
        }

        random_variable(freq_list&& list)
        {
            probability_type sum = 0;
            for (auto&& item : list)
                sum += item.second;

            for (auto&& item : list)
            {
                if (item.second == 0)
                    continue;

                probability_.insert(std::make_pair(
                    item.first,
                    item.second / sum
                ));
            }
        }

        // allow copy
        random_variable(const random_variable&) = default;
        random_variable& operator=(const random_variable&) = default;

        // allow move
        random_variable(random_variable&&) = default;
        random_variable& operator=(random_variable&&) = default;

        // true IFF there is only 1 value in its range
        bool is_constant() const
        {
            return probability_.size() == 1;
        }

        // value of the variable (makes sense for constant variables only)
        value_type value() const
        {
            assert(is_constant());
            return probability_.begin()->first;
        }

        /** Compute expected value of this random variable.
         * @return expected value of this variable
         */
        auto expected_value() const
        {
            probability_type exp = 0;
            for (auto&& pair : probability_)
            {
                exp += pair.first * pair.second;
            }
            return exp;
        }

        /** Compute variance of this random variable.
         * @return variance of this variable
         */
        auto variance() const
        {
            probability_type sum_sq = 0;
            probability_type sum = 0;
            for (auto&& pair : probability_)
            {
                sum_sq += pair.first * pair.first * pair.second;
                sum += pair.first * pair.second;
            }
            return sum_sq - sum * sum;
        }

        /** Calculate indicator that X (this r.v.) is in given interval
         * @param lower bound of the interval
         * @param upper bound of the interval
         * @return r.v. Y with a Bernoulli distribution
         *         Y = 1 <=> X is in the [lower_bound, upper_bound] interval
         *         Y = 0 otherwise
         */
        template<typename T>
        random_variable in(const T& lower_bound, const T& upper_bound) const
        {
            probability_type success_prob = 0;
            for (auto&& pair : probability_)
            {
                if (lower_bound <= static_cast<T>(pair.first) &&
                    upper_bound >= static_cast<T>(pair.first))
                {
                    success_prob += pair.second;
                }
            }
            return random_variable{ bernoulli_tag{}, success_prob };
        }

        /** Compute distribution of X + Y (X is this random variable).
         * X and Y are assumed to be independent.
         * @param other random variable Y (independent of X)
         * @return distribution of X + Y
         */
        auto operator+(const random_variable& other) const
        {
            return combine(other, [](auto&& a, auto&& b)
            {
                return a + b;
            });
        }

        /** Compute distribution of X - Y (X is this random variable).
         * X and Y are assumed to be independent.
         * @param other random variable Y (independent of X)
         * @return distribution of X - Y
         */
        auto operator-(const random_variable& other) const
        {
            return combine(other, [](auto&& a, auto&& b)
            {
                return a - b;
            });
        }

        /** Compute distribution of X * Y (X is this random variable).
         * X and Y are assumed to be independent.
         * @param other random variable Y (independent of X)
         * @return distribution of X * Y
         */
        auto operator*(const random_variable& other) const
        {
            return combine(other, [](auto&& a, auto&& b)
            {
                return a * b;
            });
        }

        /** Compute distribution of integer division X / Y.
         * X is this random variable.
         * X and Y are assumed to be independent.
         * @param other random variable Y (independent of X)
         * @return distribution of X / Y
         */
        auto operator/(const random_variable& other) const
        {
            return combine(other, [](auto&& a, auto&& b)
            {
                return a / b;
            });
        }

        /** Compute indicator of X < Y (X is this random variable).
         * X and Y are assumed to be indepedent.
         * @param other random variable Y (independent of X)
         * @return indicator of X < Y
         *         (i.e. a random variable with a bernoulli distribution)
         */
        auto less_than(const random_variable& other) const
        {
            return combine(other, [](auto&& a, auto&& b)
            {
                return static_cast<value_type>(a < b);
            });
        }

        /** Compute indicator of X <= Y (X is this random variable).
         * X and Y are assumed to be indepedent.
         * @param other random variable Y (independent of X)
         * @return indicator of X <= Y
         *         (i.e. a random variable with a bernoulli distribution)
         */
        auto less_than_or_equal(const random_variable& other) const
        {
            return combine(other, [](auto&& a, auto&& b)
            {
                return static_cast<value_type>(a <= b);
            });
        }

        /** Compute indicator of X = Y (X is this random variable).
         * X and Y are assumed to be indepedent.
         * @param other random variable Y (independent of X)
         * @return indicator of X = Y
         *         (i.e. a random variable with a bernoulli distribution)
         */
        auto equal(const random_variable& other) const
        {
            return combine(other, [](auto&& a, auto&& b)
            {
                return static_cast<value_type>(a == b);
            });
        }

        /** Compute indicator of X != Y (X is this random variable).
         * X and Y are assumed to be indepedent.
         * @param other random variable Y (independent of X)
         * @return indicator of X != Y
         *         (i.e. a random variable with a bernoulli distribution)
         */
        auto not_equal(const random_variable& other) const
        {
            return combine(other, [](auto&& a, auto&& b)
            {
                return static_cast<value_type>(a != b);
            });
        }

        /** Compute indicator of X > Y (X is this random variable).
         * X and Y are assumed to be indepedent.
         * @param other random variable Y (independent of X)
         * @return indicator of X > Y
         *         (i.e. a random variable with a bernoulli distribution)
         */
        auto greater_than(const random_variable& other) const
        {
            return combine(other, [](auto&& a, auto&& b)
            {
                return static_cast<value_type>(a > b);
            });
        }

        /** Compute indicator of X >= Y (X is this random variable).
         * X and Y are assumed to be indepedent.
         * @param other random variable Y (independent of X)
         * @return indicator of X >= Y
         *         (i.e. a random variable with a bernoulli distribution)
         */
        auto greater_than_or_equal(const random_variable& other) const
        {
            return combine(other, [](auto&& a, auto&& b)
            {
                return static_cast<value_type>(a >= b);
            });
        }

        /** Compute negation of this random variable (-X)
         * @return a random variable -X (X is this random variable)
         */
        auto operator-() const
        {
            random_variable result;
            for (auto&& pair : probability_)
            {
                result.probability_.insert(
                    std::make_pair(-pair.first, pair.second));
            }
            return result;
        }

        /** Compute restriction of the range of this random variable.
         * Values for which given predicate returns false won't be included.
         * Probabilities will be modified so that they sum up to 1.
         * @param include predicate
         *        Returns true IFF given element should be included
         * @return a new random variable with restricted range
         */
        template<typename Predicate>
        auto restrict(Predicate include) const
        {
            probability_type prob_sum = 0;
            for (auto&& pair : probability_)
            {
                if (include(pair.first))
                {
                    prob_sum += pair.second;
                }
            }

            random_variable result;
            for (auto&& pair : probability_)
            {
                if (include(pair.first))
                {
                    // make sure probabilities sum up to 1
                    result.probability_.insert(std::make_pair(
                        pair.first,
                        pair.second / prob_sum
                    ));
                }
            }
            return result;
        }

        /**
         * Create a random variable Z = XdY.
         * X times roll a Y sided dice.
         * Assumes X, Y are independent random variables.
         *
         * This funciton implements a simple dynamic programming algorithm.
         * The probability that we roll k with X throws of a Y sided die is
         * the probability that we roll k - n with X - 1 throws of a Y sided
         * die and then roll n on the last die for n = 1 to Y.
         *
         * @param number of dice X (independent of Y)
         *        Each value has to be a positive integer
         * @param number of sides of each dice Y (independent of X)
         *        Each value has to be a positive integer
         * @return distribution of XdY
         */
        friend auto roll(
            const random_variable& num_dice,
            const random_variable& num_sides)
        {
            // If there are no dice or dice sizes,
            // then this is an impossible event
            if (num_dice.probability_.size() <= 0 ||
                num_sides.probability_.size() <= 0)
            {
                return random_variable{};
            }

            // Throw an exception if the number of dice or
            // number of dice sides is not positive.
            // note: Use the restrict method to restrict variable's
            //       range to positive integers.
            for (auto&& pair : num_dice.probability_)
            {
                if (pair.first <= 0)
                {
                    throw std::runtime_error(
                        "Number of dice has to be a positive integer.");
                }
            }

            for (auto&& pair : num_sides.probability_)
            {
                if (pair.first <= 0)
                {
                    throw std::runtime_error(
                        "Number of dice sides has to be a positive integer.");
                }
            }

            // find maximal number of dice
            auto max_dice = std::numeric_limits<value_type>::min();
            for (auto&& value : num_dice.probability_)
            {
                max_dice = std::max(max_dice, value.first);
            }

            // compute distribution for each possible number of sides
            random_variable dist;
            for (auto&& pair : num_sides.probability_)
            {
                auto sides_count = pair.first;
                auto sides_prob = pair.second;

                // probability P(XdY = k | X = dice_count, Y = sides_count)
                std::vector<probability_type> probability(
                    sides_count * max_dice + 1, 0);
                for (value_type dice_count = 1;
                    dice_count <= max_dice;
                    ++dice_count)
                {
                    // iterate backwards so that we don't override
                    // probability values that will be needed
                    for (value_type i = sides_count * dice_count; i > 0; --i)
                    {
                        // compute the probability of the sum of i
                        auto base_prob =
                            1 / static_cast<probability_type>(sides_count);
                        auto prob_i = dice_count == 1 ? base_prob : 0;
                        value_type j = std::max(i - sides_count, 1);
                        for (; j < i; ++j)
                        {
                            prob_i += probability[j] * base_prob;
                        }
                        probability[i] = prob_i;

                        // save the probability
                        auto num_rolls = num_dice.probability_.find(dice_count);
                        if (num_rolls != num_dice.probability_.end())
                        {
                            auto rolls_prob = num_rolls->second;
                            auto prob = prob_i * sides_prob * rolls_prob;
                            // don't save impossible events
                            if (prob == 0)
                                continue;

                            auto result = dist.probability_.insert(
                                std::make_pair(i, prob));
                            if (!result.second)
                            {
                                result.first->second += prob;
                            }
                        }
                    }
                }
            }
            return dist;
        }

        /** Create a random variable that is a function
         *  of this r.v. (X) and the other r.v. (Y)
         * @param other random variable Y (independent of X)
         * @param combination function of X and Y
         * @return a new random variable that is a function of X and Y
         */
        template<typename Func>
        auto combine(const random_variable& other, Func&& combination) const
        {
            random_variable dist;
            for (auto&& pair_a : probability_)
            {
                for (auto&& pair_b : other.probability_)
                {
                    auto value = combination(pair_a.first, pair_b.first);
                    auto probability = pair_b.second * pair_a.second;
                    auto result = dist.probability_.insert(
                        std::make_pair(value, probability));
                    if (!result.second)
                    {
                        result.first->second += probability;
                    }
                }
            }
            return dist;
        }

        const auto& probability() const
        {
            return probability_;
        }
    private:
        std::unordered_map<value_type, probability_type> probability_;
    };

    // Calculate max(X, Y) for independent r.v. X and Y
    template<typename T, typename U>
    random_variable<T, U> max(
        const random_variable<T, U>& a,
        const random_variable<T, U>& b)
    {
        return a.combine(b, [](auto&& value_a, auto&& value_b)
        {
            return std::max(value_a, value_b);
        });
    }

    // Calculate min(X, Y) for independent r.v. X and Y
    template<typename T, typename U>
    random_variable<T, U> min(
        const random_variable<T, U>& a,
        const random_variable<T, U>& b)
    {
        return a.combine(b, [](auto&& value_a, auto&& value_b)
        {
            return std::min(value_a, value_b);
        });
    }
}

#endif // DICE_RANDOM_VARIABLE_HPP_<|endoftext|>