<commit_before>// C++ General Utility Library (mailto:cgul@zethes.com)
// Copyright (C) 2012-2014, Joshua Brookover and Amber Thrall
// All rights reserved.

/** @file String.hpp
 */

#pragma once
#include <CGUL/Config.hpp>
#include "../Containers/FixedList.hpp"
#include "../External/Defines.hpp"

#ifndef CGUL_NO_U8
#   ifdef CPP_HAS_U8
#       define U8(text) CGUL::String(u8##text)
#   else
#       ifdef CGUL_WINDOWS
#           define U8(text) CGUL::String(L##text)
#       else
#           define U8(text) CGUL::String(text)
#       endif
#   endif
#endif

namespace CGUL
{
#   ifdef CGUL_USE_REGEX
    class Regex;
#   endif

    /** @brief A Utf-8 compliant string.
     */
    class String
    {
        /** @brief A buffer for quick operations of strings under 2048 characters.
         */
        static char internalBuffer[2048];

        /** @brief Internal string object to manage the data.
         */
        std::string data;

        /** @brief Special case for a NULL string.
         */
        bool null;
    public:
        static const Size none = (Size)-1;

        _CGUL_EXPORT static String FromCodePoint(UInt32 codePoint);

        //! @brief Initializes to "".
        _CGUL_EXPORT String();
        //! @brief Copies the contents of the string into a new string.
        _CGUL_EXPORT String(const String& copy);
#       ifdef CPP_HAS_MOVE_CONSTRUCTOR
        //! @brief Moves the contents of one string to another.
        _CGUL_EXPORT String(String&& move);
#       endif
#       ifdef CGUL_WINDOWS
        //! @brief Converts a std::wstring object to a Utf-8 string.
        //! @warning Windows only!
        _CGUL_EXPORT String(const std::wstring& wideString);
#       endif
        //! @brief Copies raw character array data in a managed string object.
        _CGUL_EXPORT String(const char* data);
        //! @brief Copies a raw std::string object.
        _CGUL_EXPORT String(const std::string& data);

        //! @brief Copies the contents of a c string into this string.
        _CGUL_EXPORT String& operator=(const char* operand);
        //! @brief Copies the contents of another string into this string.
        _CGUL_EXPORT String& operator=(const String& operand);
        //! @brief Gets an individual byte from the string at the specified index.
        _CGUL_EXPORT char& operator[](Size operand);
        //! @brief Gets an individual byte from the string at the specified index.
        _CGUL_EXPORT const char operator[](Size operand) const;
        //! @brief Checks if two strings are equal.
        _CGUL_EXPORT bool operator==(const String& operand) const;
        //! @brief Checks if two strings are not equal.
        _CGUL_EXPORT bool operator!=(const String& operand) const;
        //! @brief Attempts to convert a data type to string and concatinate it to this string,
        //! returning the result.
        template <typename T>
        String operator+(const T& operand) const;
#       ifdef CPP_HAS_DOUBLE_REFERENCE
        //! @brief Attempts to convert a data type to string and concatinate it to this string,
        //! returning the result.
        template <typename T>
        String operator+(const T&& operand) const;
#       endif
        //! @brief Attempts to convert a data type to string and concatinate it to this string.
        template <typename T>
        String& operator+=(const T& operand);
#       ifdef CPP_HAS_DOUBLE_REFERENCE
        //! @brief Attempts to convert a data type to string and concatinate it to this string.
        template <typename T>
        String& operator+=(const T&& operand);
#       endif
        //! @brief Checks if this string is lexicographically less than another.
        _CGUL_EXPORT bool operator<(const String& operand) const;
        friend std::ostream& operator<<(std::ostream& stream, const String& string)
        {
            if (string.null)
            {
                stream << "[NULL]";
            }
            else
            {
                stream << string.data;
            }
            return stream;
        }

        //! @brief Gets the size of the string in bytes.
        _CGUL_EXPORT Size GetSize() const;
        //! @brief Counts the number of code points in the string.
        _CGUL_EXPORT Size GetLength() const;

        //! @brief Gets an individual character from the string.
        _CGUL_EXPORT char GetChar(Size position) const;
        //! @brief Gets an individual byte from the string.
        _CGUL_EXPORT Byte GetByte(Size position) const;
        //! @brief Gets an individual code point from the string.
        _CGUL_EXPORT Size GetCodePoint(Size start, UInt32* codePoint) const;
        //! @brief Checks if the string is empty.
        _CGUL_EXPORT Boolean IsEmpty() const;
        //! @brief Checks if the string is null.
        _CGUL_EXPORT Boolean IsNull() const;

        //! @brief An accessor to the wrapped std::string data.
        _CGUL_EXPORT std::string GetData() const;
        //! @brief Accesses the raw character data from the wrapped std::string object.
        _CGUL_EXPORT const char* GetCString() const;

        _CGUL_EXPORT UInt32 Count(const String& string) const;

        //! @brief Finds the first occurence of a string.
        _CGUL_EXPORT Size FindFirstOf(const String& string, Size offset = 0) const;
#       ifdef CGUL_USE_REGEX
        _CGUL_EXPORT Size FindFirstOf(const Regex& expression, Size offset = 0) const;
#       endif
        //! @brief Finds the last occurence of a string.
        _CGUL_EXPORT Size FindLastOf(const String& string, Size offset = 0) const;
#       ifdef CGUL_USE_REGEX
        _CGUL_EXPORT Size FindLastOf(const Regex& expression, Size offset = 0) const;
#       endif

        //! @brief Gets a part of the string.  Supports both Utf-8 and individual bytes.
        _CGUL_EXPORT String SubString(Size offset, Size count = none, bool bytes = false) const;

        //! @brief Checks if the string contains another string.
        _CGUL_EXPORT bool Contains(const String& string) const;
        //! @brief Checks if the string begins with another string.
        _CGUL_EXPORT bool BeginsWith(const String& string) const;
        //! @brief Checks if the string ends with another string.
        _CGUL_EXPORT bool EndsWith(const String& string) const;

        //! @brief Sets the value of the string given a c string.
        _CGUL_EXPORT String& Set(const char* str);
        //! @brief Sets the value of the string given another string.
        _CGUL_EXPORT String& Set(const String& str);

        //! @brief Sets to a printf like format.
        _CGUL_EXPORT String& SetFormat(const String& str, ...);

        //! @brief Trims whitespace at the beginning and end of the string.
        _CGUL_EXPORT void Trim();
        //! @brief Trims whitespace at the beginning of the string.
        _CGUL_EXPORT void TrimStart();
        //! @brief Trims whitespace at the end of the string.
        _CGUL_EXPORT void TrimEnd();
        _CGUL_EXPORT void Explode(const String& delimiter, FixedList< String >* debris) const;
        _CGUL_EXPORT void Explode(const String& delimiter, Size limit, FixedList< String >* debris) const;

        //! @brief Converts the entire string to uppercase letters.
        _CGUL_EXPORT void ToLower();
        //! @brief Converts the entire string to lowercase letters.
        _CGUL_EXPORT void ToUpper();
        //! @brief Gets the string as all lowercase letters.
        _CGUL_EXPORT String GetLower() const;
        //! @brief Gets the string as all uppercase letters.
        _CGUL_EXPORT String GetUpper() const;

        //! @brief Removes all whitespace from within a string.
        _CGUL_EXPORT void RemoveWhitespace();

        //! @brief Changes the string to empty if it is null.
        _CGUL_EXPORT void SetNullToEmpty();
        //! @brief Changes the string to null if it is empty.
        _CGUL_EXPORT void SetEmptyToNull();

        //! @brief Checks if the string can be converted to the given data type.
        template <typename T>
        bool Is() const;
        //! @brief Converts the string to the given data type.
        template <typename T>
        T To() const;
        //! @brief Converts the string to the given data type.
        template <typename T>
        T To(const T& fallback) const;
#       ifdef CPP_HAS_DOUBLE_REFERENCE
        //! @brief Converts the string to the given data type.
        template <typename T>
        T To(const T&& fallback) const;
#       endif

#       ifdef CGUL_WINDOWS
        _CGUL_EXPORT std::wstring _ToWideString() const;
        _CGUL_EXPORT void _FromWideString(const std::wstring& wideString);
#       endif

        // TODO: add in some more common string functions (maybe reference php's string, C#'s string or std::string?)
    };
}

/** @param operand The value to concatenate.
 *  @returns The new string.
 *  @details Attempts to convert the value to a string using standard template library streams.
 */
template <typename T>
CGUL::String CGUL::String::operator+(const T& operand) const
{
    std::ostringstream ss;
    ss << operand;
    return data + ss.str();
}

#ifdef CPP_HAS_DOUBLE_REFERENCE
/** @param operand The value to concatenate.
 *  @returns The new string.
 *  @details Attempts to convert the value to a string using standard template library streams.
 */
template <typename T>
CGUL::String CGUL::String::operator+(const T&& operand) const
{
    std::ostringstream ss;
    ss << operand;
    return data + ss.str();
}
#endif

/** @param operand The value to concatenate.
 *  @returns A reference to this object.
 *  @details Attempts to convert the value to a string using standard template library streams.
 */
template <typename T>
CGUL::String& CGUL::String::operator+=(const T& operand)
{
    std::ostringstream ss;
    ss << operand;
    data += ss.str();
    return *this;
}

#ifdef CPP_HAS_DOUBLE_REFERENCE
/** @param operand The value to concatenate.
 *  @returns A reference to this object.
 *  @details Attempts to convert the value to a string using standard template library streams.
 */
template <typename T>
CGUL::String& CGUL::String::operator+=(const T&& operand)
{
    std::ostringstream ss;
    ss << operand;
    data += ss.str();
    return *this;
}
#endif

/** @returns True if the string can be converted, false otherwise.
 */
template <typename T>
bool CGUL::String::Is() const
{
    std::istringstream test;
    test.str(data);
    if (!test.good())
    {
        return false;
    }
    T x;
    test >> x;
    if (test.fail() || test.good())
    {
        return false;
    }
    return true;
}

/** @returns The string as the given type.
 */
template <typename T>
T CGUL::String::To() const
{
    std::istringstream convert;
    convert.str(data);
    T x;
    convert >> x;
    return x;
}

/** @param fallback The value to set to if the conversion failed.
 *  @returns The string as the given type.
 */
template <typename T>
T CGUL::String::To(const T& fallback) const
{
    std::istringstream test;
    test.str(data);
    if (!test.good())
    {
        return false;
    }
    T x;
    test >> x;
    if (test.fail() || test.good())
    {
        x = fallback;
    }
    return x;
}

#ifdef CPP_HAS_DOUBLE_REFERENCE
/** @param fallback The value to set to if the conversion failed.
 *  @returns The string as the given type.
 */
template <typename T>
T CGUL::String::To(const T&& fallback) const
{
    std::istringstream test;
    test.str(data);
    if (!test.good())
    {
        return false;
    }
    T x;
    test >> x;
    if (test.fail() || test.good())
    {
        x = fallback;
    }
    return x;
}
#endif

#include "../External/Undefines.hpp"
<commit_msg>Added CGUL::String::From<><commit_after>// C++ General Utility Library (mailto:cgul@zethes.com)
// Copyright (C) 2012-2014, Joshua Brookover and Amber Thrall
// All rights reserved.

/** @file String.hpp
 */

#pragma once
#include <CGUL/Config.hpp>
#include "../Containers/FixedList.hpp"
#include "../External/Defines.hpp"

