<commit_before>#include "read_fru_data.hpp"

#include "fruread.hpp"
#include "types.hpp"
#include "utils.hpp"

#include <host-ipmid/ipmid-api.h>

#include <algorithm>
#include <map>
#include <phosphor-logging/elog-errors.hpp>
#include <sdbusplus/message/types.hpp>
#include <xyz/openbmc_project/Common/error.hpp>

extern const FruMap frus;
namespace ipmi
{
namespace fru
{

namespace variant_ns = sdbusplus::message::variant_ns;

using namespace phosphor::logging;
using InternalFailure =
    sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure;
std::unique_ptr<sdbusplus::bus::match_t> matchPtr(nullptr);

static constexpr auto INV_INTF = "xyz.openbmc_project.Inventory.Manager";
static constexpr auto OBJ_PATH = "/xyz/openbmc_project/inventory";
static constexpr auto PROP_INTF = "org.freedesktop.DBus.Properties";

namespace cache
{
// User initiate read FRU info area command followed by
// FRU read command. Also data is read in small chunks of
// the specified offset and count.
// Caching the data which will be invalidated when ever there
// is a change in FRU properties.
FRUAreaMap fruMap;
} // namespace cache
/**
 * @brief Read all the property value's for the specified interface
 *  from Inventory.
 *
 * @param[in] intf Interface
 * @param[in] path Object path
 * @return map of properties
 */
ipmi::PropertyMap readAllProperties(const std::string& intf,
                                    const std::string& path)
{
    ipmi::PropertyMap properties;
    sdbusplus::bus::bus bus{ipmid_get_sd_bus_connection()};
    auto service = ipmi::getService(bus, INV_INTF, OBJ_PATH);
    std::string objPath = OBJ_PATH + path;
    auto method = bus.new_method_call(service.c_str(), objPath.c_str(),
                                      PROP_INTF, "GetAll");
    method.append(intf);
    auto reply = bus.call(method);
    if (reply.is_method_error())
    {
        // If property is not found simply return empty value
        log<level::ERR>("Error in reading property values from inventory",
                        entry("INTERFACE=%s", intf.c_str()),
                        entry("PATH=%s", objPath.c_str()));
        return properties;
    }
    reply.read(properties);
    return properties;
}

void processFruPropChange(sdbusplus::message::message& msg)
{
    if (cache::fruMap.empty())
    {
        return;
    }
    std::string path = msg.get_path();
    // trim the object base path, if found at the beginning
    if (path.compare(0, strlen(OBJ_PATH), OBJ_PATH) == 0)
    {
        path.erase(0, strlen(OBJ_PATH));
    }
    for (auto& fru : frus)
    {
        auto& instanceList = fru.second;

        auto found = std::find_if(
            instanceList.begin(), instanceList.end(),
            [&path](const auto& iter) { return (iter.path == path); });

        if (found != instanceList.end())
        {
            auto& fruId = fru.first;

            cache::fruMap.erase(fruId);
            break;
        }
    }
}

// register for fru property change
int registerCallbackHandler()
{
    if (matchPtr == nullptr)
    {
        using namespace sdbusplus::bus::match::rules;
        sdbusplus::bus::bus bus{ipmid_get_sd_bus_connection()};
        matchPtr = std::make_unique<sdbusplus::bus::match_t>(
            bus,
            path_namespace(OBJ_PATH) + type::signal() +
                member("PropertiesChanged") + interface(PROP_INTF),
            std::bind(processFruPropChange, std::placeholders::_1));
    }
    return 0;
}

/**
 * @brief Read FRU property values from Inventory
 *
 * @param[in] fruNum  FRU id
 * @return populate FRU Inventory data
 */
FruInventoryData readDataFromInventory(const FRUId& fruNum)
{
    auto iter = frus.find(fruNum);
    if (iter == frus.end())
    {
        log<level::ERR>("Unsupported FRU ID ", entry("FRUID=%d", fruNum));
        elog<InternalFailure>();
    }

    FruInventoryData data;
    auto& instanceList = iter->second;
    for (auto& instance : instanceList)
    {
        for (auto& intf : instance.interfaces)
        {
            ipmi::PropertyMap allProp =
                readAllProperties(intf.first, instance.path);
            for (auto& properties : intf.second)
            {
                auto iter = allProp.find(properties.first);
                if (iter != allProp.end())
                {
                    data[properties.second.section].emplace(
                        properties.first,
                        std::move(variant_ns::get<std::string>(
                            allProp[properties.first])));
                }
            }
        }
    }
    return data;
}

const FruAreaData& getFruAreaData(const FRUId& fruNum)
{
    auto iter = cache::fruMap.find(fruNum);
    if (iter != cache::fruMap.end())
    {
        return iter->second;
    }
    auto invData = readDataFromInventory(fruNum);

    // Build area info based on inventory data
    FruAreaData newdata = buildFruAreaData(std::move(invData));
    cache::fruMap.emplace(fruNum, std::move(newdata));
    return cache::fruMap.at(fruNum);
}
} // namespace fru
} // namespace ipmi
<commit_msg>read_fru_data: use structured bindings in fru loop<commit_after>#include "read_fru_data.hpp"

#include "fruread.hpp"
#include "types.hpp"
#include "utils.hpp"

#include <host-ipmid/ipmid-api.h>

#include <algorithm>
#include <map>
#include <phosphor-logging/elog-errors.hpp>
#include <sdbusplus/message/types.hpp>
#include <xyz/openbmc_project/Common/error.hpp>

extern const FruMap frus;
namespace ipmi
{
namespace fru
{

namespace variant_ns = sdbusplus::message::variant_ns;

using namespace phosphor::logging;
using InternalFailure =
    sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure;
std::unique_ptr<sdbusplus::bus::match_t> matchPtr(nullptr);

static constexpr auto INV_INTF = "xyz.openbmc_project.Inventory.Manager";
static constexpr auto OBJ_PATH = "/xyz/openbmc_project/inventory";
static constexpr auto PROP_INTF = "org.freedesktop.DBus.Properties";

namespace cache
{
// User initiate read FRU info area command followed by
// FRU read command. Also data is read in small chunks of
// the specified offset and count.
// Caching the data which will be invalidated when ever there
// is a change in FRU properties.
FRUAreaMap fruMap;
} // namespace cache
/**
 * @brief Read all the property value's for the specified interface
 *  from Inventory.
 *
 * @param[in] intf Interface
 * @param[in] path Object path
 * @return map of properties
 */
ipmi::PropertyMap readAllProperties(const std::string& intf,
                                    const std::string& path)
{
    ipmi::PropertyMap properties;
    sdbusplus::bus::bus bus{ipmid_get_sd_bus_connection()};
    auto service = ipmi::getService(bus, INV_INTF, OBJ_PATH);
    std::string objPath = OBJ_PATH + path;
    auto method = bus.new_method_call(service.c_str(), objPath.c_str(),
                                      PROP_INTF, "GetAll");
    method.append(intf);
    auto reply = bus.call(method);
    if (reply.is_method_error())
    {
        // If property is not found simply return empty value
        log<level::ERR>("Error in reading property values from inventory",
                        entry("INTERFACE=%s", intf.c_str()),
                        entry("PATH=%s", objPath.c_str()));
        return properties;
    }
    reply.read(properties);
    return properties;
}

void processFruPropChange(sdbusplus::message::message& msg)
{
    if (cache::fruMap.empty())
    {
        return;
    }
    std::string path = msg.get_path();
    // trim the object base path, if found at the beginning
    if (path.compare(0, strlen(OBJ_PATH), OBJ_PATH) == 0)
    {
        path.erase(0, strlen(OBJ_PATH));
    }
    for (const auto& [fruId, instanceList] : frus)
    {
        auto found = std::find_if(
            instanceList.begin(), instanceList.end(),
            [&path](const auto& iter) { return (iter.path == path); });

        if (found != instanceList.end())
        {
            cache::fruMap.erase(fruId);
            break;
        }
    }
}

// register for fru property change
int registerCallbackHandler()
{
    if (matchPtr == nullptr)
    {
        using namespace sdbusplus::bus::match::rules;
        sdbusplus::bus::bus bus{ipmid_get_sd_bus_connection()};
        matchPtr = std::make_unique<sdbusplus::bus::match_t>(
            bus,
            path_namespace(OBJ_PATH) + type::signal() +
                member("PropertiesChanged") + interface(PROP_INTF),
            std::bind(processFruPropChange, std::placeholders::_1));
    }
    return 0;
}

/**
 * @brief Read FRU property values from Inventory
 *
 * @param[in] fruNum  FRU id
 * @return populate FRU Inventory data
 */
FruInventoryData readDataFromInventory(const FRUId& fruNum)
{
    auto iter = frus.find(fruNum);
    if (iter == frus.end())
    {
        log<level::ERR>("Unsupported FRU ID ", entry("FRUID=%d", fruNum));
        elog<InternalFailure>();
    }

    FruInventoryData data;
    auto& instanceList = iter->second;
    for (auto& instance : instanceList)
    {
        for (auto& intf : instance.interfaces)
        {
            ipmi::PropertyMap allProp =
                readAllProperties(intf.first, instance.path);
            for (auto& properties : intf.second)
            {
                auto iter = allProp.find(properties.first);
                if (iter != allProp.end())
                {
                    data[properties.second.section].emplace(
                        properties.first,
                        std::move(variant_ns::get<std::string>(
                            allProp[properties.first])));
                }
            }
        }
    }
    return data;
}

const FruAreaData& getFruAreaData(const FRUId& fruNum)
{
    auto iter = cache::fruMap.find(fruNum);
    if (iter != cache::fruMap.end())
    {
        return iter->second;
    }
    auto invData = readDataFromInventory(fruNum);

    // Build area info based on inventory data
    FruAreaData newdata = buildFruAreaData(std::move(invData));
    cache::fruMap.emplace(fruNum, std::move(newdata));
    return cache::fruMap.at(fruNum);
}
} // namespace fru
} // namespace ipmi
<|endoftext|>


<commit_before>#ifndef __REGEXP__REGEXP__HPP__
#define __REGEXP__REGEXP__HPP__

#include <string>

// ideally SRegExp<"ahoj|cau$">::smatch

