<commit_before>#include <core/stdafx.h>
#include <core/interpret/proptags.h>
#include <core/addin/addin.h>
#include <core/addin/mfcmapi.h>
#include <core/mapi/cache/namedPropCache.h>
#include <core/utility/strings.h>
#include <core/interpret/proptype.h>
#include <core/utility/output.h>
#include <core/utility/registry.h>

namespace proptags
{
	static WCHAR szPropSeparator[] = L", "; // STRING_OK
	std::unordered_map<ULONG64, PropTagNames> g_PropNames;

	std::wstring TagToString(ULONG ulPropTag, _In_opt_ LPMAPIPROP lpObj, bool bIsAB, bool bSingleLine)
	{
		std::wstring szTemp;

		auto namePropNames = cache::NameIDToStrings(ulPropTag, lpObj, nullptr, {}, bIsAB);

		auto propTagNames = PropTagToPropName(ulPropTag, bIsAB);

		std::wstring szFormatString;
		if (bSingleLine)
		{
			szFormatString = L"0x%1!08X! (%2)"; // STRING_OK
			if (!propTagNames.bestGuess.empty()) szFormatString += L": %3!ws!"; // STRING_OK
			if (!propTagNames.otherMatches.empty()) szFormatString += L": (%4!ws!)"; // STRING_OK
			if (!namePropNames.name.empty())
			{
				szFormatString += strings::loadstring(IDS_NAMEDPROPSINGLELINE);
			}

			if (!namePropNames.guid.empty())
			{
				szFormatString += strings::loadstring(IDS_GUIDSINGLELINE);
			}
		}
		else
		{
			szFormatString = strings::loadstring(IDS_TAGMULTILINE);
			if (!propTagNames.bestGuess.empty())
			{
				szFormatString += strings::loadstring(IDS_PROPNAMEMULTILINE);
			}

			if (!propTagNames.otherMatches.empty())
			{
				szFormatString += strings::loadstring(IDS_OTHERNAMESMULTILINE);
			}

			if (PROP_ID(ulPropTag) < 0x8000)
			{
				szFormatString += strings::loadstring(IDS_DASLPROPTAG);
			}
			else if (!namePropNames.dasl.empty())
			{
				szFormatString += strings::loadstring(IDS_DASLNAMED);
			}

			if (!namePropNames.name.empty())
			{
				szFormatString += strings::loadstring(IDS_NAMEPROPNAMEMULTILINE);
			}

			if (!namePropNames.guid.empty())
			{
				szFormatString += strings::loadstring(IDS_NAMEPROPGUIDMULTILINE);
			}
		}

		auto szRet = strings::formatmessage(
			szFormatString.c_str(),
			ulPropTag,
			proptype::TypeToString(ulPropTag).c_str(),
			propTagNames.bestGuess.c_str(),
			propTagNames.otherMatches.c_str(),
			namePropNames.name.c_str(),
			namePropNames.guid.c_str(),
			namePropNames.dasl.c_str());

		if (fIsSet(output::dbgLevel::Test))
		{
			static size_t cchMaxBuff = 0;
			const auto cchBuff = szRet.length();
			cchMaxBuff = max(cchBuff, cchMaxBuff);
			output::DebugPrint(
				output::dbgLevel::Test,
				L"TagToString parsing 0x%08X returned %u chars - max %u\n",
				ulPropTag,
				static_cast<UINT>(cchBuff),
				static_cast<UINT>(cchMaxBuff));
		}

		return szRet;
	}

	PropTagNames PropTagToPropName(ULONG ulPropTag, bool bIsAB)
	{
		auto ulKey = (bIsAB ? static_cast<ULONG64>(1) << 32 : 0) | ulPropTag;

		const auto match = g_PropNames.find(ulKey);
		if (match != g_PropNames.end())
		{
			return match->second;
		}

		std::vector<ULONG> ulExacts;
		std::vector<ULONG> ulPartials;
		FindTagArrayMatches(ulPropTag, bIsAB, PropTagArray, ulExacts, ulPartials);

		PropTagNames entry;

		if (!ulExacts.empty())
		{
			entry.bestGuess = PropTagArray[ulExacts.front()].lpszName;
			ulExacts.erase(ulExacts.begin());

			for (const auto& ulMatch : ulExacts)
			{
				if (!entry.otherMatches.empty())
				{
					entry.otherMatches += szPropSeparator;
				}

				entry.otherMatches += PropTagArray[ulMatch].lpszName;
			}
		}

		if (!ulPartials.empty())
		{
			if (entry.bestGuess.empty())
			{
				entry.bestGuess = PropTagArray[ulPartials.front()].lpszName;
				ulPartials.erase(ulPartials.begin());
			}

			for (const auto& ulMatch : ulPartials)
			{
				if (!entry.otherMatches.empty())
				{
					entry.otherMatches += szPropSeparator;
				}

				entry.otherMatches += PropTagArray[ulMatch].lpszName;
			}
		}

		g_PropNames.insert({ulKey, entry});

		return entry;
	}

	// Compare tag sort order.
	bool CompareTagsSortOrder(int a1, int a2) noexcept
	{
		const auto lpTag1 = &PropTagArray[a1];
		const auto lpTag2 = &PropTagArray[a2];

		if (lpTag1->ulSortOrder < lpTag2->ulSortOrder) return false;
		if (lpTag1->ulSortOrder == lpTag2->ulSortOrder)
		{
			return wcscmp(lpTag1->lpszName, lpTag2->lpszName) <= 0;
		}
		return true;
	}

	// Searches an array for a target number.
	// Search is done with a mask
	// Partial matches are those that match with the mask applied
	// Exact matches are those that match without the mask applied
	// lpUlNumPartials will exclude count of exact matches
	// if it wants just the true partial matches.
	// If no hits, then ulNoMatch should be returned for lpulFirstExact and/or lpulFirstPartial
	void FindTagArrayMatches(
		_In_ ULONG ulTarget,
		bool bIsAB,
		const std::vector<NAME_ARRAY_ENTRY_V2>& MyArray,
		std::vector<ULONG>& ulExacts,
		std::vector<ULONG>& ulPartials)
	{
		if (!(ulTarget & PROP_TAG_MASK)) // not dealing with a full prop tag
		{
			ulTarget = PROP_TAG(PT_UNSPECIFIED, ulTarget);
		}

		ULONG ulLowerBound = 0;
		auto ulUpperBound = static_cast<ULONG>(MyArray.size() - 1); // size-1 is the last entry
		auto ulMidPoint = (ulUpperBound + ulLowerBound) / 2;
		ULONG ulFirstMatch = cache::ulNoMatch;
		const auto ulMaskedTarget = ulTarget & PROP_TAG_MASK;

		// Short circuit property IDs with the high bit set if bIsAB wasn't passed
		if (!bIsAB && ulTarget & 0x80000000) return;

		// Find A partial match
		while (ulUpperBound - ulLowerBound > 1)
		{
			if (ulMaskedTarget == (PROP_TAG_MASK & MyArray[ulMidPoint].ulValue))
			{
				ulFirstMatch = ulMidPoint;
				break;
			}

			if (ulMaskedTarget < (PROP_TAG_MASK & MyArray[ulMidPoint].ulValue))
			{
				ulUpperBound = ulMidPoint;
			}
			else if (ulMaskedTarget > (PROP_TAG_MASK & MyArray[ulMidPoint].ulValue))
			{
				ulLowerBound = ulMidPoint;
			}

			ulMidPoint = (ulUpperBound + ulLowerBound) / 2;
		}

		// When we get down to two points, we may have only checked one of them
		// Make sure we've checked the other
		if (ulMaskedTarget == (PROP_TAG_MASK & MyArray[ulUpperBound].ulValue))
		{
			ulFirstMatch = ulUpperBound;
		}
		else if (ulMaskedTarget == (PROP_TAG_MASK & MyArray[ulLowerBound].ulValue))
		{
			ulFirstMatch = ulLowerBound;
		}

		// Check that we got a match
		if (cache::ulNoMatch != ulFirstMatch)
		{
			// Scan backwards to find the first partial match
			while (ulFirstMatch > 0 && ulMaskedTarget == (PROP_TAG_MASK & MyArray[ulFirstMatch - 1].ulValue))
			{
				ulFirstMatch = ulFirstMatch - 1;
			}

			for (auto ulCur = ulFirstMatch;
				 ulCur < MyArray.size() && ulMaskedTarget == (PROP_TAG_MASK & MyArray[ulCur].ulValue);
				 ulCur++)
			{
				if (ulTarget == MyArray[ulCur].ulValue)
				{
					ulExacts.push_back(ulCur);
				}
				else
				{
					ulPartials.push_back(ulCur);
				}
			}

			if (!ulExacts.empty()) sort(ulExacts.begin(), ulExacts.end(), CompareTagsSortOrder);
			if (!ulPartials.empty()) sort(ulPartials.begin(), ulPartials.end(), CompareTagsSortOrder);
		}
	}

	// Strictly does a lookup in the array. Does not convert otherwise
	_Check_return_ ULONG LookupPropName(_In_ const std::wstring& lpszPropName)
	{
		auto trimName = strings::trim(lpszPropName);
		if (trimName.empty()) return 0;

		for (auto& tag : PropTagArray)
		{
			if (0 == lstrcmpiW(trimName.c_str(), tag.lpszName))
			{
				return tag.ulValue;
			}
		}

		return 0;
	}

	_Check_return_ ULONG PropNameToPropTag(_In_ const std::wstring& lpszPropName)
	{
		if (lpszPropName.empty()) return 0;

		const auto ulTag = strings::wstringToUlong(lpszPropName, 16);
		if (ulTag != NULL)
		{
			return ulTag;
		}

		return LookupPropName(lpszPropName);
	}
} // namespace proptags<commit_msg>revert<commit_after>#include <core/stdafx.h>
#include <core/interpret/proptags.h>
#include <core/addin/addin.h>
#include <core/addin/mfcmapi.h>
#include <core/mapi/cache/namedPropCache.h>
#include <core/utility/strings.h>
#include <core/interpret/proptype.h>
#include <core/utility/output.h>
#include <core/utility/registry.h>

namespace proptags
{
	static WCHAR szPropSeparator[] = L", "; // STRING_OK
	std::unordered_map<ULONG64, PropTagNames> g_PropNames;

	std::wstring TagToString(ULONG ulPropTag, _In_opt_ LPMAPIPROP lpObj, bool bIsAB, bool bSingleLine)
	{
		std::wstring szTemp;

		auto namePropNames = cache::NameIDToStrings(ulPropTag, lpObj, nullptr, nullptr, bIsAB);

		auto propTagNames = PropTagToPropName(ulPropTag, bIsAB);

		std::wstring szFormatString;
		if (bSingleLine)
		{
			szFormatString = L"0x%1!08X! (%2)"; // STRING_OK
			if (!propTagNames.bestGuess.empty()) szFormatString += L": %3!ws!"; // STRING_OK
			if (!propTagNames.otherMatches.empty()) szFormatString += L": (%4!ws!)"; // STRING_OK
			if (!namePropNames.name.empty())
			{
				szFormatString += strings::loadstring(IDS_NAMEDPROPSINGLELINE);
			}

			if (!namePropNames.guid.empty())
			{
				szFormatString += strings::loadstring(IDS_GUIDSINGLELINE);
			}
		}
		else
		{
			szFormatString = strings::loadstring(IDS_TAGMULTILINE);
			if (!propTagNames.bestGuess.empty())
			{
				szFormatString += strings::loadstring(IDS_PROPNAMEMULTILINE);
			}

			if (!propTagNames.otherMatches.empty())
			{
				szFormatString += strings::loadstring(IDS_OTHERNAMESMULTILINE);
			}

			if (PROP_ID(ulPropTag) < 0x8000)
			{
				szFormatString += strings::loadstring(IDS_DASLPROPTAG);
			}
			else if (!namePropNames.dasl.empty())
			{
				szFormatString += strings::loadstring(IDS_DASLNAMED);
			}

			if (!namePropNames.name.empty())
			{
				szFormatString += strings::loadstring(IDS_NAMEPROPNAMEMULTILINE);
			}

			if (!namePropNames.guid.empty())
			{
				szFormatString += strings::loadstring(IDS_NAMEPROPGUIDMULTILINE);
			}
		}

		auto szRet = strings::formatmessage(
			szFormatString.c_str(),
			ulPropTag,
			proptype::TypeToString(ulPropTag).c_str(),
			propTagNames.bestGuess.c_str(),
			propTagNames.otherMatches.c_str(),
			namePropNames.name.c_str(),
			namePropNames.guid.c_str(),
			namePropNames.dasl.c_str());

		if (fIsSet(output::dbgLevel::Test))
		{
			static size_t cchMaxBuff = 0;
			const auto cchBuff = szRet.length();
			cchMaxBuff = max(cchBuff, cchMaxBuff);
			output::DebugPrint(
				output::dbgLevel::Test,
				L"TagToString parsing 0x%08X returned %u chars - max %u\n",
				ulPropTag,
				static_cast<UINT>(cchBuff),
				static_cast<UINT>(cchMaxBuff));
		}

		return szRet;
	}