#ifndef CGUL_NO_U8
#   ifdef CPP_HAS_U8
#       define U8(text) CGUL::String(u8##text)
#   else
#       ifdef CGUL_WINDOWS
#           define U8(text) CGUL::String(L##text)
#       else
#           define U8(text) CGUL::String(text)
#       endif
#   endif
#endif

namespace CGUL
{
#   ifdef CGUL_USE_REGEX
    class Regex;
#   endif

    /** @brief A Utf-8 compliant string.
     */
    class String
    {
        /** @brief A buffer for quick operations of strings under 2048 characters.
         */
        static char internalBuffer[2048];

        /** @brief Internal string object to manage the data.
         */
        std::string data;

        /** @brief Special case for a NULL string.
         */
        bool null;
    public:
        static const Size none = (Size)-1;

        _CGUL_EXPORT static String FromCodePoint(UInt32 codePoint);

        template< typename Type >
        static String From(Type value);

        //! @brief Initializes to "".
        _CGUL_EXPORT String();
        //! @brief Copies the contents of the string into a new string.
        _CGUL_EXPORT String(const String& copy);
#       ifdef CPP_HAS_MOVE_CONSTRUCTOR
        //! @brief Moves the contents of one string to another.
        _CGUL_EXPORT String(String&& move);
#       endif
#       ifdef CGUL_WINDOWS
        //! @brief Converts a std::wstring object to a Utf-8 string.
        //! @warning Windows only!
        _CGUL_EXPORT String(const std::wstring& wideString);
#       endif
        //! @brief Copies raw character array data in a managed string object.
        _CGUL_EXPORT String(const char* data);
        //! @brief Copies a raw std::string object.
        _CGUL_EXPORT String(const std::string& data);

        //! @brief Copies the contents of a c string into this string.
        _CGUL_EXPORT String& operator=(const char* operand);
        //! @brief Copies the contents of another string into this string.
        _CGUL_EXPORT String& operator=(const String& operand);
        //! @brief Gets an individual byte from the string at the specified index.
        _CGUL_EXPORT char& operator[](Size operand);
        //! @brief Gets an individual byte from the string at the specified index.
        _CGUL_EXPORT const char operator[](Size operand) const;
        //! @brief Checks if two strings are equal.
        _CGUL_EXPORT bool operator==(const String& operand) const;
        //! @brief Checks if two strings are not equal.
        _CGUL_EXPORT bool operator!=(const String& operand) const;
        //! @brief Attempts to convert a data type to string and concatinate it to this string,
        //! returning the result.
        template <typename T>
        String operator+(const T& operand) const;
#       ifdef CPP_HAS_DOUBLE_REFERENCE
        //! @brief Attempts to convert a data type to string and concatinate it to this string,
        //! returning the result.
        template <typename T>
        String operator+(const T&& operand) const;
#       endif
        //! @brief Attempts to convert a data type to string and concatinate it to this string.
        template <typename T>
        String& operator+=(const T& operand);
#       ifdef CPP_HAS_DOUBLE_REFERENCE
        //! @brief Attempts to convert a data type to string and concatinate it to this string.
        template <typename T>
        String& operator+=(const T&& operand);
#       endif
        //! @brief Checks if this string is lexicographically less than another.
        _CGUL_EXPORT bool operator<(const String& operand) const;
        friend std::ostream& operator<<(std::ostream& stream, const String& string)
        {
            if (string.null)
            {
                stream << "[NULL]";
            }
            else
            {
                stream << string.data;
            }
            return stream;
        }

        //! @brief Gets the size of the string in bytes.
        _CGUL_EXPORT Size GetSize() const;
        //! @brief Counts the number of code points in the string.
        _CGUL_EXPORT Size GetLength() const;

        //! @brief Gets an individual character from the string.
        _CGUL_EXPORT char GetChar(Size position) const;
        //! @brief Gets an individual byte from the string.
        _CGUL_EXPORT Byte GetByte(Size position) const;
        //! @brief Gets an individual code point from the string.
        _CGUL_EXPORT Size GetCodePoint(Size start, UInt32* codePoint) const;
        //! @brief Checks if the string is empty.
        _CGUL_EXPORT Boolean IsEmpty() const;
        //! @brief Checks if the string is null.
        _CGUL_EXPORT Boolean IsNull() const;

        //! @brief An accessor to the wrapped std::string data.
        _CGUL_EXPORT std::string GetData() const;
        //! @brief Accesses the raw character data from the wrapped std::string object.
        _CGUL_EXPORT const char* GetCString() const;

        _CGUL_EXPORT UInt32 Count(const String& string) const;

        //! @brief Finds the first occurence of a string.
        _CGUL_EXPORT Size FindFirstOf(const String& string, Size offset = 0) const;
#       ifdef CGUL_USE_REGEX
        _CGUL_EXPORT Size FindFirstOf(const Regex& expression, Size offset = 0) const;
#       endif
        //! @brief Finds the last occurence of a string.
        _CGUL_EXPORT Size FindLastOf(const String& string, Size offset = 0) const;
#       ifdef CGUL_USE_REGEX
        _CGUL_EXPORT Size FindLastOf(const Regex& expression, Size offset = 0) const;
#       endif

        //! @brief Gets a part of the string.  Supports both Utf-8 and individual bytes.
        _CGUL_EXPORT String SubString(Size offset, Size count = none, bool bytes = false) const;

        //! @brief Checks if the string contains another string.
        _CGUL_EXPORT bool Contains(const String& string) const;
        //! @brief Checks if the string begins with another string.
        _CGUL_EXPORT bool BeginsWith(const String& string) const;
        //! @brief Checks if the string ends with another string.
        _CGUL_EXPORT bool EndsWith(const String& string) const;

        //! @brief Sets the value of the string given a c string.
        _CGUL_EXPORT String& Set(const char* str);
        //! @brief Sets the value of the string given another string.
        _CGUL_EXPORT String& Set(const String& str);

        //! @brief Sets to a printf like format.
        _CGUL_EXPORT String& SetFormat(const String& str, ...);

        //! @brief Trims whitespace at the beginning and end of the string.
        _CGUL_EXPORT void Trim();
        //! @brief Trims whitespace at the beginning of the string.
        _CGUL_EXPORT void TrimStart();
        //! @brief Trims whitespace at the end of the string.
        _CGUL_EXPORT void TrimEnd();
        _CGUL_EXPORT void Explode(const String& delimiter, FixedList< String >* debris) const;
        _CGUL_EXPORT void Explode(const String& delimiter, Size limit, FixedList< String >* debris) const;

        //! @brief Converts the entire string to uppercase letters.
        _CGUL_EXPORT void ToLower();
        //! @brief Converts the entire string to lowercase letters.
        _CGUL_EXPORT void ToUpper();
        //! @brief Gets the string as all lowercase letters.
        _CGUL_EXPORT String GetLower() const;
        //! @brief Gets the string as all uppercase letters.
        _CGUL_EXPORT String GetUpper() const;

        //! @brief Removes all whitespace from within a string.
        _CGUL_EXPORT void RemoveWhitespace();

        //! @brief Changes the string to empty if it is null.
        _CGUL_EXPORT void SetNullToEmpty();
        //! @brief Changes the string to null if it is empty.
        _CGUL_EXPORT void SetEmptyToNull();

        //! @brief Checks if the string can be converted to the given data type.
        template <typename T>
        bool Is() const;
        //! @brief Converts the string to the given data type.
        template <typename T>
        T To() const;
        //! @brief Converts the string to the given data type.
        template <typename T>
        T To(const T& fallback) const;
#       ifdef CPP_HAS_DOUBLE_REFERENCE
        //! @brief Converts the string to the given data type.
        template <typename T>
        T To(const T&& fallback) const;
#       endif

#       ifdef CGUL_WINDOWS
        _CGUL_EXPORT std::wstring _ToWideString() const;
        _CGUL_EXPORT void _FromWideString(const std::wstring& wideString);
#       endif

        // TODO: add in some more common string functions (maybe reference php's string, C#'s string or std::string?)
    };
}

template< typename Type >
CGUL::String CGUL::String::From(Type value)
{
    std::ostringstream ss;
    ss << value;
    return CGUL::String(ss.str());
}

/** @param operand The value to concatenate.
 *  @returns The new string.
 *  @details Attempts to convert the value to a string using standard template library streams.
 */
template <typename T>
CGUL::String CGUL::String::operator+(const T& operand) const
{
    std::ostringstream ss;
    ss << operand;
    return data + ss.str();
}

#ifdef CPP_HAS_DOUBLE_REFERENCE
/** @param operand The value to concatenate.
 *  @returns The new string.
 *  @details Attempts to convert the value to a string using standard template library streams.
 */
template <typename T>
CGUL::String CGUL::String::operator+(const T&& operand) const
{
    std::ostringstream ss;
    ss << operand;
    return data + ss.str();
}
#endif

/** @param operand The value to concatenate.
 *  @returns A reference to this object.
 *  @details Attempts to convert the value to a string using standard template library streams.
 */
template <typename T>
CGUL::String& CGUL::String::operator+=(const T& operand)
{
    std::ostringstream ss;
    ss << operand;
    data += ss.str();
    return *this;
}

#ifdef CPP_HAS_DOUBLE_REFERENCE
/** @param operand The value to concatenate.
 *  @returns A reference to this object.
 *  @details Attempts to convert the value to a string using standard template library streams.
 */
template <typename T>
CGUL::String& CGUL::String::operator+=(const T&& operand)
{
    std::ostringstream ss;
    ss << operand;
    data += ss.str();
    return *this;
}
#endif

/** @returns True if the string can be converted, false otherwise.
 */
template <typename T>
bool CGUL::String::Is() const
{
    std::istringstream test;
    test.str(data);
    if (!test.good())
    {
        return false;
    }
    T x;
    test >> x;
    if (test.fail() || test.good())
    {
        return false;
    }
    return true;
}

/** @returns The string as the given type.
 */
template <typename T>
T CGUL::String::To() const
{
    std::istringstream convert;
    convert.str(data);
    T x;
    convert >> x;
    return x;
}

/** @param fallback The value to set to if the conversion failed.
 *  @returns The string as the given type.
 */
template <typename T>
T CGUL::String::To(const T& fallback) const
{
    std::istringstream test;
    test.str(data);
    if (!test.good())
    {
        return false;
    }
    T x;
    test >> x;
    if (test.fail() || test.good())
    {
        x = fallback;
    }
    return x;
}

#ifdef CPP_HAS_DOUBLE_REFERENCE
/** @param fallback The value to set to if the conversion failed.
 *  @returns The string as the given type.
 */
template <typename T>
T CGUL::String::To(const T&& fallback) const
{
    std::istringstream test;
    test.str(data);
    if (!test.good())
    {
        return false;
    }
    T x;
    test >> x;
    if (test.fail() || test.good())
    {
        x = fallback;
    }
    return x;
}
#endif

#include "../External/Undefines.hpp"
<|endoftext|>


<commit_before>// Time:  O(logn)
// Space: O(1)

class Solution {
public:
    /**
     * @param n: An integers.
     * @return: An integer which is the first bad version.
     */
    int findFirstBadVersion(int n) {
        int left = 1 - 1, right = n;

        VersionControl vc;

        // At the last, left is not sure for target, right is target.
        while (right - left > 1) {
            int mid = left + (right - left) / 2;
            // Is target
            if (vc.isBadVersion(mid)) {
                right = mid;
            }
            else {
                left = mid;
            }
        }
        return right;
    }
};