namespace SRegExp {
template <char c> struct Chr {
	static inline bool smatch(const char * str, size_t & pos, size_t, size_t) {
		if (*str == c) {
			pos++;
			return true;
		} else return false;
	}
};

template <char a, char b, char... rest> struct CSet {
	static inline bool smatch(const char * str, size_t & pos, size_t, size_t) {
		if (matchCharacter(*str)) {
			pos++;
			return true;
		} else return false;
	}
	static inline bool matchCharacter(char u) { return (u >= a && u <= b) || CSet<rest...>::matchCharacter(u); }
};

template <char a, char b> struct CSet<a, b> {
	static inline bool smatch(const char * str, size_t & pos, size_t, size_t) {
		if (*str >= a && *str <= b) {
			pos++;
			return true;
		} else return false;
	}
	static inline bool matchCharacter(char u) { return (u >= a && u <= b); }
};

template <char a, char b, char... rest> struct CNegSet {
	static inline bool smatch(const char * str, size_t & pos, size_t, size_t) {
		if (matchCharacter(*str)) {
			pos++;
			return true;
		} else return false;
	}
	static inline bool matchCharacter(char u) { return !(u >= a && u <= b) && CNegSet<rest...>::matchCharacter(u); }
};

template <char a, char b> struct CNegSet<a, b> {
	static inline bool smatch(const char * str, size_t & pos, size_t, size_t) {
		if (!(*str >= a && * str <= b)) {
			pos++;
			return true;
		} else return false;
	}
	static inline bool matchCharacter(char u) { return !(u >= a && u <= b); }
};

template <typename Inner, typename... rest> struct Seq {
	static inline bool smatch(const char * str, size_t & pos, size_t cpos, size_t deep) {
		size_t tmp{pos};
		if (Inner::smatch(str, tmp, cpos, deep) && Seq<rest...>::smatch(str + tmp - pos, tmp, cpos + tmp, deep)) {
			pos = tmp;
			return true;
		} else return false;
	}
};

template <typename Inner> struct Seq<Inner> {
	static inline bool smatch(const char * str, size_t & pos, size_t cpos, size_t deep) {
		return Inner::smatch(str, pos, cpos, deep);
	}
};

template <char c, char... rest> struct Str {
	static inline bool smatch(const char * str, size_t & pos, size_t cpos, size_t deep) {
		size_t tmp{pos};
		if (Chr<c>::smatch(str, tmp, cpos, deep) && Str<rest...>::smatch(str + tmp - pos, tmp, cpos + tmp, deep)) {
			pos = tmp;
			return true;
		} else return false;
	}
};

template <char c> struct Str<c> {
	static inline bool smatch(const char * str, size_t & pos, size_t cpos, size_t deep) {
		return Chr<c>::smatch(str, pos, cpos, deep);
	}
};

template <typename Inner, typename... rest> struct Sel {
	static inline bool smatch(const char * str, size_t & pos, size_t cpos, size_t deep) {
		if (Inner::smatch(str, pos, cpos, deep)) return true;
		else return Sel<rest...>::smatch(str, pos, cpos, deep);
	}
};

template <typename Inner> struct Sel<Inner> {
	static inline bool smatch(const char * str, size_t & pos, size_t cpos, size_t deep) {
		return Inner::smatch(str, pos, cpos, deep);
	}
};

struct Any {
	static inline bool smatch(const char * str, size_t & pos, size_t, size_t) {
		if (*str) {
			pos++;
			return true;
		} else return false;
	}
};

template <typename Inner, typename... rest> struct Star {
	static inline bool smatch(const char * str, size_t & pos, size_t cpos, size_t deep) {
		size_t tmp{0};
		if (Seq<rest...>::smatch(str, tmp, cpos, deep)) {
			pos += tmp;
			return true;
		} else if (Inner::smatch(str + tmp, tmp, cpos, deep)) {
			for (;;) if (Seq<rest...>::smatch(str + tmp, tmp, cpos + tmp, deep)) {
				pos += tmp;
				return true;
			} else if (!Inner::smatch(str + tmp, tmp, cpos + tmp, deep)) return false;
		} else return false;
	}
};

template <typename Inner> struct Star<Inner> {
	static inline bool smatch(const char * str, size_t & pos, size_t cpos, size_t deep) {
		size_t tmp{0};
		if (Inner::smatch(str + tmp, tmp, cpos, deep)) {
			for (;;) if (!Inner::smatch(str + tmp, tmp, cpos + tmp, deep)) {
				pos += tmp;
				return true;
			}
		} return true;
	}
};

template <typename Inner, typename... rest> struct Plus {
	static inline bool smatch(const char * str, size_t & pos, size_t cpos, size_t deep) {
		size_t tmp{0};
		if (Inner::smatch(str + tmp, tmp, cpos, deep)) {
			for (;;) if (Seq<rest...>::smatch(str + tmp, tmp, cpos + tmp, deep)) {
				pos += tmp;
				return true;
			} else if (!Inner::smatch(str + tmp, tmp, cpos + tmp, deep)) return false;
		}
		return false;
	}
};

template <typename Inner> struct Plus<Inner> {
	static inline bool smatch(const char * str, size_t & pos, size_t cpos, size_t deep) {
		size_t tmp{0};
		if (Inner::smatch(str + tmp, tmp, cpos, deep))
			for (;;) if (!Inner::smatch(str + tmp, tmp, cpos + tmp, deep)) {
				pos += tmp;
				return true;
			}
		return false;
	}
};

template <typename Inner, typename... rest> struct Opt {
	static inline bool smatch(const char * str, size_t & pos, size_t cpos, size_t deep) {
		size_t tmp{0};
		if (Seq<rest...>::smatch(str, pos, cpos, deep + 1))
			return true;
		else if (Inner::smatch(str, tmp, cpos, deep + 1) && Seq<rest...>::smatch(str + tmp, tmp, cpos + tmp, deep + 1)) {
			pos += tmp;
			return true;
		}
		return false;
	}
};

struct End {
	static inline bool smatch(const char * str, size_t &, size_t, size_t) {
		return (!* str);
	}
};

struct Begin {
	static inline bool smatch(const char *, size_t &, size_t cpos, size_t) {
		return cpos == 0;
	}
};

template <typename... rest> struct Eat {
	static inline bool smatch(const char * str, size_t &, size_t cpos, size_t deep) {
		size_t tmp{0};
		while (*(str + tmp)) {
			if (Seq<rest...>::smatch(str + tmp, tmp, cpos + tmp, deep)) return true;
			else tmp++;
		}
		return false;
	}
};

template <typename... rest> bool sregexp_smatch(const char * str) {
	size_t tmp{0};
	return Eat<rest...>::smatch(str, tmp, tmp, 0);
}

template <typename... rest> bool sregexp_smatch(std::string str) {
	size_t tmp{0};
	return Eat<rest...>::smatch(str.c_str(), tmp, tmp, 0);
}

template <typename... rest> class StaticRegExp {
protected:
	Eat<rest...> definition;

public:
	bool operator()(const char * str) {
		size_t tmp{0};
		return definition.smatch(str, tmp, tmp, 0);
	}
	bool operator()(const std::string &str) {
		size_t tmp{0};
		return definition.smatch(str.c_str(), tmp, tmp, 0);
	}
};
}

#endif
<commit_msg>Support for wide-chars<commit_after>#ifndef __REGEXP__REGEXP__HPP__
#define __REGEXP__REGEXP__HPP__

#include <string>

// ideally SRegExp<"ahoj|cau$">::smatch

namespace SRegExp {
template <char c> struct Chr {
	template <typename chartype> static inline bool smatch(const chartype str, size_t & pos, size_t, size_t) {
		if (*str == c) {
			pos++;
			return true;
		} else return false;
	}
};

template <char a, char b, char... rest> struct CSet {
	template <typename chartype> static inline bool smatch(const chartype str, size_t & pos, size_t, size_t) {
		if (matchCharacter(*str)) {
			pos++;
			return true;
		} else return false;
	}
	template <typename chartype> static inline bool matchCharacter(chartype u) { return (u >= a && u <= b) || CSet<rest...>::matchCharacter(u); }
};

template <char a, char b> struct CSet<a, b> {
	template <typename chartype> static inline bool smatch(const chartype str, size_t & pos, size_t, size_t) {
		if (*str >= a && *str <= b) {
			pos++;
			return true;
		} else return false;
	}
	template <typename chartype> static inline bool matchCharacter(chartype u) { return (u >= a && u <= b); }
};

template <char a, char b, char... rest> struct CNegSet {
	template <typename chartype> static inline bool smatch(const chartype str, size_t & pos, size_t, size_t) {
		if (matchCharacter(*str)) {
			pos++;
			return true;
		} else return false;
	}
	template <typename chartype> static inline bool matchCharacter(chartype u) { return !(u >= a && u <= b) && CNegSet<rest...>::matchCharacter(u); }
};

template <char a, char b> struct CNegSet<a, b> {
	template <typename chartype> static inline bool smatch(const chartype str, size_t & pos, size_t, size_t) {
		if (!(*str >= a && * str <= b)) {
			pos++;
			return true;
		} else return false;
	}
	template <typename chartype> static inline bool matchCharacter(chartype u) { return !(u >= a && u <= b); }
};

template <typename Inner, typename... rest> struct Seq {
	template <typename chartype> static inline bool smatch(const chartype str, size_t & pos, size_t cpos, size_t deep) {
		size_t tmp{pos};
		if (Inner::smatch(str, tmp, cpos, deep) && Seq<rest...>::smatch(str + tmp - pos, tmp, cpos + tmp, deep)) {
			pos = tmp;
			return true;
		} else return false;
	}
};

template <typename Inner> struct Seq<Inner> {
	template <typename chartype> static inline bool smatch(const chartype str, size_t & pos, size_t cpos, size_t deep) {
		return Inner::smatch(str, pos, cpos, deep);
	}
};

template <char c, char... rest> struct Str {
	template <typename chartype> static inline bool smatch(const chartype str, size_t & pos, size_t cpos, size_t deep) {
		size_t tmp{pos};
		if (Chr<c>::smatch(str, tmp, cpos, deep) && Str<rest...>::smatch(str + tmp - pos, tmp, cpos + tmp, deep)) {
			pos = tmp;
			return true;
		} else return false;
	}
};

template <char c> struct Str<c> {
	template <typename chartype> static inline bool smatch(const chartype str, size_t & pos, size_t cpos, size_t deep) {
		return Chr<c>::smatch(str, pos, cpos, deep);
	}
};

template <typename Inner, typename... rest> struct Sel {
	template <typename chartype> static inline bool smatch(const chartype str, size_t & pos, size_t cpos, size_t deep) {
		if (Inner::smatch(str, pos, cpos, deep)) return true;
		else return Sel<rest...>::smatch(str, pos, cpos, deep);
	}
};

template <typename Inner> struct Sel<Inner> {
	template <typename chartype> static inline bool smatch(const chartype str, size_t & pos, size_t cpos, size_t deep) {
		return Inner::smatch(str, pos, cpos, deep);
	}
};

struct Any {
	template <typename chartype> static inline bool smatch(const chartype str, size_t & pos, size_t, size_t) {
		if (*str) {
			pos++;
			return true;
		} else return false;
	}
};

template <typename Inner, typename... rest> struct Star {
	template <typename chartype> static inline bool smatch(const chartype str, size_t & pos, size_t cpos, size_t deep) {
		size_t tmp{0};
		if (Seq<rest...>::smatch(str, tmp, cpos, deep)) {
			pos += tmp;
			return true;
		} else if (Inner::smatch(str + tmp, tmp, cpos, deep)) {
			for (;;) if (Seq<rest...>::smatch(str + tmp, tmp, cpos + tmp, deep)) {
				pos += tmp;
				return true;
			} else if (!Inner::smatch(str + tmp, tmp, cpos + tmp, deep)) return false;
		} else return false;
	}
};

template <typename Inner> struct Star<Inner> {
	template <typename chartype> static inline bool smatch(const chartype str, size_t & pos, size_t cpos, size_t deep) {
		size_t tmp{0};
		if (Inner::smatch(str + tmp, tmp, cpos, deep)) {
			for (;;) if (!Inner::smatch(str + tmp, tmp, cpos + tmp, deep)) {
				pos += tmp;
				return true;
			}
		} return true;
	}
};

template <typename Inner, typename... rest> struct Plus {
	template <typename chartype> static inline bool smatch(const chartype str, size_t & pos, size_t cpos, size_t deep) {
		size_t tmp{0};
		if (Inner::smatch(str + tmp, tmp, cpos, deep)) {
			for (;;) if (Seq<rest...>::smatch(str + tmp, tmp, cpos + tmp, deep)) {
				pos += tmp;
				return true;
			} else if (!Inner::smatch(str + tmp, tmp, cpos + tmp, deep)) return false;
		}
		return false;
	}
};

template <typename Inner> struct Plus<Inner> {
	template <typename chartype> static inline bool smatch(const chartype str, size_t & pos, size_t cpos, size_t deep) {
		size_t tmp{0};
		if (Inner::smatch(str + tmp, tmp, cpos, deep))
			for (;;) if (!Inner::smatch(str + tmp, tmp, cpos + tmp, deep)) {
				pos += tmp;
				return true;
			}
		return false;
	}
};

template <typename Inner, typename... rest> struct Opt {
	template <typename chartype> static inline bool smatch(const chartype str, size_t & pos, size_t cpos, size_t deep) {
		size_t tmp{0};
		if (Seq<rest...>::smatch(str, pos, cpos, deep + 1))
			return true;
		else if (Inner::smatch(str, tmp, cpos, deep + 1) && Seq<rest...>::smatch(str + tmp, tmp, cpos + tmp, deep + 1)) {
			pos += tmp;
			return true;
		}
		return false;
	}
};

struct End {
	template <typename chartype> static inline bool smatch(const chartype * str, size_t &, size_t, size_t) {
		return (!* str);
	}
};

struct Begin {
	template <typename chartype> static inline bool smatch(const chartype *, size_t &, size_t cpos, size_t) {
		return cpos == 0;
	}
};

template <typename... rest> struct Eat {
	template <typename chartype> static inline bool smatch(const chartype * str, size_t &, size_t cpos, size_t deep) {
		size_t tmp{0};
		while (*(str + tmp)) {
			if (Seq<rest...>::smatch(str + tmp, tmp, cpos + tmp, deep)) return true;
			else tmp++;
		}
		return false;
	}
};

template <typename... rest> bool sregexp_smatch(const wchar_t * str) {
	size_t tmp{0};
	return Eat<rest...>::smatch(str, tmp, tmp, 0);
}

template <typename... rest> bool sregexp_smatch(std::wstring str) {
	size_t tmp{0};
	return Eat<rest...>::smatch(str.c_str(), tmp, tmp, 0);
}

template <typename... rest> bool sregexp_smatch(const char * str) {
	size_t tmp{0};
	return Eat<rest...>::smatch(str, tmp, tmp, 0);
}

template <typename... rest> bool sregexp_smatch(std::string str) {
	size_t tmp{0};
	return Eat<rest...>::smatch(str.c_str(), tmp, tmp, 0);
}

template <typename... rest> class StaticRegExp {
protected:
	Eat<rest...> definition;

public:
	bool operator()(const wchar_t * str) {
		size_t tmp{0};
		return definition.smatch(str, tmp, tmp, 0);
	}
	bool operator()(const std::wstring &str) {
		size_t tmp{0};
		return definition.smatch(str.c_str(), tmp, tmp, 0);
	}
	bool operator()(const char * str) {
		size_t tmp{0};
		return definition.smatch(str, tmp, tmp, 0);
	}
	bool operator()(const std::string &str) {
		size_t tmp{0};
		return definition.smatch(str.c_str(), tmp, tmp, 0);
	}
};
}