	PropTagNames PropTagToPropName(ULONG ulPropTag, bool bIsAB)
	{
		auto ulKey = (bIsAB ? static_cast<ULONG64>(1) << 32 : 0) | ulPropTag;

		const auto match = g_PropNames.find(ulKey);
		if (match != g_PropNames.end())
		{
			return match->second;
		}

		std::vector<ULONG> ulExacts;
		std::vector<ULONG> ulPartials;
		FindTagArrayMatches(ulPropTag, bIsAB, PropTagArray, ulExacts, ulPartials);

		PropTagNames entry;

		if (!ulExacts.empty())
		{
			entry.bestGuess = PropTagArray[ulExacts.front()].lpszName;
			ulExacts.erase(ulExacts.begin());

			for (const auto& ulMatch : ulExacts)
			{
				if (!entry.otherMatches.empty())
				{
					entry.otherMatches += szPropSeparator;
				}

				entry.otherMatches += PropTagArray[ulMatch].lpszName;
			}
		}

		if (!ulPartials.empty())
		{
			if (entry.bestGuess.empty())
			{
				entry.bestGuess = PropTagArray[ulPartials.front()].lpszName;
				ulPartials.erase(ulPartials.begin());
			}

			for (const auto& ulMatch : ulPartials)
			{
				if (!entry.otherMatches.empty())
				{
					entry.otherMatches += szPropSeparator;
				}

				entry.otherMatches += PropTagArray[ulMatch].lpszName;
			}
		}

		g_PropNames.insert({ulKey, entry});

		return entry;
	}

	// Compare tag sort order.
	bool CompareTagsSortOrder(int a1, int a2) noexcept
	{
		const auto lpTag1 = &PropTagArray[a1];
		const auto lpTag2 = &PropTagArray[a2];

		if (lpTag1->ulSortOrder < lpTag2->ulSortOrder) return false;
		if (lpTag1->ulSortOrder == lpTag2->ulSortOrder)
		{
			return wcscmp(lpTag1->lpszName, lpTag2->lpszName) <= 0;
		}
		return true;
	}

	// Searches an array for a target number.
	// Search is done with a mask
	// Partial matches are those that match with the mask applied
	// Exact matches are those that match without the mask applied
	// lpUlNumPartials will exclude count of exact matches
	// if it wants just the true partial matches.
	// If no hits, then ulNoMatch should be returned for lpulFirstExact and/or lpulFirstPartial
	void FindTagArrayMatches(
		_In_ ULONG ulTarget,
		bool bIsAB,
		const std::vector<NAME_ARRAY_ENTRY_V2>& MyArray,
		std::vector<ULONG>& ulExacts,
		std::vector<ULONG>& ulPartials)
	{
		if (!(ulTarget & PROP_TAG_MASK)) // not dealing with a full prop tag
		{
			ulTarget = PROP_TAG(PT_UNSPECIFIED, ulTarget);
		}

		ULONG ulLowerBound = 0;
		auto ulUpperBound = static_cast<ULONG>(MyArray.size() - 1); // size-1 is the last entry
		auto ulMidPoint = (ulUpperBound + ulLowerBound) / 2;
		ULONG ulFirstMatch = cache::ulNoMatch;
		const auto ulMaskedTarget = ulTarget & PROP_TAG_MASK;

		// Short circuit property IDs with the high bit set if bIsAB wasn't passed
		if (!bIsAB && ulTarget & 0x80000000) return;

		// Find A partial match
		while (ulUpperBound - ulLowerBound > 1)
		{
			if (ulMaskedTarget == (PROP_TAG_MASK & MyArray[ulMidPoint].ulValue))
			{
				ulFirstMatch = ulMidPoint;
				break;
			}

			if (ulMaskedTarget < (PROP_TAG_MASK & MyArray[ulMidPoint].ulValue))
			{
				ulUpperBound = ulMidPoint;
			}
			else if (ulMaskedTarget > (PROP_TAG_MASK & MyArray[ulMidPoint].ulValue))
			{
				ulLowerBound = ulMidPoint;
			}

			ulMidPoint = (ulUpperBound + ulLowerBound) / 2;
		}

		// When we get down to two points, we may have only checked one of them
		// Make sure we've checked the other
		if (ulMaskedTarget == (PROP_TAG_MASK & MyArray[ulUpperBound].ulValue))
		{
			ulFirstMatch = ulUpperBound;
		}
		else if (ulMaskedTarget == (PROP_TAG_MASK & MyArray[ulLowerBound].ulValue))
		{
			ulFirstMatch = ulLowerBound;
		}

		// Check that we got a match
		if (cache::ulNoMatch != ulFirstMatch)
		{
			// Scan backwards to find the first partial match
			while (ulFirstMatch > 0 && ulMaskedTarget == (PROP_TAG_MASK & MyArray[ulFirstMatch - 1].ulValue))
			{
				ulFirstMatch = ulFirstMatch - 1;
			}

			for (auto ulCur = ulFirstMatch;
				 ulCur < MyArray.size() && ulMaskedTarget == (PROP_TAG_MASK & MyArray[ulCur].ulValue);
				 ulCur++)
			{
				if (ulTarget == MyArray[ulCur].ulValue)
				{
					ulExacts.push_back(ulCur);
				}
				else
				{
					ulPartials.push_back(ulCur);
				}
			}

			if (!ulExacts.empty()) sort(ulExacts.begin(), ulExacts.end(), CompareTagsSortOrder);
			if (!ulPartials.empty()) sort(ulPartials.begin(), ulPartials.end(), CompareTagsSortOrder);
		}
	}

	// Strictly does a lookup in the array. Does not convert otherwise
	_Check_return_ ULONG LookupPropName(_In_ const std::wstring& lpszPropName)
	{
		auto trimName = strings::trim(lpszPropName);
		if (trimName.empty()) return 0;

		for (auto& tag : PropTagArray)
		{
			if (0 == lstrcmpiW(trimName.c_str(), tag.lpszName))
			{
				return tag.ulValue;
			}
		}

		return 0;
	}

	_Check_return_ ULONG PropNameToPropTag(_In_ const std::wstring& lpszPropName)
	{
		if (lpszPropName.empty()) return 0;

		const auto ulTag = strings::wstringToUlong(lpszPropName, 16);
		if (ulTag != NULL)
		{
			return ulTag;
		}

		return LookupPropName(lpszPropName);
	}
} // namespace proptags<|endoftext|>


<commit_before>// Hossein Moein
// September 12, 2017
// Copyright (C) 2018-2019 Hossein Moein
// Distributed under the BSD Software License (see file License)

#include "DateTime.h"
#include "DataFrame.h"
#if defined(__linux__) || defined(__unix__) || defined(__APPLE__)
#include "DMScu_MMapFile.h"
#endif // defined(__linux__) || defined(__unix__) || defined(__APPLE__)
#include <cstdlib>
#include <fstream>
#include <functional>

// ----------------------------------------------------------------------------

namespace hmdf
{

#define gcc_likely(x)    __builtin_expect(!!(x), 1)
#define gcc_unlikely(x)  __builtin_expect(!!(x), 0)

// ----------------------------------------------------------------------------

#ifdef _WIN32
inline static void
_get_token_from_file_  (std::ifstream &file, char delim, char *value) {

    char    c;
    int     count = 0;

    while (file.get (c))
        if (c == delim)
            break;
        else
            value[count++] = c;

    value[count] = 0;
}
#endif // _WIN32

// ----------------------------------------------------------------------------

template<typename T, typename V>
inline static void
_col_vector_push_back_(V &vec,
#if defined(__linux__) || defined(__unix__) || defined(__APPLE__)
                       DMScu_MMapFile &file,
#elif _WIN32
                       std::ifstream &file
#endif // defined(__linux__) || defined(__unix__) || defined(__APPLE__)
                       T (*converter)(const char *))  {

    char    value[1024];

#if defined(__linux__) || defined(__unix__) || defined(__APPLE__)
    while (! file.is_eof ())  {
        char    c = static_cast<char>(file.get_char());

        if (gcc_unlikely(c == '\n'))  break;
        file.put_back();
        file.get_token(',', value);
        vec.push_back(converter(value));
    }
#elif _WIN32
    char    c = 0;

    while (file.get(c)) {
        if (c == '\n')  break;
        file.unget();
        _get_token_from_file_(file, ',', value);
        vec.push_back(converter(value));
    }
#endif // defined(__linux__) || defined(__unix__) || defined(__APPLE__)
}

// -------------------------------------

template<>
inline void
_col_vector_push_back_<const char *, std::vector<std::string>>(
    std::vector<std::string> &vec,
#if defined(__linux__) || defined(__unix__) || defined(__APPLE__)
    DMScu_MMapFile &file,
#elif _WIN32
    std::ifstream &file
#endif // defined(__linux__) || defined(__unix__) || defined(__APPLE__)
    const char * (*converter)(const char *))  {

    char    value[1024];

#if defined(__linux__) || defined(__unix__) || defined(__APPLE__)
    while (! file.is_eof ())  {
        char    c = static_cast<char>(file.get_char());

        if (gcc_unlikely(c == '\n'))
            break;
        file.put_back();
        file.get_token(',', value);
        vec.push_back(value);
    }
#elif _WIN32
    char    c = 0;

    while (file.get(c)) {
        if (c == '\n')  break;
        file.unget();
        _get_token_from_file_(file, ',', value);
        vec.push_back(value);
    }
#endif // defined(__linux__) || defined(__unix__) || defined(__APPLE__)
}

// -------------------------------------

template<>
inline void
_col_vector_push_back_<DateTime, std::vector<DateTime>>(
    std::vector<DateTime> &vec,
#if defined(__linux__) || defined(__unix__) || defined(__APPLE__)
    DMScu_MMapFile &file,
#elif _WIN32
    std::ifstream &file
#endif // defined(__linux__) || defined(__unix__) || defined(__APPLE__)
    DateTime (*converter)(const char *))  {

    char    value[1024];

#if defined(__linux__) || defined(__unix__) || defined(__APPLE__)
    while (! file.is_eof ())  {
        char    c = static_cast<char>(file.get_char());

        if (gcc_unlikely(c == '\n'))
            break;
        file.put_back();
        file.get_token(',', value);

        time_t      t;
        int         n;
        DateTime    dt;

        ::sscanf(value, "%ld.%d", &t, &n);
        dt.set_time(t, n);
        vec.push_back(dt);
    }
#elif _WIN32
    char    c = 0;

    while (file.get(c)) {
        if (c == '\n')  break;
        file.unget();
        _get_token_from_file_(file, ',', value);

        time_t      t;
        int         n;
        DateTime    dt;

        ::sscanf(value, "%ld.%d", &t, &n);
        dt.set_time(t, n);
        vec.emplace_back(std::move(dt));
    }
#endif // defined(__linux__) || defined(__unix__) || defined(__APPLE__)
}

// ----------------------------------------------------------------------------

template<typename T>
struct  _IdxParserFunctor_  {