class Solution2 {
public:
    /**
     * @param n: An integers.
     * @return: An integer which is the first bad version.
     */
    int findFirstBadVersion(int n) {
        int left = 1, right = n + 1;

        VersionControl vc;

        // At the last, left is not sure for target, right is target.
        while (left < right) {
            int mid = left + (right - left) / 2;
            // Is target
            if (vc.isBadVersion(mid)) {
                right = mid;
            }
            else {
                left = mid + 1;
            }
        }
        return left;
    }
};

class Solution3 {
public:
    /**
     * @param n: An integers.
     * @return: An integer which is the first bad version.
     */
    int findFirstBadVersion(int n) {
        int left = 1, right = n;

        VersionControl vc;

        // At the last, left is not sure for target, right is not sure for target.
        while (left <= right) {
            int mid = left + (right - left) / 2;
            // Is target
            if (vc.isBadVersion(mid)) {
                right = mid - 1;
            }
            else {
                left = mid + 1;
            }
        }
        return left;
    }
};
<commit_msg>3 types of binary search<commit_after>// Time:  O(logn)
// Space: O(1)

class Solution {
public:
    /**
     * @param n: An integers.
     * @return: An integer which is the first bad version.
     */
    int findFirstBadVersion(int n) {
        int left = 1 - 1, right = n;

        VersionControl vc;

        // At the last, left is not target, right is target.
        while (right - left > 1) {
            int mid = left + (right - left) / 2;
            // Is target
            if (vc.isBadVersion(mid)) {
                right = mid;
            }
            else {
                left = mid;
            }
        }
        return right;
    }
};

class Solution2 {
public:
    /**
     * @param n: An integers.
     * @return: An integer which is the first bad version.
     */
    int findFirstBadVersion(int n) {
        int left = 1, right = n + 1;

        VersionControl vc;

        // At the last, left is not sure for target, right is target.
        while (left < right) {
            int mid = left + (right - left) / 2;
            // Is target
            if (vc.isBadVersion(mid)) {
                right = mid;
            }
            else {
                left = mid + 1;
            }
        }
        return left;
    }
};

class Solution3 {
public:
    /**
     * @param n: An integers.
     * @return: An integer which is the first bad version.
     */
    int findFirstBadVersion(int n) {
        int left = 1, right = n;

        VersionControl vc;

        // At the last, left is not sure for target, right is not sure for target.
        while (left <= right) {
            int mid = left + (right - left) / 2;
            // Is target
            if (vc.isBadVersion(mid)) {
                right = mid - 1;
            }
            else {
                left = mid + 1;
            }
        }
        return left;
    }
};
<|endoftext|>


<commit_before>/*-----------------------------------------------------------------------------------------------
The MIT License (MIT)

Copyright (c) 2015-2021 OSRE ( Open Source Render Engine ) by Kim Kulling

Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-----------------------------------------------------------------------------------------------*/
#include <osre/Common/Logger.h>
#include <osre/RenderBackend/RenderBackendService.h>
#include <osre/Scene/Camera.h>

#include <glm/gtc/matrix_transform.hpp>

namespace OSRE {
namespace Scene {

using namespace ::OSRE::RenderBackend;

static const c8 *Tag = "Camera";

Camera::Camera(const String &name, Common::Ids &ids, Node *parent) :
        Node(name, ids, parent),
        mRecalculateRequested(true),
        mCameraModel(CameraModel::Perspective),
        m_fov(60.0f),
        mResolution(1.0f, 1.0f),
        m_near(0.001f),
        m_far(1000.0f),
        m_aspectRatio(1.0),
        m_left(0.0f),
        m_right(1.0f),
        m_top(0.0f),
        m_bottom(1.0f),
        m_eye(1, 1, 1),
        m_center(0, 0, 0),
        m_up(0, 0, 1),
        m_view(1),
        m_projection(1) {
    // empty
}

Camera::~Camera() {
    // empty
}

void Camera::setProjectionParameters(f32 fov, f32 w, f32 h, f32 zNear, f32 zFar) {
    m_fov = glm::radians(fov);
    mResolution.Width = w;
    mResolution.Height = h;
    m_near = zNear;
    m_far = zFar;
    m_aspectRatio = 1.0f;
    if (0.0f != h) {
        m_aspectRatio = w / h;
    }

    setCameraModel(CameraModel::Perspective);
}

void Camera::update(Time dt) {
    onUpdate(dt);
}

void Camera::draw(RenderBackendService *rbSrv) {
    if (nullptr == rbSrv) {
        return;
    }

    onRender(rbSrv);
}

void Camera::observeBoundingBox(const TAABB<f32> &aabb) {
    const f32 diam = aabb.getDiameter();
    const Vec3f center = aabb.getCenter();

    glm::vec3 eye(-diam / 2, -diam / 2, diam / 2), up(0, 0, 1);
    glm::vec3 c(center.getX(), center.getY(), center.getZ());

    setLookAt(eye, c, up);
}

void Camera::setLookAt(const glm::vec3 &eyePosition, const glm::vec3 &center, const glm::vec3 &up) {
    m_eye = eyePosition;
    m_center = center;
    m_up = up;
}

void Camera::setProjectionMode(f32 fov, f32 aspectRatio, f32 nearPlane, f32 farPlane) {
    m_fov = fov;
    m_aspectRatio = aspectRatio;
    m_near = nearPlane;
    m_far = farPlane;

    setCameraModel(CameraModel::Perspective);
}

void Camera::setOrthoMode(f32 left, f32 right, f32 bottom, f32 top, f32 nearPlane, f32 farPlane) {
    mResolution.Width = right - left;
    mResolution.Height = bottom - top;
    m_left = left;
    m_right = right;
    m_bottom = bottom;
    m_top = top;
    m_near = nearPlane;
    m_far = farPlane;

    setCameraModel(CameraModel::Orthogonal);
}

const glm::mat4 &Camera::getView() const {
    return m_view;
}

const glm::mat4 &Camera::getProjection() const {
    return m_projection;
}

void Camera::onUpdate(Time dt) {
    const CameraModel cm = getCameraModel();
    if (cm == CameraModel::Perspective) {
        m_projection = glm::perspective(m_fov, m_aspectRatio, m_near, m_far);
    } else if (cm == CameraModel::Orthogonal) {
        m_projection = glm::ortho(m_left, m_right, m_bottom, m_top, m_near, m_far);
    }
    m_view = glm::lookAt(m_eye, m_center, m_up);
}

void Camera::onRender(RenderBackendService *rbSrv) {
    if (nullptr == rbSrv) {
        osre_debug(Tag, "Pointer to renderbackend service is nullptr.");
        return;
    }

    rbSrv->setMatrix(MatrixType::View, m_view);
    rbSrv->setMatrix(MatrixType::Projection, m_projection);
}

} // Namespace Scene
} // Namespace OSRE
<commit_msg>Remove unnessesary namespace.<commit_after>/*-----------------------------------------------------------------------------------------------
The MIT License (MIT)

Copyright (c) 2015-2021 OSRE ( Open Source Render Engine ) by Kim Kulling

Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-----------------------------------------------------------------------------------------------*/
#include <osre/Common/Logger.h>
#include <osre/RenderBackend/RenderBackendService.h>
#include <osre/Scene/Camera.h>

#include <glm/gtc/matrix_transform.hpp>

namespace OSRE {
namespace Scene {

using namespace ::OSRE::Common;
using namespace ::OSRE::RenderBackend;
using namespace ::glm;

static const c8 *Tag = "Camera";

Camera::Camera(const String &name, Ids &ids, Node *parent) :
        Node(name, ids, parent),
        mRecalculateRequested(true),
        mCameraModel(CameraModel::Perspective),
        m_fov(60.0f),
        mResolution(1.0f, 1.0f),
        m_near(0.001f),
        m_far(1000.0f),
        m_aspectRatio(1.0),
        m_left(0.0f),
        m_right(1.0f),
        m_top(0.0f),
        m_bottom(1.0f),
        m_eye(1, 1, 1),
        m_center(0, 0, 0),
        m_up(0, 0, 1),
        m_view(1),
        m_projection(1) {
    // empty
}

Camera::~Camera() {
    // empty
}

void Camera::setProjectionParameters(f32 fov, f32 w, f32 h, f32 zNear, f32 zFar) {
    m_fov = glm::radians(fov);
    mResolution.Width = w;
    mResolution.Height = h;
    m_near = zNear;
    m_far = zFar;
    m_aspectRatio = 1.0f;
    if (0.0f != h) {
        m_aspectRatio = w / h;
    }

    setCameraModel(CameraModel::Perspective);
}

void Camera::update(Time dt) {
    onUpdate(dt);
}

void Camera::draw(RenderBackendService *rbSrv) {
    if (nullptr == rbSrv) {
        return;
    }

    onRender(rbSrv);
}

void Camera::observeBoundingBox(const TAABB<f32> &aabb) {
    const f32 diam = aabb.getDiameter();
    const Vec3f center = aabb.getCenter();

    glm::vec3 eye(-diam / 2, -diam / 2, diam / 2), up(0, 0, 1);
    glm::vec3 c(center.getX(), center.getY(), center.getZ());

    setLookAt(eye, c, up);
}

void Camera::setLookAt(const glm::vec3 &eyePosition, const glm::vec3 &center, const glm::vec3 &up) {
    m_eye = eyePosition;
    m_center = center;
    m_up = up;
}

void Camera::setProjectionMode(f32 fov, f32 aspectRatio, f32 nearPlane, f32 farPlane) {
    m_fov = fov;
    m_aspectRatio = aspectRatio;
    m_near = nearPlane;
    m_far = farPlane;

    setCameraModel(CameraModel::Perspective);
}

void Camera::setOrthoMode(f32 left, f32 right, f32 bottom, f32 top, f32 nearPlane, f32 farPlane) {
    mResolution.Width = right - left;
    mResolution.Height = bottom - top;
    m_left = left;
    m_right = right;
    m_bottom = bottom;
    m_top = top;
    m_near = nearPlane;
    m_far = farPlane;

    setCameraModel(CameraModel::Orthogonal);
}

const glm::mat4 &Camera::getView() const {
    return m_view;
}

const glm::mat4 &Camera::getProjection() const {
    return m_projection;
}

void Camera::onUpdate(Time dt) {
    const CameraModel cm = getCameraModel();
    if (cm == CameraModel::Perspective) {
        m_projection = glm::perspective(m_fov, m_aspectRatio, m_near, m_far);
    } else if (cm == CameraModel::Orthogonal) {
        m_projection = glm::ortho(m_left, m_right, m_bottom, m_top, m_near, m_far);
    }
    m_view = glm::lookAt(m_eye, m_center, m_up);
}

void Camera::onRender(RenderBackendService *rbSrv) {
    if (nullptr == rbSrv) {
        osre_debug(Tag, "Pointer to renderbackend service is nullptr.");
        return;
    }

    rbSrv->setMatrix(MatrixType::View, m_view);
    rbSrv->setMatrix(MatrixType::Projection, m_projection);
}

} // Namespace Scene
} // Namespace OSRE
<|endoftext|>


<commit_before>#include "SceneMainMenu.hpp"
#include <iostream>

//--------------------------------------------------------------------
using namespace cocos2d;

//--------------------------------------------------------------------
Scene *
SceneMainMenu::createScene(){
    auto scene = Scene::create();

    auto root = SceneMainMenu::create();

    scene->addChild( root );

    return scene;
}