#endif
<|endoftext|>


<commit_before>#include <stdio.h>
#include <stdint.h>
#include <assert.h>
#include <stdlib.h>
#include <map>
#include <vector>
#include <string>
#include <iostream>

using std::string;
using std::map;
using std::vector;

typedef uint32_t Id;

struct Packet {
    Id id, parent;
    uint8_t event, type, bits, width, value_idx, num_int_args;
    char name[17];
    uint8_t payload[4096-32]; // Not all of this will be used, but this is the max possible size.

    size_t value_bytes() const {
        size_t bytes_per_elem = 1;
        while (bytes_per_elem*8 < bits) bytes_per_elem <<= 1;
        return bytes_per_elem * width;
    }

    size_t int_args_bytes() const {
        return sizeof(int) * num_int_args;
    }

    size_t payload_bytes() const {
        return value_bytes() + int_args_bytes();
    }

    // Grab a packet from stdin. Returns false when stdin closes.
    bool read_from_stdin() {
        if (!read_stdin(this, 32)) {
            return false;
        }
        assert(read_stdin(payload, payload_bytes()) &&
               "Unexpected EOF mid-packet");
        return true;
    }

private:
    bool read_stdin(void *d, ssize_t size) {
        uint8_t *dst = (uint8_t *)d;
        if (!size) return true;
        while (1) {
            ssize_t s = read(0, dst, size);
            if (s == 0) {
                // EOF
                return false;
            } else if (s < 0) {
                perror("Failed during read");
                exit(-1);
                return 0;
            } else if (s == size) {
                return true;
            }
            size -= s;
            dst += s;
        }
    }
};

class Point {
    vector<int> p;
public:
    Point(int num_int_args, const int *int_args) {
        p.insert(p.end(), int_args, int_args + num_int_args);
    }

    Point(const vector<int> &v) : p(v) {
    }

    Point() {}

    int operator[](int x) const {
        return p[x];
    }

    int &operator[](int x) {
        return p[x];
    }

    int dimensions() const {
        return (int)p.size();
    }

    bool operator<(const Point &other) const {
        for (size_t i = 0; i < p.size(); i++) {
            if (p[i] < other[i]) return true;
            if (p[i] > other[i]) return false;
        }
        return false;
    }
};

struct Box {
    Point top_left;
    Point bottom_right;

    Box() {}

    Box(const Point &tl, const Point &br) : top_left(tl), bottom_right(br) {}

    Box(int num_int_args, int *int_args) {
        vector<int> tl, br;
        for (int i = 0; i < num_int_args/2; i++) {
            tl.push_back(int_args[i*2]);
            br.push_back(int_args[i*2] + int_args[i*2+1] - 1);
        }
        top_left = Point(tl);
        bottom_right = Point(br);
    }

    int dimensions() const {
        return top_left.dimensions();
    }

    void include(const Point &p) {
        if (dimensions() == 0) {
            top_left = p;
            bottom_right = p;
        } else {
            assert(p.dimensions() == top_left.dimensions());
            assert(p.dimensions() == bottom_right.dimensions());
            for (int i = 0; i < dimensions(); i++) {
                top_left[i] = std::min(top_left[i], p[i]);
                bottom_right[i] = std::max(bottom_right[i], p[i]);
            }
        }
    }

    void include(const Box &b) {
        include(b.top_left);
        include(b.bottom_right);
    }

    bool contains(const Point &p) const {
        assert(p.dimensions() == top_left.dimensions());
        assert(p.dimensions() == bottom_right.dimensions());
        for (int i = 0; i < p.dimensions(); i++) {
            if (top_left[i] > p[i]) return false;
            if (bottom_right[i] < p[i]) return false;
        }
        return true;
    }

    bool contains(const Box &b) const {
        return contains(b.top_left) && contains(b.bottom_right);
    }

};

class Count {
    size_t val;

public:
    Count() : val(0) {}

    void operator++(int) {
        val++;
    }

    void operator+=(int x) {
        val += x;
    }

    void operator+=(const Count &x) {
        val += x.val;
    }

    size_t value() const {
        return val;
    }

};

struct Production {
    enum {Producing, Updating, Consuming} state;

    Box region;

    void load(Count clock, const Packet &p) {
        assert(state == Updating || state == Consuming);
    }

    void store(Count clock, const Packet &p) {
        assert(state == Producing || state == Updating);
    }
};

struct Realization {
    map<Id, Production *> productions;

    Box region;

    struct PointState {
        size_t last_load, last_store;
        PointState() : last_load(0), last_store(0) {}
    };
    map<Point, PointState> state_map;

    void load(Count clock, const Packet &p) {
        Production *prod = productions[p.parent];
        assert(prod && "Load without a parent");
        prod->load(clock, p);
    }

    void store(Count clock, const Packet &p) {
        Production *prod = productions[p.parent];
        assert(prod && "Store without a parent");
        prod->store(clock, p);
    }

    void produce(Count clock, const Packet &p) {
        Production *prod = new Production;
        productions[p.id] = prod;
        prod->state = Production::Producing;
    }

    void update(Count clock, const Packet &p) {
        Production *prod = productions[p.parent];
        assert(prod && "Update without a parent");
        prod->state = Production::Updating;
    }

    void consume(Count clock, const Packet &p) {
        Production *prod = productions[p.parent];
        assert(prod && "Consume without a parent");
        prod->state = Production::Consuming;
    }

    void end_consume(Count clock, const Packet &p) {
        Production *prod = productions[p.parent];
        assert(prod && "Consume without a parent");
        // Retrieve stats
        delete prod;
        productions.erase(p.parent);
    }

};

struct FuncStats {
    map<Id, Realization *> realizations;

    Count loads, stores;

    FuncStats() {}

    void load(Count clock, const Packet &p) {
        Realization *r = realizations[p.parent];
        assert(r && "Load without a parent");
        r->load(clock, p);
        loads++;
    }

    void store(Count clock, const Packet &p) {
        Realization *r = realizations[p.parent];
        assert(r && "Store without a parent");
        r->store(clock, p);
        stores++;
    }

    void produce(Count clock, const Packet &p) {
        Realization *r = realizations[p.parent];
        assert(r && "Produce without a parent");
        realizations[p.id] = r;
        r->produce(clock, p);
    }

    void update(Count clock, const Packet &p) {
        Realization *r = realizations[p.parent];
        assert(r && "Update without a parent");
        r->update(clock, p);
    }

    void consume(Count clock, const Packet &p) {
        Realization *r = realizations[p.parent];
        assert(r && "Consume without a parent");
        r->consume(clock, p);
    }

    void end_consume(Count clock, const Packet &p) {
        Realization *r = realizations[p.parent];
        assert(r && "Update without a parent");
        r->end_consume(clock, p);
        realizations.erase(p.parent);
    }

    void begin_realize(Count clock, const Packet &p) {
        Realization *r = new Realization;
        realizations[p.id] = r;
    }

    void end_realize(Count clock, const Packet &p) {
        Realization *r = realizations[p.parent];
        // Aggregate stats
        delete r;
        realizations.erase(p.parent);
    }

    void report() const {
        std::cout << " stores:" << stores.value() << '\n';
        std::cout << " loads:" << loads.value() << '\n';
    }
};

int main(int argc, char **argv) {
    assert(sizeof(Packet) == 4096);

    map<string, FuncStats> funcs;

    Count clock;

    while (1) {
        Packet p;
        if (!p.read_from_stdin()) {
            break;
        }

        //printf("Packet header: %u %u %d %d %d %d %d %d %s\n", p.id, p.parent, p.event, p.type, p.bits, p.width, p.value_idx, p.num_int_args, p.name);

        FuncStats &f = funcs[p.name];

        switch (p.event) {
        case 0:
            f.load(clock, p);
            clock += p.value_bytes();
            break;
        case 1:
            f.store(clock, p);
            clock += p.value_bytes();
            break;
        case 2: // begin realization
            f.begin_realize(clock, p);
            break;
        case 3: // end realization
            f.end_realize(clock, p);
            break;
        case 4: // produce
            f.produce(clock, p);
            break;
        case 5: // update
            f.update(clock, p);
            break;
        case 6: // consume
            f.consume(clock, p);
            break;
        case 7: // end consume
            f.end_consume(clock, p);
            break;
        default:
            exit(-1);
        }
    }

    for (map<string, FuncStats>::iterator iter = funcs.begin();
         iter != funcs.end(); ++iter) {
        std::cout << "Function " << iter->first << ":\n";
        iter->second.report();
    }

    return 0;
}
<commit_msg>Added unistd to HalideTrace<commit_after>#include <stdio.h>
#include <stdint.h>
#include <assert.h>
#include <stdlib.h>
#include <map>
#include <vector>
#include <string>
#include <iostream>
#include <unistd.h>

using std::string;
using std::map;
using std::vector;

typedef uint32_t Id;

struct Packet {
    Id id, parent;
    uint8_t event, type, bits, width, value_idx, num_int_args;
    char name[17];
    uint8_t payload[4096-32]; // Not all of this will be used, but this is the max possible size.

    size_t value_bytes() const {
        size_t bytes_per_elem = 1;
        while (bytes_per_elem*8 < bits) bytes_per_elem <<= 1;
        return bytes_per_elem * width;
    }

    size_t int_args_bytes() const {
        return sizeof(int) * num_int_args;
    }

    size_t payload_bytes() const {
        return value_bytes() + int_args_bytes();
    }

    // Grab a packet from stdin. Returns false when stdin closes.
    bool read_from_stdin() {
        if (!read_stdin(this, 32)) {
            return false;
        }
        assert(read_stdin(payload, payload_bytes()) &&
               "Unexpected EOF mid-packet");
        return true;
    }

private:
    bool read_stdin(void *d, ssize_t size) {
        uint8_t *dst = (uint8_t *)d;
        if (!size) return true;
        while (1) {
            ssize_t s = read(0, dst, size);
            if (s == 0) {
                // EOF
                return false;
            } else if (s < 0) {
                perror("Failed during read");
                exit(-1);
                return 0;
            } else if (s == size) {
                return true;
            }
            size -= s;
            dst += s;
        }
    }
};

class Point {
    vector<int> p;
public:
    Point(int num_int_args, const int *int_args) {
        p.insert(p.end(), int_args, int_args + num_int_args);
    }

    Point(const vector<int> &v) : p(v) {
    }

    Point() {}

    int operator[](int x) const {
        return p[x];
    }

    int &operator[](int x) {
        return p[x];
    }

    int dimensions() const {
        return (int)p.size();
    }

    bool operator<(const Point &other) const {
        for (size_t i = 0; i < p.size(); i++) {
            if (p[i] < other[i]) return true;
            if (p[i] > other[i]) return false;
        }
        return false;
    }
};

struct Box {
    Point top_left;
    Point bottom_right;

    Box() {}

    Box(const Point &tl, const Point &br) : top_left(tl), bottom_right(br) {}