    void operator()(std::vector<T> &, DMScu_MMapFile &)  {  }
};

// -------------------------------------

template<>
struct  _IdxParserFunctor_<double>  {

    inline void operator()(std::vector<double> &vec, DMScu_MMapFile &file)  {

        _col_vector_push_back_(vec, file, &::atof);
    }
};

// -------------------------------------

template<>
struct  _IdxParserFunctor_<int>  {

    inline void operator()(std::vector<int> &vec, DMScu_MMapFile &file)  {

        _col_vector_push_back_(vec, file, &::atoi);
    }
};

// -------------------------------------

template<>
struct  _IdxParserFunctor_<long>  {

    inline void operator()(std::vector<long> &vec, DMScu_MMapFile &file)  {

        _col_vector_push_back_(vec, file, &::atol);
    }
};

// -------------------------------------

template<>
struct  _IdxParserFunctor_<unsigned long>  {

    inline void
    operator()(std::vector<unsigned long> &vec, DMScu_MMapFile &file)  {

        _col_vector_push_back_(vec, file, &::atoll);
    }
};

// -------------------------------------

template<>
struct  _IdxParserFunctor_<std::string>  {

    inline void
    operator()(std::vector<std::string> &vec, DMScu_MMapFile &file)  {

        auto    converter =
            [](const char *s)-> const char * { return s; };

        _col_vector_push_back_<const char *, std::vector<std::string>>
            (vec, file, converter);
    }
};

// -------------------------------------

template<>
struct  _IdxParserFunctor_<DateTime>  {

    inline void
    operator()(std::vector<DateTime> &vec, DMScu_MMapFile &file)  {

        auto    converter =
            [](const char *)-> DateTime  { return DateTime(); };

        _col_vector_push_back_<DateTime, std::vector<DateTime>>
            (vec, file, converter);
    }
};

// -------------------------------------

template<>
struct  _IdxParserFunctor_<bool>  {

    inline void operator()(std::vector<bool> &vec, DMScu_MMapFile &file)  {

        _col_vector_push_back_(vec, file, &::atoi);
    }
};

// ----------------------------------------------------------------------------

template<typename TS, typename  HETERO>
bool DataFrame<TS, HETERO>::read (const char *file_name, io_format iof)  {

    static_assert(std::is_base_of<HeteroVector, HETERO>::value,
                  "Only a StdDataFrame can call read()");

#if defined(__linux__) || defined(__unix__) || defined(__APPLE__)
    DMScu_MMapFile  file (file_name,
                          DMScu_MMapFile::_read_,
                          DMScu_MMapBase::SYSTEM_PAGE_SIZE * 2);
#elif _WIN32
    std::ifstream   file;

    file.open(file_name, std::ios::in);  // Open for reading
#endif // defined(__linux__) || defined(__unix__) || defined(__APPLE__)

    char    col_name[256];
    char    value[1024];
    char    type_str[64];
    char    c;

#if defined(__linux__) || defined(__unix__) || defined(__APPLE__)
    while (! file.is_eof ())  {
        c = static_cast<char>(file.get_char());

        if (c == '#' || c == '\n' || c == '\0')  {
            if (c == '#')
                while (! file.is_eof ())  {
                    c = static_cast<char>(file.get_char());
                    if (c == '\n')
                        break;
                }
            continue;
        }
        file.put_back();

        file.get_token(':', col_name);
        c = static_cast<char>(file.get_char());
        if (c != '<')
            throw DataFrameError ("DataFrame::read(): ERROR: Expected "
                                  "'<' char to specify column type");
        file.get_token('>', type_str);
        c = static_cast<char>(file.get_char());
        if (c != ':')
            throw DataFrameError ("DataFrame::read(): ERROR: Expected "
                                  "':' char to start column values");
#elif _WIN32
    while (file.get(c)) {
        if (c == '#' || c == '\n' || c == '\0') {
            if (c == '#')
                while (file.get(c))
                    if (c == '\n') break;

            continue;
        }
        file.unget();

        _get_token_from_file_(file, ':', col_name);
        file.get(c);
        if (c != '<')
            throw DataFrameError("DataFrame::read(): ERROR: Expected "
                                 "'<' char to specify column type");
        _get_token_from_file_(file, '>', type_str);
        file.get(c);
        if (c != ':')
            throw DataFrameError("DataFrame::read(): ERROR: Expected "
                                 "':' char to start column values");
#endif // defined(__linux__) || defined(__unix__) || defined(__APPLE__)

        if (! ::strcmp(col_name, "INDEX"))  {
            TSVec   vec;

            _IdxParserFunctor_<typename TSVec::value_type>()(vec, file);
            load_index(std::forward<TSVec &&>(vec));
        }
        else  {
            if (! ::strcmp(type_str, "double"))  {
                std::vector<double> &vec = create_column<double>(col_name);

                _col_vector_push_back_(vec, file, ::atof);
            }
            else if (! ::strcmp(type_str, "int"))  {
                std::vector<int> &vec = create_column<int>(col_name);

                _col_vector_push_back_(vec, file, &::atoi);
            }
            else if (! ::strcmp(type_str, "uint"))  {
                std::vector<unsigned int>   &vec =
                    create_column<unsigned int>(col_name);

                _col_vector_push_back_(vec, file, &::atol);
            }
            else if (! ::strcmp(type_str, "long"))  {
                std::vector<long>   &vec = create_column<long>(col_name);

                _col_vector_push_back_(vec, file, &::atol);
            }
            else if (! ::strcmp(type_str, "ulong"))  {
                std::vector<unsigned long>  &vec =
                    create_column<unsigned long>(col_name);

                _col_vector_push_back_(vec, file, &::atoll);
            }
            else if (! ::strcmp(type_str, "string"))  {
                std::vector<std::string>    &vec =
                    create_column<std::string>(col_name);
                auto                        converter =
                    [](const char *s)-> const char * { return s; };

                _col_vector_push_back_<const char *, std::vector<std::string>>
                    (vec, file, converter);
            }
            else if (! ::strcmp(type_str, "DateTime"))  {
                std::vector<DateTime>   &vec =
                    create_column<DateTime>(col_name);
                auto                    converter =
                    [](const char *)-> DateTime { return DateTime(); };

                _col_vector_push_back_<DateTime, std::vector<DateTime>>
                    (vec, file, converter);
            }
            else if (! ::strcmp(type_str, "bool"))  {
                std::vector<bool>   &vec = create_column<bool>(col_name);

                _col_vector_push_back_(vec, file, &::atoi);
            }
            else
                throw DataFrameError ("DataFrame::read(): ERROR: Unknown "
                                      "column type");
        }
    }

    file.close();
    return(true);
}

// ----------------------------------------------------------------------------

template<typename TS, typename  HETERO>
std::future<bool> DataFrame<TS, HETERO>::
read_async(const char *file_name, io_format iof) {

    return (std::async(std::launch::async,
                       &DataFrame::read,
                       this,
                       file_name,
                       iof));
}

} // namespace hmdf

// ----------------------------------------------------------------------------

// Local Variables:
// mode:C++
// tab-width:4
// c-basic-offset:4
// End:
<commit_msg>windows syntax<commit_after>// Hossein Moein
// September 12, 2017
// Copyright (C) 2018-2019 Hossein Moein
// Distributed under the BSD Software License (see file License)

#include "DateTime.h"
#include "DataFrame.h"
#if defined(__linux__) || defined(__unix__) || defined(__APPLE__)
#include "DMScu_MMapFile.h"
#endif // defined(__linux__) || defined(__unix__) || defined(__APPLE__)
#include <cstdlib>
#include <fstream>
#include <functional>

// ----------------------------------------------------------------------------

namespace hmdf
{

#define gcc_likely(x)    __builtin_expect(!!(x), 1)
#define gcc_unlikely(x)  __builtin_expect(!!(x), 0)

// ----------------------------------------------------------------------------

#ifdef _WIN32
inline static void
_get_token_from_file_  (std::ifstream &file, char delim, char *value) {

    char    c;
    int     count = 0;

    while (file.get (c))
        if (c == delim)
            break;
        else
            value[count++] = c;

    value[count] = 0;
}
#endif // _WIN32

// ----------------------------------------------------------------------------

template<typename T, typename V>
inline static void
_col_vector_push_back_(V &vec,
#if defined(__linux__) || defined(__unix__) || defined(__APPLE__)
                       DMScu_MMapFile &file,
#elif _WIN32
                       std::ifstream &file,
#endif // defined(__linux__) || defined(__unix__) || defined(__APPLE__)
                       T (*converter)(const char *))  {

    char    value[1024];

#if defined(__linux__) || defined(__unix__) || defined(__APPLE__)
    while (! file.is_eof ())  {
        char    c = static_cast<char>(file.get_char());

        if (gcc_unlikely(c == '\n'))  break;
        file.put_back();
        file.get_token(',', value);
        vec.push_back(converter(value));
    }
#elif _WIN32
    char    c = 0;

    while (file.get(c)) {
        if (c == '\n')  break;
        file.unget();
        _get_token_from_file_(file, ',', value);
        vec.push_back(converter(value));
    }
#endif // defined(__linux__) || defined(__unix__) || defined(__APPLE__)
}

// -------------------------------------

template<>
inline void
_col_vector_push_back_<const char *, std::vector<std::string>>(
    std::vector<std::string> &vec,
#if defined(__linux__) || defined(__unix__) || defined(__APPLE__)
    DMScu_MMapFile &file,
#elif _WIN32
    std::ifstream &file,
#endif // defined(__linux__) || defined(__unix__) || defined(__APPLE__)
    const char * (*converter)(const char *))  {

    char    value[1024];

#if defined(__linux__) || defined(__unix__) || defined(__APPLE__)
    while (! file.is_eof ())  {
        char    c = static_cast<char>(file.get_char());

        if (gcc_unlikely(c == '\n'))
            break;
        file.put_back();
        file.get_token(',', value);
        vec.push_back(value);
    }
#elif _WIN32
    char    c = 0;

    while (file.get(c)) {
        if (c == '\n')  break;
        file.unget();
        _get_token_from_file_(file, ',', value);
        vec.push_back(value);
    }
#endif // defined(__linux__) || defined(__unix__) || defined(__APPLE__)
}

// -------------------------------------

template<>
inline void
_col_vector_push_back_<DateTime, std::vector<DateTime>>(
    std::vector<DateTime> &vec,
#if defined(__linux__) || defined(__unix__) || defined(__APPLE__)
    DMScu_MMapFile &file,
#elif _WIN32
    std::ifstream &file,
#endif // defined(__linux__) || defined(__unix__) || defined(__APPLE__)
    DateTime (*converter)(const char *))  {

    char    value[1024];

#if defined(__linux__) || defined(__unix__) || defined(__APPLE__)
    while (! file.is_eof ())  {
        char    c = static_cast<char>(file.get_char());

        if (gcc_unlikely(c == '\n'))
            break;
        file.put_back();
        file.get_token(',', value);

        time_t      t;
        int         n;
        DateTime    dt;

        ::sscanf(value, "%ld.%d", &t, &n);
        dt.set_time(t, n);
        vec.push_back(dt);
    }
#elif _WIN32
    char    c = 0;

    while (file.get(c)) {
        if (c == '\n')  break;
        file.unget();
        _get_token_from_file_(file, ',', value);

        time_t      t;
        int         n;
        DateTime    dt;

        ::sscanf(value, "%ld.%d", &t, &n);
        dt.set_time(t, n);
        vec.emplace_back(std::move(dt));
    }
#endif // defined(__linux__) || defined(__unix__) || defined(__APPLE__)
}

// ----------------------------------------------------------------------------

template<typename T>
struct  _IdxParserFunctor_  {