//--------------------------------------------------------------------
bool SceneMainMenu::init(){
    if( !Node::init() ){
        return false;
    }

    printf( "SceneMainMenu::init\n" );

    return true;
}

//--------------------------------------------------------------------
void SceneMainMenu::onEnter(){
    Node::onEnter();

    printf( "SceneMainMenu::onEnter\n" );
}

//--------------------------------------------------------------------
<commit_msg>add a label<commit_after>#include "SceneMainMenu.hpp"
#include <iostream>

//--------------------------------------------------------------------
using namespace cocos2d;

//--------------------------------------------------------------------
Scene *
SceneMainMenu::createScene(){
    auto scene = Scene::create();

    auto root = SceneMainMenu::create();

    scene->addChild( root );

    return scene;
}

//--------------------------------------------------------------------
bool SceneMainMenu::init(){
    if( !Node::init() ){
        return false;
    }

    printf( "SceneMainMenu::init\n" );

    auto label = Label::createWithTTF( "Main Menu", "fonts/gentium.ttf", 24 );

    label->setPosition( { 500, 500 } );

    this->addChild( label, 3 );

    return true;
}

//--------------------------------------------------------------------
void SceneMainMenu::onEnter(){
    Node::onEnter();

    printf( "SceneMainMenu::onEnter\n" );
}

//--------------------------------------------------------------------
<|endoftext|>


<commit_before>#include "Graph.hpp"

/*
template <typename Weight>
void add_edge(Graph<Weight> &g, int src, int to) {
  g[src].push_back(Edge<Weight>(src, to));
  g[to].push_back(Edge<Weight>(to, src));
}
*/

class LCA {
  int V, LOG_V;
  vector<vector<int>> parent;
  vector<int> depth;
  template<typename T>
  void dfs(const Graph<T> &g, int v, int p, int d) {
    parent[0][v] = p; depth[v] = d;
    for (const Edge<T> &e: g[v])
      if (e.to != p) dfs(g, e.to, v, d + 1);
  }
public:
  template<typename T>
  LCA(const Graph<T> &g, int root) : V(g.size()), LOG_V(0), depth(V, 0) {
    for (int v = V; v > 0; v >>= 1) ++LOG_V;
    parent.assign(LOG_V, vector<int>(V, 0));
    dfs(g, root, -1, 0);
    for (int k = 0; k < LOG_V - 1; ++k) {
      for (int v = 0; v < V; ++v) {
        if (parent[k][v] < 0) parent[k + 1][v] = -1;
        else parent[k + 1][v] = parent[k][parent[k][v]];
      }
    }
  }
  int lca(int u, int v) {
    if (depth[u] > depth[v]) swap(u, v);
    for (int k = 0; k < LOG_V; ++k)
      if (((depth[v] - depth[u]) >> k) & 1) v = parent[k][v];
    if (u == v) return u;
    for (int k = LOG_V - 1; k >= 0; k--) {
      if (parent[k][u] != parent[k][v]) {
        u = parent[k][u];
        v = parent[k][v];
      }
    }
    return parent[0][u];
  }
};
<commit_msg>cosmetic<commit_after>#include "Graph.hpp"

/*
template <typename Weight>
void add_edge(Graph<Weight> &g, int src, int to) {
  g[src].push_back(Edge<Weight>(to));
  g[to].push_back(Edge<Weight>(src));
}
*/

class LCA {
  int V, LOG_V;
  vector<vector<int>> parent;
  vector<int> depth;
  template<typename T>
  void dfs(const Graph<T> &g, int v, int p, int d) {
    parent[0][v] = p; depth[v] = d;
    for (const Edge<T> &e: g[v]) {
      if (e.to != p) dfs(g, e.to, v, d + 1);
    }
  }
public:
  template<typename T>
  LCA(const Graph<T> &g, int root) : V(g.size()), LOG_V(0), depth(V, 0) {
    for (int v = V; v > 0; v >>= 1) ++LOG_V;
    parent.assign(LOG_V, vector<int>(V, 0));
    dfs(g, root, -1, 0);
    for (int k = 0; k < LOG_V - 1; ++k) {
      for (int v = 0; v < V; ++v) {
        if (parent[k][v] < 0) parent[k + 1][v] = -1;
        else parent[k + 1][v] = parent[k][parent[k][v]];
      }
    }
  }
  int lca(int u, int v) {
    if (depth[u] > depth[v]) swap(u, v);
    for (int k = 0; k < LOG_V; ++k)
      if (((depth[v] - depth[u]) >> k) & 1) v = parent[k][v];
    if (u == v) return u;
    for (int k = LOG_V - 1; k >= 0; k--) {
      if (parent[k][u] != parent[k][v]) {
        u = parent[k][u];
        v = parent[k][v];
      }
    }
    return parent[0][u];
  }
};
<|endoftext|>


<commit_before>#include <algorithm>
#include <cmath>
#include <ctime>
#include <cstdlib>
#include <iomanip>
#include <iostream>
#include <sstream>
#include <string>
#include <utility>
#include <vector>

#include <openssl/sha.h>

using namespace std;

const bool DEBUG = false;

// Precision of floating point operations and representations
const double PRECISION = 6;
const double EPS = 1.0e-6;

// Value to scale relative spectra
const double RELATIVE_INTENSITY_SCALE = 1000.0;

// Separator for building spectrum strings
const char ION_SEPARATOR = ' ';

// Full spectrum hash properties
const char ION_PAIR_SEPARATOR = ':';
const int MAX_HASH_CHARATERS_ENCODED_SPECTRUM = 20;

// Top ions block properties
const int MAX_TOP_IONS = 10;
const int MAX_HASH_CHARACTERS_TOP_IONS = 10;

// Spectrum sum properties
const int SPECTRUM_SUM_PADDING = 10;
const int SPECTRUM_SUM_MAX_IONS = 100;

string sha256(const string s) {
	unsigned char digest[SHA256_DIGEST_LENGTH];

	SHA256_CTX sha256;
	SHA256_Init(&sha256);
	SHA256_Update(&sha256, s.c_str(), s.size());
	SHA256_Final(digest, &sha256);

	stringstream ss;

	for(int i = 0; i < SHA256_DIGEST_LENGTH; ++i) {
		ss << hex << setw(2) << setfill('0') << (int)digest[i];
	}

	return ss.str();
}

// http://stackoverflow.com/a/236803
vector<string> split(const string &s, char delimeter) {
	vector<string> elements;
	stringstream ss(s);
	string element;

	while(getline(ss, element, delimeter)) {
		elements.push_back(element);
	}

	return elements;
}

bool ionPairMzComparator(const pair<double, double> a, const pair<double, double> b) {
	if(abs(a.first - b.first) < EPS) {
		return a.second > b.second;
	} else {
		return a.first < b.first;
	}
}

bool ionPairIntensityComparator(const pair<double, double> a, const pair<double, double> b) {
	if(abs(a.second - b.second) < EPS) {
		return a.first < b.first;
	} else {
		return a.second > b.second;
	}
}

string buildFirstBlock(vector<pair<double, double> > &spectrum, char spectrum_type) {
	stringstream ss;
	ss << "splash" << spectrum_type << '0';
	return ss.str();
}

string encodeTopIons(vector<pair<double, double> > &spectrum, char spectrum_type) {
	sort(spectrum.begin(), spectrum.end(), ionPairIntensityComparator);

	int i = 0;
	stringstream ss;

	for(vector<pair<double, double> >::iterator it = spectrum.begin(); it != spectrum.end(); ++it) {
		ss << setprecision(6) << fixed << (*it).first;

		if(++i == MAX_TOP_IONS || i == spectrum.size()) {
			break;
		} else {
			ss << ION_SEPARATOR;
		}
	}

	if(DEBUG) {
		cerr << "Top Ions: '" << ss.str() << "'" << endl;
	}

	return sha256(ss.str()).substr(0, MAX_HASH_CHARACTERS_TOP_IONS);
}

string encodeSpectrum(vector<pair<double, double> > &spectrum, char spectrum_type) {
	sort(spectrum.begin(), spectrum.end(), ionPairMzComparator);

	int i = 0;
	stringstream ss;

	for(vector<pair<double, double> >::iterator it = spectrum.begin(); it != spectrum.end(); ++it) {
		ss << setprecision(6) << fixed << (*it).first << ION_PAIR_SEPARATOR << (*it).second;

		if(++i < spectrum.size()) {
			ss << ION_SEPARATOR;
		}
	}

	if(DEBUG) {
		cerr << "Encoded Spectrum: '" << ss.str() << "'" << endl;
	}

	return sha256(ss.str()).substr(0, MAX_HASH_CHARATERS_ENCODED_SPECTRUM);
}

string calculateSum(vector<pair<double, double> > &spectrum, char spectrum_type) {
	sort(spectrum.begin(), spectrum.end(), ionPairIntensityComparator);

	int i = 0;
	double spectrumSum = 0.0;
	stringstream ss;

	for(vector<pair<double, double> >::iterator it = spectrum.begin(); it != spectrum.end() && ++i <= SPECTRUM_SUM_MAX_IONS; ++it) {
		spectrumSum += (*it).first * (*it).second;
	}

	ss << setfill('0') << setw(SPECTRUM_SUM_PADDING) << static_cast<long>(spectrumSum);

	if(DEBUG) {
		cerr << "Spectrum Sum: " << setprecision(PRECISION) << fixed << spectrumSum << " -> " << ss.str() << endl;
	}

	return ss.str();
}

string splashIt(vector<pair<double, double> > &spectrum, char spectrum_type) {
	stringstream ss;

	ss << buildFirstBlock(spectrum, spectrum_type) << '-';
	ss << encodeTopIons(spectrum, spectrum_type) << '-';
	ss << encodeSpectrum(spectrum, spectrum_type) << '-';
	ss << calculateSum(spectrum, spectrum_type);

	return ss.str();
}

int main(int argc, char** argv) {
	int i = 0;
	string input;

	// Log times
	clock_t start = clock();
	double processingTime;

	while(getline(cin, input)) {
		++i;

		if(DEBUG) {
			cerr << "Spectrum #" << i << endl;
		}

		// Handle input of the form [id],[spectrum string]
		int delim_pos = input.find(',');

		string id = input.substr(0, delim_pos);
		string spectrum_string = input.substr(delim_pos + 1);

		// Convert spectrum to a vector of ion pairs and find the max intensity
		vector<string> ion_strings = split(spectrum_string, ' ');
		vector<pair<double, double> > spectrum;
		double maxIntensity = 0;

		for(vector<string>::iterator it = ion_strings.begin(); it != ion_strings.end(); ++it) {
			delim_pos = (*it).find(':');
			double mz = atof((*it).substr(0, delim_pos).c_str());
			double intensity = atof((*it).substr(delim_pos + 1).c_str());

			if(intensity > maxIntensity)
				maxIntensity = intensity;

			// Store ion as a pair object, with 'first' corresponding to m/z
			// and 'second' to intensity
			spectrum.push_back(make_pair(mz, intensity));
		}

		// Normalize spectrum
		for(vector<pair<double, double> >::iterator it = spectrum.begin(); it != spectrum.end(); ++it) {
			(*it).second = (*it).second / maxIntensity * RELATIVE_INTENSITY_SCALE;
		}

		// Provide output for large files
		if(i % 10000 == 0) {
			cerr << "processed " << i << " spectra, " << setprecision(2) << fixed
				 <<(std::clock() - start) / (double)(CLOCKS_PER_SEC / 1000) / i
				 << " ms average time to splash a spectrum." << endl;
		}

		// Print the spectrum id with the calculated splash id
		cout << id << "," << splashIt(spectrum, '1') << endl;
	}
}
<commit_msg>fixed export format for c++ v1<commit_after>#include <algorithm>
#include <cmath>
#include <ctime>
#include <cstdlib>
#include <iomanip>
#include <iostream>
#include <sstream>
#include <string>
#include <utility>
#include <vector>