    Box(int num_int_args, int *int_args) {
        vector<int> tl, br;
        for (int i = 0; i < num_int_args/2; i++) {
            tl.push_back(int_args[i*2]);
            br.push_back(int_args[i*2] + int_args[i*2+1] - 1);
        }
        top_left = Point(tl);
        bottom_right = Point(br);
    }

    int dimensions() const {
        return top_left.dimensions();
    }

    void include(const Point &p) {
        if (dimensions() == 0) {
            top_left = p;
            bottom_right = p;
        } else {
            assert(p.dimensions() == top_left.dimensions());
            assert(p.dimensions() == bottom_right.dimensions());
            for (int i = 0; i < dimensions(); i++) {
                top_left[i] = std::min(top_left[i], p[i]);
                bottom_right[i] = std::max(bottom_right[i], p[i]);
            }
        }
    }

    void include(const Box &b) {
        include(b.top_left);
        include(b.bottom_right);
    }

    bool contains(const Point &p) const {
        assert(p.dimensions() == top_left.dimensions());
        assert(p.dimensions() == bottom_right.dimensions());
        for (int i = 0; i < p.dimensions(); i++) {
            if (top_left[i] > p[i]) return false;
            if (bottom_right[i] < p[i]) return false;
        }
        return true;
    }

    bool contains(const Box &b) const {
        return contains(b.top_left) && contains(b.bottom_right);
    }

};

class Count {
    size_t val;

public:
    Count() : val(0) {}

    void operator++(int) {
        val++;
    }

    void operator+=(int x) {
        val += x;
    }

    void operator+=(const Count &x) {
        val += x.val;
    }

    size_t value() const {
        return val;
    }

};

struct Production {
    enum {Producing, Updating, Consuming} state;

    Box region;

    void load(Count clock, const Packet &p) {
        assert(state == Updating || state == Consuming);
    }

    void store(Count clock, const Packet &p) {
        assert(state == Producing || state == Updating);
    }
};

struct Realization {
    map<Id, Production *> productions;

    Box region;

    struct PointState {
        size_t last_load, last_store;
        PointState() : last_load(0), last_store(0) {}
    };
    map<Point, PointState> state_map;

    void load(Count clock, const Packet &p) {
        Production *prod = productions[p.parent];
        assert(prod && "Load without a parent");
        prod->load(clock, p);
    }

    void store(Count clock, const Packet &p) {
        Production *prod = productions[p.parent];
        assert(prod && "Store without a parent");
        prod->store(clock, p);
    }

    void produce(Count clock, const Packet &p) {
        Production *prod = new Production;
        productions[p.id] = prod;
        prod->state = Production::Producing;
    }

    void update(Count clock, const Packet &p) {
        Production *prod = productions[p.parent];
        assert(prod && "Update without a parent");
        prod->state = Production::Updating;
    }

    void consume(Count clock, const Packet &p) {
        Production *prod = productions[p.parent];
        assert(prod && "Consume without a parent");
        prod->state = Production::Consuming;
    }

    void end_consume(Count clock, const Packet &p) {
        Production *prod = productions[p.parent];
        assert(prod && "Consume without a parent");
        // Retrieve stats
        delete prod;
        productions.erase(p.parent);
    }

};

struct FuncStats {
    map<Id, Realization *> realizations;

    Count loads, stores;

    FuncStats() {}

    void load(Count clock, const Packet &p) {
        Realization *r = realizations[p.parent];
        assert(r && "Load without a parent");
        r->load(clock, p);
        loads++;
    }

    void store(Count clock, const Packet &p) {
        Realization *r = realizations[p.parent];
        assert(r && "Store without a parent");
        r->store(clock, p);
        stores++;
    }

    void produce(Count clock, const Packet &p) {
        Realization *r = realizations[p.parent];
        assert(r && "Produce without a parent");
        realizations[p.id] = r;
        r->produce(clock, p);
    }

    void update(Count clock, const Packet &p) {
        Realization *r = realizations[p.parent];
        assert(r && "Update without a parent");
        r->update(clock, p);
    }

    void consume(Count clock, const Packet &p) {
        Realization *r = realizations[p.parent];
        assert(r && "Consume without a parent");
        r->consume(clock, p);
    }

    void end_consume(Count clock, const Packet &p) {
        Realization *r = realizations[p.parent];
        assert(r && "Update without a parent");
        r->end_consume(clock, p);
        realizations.erase(p.parent);
    }

    void begin_realize(Count clock, const Packet &p) {
        Realization *r = new Realization;
        realizations[p.id] = r;
    }

    void end_realize(Count clock, const Packet &p) {
        Realization *r = realizations[p.parent];
        // Aggregate stats
        delete r;
        realizations.erase(p.parent);
    }

    void report() const {
        std::cout << " stores:" << stores.value() << '\n';
        std::cout << " loads:" << loads.value() << '\n';
    }
};

int main(int argc, char **argv) {
    assert(sizeof(Packet) == 4096);

    map<string, FuncStats> funcs;

    Count clock;

    while (1) {
        Packet p;
        if (!p.read_from_stdin()) {
            break;
        }

        //printf("Packet header: %u %u %d %d %d %d %d %d %s\n", p.id, p.parent, p.event, p.type, p.bits, p.width, p.value_idx, p.num_int_args, p.name);

        FuncStats &f = funcs[p.name];

        switch (p.event) {
        case 0:
            f.load(clock, p);
            clock += p.value_bytes();
            break;
        case 1:
            f.store(clock, p);
            clock += p.value_bytes();
            break;
        case 2: // begin realization
            f.begin_realize(clock, p);
            break;
        case 3: // end realization
            f.end_realize(clock, p);
            break;
        case 4: // produce
            f.produce(clock, p);
            break;
        case 5: // update
            f.update(clock, p);
            break;
        case 6: // consume
            f.consume(clock, p);
            break;
        case 7: // end consume
            f.end_consume(clock, p);
            break;
        default:
            exit(-1);
        }
    }

    for (map<string, FuncStats>::iterator iter = funcs.begin();
         iter != funcs.end(); ++iter) {
        std::cout << "Function " << iter->first << ":\n";
        iter->second.report();
    }

    return 0;
}
<|endoftext|>


<commit_before>#include "PageManager.hpp"
#include <sys/mman.h>
#include <cassert>
#include <memory.h>
#include <iostream>

namespace tell {
namespace store {

PageManager::PageManager(size_t size)
    : mData(mmap(nullptr, size, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, 0, 0)), mSize(size), mPages(
    size / TELL_PAGE_SIZE)
{
    assert(size % TELL_PAGE_SIZE == 0);
    auto numPages = size / TELL_PAGE_SIZE;
    memset(mData, 0, mSize);
    char* data = reinterpret_cast<char*>(mData);
    data += size - TELL_PAGE_SIZE; // data does now point to the last page
    for (size_t i = 0ul; i < numPages; ++i) {
        bool res = mPages.push(data);
        assert(res);
        data -= TELL_PAGE_SIZE;
    }
}

PageManager::~PageManager() {
    munmap(mData, mSize);
}

void* PageManager::alloc() {
    void* res = nullptr;
    bool success = mPages.pop(res);
    assert(success == (res != nullptr));
    assert(res >= mData && res < reinterpret_cast<char*>(mData) + mSize);
    assert((reinterpret_cast<char*>(res) - reinterpret_cast<char*>(mData)) % TELL_PAGE_SIZE == 0);
    return res;
}

void PageManager::free(void* page) {
    assert(page >= mData && page < reinterpret_cast<char*>(mData) + mSize);
    assert((reinterpret_cast<char*>(page) - reinterpret_cast<char*>(mData)) % TELL_PAGE_SIZE == 0);
    memset(page, 0, TELL_PAGE_SIZE);
    freeEmpty(page);
}

void PageManager::freeEmpty(void* page) {
    while (!mPages.push(page));
}

} // namespace store
} // namespace tell
<commit_msg>Throw bad_alloc exception when allocating memory in PageManager failed<commit_after>#include "PageManager.hpp"
#include <sys/mman.h>
#include <cassert>
#include <memory.h>
#include <iostream>
#include <new>

namespace tell {
namespace store {

PageManager::PageManager(size_t size)
    : mData(mmap(nullptr, size, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, 0, 0)), mSize(size), mPages(
    size / TELL_PAGE_SIZE)
{
    if (mData == MAP_FAILED) {
        throw std::bad_alloc();
    }
    assert(size % TELL_PAGE_SIZE == 0);
    auto numPages = size / TELL_PAGE_SIZE;
    memset(mData, 0, mSize);
    char* data = reinterpret_cast<char*>(mData);
    data += size - TELL_PAGE_SIZE; // data does now point to the last page
    for (size_t i = 0ul; i < numPages; ++i) {
        bool res = mPages.push(data);
        assert(res);
        data -= TELL_PAGE_SIZE;
    }
}

PageManager::~PageManager() {
    munmap(mData, mSize);
}

void* PageManager::alloc() {
    void* res = nullptr;
    bool success = mPages.pop(res);
    assert(success == (res != nullptr));
    assert(res >= mData && res < reinterpret_cast<char*>(mData) + mSize);
    assert((reinterpret_cast<char*>(res) - reinterpret_cast<char*>(mData)) % TELL_PAGE_SIZE == 0);
    return res;
}

void PageManager::free(void* page) {
    assert(page >= mData && page < reinterpret_cast<char*>(mData) + mSize);
    assert((reinterpret_cast<char*>(page) - reinterpret_cast<char*>(mData)) % TELL_PAGE_SIZE == 0);
    memset(page, 0, TELL_PAGE_SIZE);
    freeEmpty(page);
}

void PageManager::freeEmpty(void* page) {
    while (!mPages.push(page));
}

} // namespace store
} // namespace tell
<|endoftext|>


<commit_before>
// @(#)root/proof:$Id$
// Author: G. Ganis  Nov 2006

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

//////////////////////////////////////////////////////////////////////////
//                                                                      //
// TProofChain                                                          //
//                                                                      //
// A TChain proxy on PROOF.                                             //
// Uses an internal TDSet to handle processing.                         //
//                                                                      //
//////////////////////////////////////////////////////////////////////////

#include "TProofChain.h"
#include "TDSet.h"
#include "TList.h"
#include "TProof.h"
#include "TROOT.h"
#include "TEventList.h"
#include "TEntryList.h"

ClassImp(TProofChain)

////////////////////////////////////////////////////////////////////////////////
/// Crates a new PROOF chain proxy.

TProofChain::TProofChain() : TChain()
{
   fChain        = 0;
   fTree         = 0;
   fSet          = 0;
   fDirectory    = gDirectory;
   ResetBit(kOwnsChain);
}

////////////////////////////////////////////////////////////////////////////////
/// Crates a new PROOF chain proxy containing the files from the chain.

TProofChain::TProofChain(TChain *chain, Bool_t gettreeheader) : TChain()
{
   fChain        = chain;
   fTree         = 0;
   fSet          = chain ? new TDSet((const TChain &)(*chain)) : 0;
   fDirectory    = gDirectory;
   if (gProof) {
      gProof->AddChain(chain);
      ConnectProof();
      if (gProof->IsLite()) {
         SetBit(kProofLite);
         fTree = fChain;
      } else {
         if (gettreeheader && fSet)
            fTree = gProof->GetTreeHeader(fSet);
      }
   }
   ResetBit(kOwnsChain);
}

////////////////////////////////////////////////////////////////////////////////
/// Creates a new PROOF chain proxy containing the files from the dset.

TProofChain::TProofChain(TDSet *dset, Bool_t gettreeheader) : TChain()
{
   fChain        = 0;
   fTree         = 0;
   fSet          = dset;
   fDirectory    = gDirectory;
   if (gProof) {
      ConnectProof();
      if (gettreeheader && dset)
         fTree = gProof->GetTreeHeader(dset);
      if (gProof->IsLite())
         SetBit(kProofLite);
   }
   if (fTree && fSet) {
      fChain = new TChain(fTree->GetName());
      TIter nxe(fSet->GetListOfElements());
      TDSetElement *e = 0;
      while ((e = (TDSetElement *) nxe())) {
         fChain->AddFile(e->GetName());
      }
      SetBit(kOwnsChain);
      if (TestBit(kProofLite))
         fTree = fChain;
   }
}

////////////////////////////////////////////////////////////////////////////////
/// Destructor.