    void operator()(std::vector<T> &, DMScu_MMapFile &)  {  }
};

// -------------------------------------

template<>
struct  _IdxParserFunctor_<double>  {

    inline void operator()(std::vector<double> &vec, DMScu_MMapFile &file)  {

        _col_vector_push_back_(vec, file, &::atof);
    }
};

// -------------------------------------

template<>
struct  _IdxParserFunctor_<int>  {

    inline void operator()(std::vector<int> &vec, DMScu_MMapFile &file)  {

        _col_vector_push_back_(vec, file, &::atoi);
    }
};

// -------------------------------------

template<>
struct  _IdxParserFunctor_<long>  {

    inline void operator()(std::vector<long> &vec, DMScu_MMapFile &file)  {

        _col_vector_push_back_(vec, file, &::atol);
    }
};

// -------------------------------------

template<>
struct  _IdxParserFunctor_<unsigned long>  {

    inline void
    operator()(std::vector<unsigned long> &vec, DMScu_MMapFile &file)  {

        _col_vector_push_back_(vec, file, &::atoll);
    }
};

// -------------------------------------

template<>
struct  _IdxParserFunctor_<std::string>  {

    inline void
    operator()(std::vector<std::string> &vec, DMScu_MMapFile &file)  {

        auto    converter =
            [](const char *s)-> const char * { return s; };

        _col_vector_push_back_<const char *, std::vector<std::string>>
            (vec, file, converter);
    }
};

// -------------------------------------

template<>
struct  _IdxParserFunctor_<DateTime>  {

    inline void
    operator()(std::vector<DateTime> &vec, DMScu_MMapFile &file)  {

        auto    converter =
            [](const char *)-> DateTime  { return DateTime(); };

        _col_vector_push_back_<DateTime, std::vector<DateTime>>
            (vec, file, converter);
    }
};

// -------------------------------------

template<>
struct  _IdxParserFunctor_<bool>  {