#include <openssl/sha.h>

using namespace std;

const bool DEBUG = false;

// Precision of floating point operations and representations
const double PRECISION = 6;
const double EPS = 1.0e-6;

// Value to scale relative spectra
const double RELATIVE_INTENSITY_SCALE = 1000.0;

// Separator for building spectrum strings
const char ION_SEPARATOR = ' ';

// Full spectrum hash properties
const char ION_PAIR_SEPARATOR = ':';
const int MAX_HASH_CHARATERS_ENCODED_SPECTRUM = 20;

// Top ions block properties
const int MAX_TOP_IONS = 10;
const int MAX_HASH_CHARACTERS_TOP_IONS = 10;

// Spectrum sum properties
const int SPECTRUM_SUM_PADDING = 10;
const int SPECTRUM_SUM_MAX_IONS = 100;

string sha256(const string s) {
	unsigned char digest[SHA256_DIGEST_LENGTH];

	SHA256_CTX sha256;
	SHA256_Init(&sha256);
	SHA256_Update(&sha256, s.c_str(), s.size());
	SHA256_Final(digest, &sha256);

	stringstream ss;

	for(int i = 0; i < SHA256_DIGEST_LENGTH; ++i) {
		ss << hex << setw(2) << setfill('0') << (int)digest[i];
	}

	return ss.str();
}

// http://stackoverflow.com/a/236803
vector<string> split(const string &s, char delimeter) {
	vector<string> elements;
	stringstream ss(s);
	string element;

	while(getline(ss, element, delimeter)) {
		elements.push_back(element);
	}

	return elements;
}

bool ionPairMzComparator(const pair<double, double> a, const pair<double, double> b) {
	if(abs(a.first - b.first) < EPS) {
		return a.second > b.second;
	} else {
		return a.first < b.first;
	}
}

bool ionPairIntensityComparator(const pair<double, double> a, const pair<double, double> b) {
	if(abs(a.second - b.second) < EPS) {
		return a.first < b.first;
	} else {
		return a.second > b.second;
	}
}

string buildFirstBlock(vector<pair<double, double> > &spectrum, char spectrum_type) {
	stringstream ss;
	ss << "splash" << spectrum_type << '0';
	return ss.str();
}

string encodeTopIons(vector<pair<double, double> > &spectrum, char spectrum_type) {
	sort(spectrum.begin(), spectrum.end(), ionPairIntensityComparator);

	int i = 0;
	stringstream ss;

	for(vector<pair<double, double> >::iterator it = spectrum.begin(); it != spectrum.end(); ++it) {
		ss << setprecision(6) << fixed << (*it).first;

		if(++i == MAX_TOP_IONS || i == spectrum.size()) {
			break;
		} else {
			ss << ION_SEPARATOR;
		}
	}

	if(DEBUG) {
		cerr << "Top Ions: '" << ss.str() << "'" << endl;
	}

	return sha256(ss.str()).substr(0, MAX_HASH_CHARACTERS_TOP_IONS);
}

string encodeSpectrum(vector<pair<double, double> > &spectrum, char spectrum_type) {
	sort(spectrum.begin(), spectrum.end(), ionPairMzComparator);

	int i = 0;
	stringstream ss;

	for(vector<pair<double, double> >::iterator it = spectrum.begin(); it != spectrum.end(); ++it) {
		ss << setprecision(6) << fixed << (*it).first << ION_PAIR_SEPARATOR << (*it).second;

		if(++i < spectrum.size()) {
			ss << ION_SEPARATOR;
		}
	}

	if(DEBUG) {
		cerr << "Encoded Spectrum: '" << ss.str() << "'" << endl;
	}

	return sha256(ss.str()).substr(0, MAX_HASH_CHARATERS_ENCODED_SPECTRUM);
}

string calculateSum(vector<pair<double, double> > &spectrum, char spectrum_type) {
	sort(spectrum.begin(), spectrum.end(), ionPairIntensityComparator);

	int i = 0;
	double spectrumSum = 0.0;
	stringstream ss;

	for(vector<pair<double, double> >::iterator it = spectrum.begin(); it != spectrum.end() && ++i <= SPECTRUM_SUM_MAX_IONS; ++it) {
		spectrumSum += (*it).first * (*it).second;
	}

	ss << setfill('0') << setw(SPECTRUM_SUM_PADDING) << static_cast<long>(spectrumSum);

	if(DEBUG) {
		cerr << "Spectrum Sum: " << setprecision(PRECISION) << fixed << spectrumSum << " -> " << ss.str() << endl;
	}

	return ss.str();
}

string splashIt(vector<pair<double, double> > &spectrum, char spectrum_type) {
	stringstream ss;

	ss << buildFirstBlock(spectrum, spectrum_type) << '-';
	ss << encodeTopIons(spectrum, spectrum_type) << '-';
	ss << encodeSpectrum(spectrum, spectrum_type) << '-';
	ss << calculateSum(spectrum, spectrum_type);

	return ss.str();
}

int main(int argc, char** argv) {
	int i = 0;
	string input;

	// Log times
	clock_t start = clock();
	double processingTime;

	while(getline(cin, input)) {
		++i;

		if(DEBUG) {
			cerr << "Spectrum #" << i << endl;
		}

		// Handle input of the form [id],[spectrum string]
		int delim_pos = input.find(',');

		string id = input.substr(0, delim_pos);
		string spectrum_string = input.substr(delim_pos + 1);

		// Convert spectrum to a vector of ion pairs and find the max intensity
		vector<string> ion_strings = split(spectrum_string, ' ');
		vector<pair<double, double> > spectrum;
		double maxIntensity = 0;

		for(vector<string>::iterator it = ion_strings.begin(); it != ion_strings.end(); ++it) {
			delim_pos = (*it).find(':');
			double mz = atof((*it).substr(0, delim_pos).c_str());
			double intensity = atof((*it).substr(delim_pos + 1).c_str());

			if(intensity > maxIntensity)
				maxIntensity = intensity;

			// Store ion as a pair object, with 'first' corresponding to m/z
			// and 'second' to intensity
			spectrum.push_back(make_pair(mz, intensity));
		}

		// Normalize spectrum
		for(vector<pair<double, double> >::iterator it = spectrum.begin(); it != spectrum.end(); ++it) {
			(*it).second = (*it).second / maxIntensity * RELATIVE_INTENSITY_SCALE;
		}

		// Provide output for large files
		if(i % 10000 == 0) {
			cerr << "processed " << i << " spectra, " << setprecision(2) << fixed
				 <<(std::clock() - start) / (double)(CLOCKS_PER_SEC / 1000) / i
				 << " ms average time to splash a spectrum." << endl;
		}

		// Print the spectrum id with the calculated splash id
		cout << id << "," << splashIt(spectrum, '1') << "," << spectrum_string << endl;
	}
}
<|endoftext|>


<commit_before>/** \file    zts_client.cc
    \brief   Downloads bibliographic metadata using a Zotero Translation server.
    \author  Dr. Johannes Ruscheinski

    \copyright 2017, Library of the University of Tübingen

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU Affero General Public License as
    published by the Free Software Foundation, either version 3 of the
    License, or (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Affero General Public License for more details.

    You should have received a copy of the GNU Affero General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
#include <iostream>
#include <cinttypes>
#include <uuid/uuid.h>
#include "Compiler.h"
#include "FileDescriptor.h"
#include "HttpHeader.h"
#include "SocketUtil.h"
#include "StringUtil.h"
#include "UrlUtil.h"
#include "util.h"

void Usage() {
    std::cerr << "Usage: " << ::progname
              << " zts_server_url marc_output harvest_url1 [harvest_url2 .. harvest_urlN]\n";
    std::exit(EXIT_FAILURE);
}

bool Download(const std::string &server_address, const unsigned short server_port, const std::string &server_path,
              const TimeLimit &time_limit, const std::string &request_headers, const std::string &request_body,
              std::string * const returned_data, std::string * const error_message)
{
    returned_data->clear();
    error_message->clear();

    std::string tcp_connect_error_message;
    const FileDescriptor socket_fd(SocketUtil::TcpConnect(server_address, server_port, time_limit,
                                                          &tcp_connect_error_message, SocketUtil::DISABLE_NAGLE));
    if (socket_fd == -1) {
        *error_message = "Could not open TCP connection to " + server_address + ", port "
            + std::to_string(server_port) + ": " + tcp_connect_error_message;
        *error_message += " (Time remaining: " + std::to_string(time_limit.getRemainingTime()) + ").";
        return false;
    }

    std::string request;
    request += request_headers;
    request += "\r\n";
    request += request_body;

    if (SocketUtil::TimedWrite(socket_fd, time_limit, request.data(), request.length()) == -1) {
        *error_message = "Could not write to socket";
        *error_message += " (Time remaining: " + std::to_string(time_limit.getRemainingTime()) + ")";
        *error_message += '!';
        return false;
    }

    char http_response_header[10240 + 1];
    ssize_t no_of_bytes_read(SocketUtil::TimedRead(socket_fd, time_limit, http_response_header,
                                                   sizeof(http_response_header) - 1));
        /* Intentionally empty! */;
    if (no_of_bytes_read == -1) {
        *error_message = "Could not read from socket (1).";
        *error_message += " (Time remaining: " + std::to_string(time_limit.getRemainingTime())
            + ").";
        return false;
    }
    http_response_header[no_of_bytes_read] = '\0';
    HttpHeader http_header(http_response_header);

    // the 2xx codes indicate success:
    if (http_header.getStatusCode() < 200 or http_header.getStatusCode() > 299) {
        *error_message = "Web server returned error status code ("
            + std::to_string(http_header.getStatusCode()) + "), address was "
            + server_address + ", port was " + std::to_string(server_port) + ", path was \""
            + server_path +"\"!";
        return false;
    }

    // read the returned document source:
    std::string response(http_response_header, no_of_bytes_read);
    char buf[10240];
    do {
        no_of_bytes_read = SocketUtil::TimedRead(socket_fd, time_limit, buf, sizeof(buf));
        if (no_of_bytes_read == -1) {
            *error_message = "Could not read from socket (2).";
            *error_message += " (Time remaining: " + std::to_string(time_limit.getRemainingTime()) + ").";
            return false;
        }
        if (no_of_bytes_read > 0)
            response.append(buf, no_of_bytes_read);
    } while (no_of_bytes_read > 0);

    std::string::size_type pos = response.find("\r\n\r\n"); // the header ends with two cr/lf pairs!
    if (pos != std::string::npos) {
        pos += 4;
        *returned_data = response.substr(pos);
    }

    return true;
}

// We try to be unique for the machine we're on.  Beyond that we may have a problem.
std::string GetNextSessionId() {
    static unsigned counter;
    static uint32_t uuid[4];
    if (unlikely(counter == 0))
        ::uuid_generate(reinterpret_cast<unsigned char *>(uuid));
    ++counter;
    return "ub_tools_zts_client_" + StringUtil::ToString(uuid[0]) + StringUtil::ToString(uuid[1])
           + StringUtil::ToString(uuid[2]) + StringUtil::ToString(uuid[3]) + "_" + StringUtil::ToString(counter);
}