TProofChain::~TProofChain()
{
   if (fChain) {
      SafeDelete(fSet);
      // Remove the chain from the private lists in the TProof objects
      TIter nxp(gROOT->GetListOfSockets());
      TObject *o = 0;
      TProof *p = 0;
      while ((o = nxp()))
         if ((p = dynamic_cast<TProof *>(o)))
            p->RemoveChain(fChain);
      if (fTree == fChain) fTree = 0;
      if (TestBit(kOwnsChain)) {
         SafeDelete(fChain);
      } else {
         fChain = 0;
      }
   } else {
      // Not owner
      fSet = 0;
   }
   SafeDelete(fTree);
   fDirectory    = 0;

}

////////////////////////////////////////////////////////////////////////////////
/// Forwards the execution to the dummy tree header.
/// See TTree::Browse().

void TProofChain::Browse(TBrowser *b)
{
   fSet->Browse(b);
}

////////////////////////////////////////////////////////////////////////////////
/// Forwards the execution to the TDSet.
/// Returns -1 in case of error or number of selected events in case of success.
/// See TDSet::Browse().

Long64_t TProofChain::Draw(const char *varexp, const TCut &selection,
                           Option_t *option, Long64_t nentries, Long64_t firstentry)
{
   if (!gProof) {
      Error("Draw", "no active PROOF session");
      return -1;
   }
   ConnectProof();

   fReadEntry = firstentry;

   // Set either the entry-list (priority) or the event-list
   if (fEntryList) {
      fSet->SetEntryList(fEntryList);
   } else if (fEventList) {
      fSet->SetEntryList(fEventList);
   } else {
      // Disable previous settings, if any
      fSet->SetEntryList(0);
   }

   // Fill drawing attributes
   FillDrawAttributes(gProof);

   // Add alias information, if any
   AddAliases();

   Long64_t rv = fSet->Draw(varexp, selection, option, nentries, firstentry);
   return rv;
}

////////////////////////////////////////////////////////////////////////////////
/// Forwards the execution to the TDSet.
/// Returns -1 in case of error or number of selected events in case of success.
/// See TDSet::Browse().

Long64_t TProofChain::Draw(const char *varexp, const char *selection,
                           Option_t *option,Long64_t nentries, Long64_t firstentry)
{
   if (!gProof) {
      Error("Draw", "no active PROOF session");
      return -1;
   }
   ConnectProof();

   fReadEntry = firstentry;

   // Set either the entry-list (priority) or the event-list
   if (fEntryList) {
      fSet->SetEntryList(fEntryList);
   } else if (fEventList) {
      fSet->SetEntryList(fEventList);
   }

   // Fill drawing attributes
   FillDrawAttributes(gProof);

   // Add alias information, if any
   AddAliases();

   Long64_t rv = fSet->Draw(varexp, selection, option, nentries, firstentry);
   return rv;
}

////////////////////////////////////////////////////////////////////////////////
/// Aliases are added to the input list. The names are comma-separated in the
/// TNamed 'PROOF_ListOfAliases'. For each name, there is an trey named 'alias:<name>'.

void TProofChain::AddAliases()
{
   TList *al = fChain->GetListOfAliases();
   if (al && al->GetSize() > 0) {
      TIter nxa(al);
      TNamed *nm = 0, *nmo = 0;
      TString names, nma;
      while ((nm = (TNamed *)nxa())) {
         names += nm->GetName();
         names += ",";
         nma.Form("alias:%s", nm->GetName());
         nmo = (TNamed *)((gProof->GetInputList()) ? gProof->GetInputList()->FindObject(nma) : 0);
         if (nmo) {
            nmo->SetTitle(nm->GetTitle());
         } else {
            gProof->AddInput(new TNamed(nma.Data(), nm->GetTitle()));
         }
      }
      nmo = (TNamed *)((gProof->GetInputList()) ? gProof->GetInputList()->FindObject("PROOF_ListOfAliases") : 0);
      if (nmo) {
         nmo->SetTitle(names.Data());
      } else {
         gProof->AddInput(new TNamed("PROOF_ListOfAliases", names.Data()));
      }
   }
}

////////////////////////////////////////////////////////////////////////////////
/// Communicate the drawing attributes for this chain to the input list
/// so that the draw selectors can use them, in case of need.
/// The drawing attributes are:
///
///    LineColor          Line color
///    LineStyle          Line style
///    LineWidth          Line width
///    MarkerColor        Marker color index
///    MarkerSize         Marker size
///    MarkerStyle        Marker style
///    FillColor          Area fill color
///    FillStyle          Area fill style

void TProofChain::FillDrawAttributes(TProof *p)
{
   if (!p || !fChain) {
      Error("FillDrawAttributes", "invalid PROOF or mother chain pointers!");
      return;
   }

   // Weight
   p->SetParameter("PROOF_ChainWeight", fChain->GetWeight());

   // Line Attributes
   p->SetParameter("PROOF_LineColor", (Int_t) fChain->GetLineColor());
   p->SetParameter("PROOF_LineStyle", (Int_t) fChain->GetLineStyle());
   p->SetParameter("PROOF_LineWidth", (Int_t) fChain->GetLineWidth());

   // Marker Attributes
   p->SetParameter("PROOF_MarkerColor", (Int_t) fChain->GetMarkerColor());
   p->SetParameter("PROOF_MarkerSize", (Int_t) fChain->GetMarkerSize()*1000);
   p->SetParameter("PROOF_MarkerStyle", (Int_t) fChain->GetMarkerStyle());

   // Area fill attributes
   p->SetParameter("PROOF_FillColor", (Int_t) fChain->GetFillColor());
   p->SetParameter("PROOF_FillStyle", (Int_t) fChain->GetFillStyle());

   if (gDebug > 0) {
      Info("FillDrawAttributes","line:   color:%d, style:%d, width:%d",
           fChain->GetLineColor(), fChain->GetLineStyle(), fChain->GetLineWidth());
      Info("FillDrawAttributes","marker: color:%d, style:%d, size:%f",
           fChain->GetMarkerColor(), fChain->GetMarkerStyle(), fChain->GetMarkerSize());
      Info("FillDrawAttributes","area:   color:%d, style:%d",
           fChain->GetFillColor(), fChain->GetFillStyle());
   }
}

////////////////////////////////////////////////////////////////////////////////
/// Forwards the execution to the dummy tree header.
/// See TTree::FindBranch().

TBranch *TProofChain::FindBranch(const char* branchname)
{
   return (fTree ? fTree->FindBranch(branchname) : (TBranch *)0);
}

////////////////////////////////////////////////////////////////////////////////
/// Forwards the execution to the dummy tree header.
/// See TTree::FindLeaf().

TLeaf *TProofChain::FindLeaf(const char* searchname)
{
   return (fTree ? fTree->FindLeaf(searchname) : (TLeaf *)0);
}

////////////////////////////////////////////////////////////////////////////////
/// Forwards the execution to the dummy tree header.
/// See TTree::GetBranch().

TBranch *TProofChain::GetBranch(const char *name)
{
   return (fTree ? fTree->GetBranch(name) : (TBranch *)0);
}

////////////////////////////////////////////////////////////////////////////////
/// Forwards the execution to the dummy tree header.
/// See TTree::GetBranchStatus().

Bool_t TProofChain::GetBranchStatus(const char *branchname) const
{
   return (fTree ? fTree->GetBranchStatus(branchname) : kFALSE);
}

////////////////////////////////////////////////////////////////////////////////
/// Forwards the execution to the dummy tree header.
/// See TTree::GetPlayer().

TVirtualTreePlayer *TProofChain::GetPlayer()
{
   return (fTree ? fTree->GetPlayer() : (TVirtualTreePlayer *)0);
}

////////////////////////////////////////////////////////////////////////////////
/// Forwards the execution to the TDSet.
/// The return value is -1 in case of error and TSelector::GetStatus() in
/// in case of success.
/// See TDSet::Process().

Long64_t TProofChain::Process(const char *filename, Option_t *option,
                              Long64_t nentries, Long64_t firstentry)
{
   // Set either the entry-list (priority) or the event-list
   if (fEntryList) {
      fSet->SetEntryList(fEntryList);
   } else if (fEventList) {
      fSet->SetEntryList(fEventList);
   }

   return fSet->Process(filename, option, nentries, firstentry);
}

////////////////////////////////////////////////////////////////////////////////
/// The return value is -1 in case of error and TSelector::GetStatus() in
/// in case of success.

Long64_t TProofChain::Process(TSelector *selector, Option_t *option,
                              Long64_t nentries, Long64_t firstentry)
{
   // Set either the entry-list (priority) or the event-list
   if (fEntryList) {
      fSet->SetEntryList(fEntryList);
   } else if (fEventList) {
      fSet->SetEntryList(fEventList);
   }

   return fSet->Process(selector, option, nentries, firstentry);
}

////////////////////////////////////////////////////////////////////////////////
/// See TTree::SetDebug

void TProofChain::SetDebug(Int_t level, Long64_t min, Long64_t max)
{
   TTree::SetDebug(level, min, max);
}

////////////////////////////////////////////////////////////////////////////////
/// See TTree::GetName.

void TProofChain::SetName(const char *name)
{
   TTree::SetName(name);
}

////////////////////////////////////////////////////////////////////////////////
/// Returns the total number of entries in the TProofChain, which is
/// the number of entries in the TDSet that it holds.

Long64_t TProofChain::GetEntries() const
{
   // this was used for holding the total number of entries
   if (TestBit(kProofLite)) {
      return (fTree ? fTree->GetEntries() : (Long64_t)(-1));
   } else {
      return (fTree ? fTree->GetMaxEntryLoop() : (Long64_t)(-1));
   }
}

////////////////////////////////////////////////////////////////////////////////
/// See TTree::GetEntries(const char *selection)
/// Not implemented in TProofChain. Shouldn't be used.

Long64_t TProofChain::GetEntries(const char *selection)
{
   if (TestBit(kProofLite)) {
      return (fTree ? fTree->GetEntries(selection) : (Long64_t)(-1));
   } else {
      Warning("GetEntries", "GetEntries(selection) not yet implemented");
      return ((Long64_t)(-1));
   }
}

////////////////////////////////////////////////////////////////////////////////
/// Changes the number of processed entries.

void TProofChain::Progress(Long64_t total, Long64_t processed)
{
   if (gROOT->IsInterrupted() && gProof)
      gProof->StopProcess(kTRUE);
   if (total) { }

   fReadEntry = processed;
}

////////////////////////////////////////////////////////////////////////////////
/// Returns the number of processed entries.

Long64_t TProofChain::GetReadEntry() const
{
   return fReadEntry;
}

////////////////////////////////////////////////////////////////////////////////
/// Releases PROOF. Disconnect the "progress" signal.

void TProofChain::ReleaseProof()
{
   if (!gProof)
      return;
   gProof->Disconnect("Progress(Long64_t,Long64_t)",
                      this, "Progress(Long64_t,Long64_t)");
}

////////////////////////////////////////////////////////////////////////////////
/// Connects the proof "Progress" signal.

void TProofChain::ConnectProof()
{
   if (gProof)
      gProof->Connect("Progress(Long64_t,Long64_t)", "TProofChain",
                       this, "Progress(Long64_t,Long64_t)");
}
<commit_msg>proof/proof: fix issues with TEntryList support in PROOF<commit_after>
// @(#)root/proof:$Id$
// Author: G. Ganis  Nov 2006

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

//////////////////////////////////////////////////////////////////////////
//                                                                      //
// TProofChain                                                          //
//                                                                      //
// A TChain proxy on PROOF.                                             //
// Uses an internal TDSet to handle processing.                         //
//                                                                      //
//////////////////////////////////////////////////////////////////////////

#include "TProofChain.h"
#include "TDSet.h"
#include "TList.h"
#include "TProof.h"
#include "TROOT.h"
#include "TEventList.h"
#include "TEntryList.h"

ClassImp(TProofChain)

////////////////////////////////////////////////////////////////////////////////
/// Crates a new PROOF chain proxy.

TProofChain::TProofChain() : TChain()
{
   fChain        = 0;
   fTree         = 0;
   fSet          = 0;
   fDirectory    = gDirectory;
   ResetBit(kOwnsChain);
}

////////////////////////////////////////////////////////////////////////////////
/// Crates a new PROOF chain proxy containing the files from the chain.