    inline void operator()(std::vector<bool> &vec, DMScu_MMapFile &file)  {

        _col_vector_push_back_(vec, file, &::atoi);
    }
};

// ----------------------------------------------------------------------------

template<typename TS, typename  HETERO>
bool DataFrame<TS, HETERO>::read (const char *file_name, io_format iof)  {

    static_assert(std::is_base_of<HeteroVector, HETERO>::value,
                  "Only a StdDataFrame can call read()");

#if defined(__linux__) || defined(__unix__) || defined(__APPLE__)
    DMScu_MMapFile  file (file_name,
                          DMScu_MMapFile::_read_,
                          DMScu_MMapBase::SYSTEM_PAGE_SIZE * 2);
#elif _WIN32
    std::ifstream   file;

    file.open(file_name, std::ios::in);  // Open for reading
#endif // defined(__linux__) || defined(__unix__) || defined(__APPLE__)

    char    col_name[256];
    char    value[1024];
    char    type_str[64];
    char    c;

#if defined(__linux__) || defined(__unix__) || defined(__APPLE__)
    while (! file.is_eof ())  {
        c = static_cast<char>(file.get_char());

        if (c == '#' || c == '\n' || c == '\0')  {
            if (c == '#')
                while (! file.is_eof ())  {
                    c = static_cast<char>(file.get_char());
                    if (c == '\n')
                        break;
                }
            continue;
        }
        file.put_back();

        file.get_token(':', col_name);
        c = static_cast<char>(file.get_char());
        if (c != '<')
            throw DataFrameError ("DataFrame::read(): ERROR: Expected "
                                  "'<' char to specify column type");
        file.get_token('>', type_str);
        c = static_cast<char>(file.get_char());
        if (c != ':')
            throw DataFrameError ("DataFrame::read(): ERROR: Expected "
                                  "':' char to start column values");
#elif _WIN32
    while (file.get(c)) {
        if (c == '#' || c == '\n' || c == '\0') {
            if (c == '#')
                while (file.get(c))
                    if (c == '\n') break;

            continue;
        }
        file.unget();

        _get_token_from_file_(file, ':', col_name);
        file.get(c);
        if (c != '<')
            throw DataFrameError("DataFrame::read(): ERROR: Expected "
                                 "'<' char to specify column type");
        _get_token_from_file_(file, '>', type_str);
        file.get(c);
        if (c != ':')
            throw DataFrameError("DataFrame::read(): ERROR: Expected "
                                 "':' char to start column values");
#endif // defined(__linux__) || defined(__unix__) || defined(__APPLE__)

        if (! ::strcmp(col_name, "INDEX"))  {
            TSVec   vec;

            _IdxParserFunctor_<typename TSVec::value_type>()(vec, file);
            load_index(std::forward<TSVec &&>(vec));
        }
        else  {
            if (! ::strcmp(type_str, "double"))  {
                std::vector<double> &vec = create_column<double>(col_name);

                _col_vector_push_back_(vec, file, ::atof);
            }
            else if (! ::strcmp(type_str, "int"))  {
                std::vector<int> &vec = create_column<int>(col_name);

                _col_vector_push_back_(vec, file, &::atoi);
            }
            else if (! ::strcmp(type_str, "uint"))  {
                std::vector<unsigned int>   &vec =
                    create_column<unsigned int>(col_name);

                _col_vector_push_back_(vec, file, &::atol);
            }
            else if (! ::strcmp(type_str, "long"))  {
                std::vector<long>   &vec = create_column<long>(col_name);

                _col_vector_push_back_(vec, file, &::atol);
            }
            else if (! ::strcmp(type_str, "ulong"))  {
                std::vector<unsigned long>  &vec =
                    create_column<unsigned long>(col_name);

                _col_vector_push_back_(vec, file, &::atoll);
            }
            else if (! ::strcmp(type_str, "string"))  {
                std::vector<std::string>    &vec =
                    create_column<std::string>(col_name);
                auto                        converter =
                    [](const char *s)-> const char * { return s; };

                _col_vector_push_back_<const char *, std::vector<std::string>>
                    (vec, file, converter);
            }
            else if (! ::strcmp(type_str, "DateTime"))  {
                std::vector<DateTime>   &vec =
                    create_column<DateTime>(col_name);
                auto                    converter =
                    [](const char *)-> DateTime { return DateTime(); };

                _col_vector_push_back_<DateTime, std::vector<DateTime>>
                    (vec, file, converter);
            }
            else if (! ::strcmp(type_str, "bool"))  {
                std::vector<bool>   &vec = create_column<bool>(col_name);

                _col_vector_push_back_(vec, file, &::atoi);
            }
            else
                throw DataFrameError ("DataFrame::read(): ERROR: Unknown "
                                      "column type");
        }
    }

    file.close();
    return(true);
}

// ----------------------------------------------------------------------------

template<typename TS, typename  HETERO>
std::future<bool> DataFrame<TS, HETERO>::
read_async(const char *file_name, io_format iof) {

    return (std::async(std::launch::async,
                       &DataFrame::read,
                       this,
                       file_name,
                       iof));
}

} // namespace hmdf

// ----------------------------------------------------------------------------

// Local Variables:
// mode:C++
// tab-width:4
// c-basic-offset:4
// End:
<|endoftext|>


<commit_before>/*
This file is part of Bohrium and copyright (c) 2012 the Bohrium
team <http://www.bh107.org>.

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

Bohrium 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 General Public License for more details.

You should have received a copy of the
GNU Lesser General Public License along with Bohrium.

If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once

#include <boost/serialization/is_bitwise_serializable.hpp>
#include <boost/serialization/array.hpp>
#include <boost/serialization/vector.hpp>
#include <vector>
#include <set>

#include "bh_opcode.h"
#include <bh_view.hpp>

// Forward declaration of class boost::serialization::access
namespace boost {namespace serialization {class access;}}

// Maximum number of operands in a instruction.
#define BH_MAX_NO_OPERANDS (3)

//Memory layout of the Bohrium instruction
struct bh_instruction
{
    // Opcode: Identifies the operation
    bh_opcode  opcode;
    // Id of each operand
    std::vector<bh_view> operand;
    // Constant included in the instruction (Used if one of the operands == NULL)
    bh_constant constant;
    // Flag that indicates whether this instruction construct the output array (i.e. is the first operation on that array)
    // For now, this flag is only used by the code generators.
    bool constructor;
    // An identifier to track the original source of instruction transformations thus transformations such as
    // copy, transpose, and reshape does not change the 'origin_id'.
    // For now, this flag is only used by the code generators.
    int64_t origin_id = -1; // -1 indicates: unset

    // Constructors
    bh_instruction(){}
    bh_instruction(bh_opcode opcode, const std::vector<bh_view> &operands) : opcode(opcode), operand(operands) {}
    bh_instruction(const bh_instruction& instr)
    {
        opcode      = instr.opcode;
        constant    = instr.constant;
        constructor = instr.constructor;
        origin_id   = instr.origin_id;
        operand     = instr.operand;
    }

    // Return a set of all bases used by the instruction
    std::set<const bh_base *> get_bases_const() const;
    std::set<bh_base *> get_bases();

    // Return a vector of views in this instruction.
    // The first element is the output and the rest are inputs (the constant is ignored)
    std::vector<const bh_view*> get_views() const;

    // Returns true when one of the operands of 'instr' is a constant
    bool has_constant() const {
        for (const bh_view &v: operand) {
            if (bh_is_constant(&v)) {
                return true;
            }
        }
        return false;
    }

    // Check if all views in this instruction is contiguous
    bool isContiguous() const;

    // Check if all view in this instruction have the same shape
    bool all_same_shape() const;

    // Is this instruction (and all its views) reshapable?
    bool reshapable() const;

    // Returns the principal shape of this instructions, which is the shape of the computation that constitute
    // this instruction. E.g. in reduce, this function returns the shape of the reduced array
    std::vector<int64_t> shape() const;

    // Returns the principal number of dimension of this instruction, which is the number of dimension of the
    // computation that constitute this instruction
    int64_t ndim() const;

    // Returns the axis this instruction reduces over or 'BH_MAXDIM' if 'instr' isn't a reduction
    int sweep_axis() const;

    // Reshape the views of the instruction to 'shape'
    void reshape(const std::vector<int64_t> &shape);

    // Reshape the views of the instruction to 'shape' (no checks!)
    void reshape_force(const std::vector<int64_t> &shape);

    // Remove 'axis' from all views in this instruction.
    // Notice that 'axis' is based on the 'dominating shape' thus remove_axis() will correct
    // the axis value when handling reductions automatically
    void remove_axis(int64_t axis);

    // Transposes by swapping the two axes 'axis1' and 'axis2'
    void transpose(int64_t axis1, int64_t axis2);

    // Returns the type of the operand at given index (support constants)
    bh_type operand_type(int operand_index) const;

    // Returns a pretty print of this instruction (as a string)
    std::string pprint(bool python_notation = true) const;

    // Equality
    bool operator==(const bh_instruction& other) const {
        if (opcode != other.opcode) {
            return false;
        }
        for (size_t i = 0; i < operand.size(); ++i) {
            if (bh_is_constant(&operand[i]) != bh_is_constant(&other.operand[i])) {
                return false;
            } else if (bh_is_constant(&operand[i])) { // Both are constant
                if (constant != other.constant)
                    return false;
            } else {
                if (operand[i] != other.operand[i])
                    return false;
            }
        }
        return true;
    }

    // Inequality
    bool operator!=(const bh_instruction& other) const {
        return !(*this == other);
    }

    // Serialization using Boost
    friend class boost::serialization::access;
    template<class Archive>
    void serialize(Archive &ar, const unsigned int version)
    {
        ar & opcode;
        ar & operand;
        //We use make_array as a hack to make bh_constant BOOST_IS_BITWISE_SERIALIZABLE
        ar & boost::serialization::make_array(&constant, 1);
    }
};
BOOST_IS_BITWISE_SERIALIZABLE(bh_constant)

//Implements pprint of an instruction
DLLEXPORT std::ostream& operator<<(std::ostream& out, const bh_instruction& instr);

/* Retrive the operands of a instruction.
 *
 * @instruction  The instruction in question
 * @return The operand list
 */
DLLEXPORT bh_view *bh_inst_operands(bh_instruction *instruction);

/* Determines whether instruction 'a' depends on instruction 'b',
 * which is true when:
 *      'b' writes to an array that 'a' access
 *                        or
 *      'a' writes to an array that 'b' access
 *
 * @a The first instruction
 * @b The second instruction
 * @return The boolean answer
 */
DLLEXPORT bool bh_instr_dependency(const bh_instruction *a, const bh_instruction *b);
<commit_msg>bh_instruction(): now uses std::move()<commit_after>/*
This file is part of Bohrium and copyright (c) 2012 the Bohrium
team <http://www.bh107.org>.

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

Bohrium 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 General Public License for more details.

You should have received a copy of the
GNU Lesser General Public License along with Bohrium.

If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once

#include <boost/serialization/is_bitwise_serializable.hpp>
#include <boost/serialization/array.hpp>
#include <boost/serialization/vector.hpp>
#include <vector>
#include <set>

#include "bh_opcode.h"
#include <bh_view.hpp>

// Forward declaration of class boost::serialization::access
namespace boost {namespace serialization {class access;}}

// Maximum number of operands in a instruction.
#define BH_MAX_NO_OPERANDS (3)

//Memory layout of the Bohrium instruction
struct bh_instruction
{
    // Opcode: Identifies the operation
    bh_opcode  opcode;
    // Id of each operand
    std::vector<bh_view> operand;
    // Constant included in the instruction (Used if one of the operands == NULL)
    bh_constant constant;
    // Flag that indicates whether this instruction construct the output array (i.e. is the first operation on that array)
    // For now, this flag is only used by the code generators.
    bool constructor;
    // An identifier to track the original source of instruction transformations thus transformations such as
    // copy, transpose, and reshape does not change the 'origin_id'.
    // For now, this flag is only used by the code generators.
    int64_t origin_id = -1; // -1 indicates: unset

    // Constructors
    bh_instruction(){}
    bh_instruction(bh_opcode opcode, std::vector<bh_view> operands) : opcode(opcode), operand(std::move(operands)) {}
    bh_instruction(const bh_instruction& instr)
    {
        opcode      = instr.opcode;
        constant    = instr.constant;
        constructor = instr.constructor;
        origin_id   = instr.origin_id;
        operand     = instr.operand;
    }

    // Return a set of all bases used by the instruction
    std::set<const bh_base *> get_bases_const() const;
    std::set<bh_base *> get_bases();

    // Return a vector of views in this instruction.
    // The first element is the output and the rest are inputs (the constant is ignored)
    std::vector<const bh_view*> get_views() const;

    // Returns true when one of the operands of 'instr' is a constant
    bool has_constant() const {
        for (const bh_view &v: operand) {
            if (bh_is_constant(&v)) {
                return true;
            }
        }
        return false;
    }

    // Check if all views in this instruction is contiguous
    bool isContiguous() const;

    // Check if all view in this instruction have the same shape
    bool all_same_shape() const;

    // Is this instruction (and all its views) reshapable?
    bool reshapable() const;

    // Returns the principal shape of this instructions, which is the shape of the computation that constitute
    // this instruction. E.g. in reduce, this function returns the shape of the reduced array
    std::vector<int64_t> shape() const;

    // Returns the principal number of dimension of this instruction, which is the number of dimension of the
    // computation that constitute this instruction
    int64_t ndim() const;

    // Returns the axis this instruction reduces over or 'BH_MAXDIM' if 'instr' isn't a reduction
    int sweep_axis() const;

    // Reshape the views of the instruction to 'shape'
    void reshape(const std::vector<int64_t> &shape);

    // Reshape the views of the instruction to 'shape' (no checks!)
    void reshape_force(const std::vector<int64_t> &shape);

    // Remove 'axis' from all views in this instruction.
    // Notice that 'axis' is based on the 'dominating shape' thus remove_axis() will correct
    // the axis value when handling reductions automatically
    void remove_axis(int64_t axis);

    // Transposes by swapping the two axes 'axis1' and 'axis2'
    void transpose(int64_t axis1, int64_t axis2);

    // Returns the type of the operand at given index (support constants)
    bh_type operand_type(int operand_index) const;

    // Returns a pretty print of this instruction (as a string)
    std::string pprint(bool python_notation = true) const;

    // Equality
    bool operator==(const bh_instruction& other) const {
        if (opcode != other.opcode) {
            return false;
        }
        for (size_t i = 0; i < operand.size(); ++i) {
            if (bh_is_constant(&operand[i]) != bh_is_constant(&other.operand[i])) {
                return false;
            } else if (bh_is_constant(&operand[i])) { // Both are constant
                if (constant != other.constant)
                    return false;
            } else {
                if (operand[i] != other.operand[i])
                    return false;
            }
        }
        return true;
    }

    // Inequality
    bool operator!=(const bh_instruction& other) const {
        return !(*this == other);
    }

    // Serialization using Boost
    friend class boost::serialization::access;
    template<class Archive>
    void serialize(Archive &ar, const unsigned int version)
    {
        ar & opcode;
        ar & operand;
        //We use make_array as a hack to make bh_constant BOOST_IS_BITWISE_SERIALIZABLE
        ar & boost::serialization::make_array(&constant, 1);
    }
};
BOOST_IS_BITWISE_SERIALIZABLE(bh_constant)

//Implements pprint of an instruction
DLLEXPORT std::ostream& operator<<(std::ostream& out, const bh_instruction& instr);

/* Retrive the operands of a instruction.
 *
 * @instruction  The instruction in question
 * @return The operand list
 */
DLLEXPORT bh_view *bh_inst_operands(bh_instruction *instruction);

/* Determines whether instruction 'a' depends on instruction 'b',
 * which is true when:
 *      'b' writes to an array that 'a' access
 *                        or
 *      'a' writes to an array that 'b' access
 *
 * @a The first instruction
 * @b The second instruction
 * @return The boolean answer
 */
DLLEXPORT bool bh_instr_dependency(const bh_instruction *a, const bh_instruction *b);
<|endoftext|>


<commit_before>//#ifndef CLPP_RET_CODE_HPP
//#define CLPP_RET_CODE_HPP

//#include "clpp/detail/common.hpp"

//#include <experimental/string_view>

//namespace cl {
//	enum class RetCode : cl_int {
//		success                               = CL_SUCCESS,

//		deviceNotFound                        = CL_DEVICE_NOT_FOUND,
//		deviceNotAvailable                    = CL_DEVICE_NOT_AVAILABLE,
//		compilerNotAvailable                  = CL_COMPILER_NOT_AVAILABLE,
//		memoryObjectAllocationFailure         = CL_MEM_OBJECT_ALLOCATION_FAILURE,
//		outOfResources                        = CL_OUT_OF_RESOURCES,
//		outOfHostMemory                       = CL_OUT_OF_HOST_MEMORY,
//		profilingInfoNotAvailable             = CL_PROFILING_INFO_NOT_AVAILABLE,
//		memoryCopyOverlap                     = CL_MEM_COPY_OVERLAP,
//		imageFormatMismatch                   = CL_IMAGE_FORMAT_MISMATCH,
//		imageFormatNotSupported               = CL_IMAGE_FORMAT_NOT_SUPPORTED,
//		buildProgramFailure                   = CL_BUILD_PROGRAM_FAILURE,
//		mapFailure                            = CL_MAP_FAILURE,
//		misalignedSubBufferOffset             = CL_MISALIGNED_SUB_BUFFER_OFFSET,
//		executeStatusErrorForEventsInWaitList = CL_EXEC_STATUS_ERROR_FOR_EVENTS_IN_WAIT_LIST,
//		compileProgramFailure                 = CL_COMPILE_PROGRAM_FAILURE,
//		linkerNotAvailable                    = CL_LINKER_NOT_AVAILABLE,
//		linkProgramFailure                    = CL_LINK_PROGRAM_FAILURE,
//		devicePartitionFailed                 = CL_DEVICE_PARTITION_FAILED,
//		kernelArgumentInfoNotAvailable        = CL_KERNEL_ARG_INFO_NOT_AVAILABLE,

//		invalidValue                     = CL_INVALID_VALUE,
//		invalidDeviceType                = CL_INVALID_DEVICE_TYPE,
//		invalidPlatform                  = CL_INVALID_PLATFORM,
//		invalidDevice                    = CL_INVALID_DEVICE,
//		invalidContext                   = CL_INVALID_CONTEXT,
//		invalidQueueProperties           = CL_INVALID_QUEUE_PROPERTIES,
//		invalidCommandQueue              = CL_INVALID_COMMAND_QUEUE,
//		invalidHostPtr                   = CL_INVALID_HOST_PTR,
//		invalidMemoryObject              = CL_INVALID_MEM_OBJECT,
//		invalidImageFormatDescriptor     = CL_INVALID_IMAGE_FORMAT_DESCRIPTOR,
//		invalidImageSize                 = CL_INVALID_IMAGE_SIZE,
//		invalidSampler                   = CL_INVALID_SAMPLER,
//		invalidBinary                    = CL_INVALID_BINARY,
//		invalidBuildOptions              = CL_INVALID_BUILD_OPTIONS,
//		invalidProgram                   = CL_INVALID_PROGRAM,
//		invalidProgramExecutable         = CL_INVALID_PROGRAM_EXECUTABLE,
//		invalidKernelName                = CL_INVALID_KERNEL_NAME,
//		invalidKernelDefinition          = CL_INVALID_KERNEL_DEFINITION,
//		invalidKernel                    = CL_INVALID_KERNEL,
//		invalidArgumentIndex             = CL_INVALID_ARG_INDEX,
//		invalidArgumentValue             = CL_INVALID_ARG_VALUE,
//		invalidArgumentSize              = CL_INVALID_ARG_SIZE,
//		invalidKernelArguments           = CL_INVALID_KERNEL_ARGS,
//		invalidWorkDimension             = CL_INVALID_WORK_DIMENSION,
//		invalidWorkGroupSize             = CL_INVALID_WORK_GROUP_SIZE,
//		invalidWorkItemSize              = CL_INVALID_WORK_ITEM_SIZE,
//		invalidGlobalOffset              = CL_INVALID_GLOBAL_OFFSET,
//		invalidEventWaitList             = CL_INVALID_EVENT_WAIT_LIST,
//		invalidEvent                     = CL_INVALID_EVENT,
//		invalidOperation                 = CL_INVALID_OPERATION,
//		invalidGlObject                  = CL_INVALID_GL_OBJECT,
//		invalidBufferSize                = CL_INVALID_BUFFER_SIZE,
//		invalidMipLevel                  = CL_INVALID_MIP_LEVEL,
//		invalidGlobalWorkSize            = CL_INVALID_GLOBAL_WORK_SIZE,
//		invalidProperty                  = CL_INVALID_PROPERTY,
//		invalidImageDescriptor           = CL_INVALID_IMAGE_DESCRIPTOR,
//		invalidCompilerOptions           = CL_INVALID_COMPILER_OPTIONS,
//		invalidLinkerOptions             = CL_INVALID_LINKER_OPTIONS,
//		invalidDevicePartitionCount      = CL_INVALID_DEVICE_PARTITION_COUNT
//	};
//}

//#endif
<commit_msg>removed old RetCode<commit_after><|endoftext|>


<commit_before>//=======================================================================
// Copyright (c) 2014 Baptiste Wicht
// Distributed under the terms of the MIT License.
// (See accompanying file LICENSE or copy at
//  http://opensource.org/licenses/MIT)
//=======================================================================

#ifndef DBN_RBM_TRAITS_HPP
#define DBN_RBM_TRAITS_HPP

#include "tmp.hpp"
#include "decay_type.hpp"

namespace dll {

template<typename Layer>
class conv_rbm;

template<typename Layer>
class conv_rbm_mp;

template<typename RBM>
struct rbm_traits {
    using rbm_t = RBM;