bool Download(const std::string &server_address, const unsigned short server_port, const std::string &server_path,
              const TimeLimit &time_limit, const std::string &harvest_url, std::string * const json_result,
              std::string * const error_message)
{
        const std::string JSON_REQUEST("{\"url\":\"" + harvest_url + "\",\"sessionid\":\"" + GetNextSessionId()
                                       + "\"}");
        std::string headers;
        headers += "POST " + server_path + " HTTP/1.0\r\n";
        headers += "Host: " + server_address + "\r\n";
        headers += "User-Agent: zts_client/1.0 ub_tools\r\n";
        headers += "Accept: application/json\r\n";
        headers += "Connection: close\r\n";
        headers += "Content-Type: application/json\r\n";
        headers += "Content-Length: " + std::to_string(JSON_REQUEST.length()) + "\r\n";

        return Download(server_address, server_port, server_path, time_limit, headers, JSON_REQUEST, json_result,
                        error_message);
}

inline bool Download(const Url &url, const TimeLimit &time_limit, const std::string &harvest_url,
                     std::string * const json_result, std::string * const error_message)
{
    return Download(url.getAuthority(), url.getPort(), url.getPath(), time_limit, harvest_url, json_result,
                    error_message);
}

void Harvest(const std::string &zts_server_url, const std::string &harvest_url) {
    const Url server_url(zts_server_url);
    std::string json_document, error_message;
    if (not Download(server_url.getAuthority(), server_url.getPort(), server_url.getPath(), /* time_limit = */ 10000,
                     harvest_url, &json_document, &error_message))
        Error("Download for harvest URL \"" + harvest_url + "\" failed: " + error_message);
    std::cout << "Server sent: \n" << json_document << '\n';
}

int main(int argc, char *argv[]) {
    ::progname = argv[0];
    if (argc < 4)
        Usage();

    const std::string ZTS_SERVER_URL(argv[1]);

    try {
        for (int arg_no(3); arg_no < argc; ++arg_no)
            Harvest(ZTS_SERVER_URL, argv[arg_no]);
    } catch (const std::exception &x) {
        Error("caught exception: " + std::string(x.what()));
    }
}
<commit_msg>Used simpler version of Download().<commit_after>/** \file    zts_client.cc
    \brief   Downloads bibliographic metadata using a Zotero Translation server.
    \author  Dr. Johannes Ruscheinski

    \copyright 2017, Library of the University of Tübingen

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU Affero General Public License as
    published by the Free Software Foundation, either version 3 of the
    License, or (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Affero General Public License for more details.

    You should have received a copy of the GNU Affero General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
#include <iostream>
#include <cinttypes>
#include <uuid/uuid.h>
#include "Compiler.h"
#include "FileDescriptor.h"
#include "HttpHeader.h"
#include "SocketUtil.h"
#include "StringUtil.h"
#include "UrlUtil.h"
#include "util.h"

void Usage() {
    std::cerr << "Usage: " << ::progname
              << " zts_server_url marc_output harvest_url1 [harvest_url2 .. harvest_urlN]\n";
    std::exit(EXIT_FAILURE);
}

bool Download(const std::string &server_address, const unsigned short server_port, const std::string &server_path,
              const TimeLimit &time_limit, const std::string &request_headers, const std::string &request_body,
              std::string * const returned_data, std::string * const error_message)
{
    returned_data->clear();
    error_message->clear();

    std::string tcp_connect_error_message;
    const FileDescriptor socket_fd(SocketUtil::TcpConnect(server_address, server_port, time_limit,
                                                          &tcp_connect_error_message, SocketUtil::DISABLE_NAGLE));
    if (socket_fd == -1) {
        *error_message = "Could not open TCP connection to " + server_address + ", port "
            + std::to_string(server_port) + ": " + tcp_connect_error_message;
        *error_message += " (Time remaining: " + std::to_string(time_limit.getRemainingTime()) + ").";
        return false;
    }

    std::string request;
    request += request_headers;
    request += "\r\n";
    request += request_body;

    if (SocketUtil::TimedWrite(socket_fd, time_limit, request.data(), request.length()) == -1) {
        *error_message = "Could not write to socket";
        *error_message += " (Time remaining: " + std::to_string(time_limit.getRemainingTime()) + ")";
        *error_message += '!';
        return false;
    }

    char http_response_header[10240 + 1];
    ssize_t no_of_bytes_read(SocketUtil::TimedRead(socket_fd, time_limit, http_response_header,
                                                   sizeof(http_response_header) - 1));
        /* Intentionally empty! */;
    if (no_of_bytes_read == -1) {
        *error_message = "Could not read from socket (1).";
        *error_message += " (Time remaining: " + std::to_string(time_limit.getRemainingTime())
            + ").";
        return false;
    }
    http_response_header[no_of_bytes_read] = '\0';
    HttpHeader http_header(http_response_header);

    // the 2xx codes indicate success:
    if (http_header.getStatusCode() < 200 or http_header.getStatusCode() > 299) {
        *error_message = "Web server returned error status code ("
            + std::to_string(http_header.getStatusCode()) + "), address was "
            + server_address + ", port was " + std::to_string(server_port) + ", path was \""
            + server_path +"\"!";
        return false;
    }

    // read the returned document source:
    std::string response(http_response_header, no_of_bytes_read);
    char buf[10240];
    do {
        no_of_bytes_read = SocketUtil::TimedRead(socket_fd, time_limit, buf, sizeof(buf));
        if (no_of_bytes_read == -1) {
            *error_message = "Could not read from socket (2).";
            *error_message += " (Time remaining: " + std::to_string(time_limit.getRemainingTime()) + ").";
            return false;
        }
        if (no_of_bytes_read > 0)
            response.append(buf, no_of_bytes_read);
    } while (no_of_bytes_read > 0);

    std::string::size_type pos = response.find("\r\n\r\n"); // the header ends with two cr/lf pairs!
    if (pos != std::string::npos) {
        pos += 4;
        *returned_data = response.substr(pos);
    }

    return true;
}

// We try to be unique for the machine we're on.  Beyond that we may have a problem.
std::string GetNextSessionId() {
    static unsigned counter;
    static uint32_t uuid[4];
    if (unlikely(counter == 0))
        ::uuid_generate(reinterpret_cast<unsigned char *>(uuid));
    ++counter;
    return "ub_tools_zts_client_" + StringUtil::ToString(uuid[0]) + StringUtil::ToString(uuid[1])
           + StringUtil::ToString(uuid[2]) + StringUtil::ToString(uuid[3]) + "_" + StringUtil::ToString(counter);
}

bool Download(const std::string &server_address, const unsigned short server_port, const std::string &server_path,
              const TimeLimit &time_limit, const std::string &harvest_url, std::string * const json_result,
              std::string * const error_message)
{
        const std::string JSON_REQUEST("{\"url\":\"" + harvest_url + "\",\"sessionid\":\"" + GetNextSessionId()
                                       + "\"}");
        std::string headers;
        headers += "POST " + server_path + " HTTP/1.0\r\n";
        headers += "Host: " + server_address + "\r\n";
        headers += "User-Agent: zts_client/1.0 ub_tools\r\n";
        headers += "Accept: application/json\r\n";
        headers += "Connection: close\r\n";
        headers += "Content-Type: application/json\r\n";
        headers += "Content-Length: " + std::to_string(JSON_REQUEST.length()) + "\r\n";

        return Download(server_address, server_port, server_path, time_limit, headers, JSON_REQUEST, json_result,
                        error_message);
}

inline bool Download(const Url &url, const TimeLimit &time_limit, const std::string &harvest_url,
                     std::string * const json_result, std::string * const error_message)
{
    return Download(url.getAuthority(), url.getPort(), url.getPath(), time_limit, harvest_url, json_result,
                    error_message);
}

void Harvest(const std::string &zts_server_url, const std::string &harvest_url) {
    const Url server_url(zts_server_url);
    std::string json_document, error_message;
    if (not Download(server_url, /* time_limit = */ 10000, harvest_url, &json_document, &error_message))
        Error("Download for harvest URL \"" + harvest_url + "\" failed: " + error_message);
    std::cout << "Server sent: \n" << json_document << '\n';
}

int main(int argc, char *argv[]) {
    ::progname = argv[0];
    if (argc < 4)
        Usage();

    const std::string ZTS_SERVER_URL(argv[1]);

    try {
        for (int arg_no(3); arg_no < argc; ++arg_no)
            Harvest(ZTS_SERVER_URL, argv[arg_no]);
    } catch (const std::exception &x) {
        Error("caught exception: " + std::string(x.what()));
    }
}
<|endoftext|>


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

#include <stddef.h>
#include <stdint.h>

#include "perfetto/base/utils.h"
#include "src/ipc/buffered_frame_deserializer.h"
#include "src/ipc/wire_protocol.pb.h"

extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size);

extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
  perfetto::ipc::BufferedFrameDeserializer bfd;
  auto rbuf = bfd.BeginReceive();
  memcpy(rbuf.data, data, std::min(rbuf.size, size));
  ::perfetto::base::ignore_result(bfd.EndReceive(size));
  // TODO(fmayer): Determine if this has value.
  // This slows down fuzzing from 190k / s to 140k / sec.
  while (bfd.PopNextFrame() != nullptr) {
  }
  return 0;
}
<commit_msg>fuzzing: Consume everything in buffered_frame_deserialzier. am: ca5569f2c9 am: 292082487b am: a4834fef78<commit_after>/*
 * Copyright (C) 2017 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <stddef.h>
#include <stdint.h>

#include "perfetto/base/utils.h"
#include "src/ipc/buffered_frame_deserializer.h"
#include "src/ipc/wire_protocol.pb.h"

extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size);

extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
  perfetto::ipc::BufferedFrameDeserializer bfd;
  size_t write_offset = 0;
  while (write_offset < size) {
    size_t available_size = size - write_offset;
    auto rbuf = bfd.BeginReceive();
    size_t chunk_size = std::min(available_size, rbuf.size);
    memcpy(rbuf.data, data, chunk_size);
    if (!bfd.EndReceive(chunk_size))
      break;
    write_offset += chunk_size;
  }
  return 0;
}
<|endoftext|>


<commit_before>#pragma once
#include <boost/preprocessor.hpp>
#include <boost/format.hpp>
#include <iostream>
#include <sstream>
#include "argholder.hpp"
#include "type.hpp"

#ifdef ANDROID
	#include <android/log.h>
	#define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, "threaded_app", __VA_ARGS__))
	#define LOGE(...) ((void)__android_log_print(ANDROID_LOG_ERROR, "threaded_app", __VA_ARGS__))
	/* For debug builds, always enable the debug traces in this library */
	#ifndef NDEBUG
	#  define LOGV(...)  ((void)__android_log_print(ANDROID_LOG_VERBOSE, "threaded_app", __VA_ARGS__))
	#else
	#  define LOGV(...)  ((void)0)
	#endif
#endif

// Debug=assert, Release=throw		[Assert_Trap]
// Debug=assert, Release=none		[Assert_TrapP]
// Debug=throw, Release=throw		[Assert_Throw]
// Debug=throw, Release=none		[Assert_ThrowP]
// Debug=warning, Release=warning	[Assert_Warn]
// Debug=warning, Release=none		[Assert_WarnP]