TProofChain::TProofChain(TChain *chain, Bool_t gettreeheader) : TChain()
{
   fChain        = chain;
   fTree         = 0;
   fSet          = chain ? new TDSet((const TChain &)(*chain)) : 0;
   fDirectory    = gDirectory;
   if (gProof) {
      gProof->AddChain(chain);
      ConnectProof();
      if (gProof->IsLite()) {
         SetBit(kProofLite);
         fTree = fChain;
      } else {
         if (gettreeheader && fSet)
            fTree = gProof->GetTreeHeader(fSet);
      }
   }
   ResetBit(kOwnsChain);
   fEntryList = (chain) ? chain->GetEntryList() : 0;
   fEventList = (chain) ? chain->GetEventList() : 0;
}

////////////////////////////////////////////////////////////////////////////////
/// Creates a new PROOF chain proxy containing the files from the dset.

TProofChain::TProofChain(TDSet *dset, Bool_t gettreeheader) : TChain()
{
   fChain        = 0;
   fTree         = 0;
   fSet          = dset;
   fDirectory    = gDirectory;
   if (gProof) {
      ConnectProof();
      if (gettreeheader && dset)
         fTree = gProof->GetTreeHeader(dset);
      if (gProof->IsLite())
         SetBit(kProofLite);
   }
   if (fTree && fSet) {
      fChain = new TChain(fTree->GetName());
      TIter nxe(fSet->GetListOfElements());
      TDSetElement *e = 0;
      while ((e = (TDSetElement *) nxe())) {
         fChain->AddFile(e->GetName());
      }
      SetBit(kOwnsChain);
      if (TestBit(kProofLite))
         fTree = fChain;
   }
   TObject *en = (dset) ? dset->GetEntryList() : 0;
   if (en) {
      if (en->InheritsFrom("TEntryList")) {
         fEntryList = (TEntryList *) en;
      }  else {
         fEventList = (TEventList *) en;
      }
   }
}

////////////////////////////////////////////////////////////////////////////////
/// Destructor.

TProofChain::~TProofChain()
{
   if (fChain) {
      SafeDelete(fSet);
      // Remove the chain from the private lists in the TProof objects
      TIter nxp(gROOT->GetListOfSockets());
      TObject *o = 0;
      TProof *p = 0;
      while ((o = nxp()))
         if ((p = dynamic_cast<TProof *>(o)))
            p->RemoveChain(fChain);
      if (fTree == fChain) fTree = 0;
      if (TestBit(kOwnsChain)) {
         SafeDelete(fChain);
      } else {
         fChain = 0;
      }
   } else {
      // Not owner
      fSet = 0;
   }
   SafeDelete(fTree);
   fDirectory    = 0;

}

////////////////////////////////////////////////////////////////////////////////
/// Forwards the execution to the dummy tree header.
/// See TTree::Browse().

void TProofChain::Browse(TBrowser *b)
{
   fSet->Browse(b);
}

////////////////////////////////////////////////////////////////////////////////
/// Forwards the execution to the TDSet.
/// Returns -1 in case of error or number of selected events in case of success.
/// See TDSet::Browse().

Long64_t TProofChain::Draw(const char *varexp, const TCut &selection,
                           Option_t *option, Long64_t nentries, Long64_t firstentry)
{
   if (!gProof) {
      Error("Draw", "no active PROOF session");
      return -1;
   }
   ConnectProof();

   fReadEntry = firstentry;

   // Set either the entry-list (priority) or the event-list
   if (fEntryList) {
      fSet->SetEntryList(fEntryList);
   } else if (fEventList) {
      fSet->SetEntryList(fEventList);
   } else {
      // Disable previous settings, if any
      fSet->SetEntryList(0);
   }

   // Fill drawing attributes
   FillDrawAttributes(gProof);

   // Add alias information, if any
   AddAliases();

   Long64_t rv = fSet->Draw(varexp, selection, option, nentries, firstentry);
   return rv;
}

////////////////////////////////////////////////////////////////////////////////
/// Forwards the execution to the TDSet.
/// Returns -1 in case of error or number of selected events in case of success.
/// See TDSet::Browse().

Long64_t TProofChain::Draw(const char *varexp, const char *selection,
                           Option_t *option,Long64_t nentries, Long64_t firstentry)
{
   if (!gProof) {
      Error("Draw", "no active PROOF session");
      return -1;
   }
   ConnectProof();

   fReadEntry = firstentry;

   // Set either the entry-list (priority) or the event-list
   if (fEntryList) {
      fSet->SetEntryList(fEntryList);
   } else if (fEventList) {
      fSet->SetEntryList(fEventList);
   } else {
      // Disable previous settings, if any
      fSet->SetEntryList(0);
   }

   // Fill drawing attributes
   FillDrawAttributes(gProof);

   // Add alias information, if any
   AddAliases();

   Long64_t rv = fSet->Draw(varexp, selection, option, nentries, firstentry);
   return rv;
}

////////////////////////////////////////////////////////////////////////////////
/// Aliases are added to the input list. The names are comma-separated in the
/// TNamed 'PROOF_ListOfAliases'. For each name, there is an trey named 'alias:<name>'.

void TProofChain::AddAliases()
{
   TList *al = fChain->GetListOfAliases();
   if (al && al->GetSize() > 0) {
      TIter nxa(al);
      TNamed *nm = 0, *nmo = 0;
      TString names, nma;
      while ((nm = (TNamed *)nxa())) {
         names += nm->GetName();
         names += ",";
         nma.Form("alias:%s", nm->GetName());
         nmo = (TNamed *)((gProof->GetInputList()) ? gProof->GetInputList()->FindObject(nma) : 0);
         if (nmo) {
            nmo->SetTitle(nm->GetTitle());
         } else {
            gProof->AddInput(new TNamed(nma.Data(), nm->GetTitle()));
         }
      }
      nmo = (TNamed *)((gProof->GetInputList()) ? gProof->GetInputList()->FindObject("PROOF_ListOfAliases") : 0);
      if (nmo) {
         nmo->SetTitle(names.Data());
      } else {
         gProof->AddInput(new TNamed("PROOF_ListOfAliases", names.Data()));
      }
   }
}

////////////////////////////////////////////////////////////////////////////////
/// Communicate the drawing attributes for this chain to the input list
/// so that the draw selectors can use them, in case of need.
/// The drawing attributes are:
///
///    LineColor          Line color
///    LineStyle          Line style
///    LineWidth          Line width
///    MarkerColor        Marker color index
///    MarkerSize         Marker size
///    MarkerStyle        Marker style
///    FillColor          Area fill color
///    FillStyle          Area fill style

void TProofChain::FillDrawAttributes(TProof *p)
{
   if (!p || !fChain) {
      Error("FillDrawAttributes", "invalid PROOF or mother chain pointers!");
      return;
   }

   // Weight
   p->SetParameter("PROOF_ChainWeight", fChain->GetWeight());

   // Line Attributes
   p->SetParameter("PROOF_LineColor", (Int_t) fChain->GetLineColor());
   p->SetParameter("PROOF_LineStyle", (Int_t) fChain->GetLineStyle());
   p->SetParameter("PROOF_LineWidth", (Int_t) fChain->GetLineWidth());

   // Marker Attributes
   p->SetParameter("PROOF_MarkerColor", (Int_t) fChain->GetMarkerColor());
   p->SetParameter("PROOF_MarkerSize", (Int_t) fChain->GetMarkerSize()*1000);
   p->SetParameter("PROOF_MarkerStyle", (Int_t) fChain->GetMarkerStyle());

   // Area fill attributes
   p->SetParameter("PROOF_FillColor", (Int_t) fChain->GetFillColor());
   p->SetParameter("PROOF_FillStyle", (Int_t) fChain->GetFillStyle());

   if (gDebug > 0) {
      Info("FillDrawAttributes","line:   color:%d, style:%d, width:%d",
           fChain->GetLineColor(), fChain->GetLineStyle(), fChain->GetLineWidth());
      Info("FillDrawAttributes","marker: color:%d, style:%d, size:%f",
           fChain->GetMarkerColor(), fChain->GetMarkerStyle(), fChain->GetMarkerSize());
      Info("FillDrawAttributes","area:   color:%d, style:%d",
           fChain->GetFillColor(), fChain->GetFillStyle());
   }
}

////////////////////////////////////////////////////////////////////////////////
/// Forwards the execution to the dummy tree header.
/// See TTree::FindBranch().

TBranch *TProofChain::FindBranch(const char* branchname)
{
   return (fTree ? fTree->FindBranch(branchname) : (TBranch *)0);
}

////////////////////////////////////////////////////////////////////////////////
/// Forwards the execution to the dummy tree header.
/// See TTree::FindLeaf().

TLeaf *TProofChain::FindLeaf(const char* searchname)
{
   return (fTree ? fTree->FindLeaf(searchname) : (TLeaf *)0);
}

////////////////////////////////////////////////////////////////////////////////
/// Forwards the execution to the dummy tree header.
/// See TTree::GetBranch().

TBranch *TProofChain::GetBranch(const char *name)
{
   return (fTree ? fTree->GetBranch(name) : (TBranch *)0);
}

////////////////////////////////////////////////////////////////////////////////
/// Forwards the execution to the dummy tree header.
/// See TTree::GetBranchStatus().

Bool_t TProofChain::GetBranchStatus(const char *branchname) const
{
   return (fTree ? fTree->GetBranchStatus(branchname) : kFALSE);
}

////////////////////////////////////////////////////////////////////////////////
/// Forwards the execution to the dummy tree header.
/// See TTree::GetPlayer().

TVirtualTreePlayer *TProofChain::GetPlayer()
{
   return (fTree ? fTree->GetPlayer() : (TVirtualTreePlayer *)0);
}

////////////////////////////////////////////////////////////////////////////////
/// Forwards the execution to the TDSet.
/// The return value is -1 in case of error and TSelector::GetStatus() in
/// in case of success.
/// See TDSet::Process().

Long64_t TProofChain::Process(const char *filename, Option_t *option,
                              Long64_t nentries, Long64_t firstentry)
{
   // Set either the entry-list (priority) or the event-list
   TObject *enl = 0;
   if (fEntryList) {
      enl = fEntryList;
   } else if (fEventList) {
      enl = fEventList;
   }

   return fSet->Process(filename, option, nentries, firstentry, enl);
}

////////////////////////////////////////////////////////////////////////////////
/// The return value is -1 in case of error and TSelector::GetStatus() in
/// in case of success.

Long64_t TProofChain::Process(TSelector *selector, Option_t *option,
                              Long64_t nentries, Long64_t firstentry)
{
   // Set either the entry-list (priority) or the event-list
   TObject *enl = 0;
   if (fEntryList) {
      enl = fEntryList;
   } else if (fEventList) {
      enl = fEventList;
   }

   return fSet->Process(selector, option, nentries, firstentry, enl);
}

////////////////////////////////////////////////////////////////////////////////
/// See TTree::SetDebug

void TProofChain::SetDebug(Int_t level, Long64_t min, Long64_t max)
{
   TTree::SetDebug(level, min, max);
}

////////////////////////////////////////////////////////////////////////////////
/// See TTree::GetName.

void TProofChain::SetName(const char *name)
{
   TTree::SetName(name);
}

////////////////////////////////////////////////////////////////////////////////
/// Returns the total number of entries in the TProofChain, which is
/// the number of entries in the TDSet that it holds.

Long64_t TProofChain::GetEntries() const
{
   // this was used for holding the total number of entries
   if (TestBit(kProofLite)) {
      return (fTree ? fTree->GetEntries() : (Long64_t)(-1));
   } else {
      return (fTree ? fTree->GetMaxEntryLoop() : (Long64_t)(-1));
   }
}

////////////////////////////////////////////////////////////////////////////////
/// See TTree::GetEntries(const char *selection)
/// Not implemented in TProofChain. Shouldn't be used.

Long64_t TProofChain::GetEntries(const char *selection)
{
   if (TestBit(kProofLite)) {
      return (fTree ? fTree->GetEntries(selection) : (Long64_t)(-1));
   } else {
      Warning("GetEntries", "GetEntries(selection) not yet implemented");
      return ((Long64_t)(-1));
   }
}

////////////////////////////////////////////////////////////////////////////////
/// Changes the number of processed entries.