    HAS_STATIC_FIELD(BatchSize, has_batch_size_field)
    HAS_STATIC_FIELD(Sparsity, has_sparsity_field)
    HAS_STATIC_FIELD(Decay, has_decay_field)
    HAS_STATIC_FIELD(Init, has_init_field)
    HAS_STATIC_FIELD(Momentum, has_momentum_field)

    static constexpr bool is_convolutional(){
        return is_instantiation_of<conv_rbm, rbm_t>::value
            || is_instantiation_of<conv_rbm_mp, rbm_t>::value;
    }

    template<typename R = RBM, enable_if_u<has_batch_size_field<typename R::layer>::value> = detail::dummy>
    static constexpr std::size_t batch_size(){
        return rbm_t::layer::BatchSize;
    }

    template<typename R = RBM, disable_if_u<has_batch_size_field<typename R::layer>::value> = detail::dummy>
    static constexpr std::size_t batch_size(){
        return 1;
    }

    template<typename R = RBM, enable_if_u<has_momentum_field<typename R::layer>::value> = detail::dummy>
    static constexpr bool has_momentum(){
        return rbm_t::layer::Momentum;
    }

    template<typename R = RBM, disable_if_u<has_momentum_field<typename R::layer>::value> = detail::dummy>
    static constexpr bool has_momentum(){
        return false;
    }

    template<typename R = RBM, enable_if_u<has_sparsity_field<typename R::layer>::value> = detail::dummy>
    static constexpr bool has_sparsity(){
        return rbm_t::layer::Sparsity;
    }

    template<typename R = RBM, disable_if_u<has_sparsity_field<typename R::layer>::value> = detail::dummy>
    static constexpr bool has_sparsity(){
        return false;
    }

    template<typename R = RBM, enable_if_u<has_decay_field<typename R::layer>::value> = detail::dummy>
    static constexpr decay_type decay(){
        return rbm_t::layer::Decay;
    }

    template<typename R = RBM, disable_if_u<has_decay_field<typename R::layer>::value> = detail::dummy>
    static constexpr decay_type decay(){
        return decay_type::NONE;
    }

    template<typename R = RBM, enable_if_u<has_init_field<typename R::layer>::value> = detail::dummy>
    static constexpr bool init_weights(){
        return rbm_t::layer::Init;
    }

    template<typename R = RBM, disable_if_u<has_init_field<typename R::layer>::value> = detail::dummy>
    static constexpr bool init_weights(){
        return false;
    }
};

} //end of dbn namespace

#endif<commit_msg>Add new function to the traits<commit_after>//=======================================================================
// Copyright (c) 2014 Baptiste Wicht
// Distributed under the terms of the MIT License.
// (See accompanying file LICENSE or copy at
//  http://opensource.org/licenses/MIT)
//=======================================================================

#ifndef DBN_RBM_TRAITS_HPP
#define DBN_RBM_TRAITS_HPP

#include "tmp.hpp"
#include "decay_type.hpp"

namespace dll {

template<typename Layer>
class conv_rbm;

template<typename Layer>
class conv_rbm_mp;

template<typename RBM>
struct rbm_traits {
    using rbm_t = RBM;

    HAS_STATIC_FIELD(BatchSize, has_batch_size_field)
    HAS_STATIC_FIELD(Sparsity, has_sparsity_field)
    HAS_STATIC_FIELD(Decay, has_decay_field)
    HAS_STATIC_FIELD(Init, has_init_field)
    HAS_STATIC_FIELD(Momentum, has_momentum_field)

    static constexpr bool is_convolutional(){
        return is_instantiation_of<conv_rbm, rbm_t>::value
            || is_instantiation_of<conv_rbm_mp, rbm_t>::value;
    }

    static constexpr bool has_probabilistic_max_pooling(){
        return is_instantiation_of<conv_rbm_mp, rbm_t>::value;
    }

    template<typename R = RBM, enable_if_u<has_batch_size_field<typename R::layer>::value> = detail::dummy>
    static constexpr std::size_t batch_size(){
        return rbm_t::layer::BatchSize;
    }

    template<typename R = RBM, disable_if_u<has_batch_size_field<typename R::layer>::value> = detail::dummy>
    static constexpr std::size_t batch_size(){
        return 1;
    }

    template<typename R = RBM, enable_if_u<has_momentum_field<typename R::layer>::value> = detail::dummy>
    static constexpr bool has_momentum(){
        return rbm_t::layer::Momentum;
    }

    template<typename R = RBM, disable_if_u<has_momentum_field<typename R::layer>::value> = detail::dummy>
    static constexpr bool has_momentum(){
        return false;
    }

    template<typename R = RBM, enable_if_u<has_sparsity_field<typename R::layer>::value> = detail::dummy>
    static constexpr bool has_sparsity(){
        return rbm_t::layer::Sparsity;
    }

    template<typename R = RBM, disable_if_u<has_sparsity_field<typename R::layer>::value> = detail::dummy>
    static constexpr bool has_sparsity(){
        return false;
    }

    template<typename R = RBM, enable_if_u<has_decay_field<typename R::layer>::value> = detail::dummy>
    static constexpr decay_type decay(){
        return rbm_t::layer::Decay;
    }

    template<typename R = RBM, disable_if_u<has_decay_field<typename R::layer>::value> = detail::dummy>
    static constexpr decay_type decay(){
        return decay_type::NONE;
    }

    template<typename R = RBM, enable_if_u<has_init_field<typename R::layer>::value> = detail::dummy>
    static constexpr bool init_weights(){
        return rbm_t::layer::Init;
    }

    template<typename R = RBM, disable_if_u<has_init_field<typename R::layer>::value> = detail::dummy>
    static constexpr bool init_weights(){
        return false;
    }
};

} //end of dbn namespace

#endif<|endoftext|>


<commit_before>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2011 Artem Pavlenko
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

#ifndef MAPNIK_VERSION_HPP
#define MAPNIK_VERSION_HPP

#define MAPNIK_VERSION_IS_RELEASE 0

#define MAPNIK_MAJOR_VERSION 3
#define MAPNIK_MINOR_VERSION 0
#define MAPNIK_PATCH_VERSION 0

// translates to 300000
#define MAPNIK_VERSION (MAPNIK_MAJOR_VERSION*100000) + (MAPNIK_MINOR_VERSION*100) + (MAPNIK_PATCH_VERSION)

#ifndef MAPNIK_STRINGIFY
#define MAPNIK_STRINGIFY(n) MAPNIK_STRINGIFY_HELPER(n)
#define MAPNIK_STRINGIFY_HELPER(n) #n
#endif

#if MAPNIK_VERSION_IS_RELEASE
#define MAPNIK_VERSION_STRING   MAPNIK_STRINGIFY(MAPNIK_MAJOR_VERSION) "." \
                                MAPNIK_STRINGIFY(MAPNIK_MINOR_VERSION) "." \
                                MAPNIK_STRINGIFY(MAPNIK_PATCH_VERSION)

#else
#define MAPNIK_VERSION_STRING   MAPNIK_STRINGIFY(MAPNIK_MAJOR_VERSION) "." \
                                MAPNIK_STRINGIFY(MAPNIK_MINOR_VERSION) "." \
                                MAPNIK_STRINGIFY(MAPNIK_PATCH_VERSION) "-pre"
#endif

#endif // MAPNIK_VERSION_HPP
<commit_msg>mark release<commit_after>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2011 Artem Pavlenko
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

#ifndef MAPNIK_VERSION_HPP
#define MAPNIK_VERSION_HPP

#define MAPNIK_VERSION_IS_RELEASE 1

#define MAPNIK_MAJOR_VERSION 3
#define MAPNIK_MINOR_VERSION 0
#define MAPNIK_PATCH_VERSION 0

// translates to 300000
#define MAPNIK_VERSION (MAPNIK_MAJOR_VERSION*100000) + (MAPNIK_MINOR_VERSION*100) + (MAPNIK_PATCH_VERSION)

#ifndef MAPNIK_STRINGIFY
#define MAPNIK_STRINGIFY(n) MAPNIK_STRINGIFY_HELPER(n)
#define MAPNIK_STRINGIFY_HELPER(n) #n
#endif

#if MAPNIK_VERSION_IS_RELEASE
#define MAPNIK_VERSION_STRING   MAPNIK_STRINGIFY(MAPNIK_MAJOR_VERSION) "." \
                                MAPNIK_STRINGIFY(MAPNIK_MINOR_VERSION) "." \
                                MAPNIK_STRINGIFY(MAPNIK_PATCH_VERSION)

#else
#define MAPNIK_VERSION_STRING   MAPNIK_STRINGIFY(MAPNIK_MAJOR_VERSION) "." \
                                MAPNIK_STRINGIFY(MAPNIK_MINOR_VERSION) "." \
                                MAPNIK_STRINGIFY(MAPNIK_PATCH_VERSION) "-pre"
#endif

#endif // MAPNIK_VERSION_HPP
<|endoftext|>


<commit_before>#include "../config.hpp"

#include <cassert>
#include <fstream>

namespace stx {

void config::set(std::string name, std::string value) noexcept {
	m_entries[std::move(name)] = std::move(value);
}

std::string config::get(std::string const& name) {
	std::string result;
	if(!get(name, &result)) throw std::runtime_error("Couldn't find config entry '" + name + "'");
	return result;
}
bool config::get(std::string const& name, std::string* into) noexcept {
	assert(into);

	auto iter = m_entries.find(name);

	if(iter == m_entries.end()) return false; // Not found

	*into = iter->second;
	return true;
}
std::string config::get(std::string const& name, std::string const& fallback) noexcept {
	std::string result;
	return get(name, &result) ? result : fallback;
}

double config::getf(std::string const& name) {
	double result;
	if(!get(name, &result)) throw std::runtime_error("Couldn't find config entry '" + name + "'");
	return result;
}
bool config::get(std::string const& name, double* into) noexcept {
	auto iter = m_entries.find(name);

	if(iter == m_entries.end()) return false; // Not found

	*into = std::stod(iter->second);
	return true;
}
double config::get(std::string const& name, double fallback) noexcept {
	double result;
	return get(name, &result) ? result : fallback;
}

void config::parseIni(std::string const& path) {
	std::ifstream file(path);
	parseIni(file);
}

void config::parseIni(std::istream& stream) {
	std::string section;

	std::string raw_line;
	while(std::getline(stream, raw_line)) {
		std::string_view line = raw_line;

		// Trim leading whitespace
		while(!line.empty() && std::isspace(line.front())) line.remove_prefix(1);

		if(line.front() == ';') continue; // Comment

		// Trim trailing whitespace
		while(!line.empty() && std::isspace(line.back()))  line.remove_suffix(1);

		if(line.empty()) continue; // Line is empty

		// New Section?
		if(line.front() == '[' && line.back() == ']') {
			line.remove_prefix(1);
			line.remove_suffix(1);
			section = std::string(line) + ".";
			continue;
		}

		std::string_view key, value;
		value = line;
		while(value.size() && value.front() != '=')
			value.remove_prefix(1);
		if(value.empty()) throw std::runtime_error("Missing =");
		value.remove_prefix(1);

		key = line.substr(0, line.size() - value.size() - 1);

		set(section + std::string(key), std::string(value));
	}
}

} // namespace stx
<commit_msg>Added folder support to config<commit_after>#include "../config.hpp"

#include <cassert>
#include <fstream>

#if __has_include(<filesystem>)
	#include <filesystem>
	namespace filesystem = std::filesystem;
#elif __has_include(<experimental/filesystem>)
	#include <experimental/filesystem>
	namespace filesystem = std::experimental::filesystem;
#endif

namespace stx {

void config::set(std::string name, std::string value) noexcept {
	m_entries[std::move(name)] = std::move(value);
}

std::string config::get(std::string const& name) {
	std::string result;
	if(!get(name, &result)) throw std::runtime_error("Couldn't find config entry '" + name + "'");
	return result;
}
bool config::get(std::string const& name, std::string* into) noexcept {
	assert(into);

	auto iter = m_entries.find(name);

	if(iter == m_entries.end()) return false; // Not found

	*into = iter->second;
	return true;
}
std::string config::get(std::string const& name, std::string const& fallback) noexcept {
	std::string result;
	return get(name, &result) ? result : fallback;
}

double config::getf(std::string const& name) {
	double result;
	if(!get(name, &result)) throw std::runtime_error("Couldn't find config entry '" + name + "'");
	return result;
}
bool config::get(std::string const& name, double* into) noexcept {
	auto iter = m_entries.find(name);

	if(iter == m_entries.end()) return false; // Not found

	*into = std::stod(iter->second);
	return true;
}
double config::get(std::string const& name, double fallback) noexcept {
	double result;
	return get(name, &result) ? result : fallback;
}

void config::parseIni(std::string const& path) {
	auto status = filesystem::status(path);

	// Is path a directory?
	if(status.type() == filesystem::file_type::directory) {
		// A directory
		using iter_t = filesystem::directory_iterator;
		for(iter_t i = iter_t(path); i != iter_t(); i++) {
			parseIni(i->path().string());
		}
	}
	else {
		// A file
		puts(path.c_str());

		std::ifstream file(path);
		parseIni(file);
	}
}

void config::parseIni(std::istream& stream) {
	std::string section;

	std::string raw_line;
	while(std::getline(stream, raw_line)) {
		std::string_view line = raw_line;

		// Trim leading whitespace
		while(!line.empty() && std::isspace(line.front())) line.remove_prefix(1);

		if(line.front() == ';') continue; // Comment

		// Trim trailing whitespace
		while(!line.empty() && std::isspace(line.back()))  line.remove_suffix(1);

		if(line.empty()) continue; // Line is empty

		// New Section?
		if(line.front() == '[' && line.back() == ']') {
			line.remove_prefix(1);
			line.remove_suffix(1);
			section = std::string(line) + ".";
			continue;
		}

		std::string_view key, value;
		value = line;
		while(value.size() && value.front() != '=')
			value.remove_prefix(1);
		if(value.empty()) throw std::runtime_error("Missing =");
		value.remove_prefix(1);

		key = line.substr(0, line.size() - value.size() - 1);

		set(section + std::string(key), std::string(value));
	}
}

} // namespace stx
<|endoftext|>


<commit_before>#ifndef TCFRAME_RUNNER_H
#define TCFRAME_RUNNER_H

#include "generator.hpp"
#include "macro.hpp"
#include "submitter.hpp"

#include <getopt.h>
#include <iostream>
#include <string>

using std::cout;
using std::endl;
using std::string;

namespace tcframe {

enum RunnerMode {
    GENERATION,
    SUBMISSION
};

template<typename TProblem>
class Runner {
public:
    Runner(int argc, char** argv)
            : argc(argc), argv(argv), problem(new TProblem()), mode(RunnerMode::GENERATION) { }