#define _Assert_Base(expr, act, ...)			{if(!(expr)) { act.onError(MakeAssertMsg(#expr, __FILE__, __FUNCTION__, __LINE__, __VA_ARGS__)); }}
#define _AssertT(act, expr, throwtype)			_Assert_Base(expr, (AAct_##act<BOOST_PP_SEQ_ENUM(throwtype)>()), BOOST_PP_STRINGIZE(BOOST_PP_SEQ_ELEM(0,throwtype)))
#define _AssertTArg(act, expr, throwtype, ...)	_Assert_Base(expr, (AAct_##act<BOOST_PP_SEQ_ENUM(throwtype)>(__VA_ARGS__)), BOOST_PP_STRINGIZE(BOOST_PP_SEQ_ELEM(0,throwtype)))
// 任意の例外クラスを指定してアサートチェック
// 引数の有無で_AssertT(), _AssertTArg()を呼び分ける
#define AssertT(act, expr, ...)					BOOST_PP_IF(BOOST_PP_EQUAL(1, BOOST_PP_VARIADIC_SIZE(__VA_ARGS__)), _AssertT, _AssertTArg)(act,expr,__VA_ARGS__)
// デフォルトのエラーメッセージでアサートチェック
#define _Assert(act, expr)						_AssertArg(act, expr, "Assertion failed")
#define _AssertArg(act, expr, ...)				_Assert_Base(expr, (AAct_##act<std::runtime_error>()), __VA_ARGS__)
// Act,Exprに続く引数が無いときは_Assert(), あるなら_AssertArg()を呼ぶ
// 例外形式はstd::runtime_errorとして与えられた引数でエラーメッセージを生成
#define Assert(act, ...)						BOOST_PP_IF(BOOST_PP_EQUAL(1, BOOST_PP_VARIADIC_SIZE(__VA_ARGS__)), _Assert, _AssertArg)(act, __VA_ARGS__)

#ifdef DEBUG
	#define AssertP(act, ...)						Assert(act, __VA_ARGS__)
	#define AssertTP(act, expr, throwtype, ...)		AssertT(act,expr,throwtype, __VA_ARGS__)
#else
	#define AssertP(act, ...)
	#define AssertTP(act, expr, throwtype, ...)
#endif
template <class... Ts>
std::string ConcatMessage(boost::format& fmt, Ts&&... /*t*/) { return fmt.str(); }
template <class T, class... Ts>
std::string ConcatMessage(boost::format& fmt, T&& t, Ts&&... ts) {
	fmt % std::forward<T>(t);
	return ConcatMessage(fmt, std::forward<Ts>(ts)...);
}
template <class... Ts>
std::string MakeAssertMsg(const char* base, const char* filename, const char* funcname, int line, const char* fmt, Ts&&... ts) {
	using std::endl;
	boost::format bf(fmt);
	std::stringstream ss;
	ss << ConcatMessage(bf, std::forward<Ts>(ts)...) << endl
		<< base << endl
		<< "at file:\t" << filename << endl
		<< "at function:\t" << funcname << endl
		<< "on line:\t" << line << endl;
	return ss.str();
}

using LogOUT = std::function<void (const std::string&)>;
extern LogOUT g_logOut;
void LogOutput(const std::string& s);
template <class... Ts>
void LogOutput(const char* fmt, Ts&&... ts) {
	boost::format msg(fmt);
	LogOutput(ConcatMessage(msg, std::forward<Ts>(ts)...));
}

//! エラー時にメッセージ出力だけする
template <class E, class... Ts>
struct AAct_Warn {
	template <class... TA>
	AAct_Warn(TA&&...) {}
	void onError(const std::string& str) {
		LogOutput(str);
	}
};
//! エラー時にメッセージ出力と例外の送出を行う
template <class E, class... Ts>
struct AAct_Throw : spn::ArgHolder<Ts...> {
	using spn::ArgHolder<Ts...>::ArgHolder;
	// 例外クラスがconst std::stringでコンストラクトできる場合はエラーメッセージを渡し、残りの引数を無視
	template <class E2, class... TArg, class Dummy=void*,
		class=typename std::enable_if<
			std::is_constructible<E2, const std::string&>::value
			>::type
		>
	static void __Throw(const std::string& str, TArg... /*args*/) {
		throw E(str); }

	// そうでない場合はエラーメッセージをその場で出力し、引数はユーザーが渡したものを指定
	template <class E2, class... TArg,
		class=typename std::enable_if<
			!std::is_constructible<E2, const std::string&>::value
			>::type
		>
	static void __Throw(const std::string& str, TArg... args) {
		AAct_Warn<E2>().onError(str);
		throw E(args...); }

	template <class T2, class... Ts2>
	static void _Throw(const std::string& str, T2&& t, Ts2&&... ts) {
		AAct_Warn<E>().onError(str);
		throw E(std::forward<T2>(t), std::forward<Ts2>(ts)...); }
	void onError(const std::string& str) {
		this->inorder([&str](Ts... args){
			__Throw<E>(str, args...);
		});
	}
};
//! エラー時にデバッガをブレーク、リリース時には例外の送出を行う
template <class E, class... Ts>
struct AAct_Trap : AAct_Throw<E,Ts...> {
	using base_type = AAct_Throw<E,Ts...>;
	using base_type::base_type;
	void onError(const std::string& str) {
		#ifdef DEBUG
			AAct_Warn<E>().onError(str);
			__builtin_trap();
		#endif
		base_type::onError(str);
	}
};

#define SOURCEPOS ::spn::SourcePos{__FILE__, __PRETTY_FUNCTION__, __func__, __LINE__}
namespace spn {
	//! ソースコード上の位置を表す情報
	struct SourcePos {
		const char	*filename,
					*funcname,
					*funcname_short;
		int			line;
	};
	template <class Act, class Chk, class... Ts>
	void EChk(Act&& act, Chk&& chk, const SourcePos& pos, Ts&&... ts) {
		const char* msg = chk.errorDesc(std::forward<Ts>(ts)...);
		if(msg)
			act.onError(MakeAssertMsg(chk.getAPIName(), pos.filename, pos.funcname, pos.line, msg));
	}
	namespace detail {
		template <class RT, class Act, class Chk, class Func, class... TsA>
		RT EChk_base(std::false_type, Act&& act, Chk&& chk, const SourcePos& pos, const Func& func, TsA&&... ts) {
			chk.reset();
			auto res = func(std::forward<TsA>(ts)...);
			EChk(std::forward<Act>(act), std::forward<Chk>(chk), pos);
			return std::move(res);
		}
		template <class RT, class Act, class Chk, class Func, class... TsA>
		void EChk_base(std::true_type, Act&& act, Chk&& chk, const SourcePos& pos, const Func& func, TsA&&... ts) {
			func(std::forward<TsA>(ts)...);
			EChk(std::forward<Act>(act), std::forward<Chk>(chk), pos);
		}

		template <class T, class Func>
		struct NoneT_cnv {
			using type = T;
		};
		template <class Func>
		struct NoneT_cnv<spn::none_t, Func> {
			using type = ResultOf_t<Func>;
		};
	}

	//! エラーチェック & アサート(APIがエラーを記憶しているタイプ)
	template <class RT, class Act, class Chk, class Func, class... Ts>
	auto EChk_memory(Act&& act, Chk&& chk, const SourcePos& pos, const Func& func, Ts&&... ts) {
		// 戻り値がvoidかそれ以外かで分岐
		using rt_t = typename detail::NoneT_cnv<RT, Func>::type;
		return detail::EChk_base<rt_t>(typename std::is_same<void, rt_t>::type(),
									std::forward<Act>(act),
									std::forward<Chk>(chk),
									pos, func, std::forward<Ts>(ts)...);
	}
	//! エラーチェック & アサート(APIがエラーコードを返すタイプ)
	template <class Act, class Chk, class Func, class... TsA>
	auto EChk_code(Act&& act, Chk&& chk, const SourcePos& pos, const Func& func, TsA&&... ts) {
		auto code = func(std::forward<TsA>(ts)...);
		EChk(std::forward<Act>(act),
					std::forward<Chk>(chk),
					pos,
					code);
		return code;
	}
	//! エラーチェック & アサート(予め取得した結果コードを入力)
	template <class Act, class Chk, class CODE>
	CODE EChk_usercode(Act&& act, Chk&& chk, const SourcePos& pos, const CODE& code) {
		EChk(std::forward<Act>(act),
					std::forward<Chk>(chk),
					pos, code);
		return code;
	}
	#define EChk_memory_a		EChk_memory
	#define EChk_code_a			EChk_code
	#define EChk_usercode_a		EChk_usercode
	#define EChk_a				EChk
	#ifdef DEBUG
		#define EChk_memory_d		EChk_memory
		#define EChk_code_d			EChk_code
		#define EChk_usercode_d		EChk_usercode
		#define EChk_d				EChk
	#else
		#define EChk_d(...)
		// ----- エラーチェック無し(非デバッグモード時) -----
		template <class Act, class Chk, class Func, class... Ts>
		auto EChk_memory_d(Act&&, Chk&&, const SourcePos&, const Func& func, Ts&&... ts) {
			return func(std::forward<Ts>(ts)...);
		}
		auto EChk_code_d(Ts&&... ts) {
			return EChk_memory_d(std::forward<Ts>(ts)...);
		}
		template <class Act, class Chk, class CODE>
		CODE EChk_usercode_d(Act&&, Chk&&, const SourcePos&, const CODE& code) { return code; }
	#endif
}

// ---- ログ出力 ----
#define PrintLog			LogOutput(SOURCEPOS, "")
#define PrintLogMsg(...)	LogOutput(SOURCEPOS, __VA_ARGS__)
void LogOutput(const ::spn::SourcePos& pos, const std::string& msg);
template <class... Ts>
void LogOutput(const ::spn::SourcePos& pos, const std::string& msg, Ts&&... ts) {
	boost::format str(msg);
	ConcatMessage(str, std::forward<Ts>(ts)...);
	LogOutput(pos, str.str());
}

<commit_msg>リリースビルド時の文法エラー修正<commit_after>#pragma once
#include <boost/preprocessor.hpp>
#include <boost/format.hpp>
#include <iostream>
#include <sstream>
#include "argholder.hpp"
#include "type.hpp"

#ifdef ANDROID
	#include <android/log.h>
	#define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, "threaded_app", __VA_ARGS__))
	#define LOGE(...) ((void)__android_log_print(ANDROID_LOG_ERROR, "threaded_app", __VA_ARGS__))
	/* For debug builds, always enable the debug traces in this library */
	#ifndef NDEBUG
	#  define LOGV(...)  ((void)__android_log_print(ANDROID_LOG_VERBOSE, "threaded_app", __VA_ARGS__))
	#else
	#  define LOGV(...)  ((void)0)
	#endif
#endif

// Debug=assert, Release=throw		[Assert_Trap]
// Debug=assert, Release=none		[Assert_TrapP]
// Debug=throw, Release=throw		[Assert_Throw]
// Debug=throw, Release=none		[Assert_ThrowP]
// Debug=warning, Release=warning	[Assert_Warn]
// Debug=warning, Release=none		[Assert_WarnP]