void TProofChain::Progress(Long64_t total, Long64_t processed)
{
   if (gROOT->IsInterrupted() && gProof)
      gProof->StopProcess(kTRUE);
   if (total) { }

   fReadEntry = processed;
}

////////////////////////////////////////////////////////////////////////////////
/// Returns the number of processed entries.

Long64_t TProofChain::GetReadEntry() const
{
   return fReadEntry;
}

////////////////////////////////////////////////////////////////////////////////
/// Releases PROOF. Disconnect the "progress" signal.

void TProofChain::ReleaseProof()
{
   if (!gProof)
      return;
   gProof->Disconnect("Progress(Long64_t,Long64_t)",
                      this, "Progress(Long64_t,Long64_t)");
}

////////////////////////////////////////////////////////////////////////////////
/// Connects the proof "Progress" signal.

void TProofChain::ConnectProof()
{
   if (gProof)
      gProof->Connect("Progress(Long64_t,Long64_t)", "TProofChain",
                       this, "Progress(Long64_t,Long64_t)");
}
<|endoftext|>


<commit_before>/** Copyright (C) 2016, 2017 European Spallation Source ERIC */

#include <algorithm>
#include <arpa/inet.h>
#include <cassert>
#include <cinttypes>
#include <cstring>
#include <tools/ReaderPcap.h>
#include <netinet/ip.h>
#include <netinet/udp.h>
#include <fmt/format.h>

// GCOVR_EXCL_START

// Protocol identifiers
#define ETHERTYPE_ARP    0x0806
#define ETHERTYPE_IPV4   0x0800
#define IPPROTO_UDP          17
// Header and data location specifications
#define ETHERTYPE_OFFSET     12
#define ETHERNET_HEADER_SIZE 14
#define IP_HEADR_OFFSET      14
#define IP_HEADER_SIZE       20
#define UDP_HEADER_OFFSET    34
#define UDP_HEADER_SIZE       8
#define UDP_DATA_OFFSET      42

ReaderPcap::ReaderPcap(std::string filename)
  : FileName(filename) {
  memset(&Stats, 0, sizeof(struct stats_t));
}

ReaderPcap::~ReaderPcap() {
  if (PcapHandle != NULL ) {
    pcap_close(PcapHandle);
  }
}

int ReaderPcap::open() {
  char errbuff[PCAP_ERRBUF_SIZE];
  PcapHandle = pcap_open_offline(FileName.c_str(), errbuff);
  if (PcapHandle == NULL) {
    return -1;
  }
  return 0;
}

int ReaderPcap::validatePacket(struct pcap_pkthdr *header, const unsigned char *data) {
  Stats.PacketsTotal++; /**< total packets in pcap file */
  Stats.BytesTotal += header->len;

  if (header->len != header->caplen) {
    Stats.PacketsTruncated++;
    return 0;
  }

  uint16_t type = ntohs(*(uint16_t *)&data[ETHERTYPE_OFFSET]);
  // printf("packet header len %d, type %x\n", header->len, type);

  if (type == ETHERTYPE_ARP) {
    Stats.EtherTypeArp++;
  } else if (type == ETHERTYPE_IPV4) {
    Stats.EtherTypeIpv4++;
  } else {
    Stats.EtherTypeUnknown++;
  }

  if (type != ETHERTYPE_IPV4) { // must be ipv4
    return 0;
  }

  struct ip *ip = (struct ip *)&data[IP_HEADR_OFFSET];

  // IPv4 header length must be 20, ip version 4, ipproto must be UDP
  if ((ip->ip_hl != 5) or (ip->ip_v != 4) or (ip->ip_p != IPPROTO_UDP)) {
    Stats.IpProtoUnknown++;
    return 0;
  }
  Stats.IpProtoUDP++;

  assert(header->len > ETHERNET_HEADER_SIZE + IP_HEADER_SIZE + UDP_HEADER_SIZE);
  assert(Stats.PacketsTotal == Stats.EtherTypeIpv4 + Stats.EtherTypeArp + Stats.EtherTypeUnknown);
  assert(Stats.EtherTypeIpv4 == Stats.IpProtoUDP + Stats.IpProtoUnknown);

  struct udphdr *udp = (struct udphdr *)&data[UDP_HEADER_OFFSET];
  #ifndef __FAVOR_BSD // Why is __FAVOR_BSD not defined here?
  uint16_t UdpLen = htons(udp->len);
  #else
  uint16_t UdpLen = htons(udp->uh_ulen);
  #endif
  assert(UdpLen >= UDP_HEADER_SIZE);

  #if 0
  printf("UDP Payload, Packet %" PRIu64 ", time: %d:%d seconds, size: %d bytes\n",
       Stats.PacketsTotal, (int)header->ts.tv_sec, (int)header->ts.tv_usec,
       (int)header->len);
  printf("ip src->dest: 0x%08x:%d ->0x%08x:%d\n",
         ntohl(*(uint32_t*)&ip->ip_src), ntohs(udp->uh_sport),
         ntohl(*(uint32_t*)&ip->ip_dst), ntohs(udp->uh_dport));
  #endif

  return UdpLen;
}

int ReaderPcap::read(char *buffer, size_t bufferlen) {
  if (PcapHandle == nullptr) {
    return -1;
  }

  struct pcap_pkthdr *Header;
  const unsigned char *Data;
  int ret = pcap_next_ex(PcapHandle, &Header, &Data);
  if (ret < 0) {
    return -1;
  }

  int UdpDataLength;
  if ((UdpDataLength = validatePacket(Header, Data)) <= 0) {
    return UdpDataLength;
  }

  auto DataLength = std::min((size_t)(UdpDataLength - UDP_HEADER_SIZE), bufferlen);
  std::memcpy(buffer, &Data[UDP_DATA_OFFSET], DataLength);

  return DataLength;
}

int ReaderPcap::getStats() {
  if (PcapHandle == NULL) {
    return -1;
  }

  while (true) {
    int RetVal;
    struct pcap_pkthdr *Header;
    const unsigned char *Data;
    if ((RetVal = pcap_next_ex(PcapHandle, &Header, &Data))  < 0) {
      break;
    }
    validatePacket(Header, Data);
  }
  return 0;
}

void ReaderPcap::printPacket(unsigned char *data, size_t len) {
  for (unsigned int i = 0; i < len; i++) {
    if ((i % 16) == 0 && i != 0) {
      printf("\n");
    }
    printf("%.2x ", data[i]);
  }
  printf("\n");
}

void ReaderPcap::printStats() {
  printf("Total packets        %" PRIu64 "\n", Stats.PacketsTotal);
  printf("Truncated packets    %" PRIu64 "\n", Stats.PacketsTruncated);
  printf("Ethertype IPv4       %" PRIu64 "\n", Stats.EtherTypeIpv4);
  printf("  ipproto UDP        %" PRIu64 "\n", Stats.IpProtoUDP);
  printf("  ipproto other      %" PRIu64 "\n", Stats.IpProtoUnknown);
  printf("Ethertype unknown    %" PRIu64 "\n", Stats.EtherTypeUnknown);
  printf("Ethertype ARP        %" PRIu64 "\n", Stats.EtherTypeArp);
  printf("Total bytes          %" PRIu64 "\n", Stats.BytesTotal);

}
// GCOVR_EXCL_STOP
<commit_msg>Update prototype2/tools/ReaderPcap.cpp<commit_after>/** Copyright (C) 2016, 2017 European Spallation Source ERIC */

#include <algorithm>
#include <arpa/inet.h>
#include <cassert>
#include <cinttypes>
#include <cstring>
#include <tools/ReaderPcap.h>
#include <netinet/ip.h>
#include <netinet/udp.h>
#include <fmt/format.h>

// GCOVR_EXCL_START

// Protocol identifiers
const int ETHERTYPE_ARP = 0x0806;
#define ETHERTYPE_IPV4   0x0800
#define IPPROTO_UDP          17
// Header and data location specifications
#define ETHERTYPE_OFFSET     12
#define ETHERNET_HEADER_SIZE 14
#define IP_HEADR_OFFSET      14
#define IP_HEADER_SIZE       20
#define UDP_HEADER_OFFSET    34
#define UDP_HEADER_SIZE       8
#define UDP_DATA_OFFSET      42

ReaderPcap::ReaderPcap(std::string filename)
  : FileName(filename) {
  memset(&Stats, 0, sizeof(struct stats_t));
}

ReaderPcap::~ReaderPcap() {
  if (PcapHandle != NULL ) {
    pcap_close(PcapHandle);
  }
}

int ReaderPcap::open() {
  char errbuff[PCAP_ERRBUF_SIZE];
  PcapHandle = pcap_open_offline(FileName.c_str(), errbuff);
  if (PcapHandle == NULL) {
    return -1;
  }
  return 0;
}

int ReaderPcap::validatePacket(struct pcap_pkthdr *header, const unsigned char *data) {
  Stats.PacketsTotal++; /**< total packets in pcap file */
  Stats.BytesTotal += header->len;

  if (header->len != header->caplen) {
    Stats.PacketsTruncated++;
    return 0;
  }

  uint16_t type = ntohs(*(uint16_t *)&data[ETHERTYPE_OFFSET]);
  // printf("packet header len %d, type %x\n", header->len, type);

  if (type == ETHERTYPE_ARP) {
    Stats.EtherTypeArp++;
  } else if (type == ETHERTYPE_IPV4) {
    Stats.EtherTypeIpv4++;
  } else {
    Stats.EtherTypeUnknown++;
  }

  if (type != ETHERTYPE_IPV4) { // must be ipv4
    return 0;
  }

  struct ip *ip = (struct ip *)&data[IP_HEADR_OFFSET];

  // IPv4 header length must be 20, ip version 4, ipproto must be UDP
  if ((ip->ip_hl != 5) or (ip->ip_v != 4) or (ip->ip_p != IPPROTO_UDP)) {
    Stats.IpProtoUnknown++;
    return 0;
  }
  Stats.IpProtoUDP++;

  assert(header->len > ETHERNET_HEADER_SIZE + IP_HEADER_SIZE + UDP_HEADER_SIZE);
  assert(Stats.PacketsTotal == Stats.EtherTypeIpv4 + Stats.EtherTypeArp + Stats.EtherTypeUnknown);
  assert(Stats.EtherTypeIpv4 == Stats.IpProtoUDP + Stats.IpProtoUnknown);

  struct udphdr *udp = (struct udphdr *)&data[UDP_HEADER_OFFSET];
  #ifndef __FAVOR_BSD // Why is __FAVOR_BSD not defined here?
  uint16_t UdpLen = htons(udp->len);
  #else
  uint16_t UdpLen = htons(udp->uh_ulen);
  #endif
  assert(UdpLen >= UDP_HEADER_SIZE);

  #if 0
  printf("UDP Payload, Packet %" PRIu64 ", time: %d:%d seconds, size: %d bytes\n",
       Stats.PacketsTotal, (int)header->ts.tv_sec, (int)header->ts.tv_usec,
       (int)header->len);
  printf("ip src->dest: 0x%08x:%d ->0x%08x:%d\n",
         ntohl(*(uint32_t*)&ip->ip_src), ntohs(udp->uh_sport),
         ntohl(*(uint32_t*)&ip->ip_dst), ntohs(udp->uh_dport));
  #endif

  return UdpLen;
}

int ReaderPcap::read(char *buffer, size_t bufferlen) {
  if (PcapHandle == nullptr) {
    return -1;
  }

  struct pcap_pkthdr *Header;
  const unsigned char *Data;
  int ret = pcap_next_ex(PcapHandle, &Header, &Data);
  if (ret < 0) {
    return -1;
  }

  int UdpDataLength;
  if ((UdpDataLength = validatePacket(Header, Data)) <= 0) {
    return UdpDataLength;
  }

  auto DataLength = std::min((size_t)(UdpDataLength - UDP_HEADER_SIZE), bufferlen);
  std::memcpy(buffer, &Data[UDP_DATA_OFFSET], DataLength);

  return DataLength;
}

int ReaderPcap::getStats() {
  if (PcapHandle == NULL) {
    return -1;
  }

  while (true) {
    int RetVal;
    struct pcap_pkthdr *Header;
    const unsigned char *Data;
    if ((RetVal = pcap_next_ex(PcapHandle, &Header, &Data))  < 0) {
      break;
    }
    validatePacket(Header, Data);
  }
  return 0;
}