    Runner(int argc, char** argv, TProblem* problem)
            : argc(argc), argv(argv), problem(problem), mode(RunnerMode::GENERATION) { }

    void setGenerator(BaseGenerator<TProblem>* generator) {
        this->generator = generator;
    }

    void applyCommandLineOptions() {
        option longopts[5] = {
                { "slug", required_argument, nullptr, 's'},
                { "tc-dir", required_argument, nullptr, 'd'},
                { "solution-command", required_argument, nullptr, 'c'},
                { "porcelain", no_argument, &isPorcelain, 1},
                { 0, 0, 0, 0 }
        };

        int c;
        while ((c = getopt_long(argc, argv, "", longopts, nullptr)) != -1) {
            switch (c) {
                case 's':
                    problem->setSlug(string(optarg));
                    break;
                case 'd':
                    generator->setTestCasesDir(string(optarg));
                    break;
                case 'c':
                    generator->setSolutionCommand(string(optarg));
                    break;
                case '?':
                case ':':
                    exit(1);
                default:
                    break;
            }
        }
    }

    int run() {
        if (argc > 1 && string(argv[1]) == "submit") {
            mode = RunnerMode::SUBMISSION;

            if (argc == 2) {
                submissionCommand = generator->getSolutionCommand();
                argc--;
                argv++;
            } else {
                submissionCommand = string(argv[2]);
                argc -= 2;
                argv += 2;
            }
        }

        problem->applyConfiguration();
        generator->applyConfiguration();

        applyCommandLineOptions();

        if (mode == RunnerMode::GENERATION) {
            return generator->generate();
        } else {
            Submitter<TProblem>* submitter = new Submitter<TProblem>(problem, generator);
            submitter->setPorcelain((bool) isPorcelain);
            return submitter->submit(submissionCommand);
        }
    }

private:
    int argc;
    char** argv;

    RunnerMode mode;
    string submissionCommand;

    int isPorcelain;

    TProblem* problem;
    BaseGenerator<TProblem>* generator;
};

}

#endif
<commit_msg>Set isPorcelain = false by default<commit_after>#ifndef TCFRAME_RUNNER_H
#define TCFRAME_RUNNER_H

#include "generator.hpp"
#include "macro.hpp"
#include "submitter.hpp"

#include <getopt.h>
#include <iostream>
#include <string>

using std::cout;
using std::endl;
using std::string;

namespace tcframe {

enum RunnerMode {
    GENERATION,
    SUBMISSION
};

template<typename TProblem>
class Runner {
public:
    Runner(int argc, char** argv)
            : argc(argc), argv(argv), problem(new TProblem()), mode(RunnerMode::GENERATION), isPorcelain(0) { }

    Runner(int argc, char** argv, TProblem* problem)
            : argc(argc), argv(argv), problem(problem), mode(RunnerMode::GENERATION), isPorcelain(0) { }

    void setGenerator(BaseGenerator<TProblem>* generator) {
        this->generator = generator;
    }

    void applyCommandLineOptions() {
        option longopts[5] = {
                { "slug", required_argument, nullptr, 's'},
                { "tc-dir", required_argument, nullptr, 'd'},
                { "solution-command", required_argument, nullptr, 'c'},
                { "porcelain", no_argument, &isPorcelain, 1},
                { 0, 0, 0, 0 }
        };

        int c;
        while ((c = getopt_long(argc, argv, "", longopts, nullptr)) != -1) {
            switch (c) {
                case 's':
                    problem->setSlug(string(optarg));
                    break;
                case 'd':
                    generator->setTestCasesDir(string(optarg));
                    break;
                case 'c':
                    generator->setSolutionCommand(string(optarg));
                    break;
                case '?':
                case ':':
                    exit(1);
                default:
                    break;
            }
        }
    }

    int run() {
        if (argc > 1 && string(argv[1]) == "submit") {
            mode = RunnerMode::SUBMISSION;

            if (argc == 2) {
                submissionCommand = generator->getSolutionCommand();
                argc--;
                argv++;
            } else {
                submissionCommand = string(argv[2]);
                argc -= 2;
                argv += 2;
            }
        }

        problem->applyConfiguration();
        generator->applyConfiguration();

        applyCommandLineOptions();

        if (mode == RunnerMode::GENERATION) {
            return generator->generate();
        } else {
            Submitter<TProblem>* submitter = new Submitter<TProblem>(problem, generator);
            submitter->setPorcelain((bool) isPorcelain);
            return submitter->submit(submissionCommand);
        }
    }

private:
    int argc;
    char** argv;

    RunnerMode mode;
    string submissionCommand;

    int isPorcelain;

    TProblem* problem;
    BaseGenerator<TProblem>* generator;
};

}

#endif
<|endoftext|>


<commit_before>#ifndef LIBTEN_SHARED_POOL_HH
#define LIBTEN_SHARED_POOL_HH

#include "task/rendez.hh"
#include "ten/logging.hh"

#include <boost/call_traits.hpp>
#include <set>
#include <deque>

namespace ten {

namespace detail {
    template <typename T> class scoped_resource;
}

//! thread and task safe pool of shared resources
//
//! useful for connection pools and other types of shared resources
template <typename ResourceT, typename ScopeT = detail::scoped_resource<ResourceT> >
class shared_pool {
public:
    // use this scoped_resource type to RAII resources from the pool
    typedef ScopeT scoped_resource;
    typedef std::deque<std::shared_ptr<ResourceT> > queue_type;
    typedef std::set<std::shared_ptr<ResourceT> > set_type;
    typedef std::function<std::shared_ptr<ResourceT> ()> alloc_func;
protected:
    template <typename TT> friend class detail::scoped_resource;

    qutex _mut;
    rendez _not_empty;
    queue_type _q;
    set_type _set;
    std::string _name;
    alloc_func _new_resource;
    ssize_t _max;

public:
    shared_pool(const std::string &name_,
            const alloc_func &alloc_,
            ssize_t max_ = -1)
        : _name(name_),
        _new_resource(alloc_),
        _max(max_)
    {}

    shared_pool(const shared_pool &) = delete;
    shared_pool &operator =(const shared_pool &) = delete;

    size_t size() {
        std::unique_lock<qutex> lk(_mut);
        return _set.size();
    }

    void clear() {
        std::unique_lock<qutex> lk(_mut);
        _q.clear();
        _set.clear();
    }

    const std::string &name() const { return _name; }

protected:
    bool is_not_empty() const { return !_q.empty(); }

    std::shared_ptr<ResourceT> acquire() {
        std::unique_lock<qutex> lk(_mut);
        return create_or_acquire_nolock(lk);
    }

    // internal, does not lock mutex
    std::shared_ptr<ResourceT> create_or_acquire_nolock(std::unique_lock<qutex> &lk) {
        std::shared_ptr<ResourceT> c;
        if (_q.empty()) {
            // need to create a new resource
            if (_max < 0 || _set.size() < (size_t)_max) {
                try {
                    c = _new_resource();
                    CHECK(c) << "new_resource failed for pool: " << _name;
                    DVLOG(4) << "inserting to shared_pool(" << _name << "): " << c;
                    _set.insert(c);
                } catch (std::exception &e) {
                    LOG(ERROR) << "exception creating new resource for pool: " <<_name << " " << e.what();
                    throw;
                }
            } else {
                // can't create anymore we're at max, try waiting
                while (_q.empty()) {
                    _not_empty.sleep(lk);
                }
                CHECK(!_q.empty());
                c = _q.front();
                _q.pop_front();
            }
        } else {
            // pop resource from front of queue
            c = _q.front();
            _q.pop_front();
        }
        CHECK(c) << "acquire shared resource failed in pool: " << _name;
        return c;
    }

    bool insert(std::shared_ptr<ResourceT> &c) {
        // add a resource to the pool. use with care
        std::unique_lock<qutex> lk(_mut);
        auto p = _set.insert(c);
        if (p.second) {
            _q.push_front(c);
            _not_empty.wakeup();
        }
        return p.second;
    }

    void release(std::shared_ptr<ResourceT> &c) {
        std::unique_lock<qutex> lk(_mut);
        // don't add resource to queue if it was removed from _set
        if (_set.count(c)) {
            _q.push_front(c);
            _not_empty.wakeup();
        }
    }

    // return a defective resource to the pool
    // get a new one back.
    std::shared_ptr<ResourceT> exchange(std::shared_ptr<ResourceT> &c) {
        std::unique_lock<qutex> lk(_mut);
        // remove bad resource
        if (c) {
            _set.erase(c);
            c.reset();
        }

        return create_or_acquire_nolock(lk);
    }