#define _Assert_Base(expr, act, ...)			{if(!(expr)) { act.onError(MakeAssertMsg(#expr, __FILE__, __FUNCTION__, __LINE__, __VA_ARGS__)); }}
#define _AssertT(act, expr, throwtype)			_Assert_Base(expr, (AAct_##act<BOOST_PP_SEQ_ENUM(throwtype)>()), BOOST_PP_STRINGIZE(BOOST_PP_SEQ_ELEM(0,throwtype)))
#define _AssertTArg(act, expr, throwtype, ...)	_Assert_Base(expr, (AAct_##act<BOOST_PP_SEQ_ENUM(throwtype)>(__VA_ARGS__)), BOOST_PP_STRINGIZE(BOOST_PP_SEQ_ELEM(0,throwtype)))
// 任意の例外クラスを指定してアサートチェック
// 引数の有無で_AssertT(), _AssertTArg()を呼び分ける
#define AssertT(act, expr, ...)					BOOST_PP_IF(BOOST_PP_EQUAL(1, BOOST_PP_VARIADIC_SIZE(__VA_ARGS__)), _AssertT, _AssertTArg)(act,expr,__VA_ARGS__)
// デフォルトのエラーメッセージでアサートチェック
#define _Assert(act, expr)						_AssertArg(act, expr, "Assertion failed")
#define _AssertArg(act, expr, ...)				_Assert_Base(expr, (AAct_##act<std::runtime_error>()), __VA_ARGS__)
// Act,Exprに続く引数が無いときは_Assert(), あるなら_AssertArg()を呼ぶ
// 例外形式はstd::runtime_errorとして与えられた引数でエラーメッセージを生成
#define Assert(act, ...)						BOOST_PP_IF(BOOST_PP_EQUAL(1, BOOST_PP_VARIADIC_SIZE(__VA_ARGS__)), _Assert, _AssertArg)(act, __VA_ARGS__)

#ifdef DEBUG
	#define AssertP(act, ...)						Assert(act, __VA_ARGS__)
	#define AssertTP(act, expr, throwtype, ...)		AssertT(act,expr,throwtype, __VA_ARGS__)
#else
	#define AssertP(act, ...)
	#define AssertTP(act, expr, throwtype, ...)
#endif
template <class... Ts>
std::string ConcatMessage(boost::format& fmt, Ts&&... /*t*/) { return fmt.str(); }
template <class T, class... Ts>
std::string ConcatMessage(boost::format& fmt, T&& t, Ts&&... ts) {
	fmt % std::forward<T>(t);
	return ConcatMessage(fmt, std::forward<Ts>(ts)...);
}
template <class... Ts>
std::string MakeAssertMsg(const char* base, const char* filename, const char* funcname, int line, const char* fmt, Ts&&... ts) {
	using std::endl;
	boost::format bf(fmt);
	std::stringstream ss;
	ss << ConcatMessage(bf, std::forward<Ts>(ts)...) << endl
		<< base << endl
		<< "at file:\t" << filename << endl
		<< "at function:\t" << funcname << endl
		<< "on line:\t" << line << endl;
	return ss.str();
}

using LogOUT = std::function<void (const std::string&)>;
extern LogOUT g_logOut;
void LogOutput(const std::string& s);
template <class... Ts>
void LogOutput(const char* fmt, Ts&&... ts) {
	boost::format msg(fmt);
	LogOutput(ConcatMessage(msg, std::forward<Ts>(ts)...));
}

//! エラー時にメッセージ出力だけする
template <class E, class... Ts>
struct AAct_Warn {
	template <class... TA>
	AAct_Warn(TA&&...) {}
	void onError(const std::string& str) {
		LogOutput(str);
	}
};
//! エラー時にメッセージ出力と例外の送出を行う
template <class E, class... Ts>
struct AAct_Throw : spn::ArgHolder<Ts...> {
	using spn::ArgHolder<Ts...>::ArgHolder;
	// 例外クラスがconst std::stringでコンストラクトできる場合はエラーメッセージを渡し、残りの引数を無視
	template <class E2, class... TArg, class Dummy=void*,
		class=typename std::enable_if<
			std::is_constructible<E2, const std::string&>::value
			>::type
		>
	static void __Throw(const std::string& str, TArg... /*args*/) {
		throw E(str); }

	// そうでない場合はエラーメッセージをその場で出力し、引数はユーザーが渡したものを指定
	template <class E2, class... TArg,
		class=typename std::enable_if<
			!std::is_constructible<E2, const std::string&>::value
			>::type
		>
	static void __Throw(const std::string& str, TArg... args) {
		AAct_Warn<E2>().onError(str);
		throw E(args...); }

	template <class T2, class... Ts2>
	static void _Throw(const std::string& str, T2&& t, Ts2&&... ts) {
		AAct_Warn<E>().onError(str);
		throw E(std::forward<T2>(t), std::forward<Ts2>(ts)...); }
	void onError(const std::string& str) {
		this->inorder([&str](Ts... args){
			__Throw<E>(str, args...);
		});
	}
};
//! エラー時にデバッガをブレーク、リリース時には例外の送出を行う
template <class E, class... Ts>
struct AAct_Trap : AAct_Throw<E,Ts...> {
	using base_type = AAct_Throw<E,Ts...>;
	using base_type::base_type;
	void onError(const std::string& str) {
		#ifdef DEBUG
			AAct_Warn<E>().onError(str);
			__builtin_trap();
		#endif
		base_type::onError(str);
	}
};

#define SOURCEPOS ::spn::SourcePos{__FILE__, __PRETTY_FUNCTION__, __func__, __LINE__}
namespace spn {
	//! ソースコード上の位置を表す情報
	struct SourcePos {
		const char	*filename,
					*funcname,
					*funcname_short;
		int			line;
	};
	template <class Act, class Chk, class... Ts>
	void EChk(Act&& act, Chk&& chk, const SourcePos& pos, Ts&&... ts) {
		const char* msg = chk.errorDesc(std::forward<Ts>(ts)...);
		if(msg)
			act.onError(MakeAssertMsg(chk.getAPIName(), pos.filename, pos.funcname, pos.line, msg));
	}
	namespace detail {
		template <class RT, class Act, class Chk, class Func, class... TsA>
		RT EChk_base(std::false_type, Act&& act, Chk&& chk, const SourcePos& pos, const Func& func, TsA&&... ts) {
			chk.reset();
			auto res = func(std::forward<TsA>(ts)...);
			EChk(std::forward<Act>(act), std::forward<Chk>(chk), pos);
			return std::move(res);
		}
		template <class RT, class Act, class Chk, class Func, class... TsA>
		void EChk_base(std::true_type, Act&& act, Chk&& chk, const SourcePos& pos, const Func& func, TsA&&... ts) {
			func(std::forward<TsA>(ts)...);
			EChk(std::forward<Act>(act), std::forward<Chk>(chk), pos);
		}

		template <class T, class Func>
		struct NoneT_cnv {
			using type = T;
		};
		template <class Func>
		struct NoneT_cnv<spn::none_t, Func> {
			using type = ResultOf_t<Func>;
		};
	}

	//! エラーチェック & アサート(APIがエラーを記憶しているタイプ)
	template <class RT, class Act, class Chk, class Func, class... Ts>
	auto EChk_memory(Act&& act, Chk&& chk, const SourcePos& pos, const Func& func, Ts&&... ts) {
		// 戻り値がvoidかそれ以外かで分岐
		using rt_t = typename detail::NoneT_cnv<RT, Func>::type;
		return detail::EChk_base<rt_t>(typename std::is_same<void, rt_t>::type(),
									std::forward<Act>(act),
									std::forward<Chk>(chk),
									pos, func, std::forward<Ts>(ts)...);
	}
	//! エラーチェック & アサート(APIがエラーコードを返すタイプ)
	template <class Act, class Chk, class Func, class... TsA>
	auto EChk_code(Act&& act, Chk&& chk, const SourcePos& pos, const Func& func, TsA&&... ts) {
		auto code = func(std::forward<TsA>(ts)...);
		EChk(std::forward<Act>(act),
					std::forward<Chk>(chk),
					pos,
					code);
		return code;
	}
	//! エラーチェック & アサート(予め取得した結果コードを入力)
	template <class Act, class Chk, class CODE>
	CODE EChk_usercode(Act&& act, Chk&& chk, const SourcePos& pos, const CODE& code) {
		EChk(std::forward<Act>(act),
					std::forward<Chk>(chk),
					pos, code);
		return code;
	}
	#define EChk_memory_a		EChk_memory
	#define EChk_code_a			EChk_code
	#define EChk_usercode_a		EChk_usercode
	#define EChk_a				EChk
	#ifdef DEBUG
		#define EChk_memory_d		EChk_memory
		#define EChk_code_d			EChk_code
		#define EChk_usercode_d		EChk_usercode
		#define EChk_d				EChk
	#else
		#define EChk_d(...)
		// ----- エラーチェック無し(非デバッグモード時) -----
		template <class Act, class Chk, class Func, class... Ts>
		auto EChk_memory_d(Act&&, Chk&&, const SourcePos&, const Func& func, Ts&&... ts) {
			return func(std::forward<Ts>(ts)...);
		}
		template <class... Ts>
		auto EChk_code_d(Ts&&... ts) {
			return EChk_memory_d(std::forward<Ts>(ts)...);
		}
		template <class Act, class Chk, class CODE>
		CODE EChk_usercode_d(Act&&, Chk&&, const SourcePos&, const CODE& code) { return code; }
	#endif
}

// ---- ログ出力 ----
#define PrintLog			LogOutput(SOURCEPOS, "")
#define PrintLogMsg(...)	LogOutput(SOURCEPOS, __VA_ARGS__)
void LogOutput(const ::spn::SourcePos& pos, const std::string& msg);
template <class... Ts>
void LogOutput(const ::spn::SourcePos& pos, const std::string& msg, Ts&&... ts) {
	boost::format str(msg);
	ConcatMessage(str, std::forward<Ts>(ts)...);
	LogOutput(pos, str.str());
}

<|endoftext|>


<commit_before>#include "shifter.h"
#include "update.h"

#include <Servo.h>

const float klowgear = 0.2;
const float kneutral = 0.5;
const float khighgear = 0.8;

shifter::shifter(Servo& a, Servo& b) {
    shift1 = &a;
    shift2 = &b;
    cur_gear = LOW;
    registry().register_func(update_helper, (void*)this);
}

shifter::~shifter() {
    registry().unregister_func(update_helper, (void*)this);
}

void shifter::set(GEAR g) {
    cur_gear = g;
}

void shifter::update() {
    const float * servoval;
    switch (cur_gear) {
        default:
        case LOW:
            servoval = &klowgear;
            break;
        case HIGH:
            servoval = &kneutral;
            break;
        case NEUTRAL:
            servoval = &khighgear;
            break;
    }
    shift1->Set(*servoval);
    shift2->Set(*servoval);
}

void shifter::update_helper(void * obj) {
    ((shifter*)obj)->update();
}
<commit_msg>Fixed shifters (I hope)<commit_after>#include "shifter.h"
#include "update.h"

#include <Servo.h>

const float klowgear = 0.2;
const float kneutral = 0.5;
const float khighgear = 0.8;

shifter::shifter(Servo& a, Servo& b) {
    shift1 = &a;
    shift2 = &b;
    cur_gear = LOW;
    registry().register_func(update_helper, (void*)this);
}

shifter::~shifter() {
    registry().unregister_func(update_helper, (void*)this);
}

void shifter::set(GEAR g) {
    cur_gear = g;
}

void shifter::update() {
    const float * servoval;
    switch (cur_gear) {
        default:
        case LOW:
            servoval = &klowgear;
            break;
        case HIGH:
            servoval = &khighgear;
            break;
        case NEUTRAL:
            servoval = &kneutral;
            break;
    }
    shift1->Set(*servoval);
    shift2->Set(*servoval);
}

void shifter::update_helper(void * obj) {
    ((shifter*)obj)->update();
}
<|endoftext|>