void ReaderPcap::printPacket(unsigned char *data, size_t len) {
  for (unsigned int i = 0; i < len; i++) {
    if ((i % 16) == 0 && i != 0) {
      printf("\n");
    }
    printf("%.2x ", data[i]);
  }
  printf("\n");
}

void ReaderPcap::printStats() {
  printf("Total packets        %" PRIu64 "\n", Stats.PacketsTotal);
  printf("Truncated packets    %" PRIu64 "\n", Stats.PacketsTruncated);
  printf("Ethertype IPv4       %" PRIu64 "\n", Stats.EtherTypeIpv4);
  printf("  ipproto UDP        %" PRIu64 "\n", Stats.IpProtoUDP);
  printf("  ipproto other      %" PRIu64 "\n", Stats.IpProtoUnknown);
  printf("Ethertype unknown    %" PRIu64 "\n", Stats.EtherTypeUnknown);
  printf("Ethertype ARP        %" PRIu64 "\n", Stats.EtherTypeArp);
  printf("Total bytes          %" PRIu64 "\n", Stats.BytesTotal);

}
// GCOVR_EXCL_STOP
<|endoftext|>


<commit_before>/*

  Lempel-Ziv-Welch (encoder)
  lossless data compression algorithm, dictionary coder

  The main function takes as argument
  arg1: input file name, this shall be an ASCII-only textfile.
  arg2: [optional] file name of the input alphabet.

  It then writes the following files:
  fout1: output file name: see fname1,
         specifies the output, after applying LZW. It
	 only contains '0' and '1'.
  fout2: output file name: see fname2,
         the alphabet read from the file specified by arg2
         (if provided).
  fout3: output file name: see fname3,
         C code for a 2D C string specifying the alphabet.

*/

#include <cstdio>
#include <iostream>
#include <string>
#include <stack>
#include <map>
#include <vector>
#include <utility>
#define DEBUG_PRINTF 0
const char fname1[] = "LZW_encoded.txt";
const char fname2[] = "LZW_alphabet.txt";
const char fname3[] = "LZW_alphabet_C.txt";
using std::map;
using std::vector;
using std::string;
using std::stack;
using std::pair;
using std::make_pair;

// return the number of bits integer x contains
int num_bits(int x) {
  int bits = 0;
  while (x > 0) {
    x /= 2;
    bits++;
  }
  return bits;
}

// A = {a_1, ..., a_alen} alphabet, as an array of chars
//   it is assumed that 0 <= a_i <= n-1 and all a_i are
//   distinct, A is terminated with a '0' (C string)
// S = {s_1, ..., s_n} input char string, null terminated
// C = {c_1, ..., c_m} output binary sequence
void LZW(char* A, char* S, vector<bool>& C) {
  int alen = strlen(A), slen = strlen(S);
  int entries = alen;
  // M = (u_i, v_i) LZW extended dictionary, map string u_i
  //     to code number v_i
  map<string, int> MSI;
  map<int, string> MIS; // reverse mapping
  MSI.clear();
  MIS.clear();
  // initialize the dictionary to contain all strings of
  // length one
  for (int i = 0; i < alen; i++) {
    string tempchar(A+i, A+i+1);
    MIS.insert(make_pair(i, tempchar));
    MSI.insert(make_pair(tempchar, i));
  }

  C.clear();
  for (int i = 0; i < slen; i++) {
    // find the longest string W in the dictionary that
    // matches the current input
    string curr(S+i, S+i+1);
    int found = -1;
    while (MSI.find(curr) != MSI.end() && S[i] != '\0') {
      found = MSI[curr];
      curr += S[++i];
    }
    i--;
    printf("found: %d (%s) ", found, MIS[found].c_str());
    if (S[i+1] != 0) {
      MSI[curr] = entries;
      MIS[entries] = curr;
    }
    // transform "found" to binary and save to output
    // this binary number needs to have log_2(entries) (rounded
    // down) digits
    if (found != -1) {
      printf("[");
      for (int j = num_bits(entries-1) - 1; j >= 0; j--) {
	C.push_back((found >> j)&1);
	printf("%d", (found >> j)&1);
      }
      printf("]\n");

      // debug
      if (S[i+1] != 0) {
	printf("new entry %d: %s\n", entries, curr.c_str());
	entries++;
      }

    }
  }

  printf("\nDictionary\n");
  for (map<int, string>::iterator it  = MIS.begin(); it != MIS.end(); it++) {
    printf("%3d: %s\n", it->first, it->second.c_str());
  }
}

int main(int argc, char** argv) {
  if (argc > 3 || argc <= 1) {
    fprintf(stderr, "Wrong number of arguments specified.\n");
    return 1;
  }

  FILE *fin1 = fopen(argv[1], "r");

  if (fin1 == NULL) {
    fprintf(stderr, "Input file %s could not be opened.\n", argv[1]);
    return 1;
  }

  FILE *fin2 = fopen(argv[2], "r");
  if (argc >= 3) {
    if (fin2 == NULL) {
      fprintf(stderr, "Input file %s could not be opened.\n", argv[2]);
      return 1;
    }
  }

  FILE *fout1 = fopen(fname1, "w");
  FILE *fout2 = fopen(fname2, "w");
  FILE *fout3 = fopen(fname3, "w");

  // read input
  char S[1000000];
  fread(S, sizeof(char), sizeof(S), fin1);

  // read alphabet
  char A[100000];
  int alen;
  if (argc >= 3) {
    fread(A, sizeof(char), sizeof(A), fin2);
    alen = strlen(A);
  }
  else {
    // generate alphabet
    alen = 0;
    bool B[256];
    memset(B, 0, sizeof(B));
    int slen = strlen(S);
    for (int i = 0; i < slen; i++)
      B[(int) S[i]] = true;

    for (int i = 0; i < 256; i++)
      if (B[i])
	A[alen++] = (char) i;
  }

  printf("The alphabet: ");
  for (int i = 0; i < alen; i++) {
    printf("%c", A[i]);
    if (i != alen-1)
      printf(", ");
    else
      printf("\n");
  }

  printf("Lempel-Ziv-Welch...\n");
  vector<bool> C;
  LZW(A, S, C);

  // print output
  for (vector<bool>::iterator it = C.begin(); it != C.end(); it++) {
    printf("%c", '0' + *it );
  }
  printf("\n");

  // fout1
  for (vector<bool>::iterator it = C.begin(); it != C.end(); it++) {
    fprintf(fout1, "%c", '0' + *it );
  }

  // fout2
  fprintf(fout2, "%s", A);

  // fout3
  fprintf(fout3, "char A[]=\"");
  for (int i = 0; i < alen; i++) {
    fprintf(fout3, "%c", A[i]);
  }
  fprintf(fout3, "\";\n");
}
<commit_msg>Even more formatting changes in LZW README.<commit_after>/*
  Lempel-Ziv-Welch (encoder)
  lossless data compression algorithm, dictionary coder

  The main function takes as argument
  arg1: input file name, this shall be an ASCII-only textfile.
  arg2: [optional] file name of the input alphabet.

  It then writes the following files:
  fout1: output file name: see fname1,
         specifies the output, after applying LZW. It
	 only contains '0' and '1'.
  fout2: output file name: see fname2,
         the alphabet read from the file specified by arg2
         (if provided).
  fout3: output file name: see fname3,
         C code for a 2D C string specifying the alphabet.

*/

#include <cstdio>
#include <iostream>
#include <string>
#include <stack>
#include <map>
#include <vector>
#include <utility>
#define DEBUG_PRINTF 0
const char fname1[] = "LZW_encoded.txt";
const char fname2[] = "LZW_alphabet.txt";
const char fname3[] = "LZW_alphabet_C.txt";
using std::map;
using std::vector;
using std::string;
using std::stack;
using std::pair;
using std::make_pair;

// return the number of bits integer x contains
int num_bits(int x) {
  int bits = 0;
  while (x > 0) {
    x /= 2;
    bits++;
  }
  return bits;
}

// A = {a_1, ..., a_alen} alphabet, as an array of chars
//   it is assumed that 0 <= a_i <= n-1 and all a_i are
//   distinct, A is terminated with a '0' (C string)
// S = {s_1, ..., s_n} input char string, null terminated
// C = {c_1, ..., c_m} output binary sequence
void LZW(char* A, char* S, vector<bool>& C) {
  int alen = strlen(A), slen = strlen(S);
  int entries = alen;
  // M = (u_i, v_i) LZW extended dictionary, map string u_i
  //     to code number v_i
  map<string, int> MSI;
  map<int, string> MIS; // reverse mapping
  MSI.clear();
  MIS.clear();
  // initialize the dictionary to contain all strings of
  // length one
  for (int i = 0; i < alen; i++) {
    string tempchar(A+i, A+i+1);
    MIS.insert(make_pair(i, tempchar));
    MSI.insert(make_pair(tempchar, i));
  }

  C.clear();
  for (int i = 0; i < slen; i++) {
    // find the longest string W in the dictionary that
    // matches the current input
    string curr(S+i, S+i+1);
    int found = -1;
    while (MSI.find(curr) != MSI.end() && S[i] != '\0') {
      found = MSI[curr];
      curr += S[++i];
    }
    i--;
    printf("found: %d (%s) ", found, MIS[found].c_str());
    if (S[i+1] != 0) {
      MSI[curr] = entries;
      MIS[entries] = curr;
    }
    // transform "found" to binary and save to output
    // this binary number needs to have log_2(entries) (rounded
    // down) digits
    if (found != -1) {
      printf("[");
      for (int j = num_bits(entries-1) - 1; j >= 0; j--) {
	C.push_back((found >> j)&1);
	printf("%d", (found >> j)&1);
      }
      printf("]\n");

      // debug
      if (S[i+1] != 0) {
	printf("new entry %d: %s\n", entries, curr.c_str());
	entries++;
      }

    }
  }

  printf("\nDictionary\n");
  for (map<int, string>::iterator it  = MIS.begin(); it != MIS.end(); it++) {
    printf("%3d: %s\n", it->first, it->second.c_str());
  }
}

int main(int argc, char** argv) {
  if (argc > 3 || argc <= 1) {
    fprintf(stderr, "Wrong number of arguments specified.\n");
    return 1;
  }

  FILE *fin1 = fopen(argv[1], "r");

  if (fin1 == NULL) {
    fprintf(stderr, "Input file %s could not be opened.\n", argv[1]);
    return 1;
  }

  FILE *fin2 = fopen(argv[2], "r");
  if (argc >= 3) {
    if (fin2 == NULL) {
      fprintf(stderr, "Input file %s could not be opened.\n", argv[2]);
      return 1;
    }
  }

  FILE *fout1 = fopen(fname1, "w");
  FILE *fout2 = fopen(fname2, "w");
  FILE *fout3 = fopen(fname3, "w");

  // read input
  char S[1000000];
  fread(S, sizeof(char), sizeof(S), fin1);

  // read alphabet
  char A[100000];
  int alen;
  if (argc >= 3) {
    fread(A, sizeof(char), sizeof(A), fin2);
    alen = strlen(A);
  }
  else {
    // generate alphabet
    alen = 0;
    bool B[256];
    memset(B, 0, sizeof(B));
    int slen = strlen(S);
    for (int i = 0; i < slen; i++)
      B[(int) S[i]] = true;

    for (int i = 0; i < 256; i++)
      if (B[i])
	A[alen++] = (char) i;
  }

  printf("The alphabet: ");
  for (int i = 0; i < alen; i++) {
    printf("%c", A[i]);
    if (i != alen-1)
      printf(", ");
    else
      printf("\n");
  }

  printf("Lempel-Ziv-Welch...\n");
  vector<bool> C;
  LZW(A, S, C);

  // print output
  for (vector<bool>::iterator it = C.begin(); it != C.end(); it++) {
    printf("%c", '0' + *it );
  }
  printf("\n");

  // fout1
  for (vector<bool>::iterator it = C.begin(); it != C.end(); it++) {
    fprintf(fout1, "%c", '0' + *it );
  }

  // fout2
  fprintf(fout2, "%s", A);

  // fout3
  fprintf(fout3, "char A[]=\"");
  for (int i = 0; i < alen; i++) {
    fprintf(fout3, "%c", A[i]);
  }
  fprintf(fout3, "\";\n");
}
<|endoftext|>