    void destroy(std::shared_ptr<ResourceT> &c) {
        std::unique_lock<qutex> lk(_mut);
        // remove bad resource
        DVLOG(4) << "shared_pool(" << _name
            << ") destroy in set? " << _set.count(c)
            << " : " << c << " rc: " << c.use_count();
        _set.erase(c);
        typename queue_type::iterator i = find(_q.begin(), _q.end(), c);
        if (i!=_q.end()) { _q.erase(i); }

        c.reset();

        // replace the destroyed resource
        std::shared_ptr<ResourceT> cc = _new_resource();
        _set.insert(cc);
        _q.push_front(cc);
        cc.reset();
        _not_empty.wakeup();
    }

};

namespace detail {

// do not use this class directly, instead use your shared_pool<>::scoped_resource
template <typename T> class scoped_resource {
public:
    typedef typename boost::call_traits<shared_pool<T> >::reference poolref;
protected:
    poolref _pool;
    std::shared_ptr<T> _c;
public:
    explicit scoped_resource(poolref p)
        : _pool(p) {
            _c = _pool.acquire();
        }

    //! must call done() to return the resource to the pool
    //! otherwise we destroy it because a timeout or other exception
    //! could have occured causing the resource state to be in transition
    ~scoped_resource() {
        if (!_c) return;
        _pool.destroy(_c);
    }

    void exchange() {
        _c = _pool.exchange(_c);
    }

    void destroy() {
        _pool.destroy(_c);
    }

    void acquire() {
        if (_c) return;
        _c = _pool.acquire();
    }

    void done() {
        if (!_c) return;
        _pool.release(_c);
        _c.reset();
    }

    T *operator->() {
        if (!_c) throw std::runtime_error("null pointer");
        return _c.get();
    }

};

} // end detail namespace

} // end namespace ten

#endif // LIBTEN_SHARED_POOL_HH
<commit_msg>remove dangerous apis from shared_pool<commit_after>#ifndef LIBTEN_SHARED_POOL_HH
#define LIBTEN_SHARED_POOL_HH

#include "task/rendez.hh"
#include "ten/logging.hh"

#include <boost/call_traits.hpp>
#include <set>
#include <deque>

namespace ten {

namespace detail {
    template <typename T> class scoped_resource;
}

//! thread and task safe pool of shared resources
//
//! useful for connection pools and other types of shared resources
template <typename ResourceT, typename ScopeT = detail::scoped_resource<ResourceT> >
class shared_pool {
public:
    // use this scoped_resource type to RAII resources from the pool
    typedef ScopeT scoped_resource;
    typedef std::deque<std::shared_ptr<ResourceT> > queue_type;
    typedef std::set<std::shared_ptr<ResourceT> > set_type;
    typedef std::function<std::shared_ptr<ResourceT> ()> alloc_func;
protected:
    template <typename TT> friend class detail::scoped_resource;

    qutex _mut;
    rendez _not_empty;
    queue_type _q;
    set_type _set;
    std::string _name;
    alloc_func _new_resource;
    ssize_t _max;

public:
    shared_pool(const std::string &name_,
            const alloc_func &alloc_,
            ssize_t max_ = -1)
        : _name(name_),
        _new_resource(alloc_),
        _max(max_)
    {}

    shared_pool(const shared_pool &) = delete;
    shared_pool &operator =(const shared_pool &) = delete;

    size_t size() {
        std::unique_lock<qutex> lk(_mut);
        return _set.size();
    }

    void clear() {
        std::unique_lock<qutex> lk(_mut);
        _q.clear();
        _set.clear();
    }

    const std::string &name() const { return _name; }

protected:
    bool is_not_empty() const { return !_q.empty(); }

    std::shared_ptr<ResourceT> acquire() {
        std::unique_lock<qutex> lk(_mut);
        return create_or_acquire_nolock(lk);
    }

    // internal, does not lock mutex
    std::shared_ptr<ResourceT> create_or_acquire_nolock(std::unique_lock<qutex> &lk) {
        std::shared_ptr<ResourceT> c;
        if (_q.empty()) {
            // need to create a new resource
            if (_max < 0 || _set.size() < (size_t)_max) {
                c = add_new_resource(lk);
            } else {
                // can't create anymore we're at max, try waiting
                _not_empty.sleep(lk, [&] {
                    return _q.empty();
                });
                DCHECK(!_q.empty());
                c = _q.front();
                _q.pop_front();
            }
        } else {
            // pop resource from front of queue
            c = _q.front();
            _q.pop_front();
        }
        CHECK(c) << "acquire shared resource failed in pool: " << _name;
        return c;
    }

    void release(std::shared_ptr<ResourceT> &c) {
        std::unique_lock<qutex> lk(_mut);
        // don't add resource to queue if it was removed from _set
        if (_set.count(c)) {
            _q.push_front(c);
            _not_empty.wakeup();
        }
    }

    void destroy(std::shared_ptr<ResourceT> &c) {
        std::unique_lock<qutex> lk(_mut);
        // remove bad resource
        DVLOG(4) << "shared_pool(" << _name
            << ") destroy in set? " << _set.count(c)
            << " : " << c << " rc: " << c.use_count();
        size_t count = _set.erase(c);
        if (count) {
            LOG(WARNING) << "destroying shared resource from pool " << _name;
        }
        typename queue_type::iterator i = std::find(_q.begin(), _q.end(), c);
        if (i!=_q.end()) { _q.erase(i); }

        c.reset();

        // replace the destroyed resource
        std::shared_ptr<ResourceT> cc = add_new_resource(lk);
        _q.push_front(cc);
        cc.reset();
        _not_empty.wakeup();
    }

    std::shared_ptr<ResourceT> add_new_resource(std::unique_lock<qutex> &lk) {
        std::shared_ptr<ResourceT> c;
        lk.unlock(); // unlock while newing resource
        try {
            c = _new_resource();
            CHECK(c) << "new_resource failed for pool: " << _name;
            DVLOG(4) << "inserting to shared_pool(" << _name << "): " << c;
        } catch (std::exception &e) {
            LOG(ERROR) << "exception creating new resource for pool: " <<_name << " " << e.what();
            throw;
        }
        lk.lock(); // re-lock before inserting to set
        _set.insert(c);
        return c;
    }

};

namespace detail {

// do not use this class directly, instead use your shared_pool<>::scoped_resource
template <typename T> class scoped_resource {
public:
    //typedef typename std::add_reference<shared_pool<T>>::type poolref;
    typedef typename boost::call_traits<shared_pool<T>>::reference poolref;
protected:
    poolref _pool;
    std::shared_ptr<T> _c;
    bool _success;
public:
    explicit scoped_resource(poolref p)
        : _pool(p), _success(false) {
            _c = _pool.acquire();
        }

    //! must call done() to return the resource to the pool
    //! otherwise we destroy it because a timeout or other exception
    //! could have occured causing the resource state to be in transition
    ~scoped_resource() {
        if (_success) {
            _pool.release(_c);
        } else {
            _pool.destroy(_c);
        }
    }

    void done() {
        DCHECK(!_success);
        _success = true;
    }

    T *operator->() {
        if (!_c) throw std::runtime_error("null pointer");
        return _c.get();
    }

};

} // end detail namespace

} // end namespace ten

#endif // LIBTEN_SHARED_POOL_HH
<|endoftext|>


<commit_before>//----------------------------------------------------------------------------
/// \file stream_io.hpp
/// \author Serge Aleynikov
//----------------------------------------------------------------------------
/// Defines functions for stream input/output
//----------------------------------------------------------------------------
// Copyright (C) 2016 Serge Aleynikov <saleyn@gmail.com>
// Created: 2016-02-26
//----------------------------------------------------------------------------
/*
***** BEGIN LICENSE BLOCK *****

This file is a part of utxx open-source project.

Copyright (C) 2016 Serge Aleynikov <saleyn@gmail.com>

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

This library 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
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

***** END LICENSE BLOCK *****
*/
#pragma once

#include <fstream>
#include <utxx/convert.hpp>
#include <utxx/container/stack_container.hpp>

namespace utxx {

//------------------------------------------------------------------------------
/// Read \a a_cnt values from the input stream.
/// @param in       input stream.
/// @param a_output array of \a a_cnt double values.
/// @param a_fields array of \a a_cnt field positions (ascending order). If this
///                 value is NULL, the values are read from the input stream
///                 in consequitive order disregarding field positions.
/// @param a_cnt    count of values to read.
/// @param a_convert lambda used to convert a string value to type \a T:
///   const char* (const char* begin, const char* end, T& outout);
///   The function must return NULL if conversion is unsuccessful, or a pointer
///   past last successfully parsed character otherwise.
/// @return true if successfully read \a a_cnt values.
//------------------------------------------------------------------------------
template <typename T = double, int StrSize = 256, class Convert>
bool read_values(std::ifstream& in, T* a_output, int* a_fields, int a_cnt,
                 const Convert& a_convert)
{
  basic_stack_string<StrSize> str;

  auto& line = str.container();

  if (a_fields == nullptr) {
    for (int i=0; i < a_cnt; ++i) {
      if (in.eof()) return false;
      in >> *a_output++;
    }
  }
  else if (!std::getline(in, line))
    return false;
  else {
    const char* p = &*line.begin();
    const char* e = &*line.end();

    int fld = 0;

    auto ws      = [](char c)     { return c == ' ' || c == '\t'; };
    auto skip_ws = [&p, e, &ws]() { while (ws(*p) && p != e) p++; };

    for (int i=0; i < a_cnt; ++i, ++a_fields, ++a_output) {
      while (p != e) {
        skip_ws();
        if (++fld == *a_fields)
          break;
        while (!ws(*p) && p != e) p++;
      }

      if (fld != *a_fields)
        return false;

      p = a_convert(p, e, *a_output);

      if (!p)
          return false;
    }
  }

  return true;
}

} // namespace utxx<commit_msg>Use more generic istream primitive<commit_after>//----------------------------------------------------------------------------
/// \file stream_io.hpp
/// \author Serge Aleynikov
//----------------------------------------------------------------------------
/// Defines functions for stream input/output
//----------------------------------------------------------------------------
// Copyright (C) 2016 Serge Aleynikov <saleyn@gmail.com>
// Created: 2016-02-26
//----------------------------------------------------------------------------
/*
***** BEGIN LICENSE BLOCK *****

This file is a part of utxx open-source project.

Copyright (C) 2016 Serge Aleynikov <saleyn@gmail.com>

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

This library 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
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

***** END LICENSE BLOCK *****
*/
#pragma once

#include <iosfwd>
#include <utxx/convert.hpp>
#include <utxx/container/stack_container.hpp>

namespace utxx {

//------------------------------------------------------------------------------
/// Read \a a_cnt values from the input stream.
/// @param in       input stream.
/// @param a_output array of \a a_cnt double values.
/// @param a_fields array of \a a_cnt field positions (ascending order). If this
///                 value is NULL, the values are read from the input stream
///                 in consequitive order disregarding field positions.
/// @param a_cnt    count of values to read.
/// @param a_convert lambda used to convert a string value to type \a T:
///   const char* (const char* begin, const char* end, T& outout);
///   The function must return NULL if conversion is unsuccessful, or a pointer
///   past last successfully parsed character otherwise.
/// @return true if successfully read \a a_cnt values.
//------------------------------------------------------------------------------
template <typename T = double, int StrSize = 256, class Convert>
bool read_values(std::istream& in, T* a_output, int* a_fields, int a_cnt,
                 const Convert& a_convert)
{
  basic_stack_string<StrSize> str;

  auto& line = str.container();

  if (a_fields == nullptr) {
    for (int i=0; i < a_cnt; ++i) {
      if (in.eof()) return false;
      in >> *a_output++;
    }
  }
  else if (!std::getline(in, line))
    return false;
  else {
    const char* p = &*line.begin();
    const char* e = &*line.end();

    int fld = 0;

    auto ws      = [](char c)     { return c == ' ' || c == '\t'; };
    auto skip_ws = [&p, e, &ws]() { while (ws(*p) && p != e) p++; };

    for (int i=0; i < a_cnt; ++i, ++a_fields, ++a_output) {
      while (p != e) {
        skip_ws();
        if (++fld == *a_fields)
          break;
        while (!ws(*p) && p != e) p++;
      }

      if (fld != *a_fields)
        return false;

      p = a_convert(p, e, *a_output);

      if (!p)
          return false;
    }
  }

  return true;
}

} // namespace utxx<|endoftext|>