<commit_before>/**
 * @file
 *
 * @brief Write key sets using yaml-cpp
 *
 * @copyright BSD License (see LICENSE.md or https://www.libelektra.org)
 */

#include "write.hpp"
#include "log.hpp"
#include "yaml-cpp/yaml.h"

#include <kdb.hpp>
#include <kdbease.h>
#include <kdblogger.h>

#include <fstream>
#include <stack>

namespace
{

using std::endl;
using std::istringstream;
using std::ofstream;
using std::ostringstream;
using std::pair;
using std::stack;
using std::string;

using kdb::Key;
using kdb::KeySet;
using kdb::NameIterator;
using KeySetPair = pair<KeySet, KeySet>;

/**
 * @brief This function determines all keys “missing” from the given keyset.
 *
 * The term “missing” refers to keys that are not part of the hierarchy. For example in a key set with the parent key
 *
 *  - `user/parent`
 *
 * that contains the keys
 *
 * - `user/parent/level1/level2`, and
 * - `user/parent/level1/level2/level3/level4`
 *
 * , the keys
 *
 * - `user/parent/level1`, and
 * - `user/parent/level1/level2/level3`
 *
 * are missing.
 *
 * @param keys This parameter contains the key set for which this function determines missing keys.
 * @param parent This value stores the parent key of `keys`.
 *
 * @return A key set that contains all keys missing from `keys`
 */
KeySet missingKeys (KeySet const & keys, Key const & parent)
{
	KeySet missing;

	keys.rewind ();
	Key previous{ parent.getName (), KEY_BINARY, KEY_END };
	for (; keys.next (); previous = keys.current ())
	{
		if (keys.current ().isDirectBelow (previous) || !keys.current ().isBelow (previous)) continue;

		Key current{ keys.current ().getName (), KEY_BINARY, KEY_END };
		while (!current.isDirectBelow (previous))
		{
			ckdb::keySetBaseName (*current, NULL);
			missing.append (current);
			current = current.dup ();
		}
	}

#ifdef HAVE_LOGGER
	ELEKTRA_LOG_DEBUG ("Add missing keys:");
	logKeySet (missing);
#endif

	return missing;
}

/**
 * @brief This function returns a `NameIterator` starting at the first level that is not part of `parent`.
 *
 * @pre The parameter `key` must be a child of `parent`.
 *
 * @param key This is the key for which this function returns a relative iterator.
 * @param parent This key specifies the part of the name iterator that will not be part of the return value of this function.
 *
 * @returns A relative iterator that starts with the first part of the name of `key` not contained in `parent`.
 */
NameIterator relativeKeyIterator (Key const & key, Key const & parent)
{
	auto parentIterator = parent.begin ();
	auto keyIterator = key.begin ();
	while (parentIterator != parent.end () && keyIterator != key.end ())
	{
		parentIterator++;
		keyIterator++;
	}
	return keyIterator;
}

/**
 * @brief This function returns the array index for a given key part.
 *
 * @param nameIterator This iterator specifies the name of the key.
 *
 * @retval The index of the array element, or `0` if the given key part is not an array element.
 */
unsigned long long getArrayIndex (NameIterator const & nameIterator)
{
	string const name = *nameIterator;
	auto const offsetIndex = ckdb::elektraArrayValidateBaseNameString (name.c_str ());
	auto const isArrayElement = offsetIndex >= 1;
	return isArrayElement ? stoull (name.substr (static_cast<size_t> (offsetIndex))) : 0;
}

/**
 * @brief This function creates a YAML node representing a key value.
 *
 * @param key This key specifies the data that should be saved in the YAML node returned by this function.
 *
 * @note Since YAML does not support non-empty binary data directly this function replaces data stored in binary keys with the string
 *       `Unsupported binary value!`. If you need support for binary data, please load the Base64 plugin before you use YAML CPP.
 *
 * @returns A new YAML node containing the data specified in `key`
 */
YAML::Node createNode (Key const & key)
{
	if (key.hasMeta ("array"))
	{
		return YAML::Node (YAML::NodeType::Sequence);
	}
	if (key.getBinarySize () == 0)
	{
		return YAML::Node (YAML::NodeType::Null);
	}
	if (key.isBinary ())
	{
		return YAML::Node ("Unsupported binary value!");
	}

	auto value = key.get<string> ();
	if (value == "0" || value == "1")
	{
		return YAML::Node (key.get<bool> ());
	}
	return YAML::Node (value);
}

/**
 * @brief This function creates a YAML Node containing a key value and optionally metadata.
 *
 * @param key This key specifies the data that should be saved in the YAML node returned by this function.
 *
 * @note Since YAML does not support non-empty binary data directly this function replaces data stored in binary keys with the string
 *       `Unsupported binary value!`. If you need support for binary data, please load the Base64 before you use YAML CPP.
 *
 * @returns A new YAML node containing the data and metadata specified in `key`
 */
YAML::Node createLeafNode (Key & key)
{

	YAML::Node metaNode{ YAML::Node (YAML::NodeType::Map) };
	YAML::Node dataNode = createNode (key);

	key.rewindMeta ();
	while (Key meta = key.nextMeta ())
	{
		if (meta.getName () == "array" || meta.getName () == "binary") continue;
		if (meta.getName () == "type" && meta.getString () == "binary")
		{
			dataNode.SetTag ("tag:yaml.org,2002:binary");
			continue;
		}
		metaNode[meta.getName ()] = meta.getString ();
		ELEKTRA_LOG_DEBUG ("Add metakey “%s: %s”", meta.getName ().c_str (), meta.getString ().c_str ());
	}

	if (metaNode.size () <= 0)
	{
		ELEKTRA_LOG_DEBUG ("Return leaf node with value “%s”",
				   dataNode.IsNull () ? "~" : dataNode.IsSequence () ? "[]" : dataNode.as<string> ().c_str ());
		return dataNode;
	}

	YAML::Node node{ YAML::Node (YAML::NodeType::Sequence) };
	node.SetTag ("!elektra/meta");
	node.push_back (dataNode);
	node.push_back (metaNode);

#ifdef HAVE_LOGGER
	ostringstream data;
	data << node;
	ELEKTRA_LOG_DEBUG ("Return meta leaf node with value “%s”", data.str ().c_str ());
#endif

	return node;
}

/**
 * @brief This function adds `null` elements to the given YAML collection.
 *
 * @param sequence This node stores the collection to which this function adds `numberOfElements` empty elements.
 * @param numberOfElements This parameter specifies the number of empty element this function adds to `sequence`.
 */
void addEmptyArrayElements (YAML::Node & sequence, unsigned long long const numberOfElements)
{
	ELEKTRA_LOG_DEBUG ("Add %llu empty array elements", numberOfElements);
	for (auto missingFields = numberOfElements; missingFields > 0; missingFields--)
	{
		sequence.push_back ({});
	}
}

/**
 * @brief This function adds a key that is either, element of an array, or an array parent to a YAML node.
 *
 * @param data This node stores the data specified via `keyIterator`.
 * @param keyIterator This iterator specifies the current part of the key name this function adds to `data`.
 * @param key This parameter specifies the key that should be added to `data`.
 * @param converted This partial key specifies the part of `key` that is already part of `data`.
 * @param arrayParent This key stores the (possible) array parent of the current part of `key` this
 *                    function should add to `data`.
 */
void addKeyArray (YAML::Node & data, NameIterator & keyIterator, Key & key, Key & converted, Key * arrayParent)
{
	if (keyIterator == key.end ())
	{
		ELEKTRA_LOG_DEBUG ("Create leaf node for value “%s”", key.getString ().c_str ());
		data = createLeafNode (key);
		return;
	}

	converted.addBaseName (*keyIterator);
	auto const isArrayElement = data.IsSequence () || (arrayParent && converted.isDirectBelow (*arrayParent));
	auto const arrayIndex = isArrayElement ? getArrayIndex (keyIterator) : 0;

	ELEKTRA_LOG_DEBUG ("Add key part “%s”", (*keyIterator).c_str ());

	if (data.IsScalar ()) data = YAML::Node ();
	if (isArrayElement)
	{
		YAML::Node node = arrayIndex < data.size () ? data[arrayIndex] : YAML::Node ();
		addKeyArray (node, ++keyIterator, key, converted, arrayParent);
		if (arrayIndex > data.size ()) addEmptyArrayElements (data, arrayIndex - data.size ());
		data[arrayIndex] = node;
	}
	else
	{
		string part = *keyIterator;
		YAML::Node node = data[part] ? data[part] : YAML::Node ();
		addKeyArray (node, ++keyIterator, key, converted, arrayParent);
		data[part] = node;
	}
}

/**
 * @brief This function adds a key set to a YAML node.
 *
 * @param data This node stores the data specified via `mappings`.
 * @param mappings This keyset specifies all keys and values this function adds to `data`.
 * @param parent This key is the root of all keys stored in `mappings`.
 */
void addKeys (YAML::Node & data, KeySet const & mappings, Key const & parent)
{
	stack<Key> arrayParents;

	for (auto key : mappings)
	{
		ELEKTRA_LOG_DEBUG ("Convert key “%s”: “%s”", key.getName ().c_str (),
				   key.getBinarySize () == 0 ? "NULL" : key.isString () ? key.getString ().c_str () : "binary value!");
		NameIterator keyIterator = relativeKeyIterator (key, parent);

		if (key.hasMeta ("array"))
		{
			ELEKTRA_LOG_DEBUG ("Add array parent “%s”", key.getName ().c_str ());
			arrayParents.push (key);
		}
		else if (!arrayParents.empty () && !key.isBelow (arrayParents.top ()))
		{
			ELEKTRA_LOG_DEBUG ("Remove array parent “%s”", arrayParents.top ().getName ().c_str ());
			arrayParents.pop ();
		}

		Key converted{ parent.getName (), KEY_END };
		addKeyArray (data, keyIterator, key, converted, arrayParents.empty () ? nullptr : &arrayParents.top ());

#ifdef HAVE_LOGGER
		ostringstream output;
		output << data;

		ELEKTRA_LOG_DEBUG ("Converted Data:");
		ELEKTRA_LOG_DEBUG ("——————————");

		istringstream stream (output.str ());
		for (string line; std::getline (stream, line);)
		{
			ELEKTRA_LOG_DEBUG ("%s", line.c_str ());
		}

		ELEKTRA_LOG_DEBUG ("——————————");
#endif
	}
}

} // end namespace

/**
 * @brief This function saves the key-value pairs stored in `mappings` as YAML data in the location specified via `parent`.
 *
 * @param mappings This key set stores the mappings that should be saved as YAML data.
 * @param parent This key specifies the path to the YAML data file that should be written.
 */
void yamlcpp::yamlWrite (KeySet const & mappings, Key const & parent)
{
	KeySet keys = mappings;
	auto missing = missingKeys (keys, parent);
	keys.append (missing);

	YAML::Node data;
	addKeys (data, keys, parent);

#ifdef HAVE_LOGGER
	ELEKTRA_LOG_DEBUG ("Write Data:");
	ELEKTRA_LOG_DEBUG ("——————————");

	ostringstream outputString;
	outputString << data;
	istringstream stream (outputString.str ());
	for (string line; std::getline (stream, line);)
	{
		ELEKTRA_LOG_DEBUG ("%s", line.c_str ());
	}

	ELEKTRA_LOG_DEBUG ("——————————");
#endif

	ofstream output (parent.getString ());
	output << data << endl;
}
<commit_msg>YAML CPP: Update name and docu of function<commit_after>/**
 * @file
 *
 * @brief Write key sets using yaml-cpp
 *
 * @copyright BSD License (see LICENSE.md or https://www.libelektra.org)
 */

#include "write.hpp"
#include "log.hpp"
#include "yaml-cpp/yaml.h"

#include <kdb.hpp>
#include <kdbease.h>
#include <kdblogger.h>

#include <fstream>
#include <stack>

namespace
{

using std::endl;
using std::istringstream;
using std::ofstream;
using std::ostringstream;
using std::pair;
using std::stack;
using std::string;

using kdb::Key;
using kdb::KeySet;
using kdb::NameIterator;
using KeySetPair = pair<KeySet, KeySet>;

/**
 * @brief This function determines all keys “missing” from the given keyset.
 *
 * The term “missing” refers to keys that are not part of the hierarchy. For example in a key set with the parent key
 *
 *  - `user/parent`
 *
 * that contains the keys
 *
 * - `user/parent/level1/level2`, and
 * - `user/parent/level1/level2/level3/level4`
 *
 * , the keys
 *
 * - `user/parent/level1`, and
 * - `user/parent/level1/level2/level3`
 *
 * are missing.
 *
 * @param keys This parameter contains the key set for which this function determines missing keys.
 * @param parent This value stores the parent key of `keys`.
 *
 * @return A key set that contains all keys missing from `keys`
 */
KeySet missingKeys (KeySet const & keys, Key const & parent)
{
	KeySet missing;

	keys.rewind ();
	Key previous{ parent.getName (), KEY_BINARY, KEY_END };
	for (; keys.next (); previous = keys.current ())
	{
		if (keys.current ().isDirectBelow (previous) || !keys.current ().isBelow (previous)) continue;

		Key current{ keys.current ().getName (), KEY_BINARY, KEY_END };
		while (!current.isDirectBelow (previous))
		{
			ckdb::keySetBaseName (*current, NULL);
			missing.append (current);
			current = current.dup ();
		}
	}

#ifdef HAVE_LOGGER
	ELEKTRA_LOG_DEBUG ("Add missing keys:");
	logKeySet (missing);
#endif

	return missing;
}

/**
 * @brief This function returns a `NameIterator` starting at the first level that is not part of `parent`.
 *
 * @pre The parameter `key` must be a child of `parent`.
 *
 * @param key This is the key for which this function returns a relative iterator.
 * @param parent This key specifies the part of the name iterator that will not be part of the return value of this function.
 *
 * @returns A relative iterator that starts with the first part of the name of `key` not contained in `parent`.
 */
NameIterator relativeKeyIterator (Key const & key, Key const & parent)
{
	auto parentIterator = parent.begin ();
	auto keyIterator = key.begin ();
	while (parentIterator != parent.end () && keyIterator != key.end ())
	{
		parentIterator++;
		keyIterator++;
	}
	return keyIterator;
}

/**
 * @brief This function returns the array index for a given key part.
 *
 * @param nameIterator This iterator specifies the name of the key.
 *
 * @retval The index of the array element, or `0` if the given key part is not an array element.
 */
unsigned long long getArrayIndex (NameIterator const & nameIterator)
{
	string const name = *nameIterator;
	auto const offsetIndex = ckdb::elektraArrayValidateBaseNameString (name.c_str ());
	auto const isArrayElement = offsetIndex >= 1;
	return isArrayElement ? stoull (name.substr (static_cast<size_t> (offsetIndex))) : 0;
}

/**
 * @brief This function creates a YAML node representing a key value.
 *
 * @param key This key specifies the data that should be saved in the YAML node returned by this function.
 *
 * @note Since YAML does not support non-empty binary data directly this function replaces data stored in binary keys with the string
 *       `Unsupported binary value!`. If you need support for binary data, please load the Base64 plugin before you use YAML CPP.
 *
 * @returns A new YAML node containing the data specified in `key`
 */
YAML::Node createNode (Key const & key)
{
	if (key.hasMeta ("array"))
	{
		return YAML::Node (YAML::NodeType::Sequence);
	}
	if (key.getBinarySize () == 0)
	{
		return YAML::Node (YAML::NodeType::Null);
	}
	if (key.isBinary ())
	{
		return YAML::Node ("Unsupported binary value!");
	}

	auto value = key.get<string> ();
	if (value == "0" || value == "1")
	{
		return YAML::Node (key.get<bool> ());
	}
	return YAML::Node (value);
}

/**
 * @brief This function creates a YAML Node containing a key value and optionally metadata.
 *
 * @param key This key specifies the data that should be saved in the YAML node returned by this function.
 *
 * @note Since YAML does not support non-empty binary data directly this function replaces data stored in binary keys with the string
 *       `Unsupported binary value!`. If you need support for binary data, please load the Base64 before you use YAML CPP.
 *
 * @returns A new YAML node containing the data and metadata specified in `key`
 */
YAML::Node createLeafNode (Key & key)
{

	YAML::Node metaNode{ YAML::Node (YAML::NodeType::Map) };
	YAML::Node dataNode = createNode (key);

	key.rewindMeta ();
	while (Key meta = key.nextMeta ())
	{
		if (meta.getName () == "array" || meta.getName () == "binary") continue;
		if (meta.getName () == "type" && meta.getString () == "binary")
		{
			dataNode.SetTag ("tag:yaml.org,2002:binary");
			continue;
		}
		metaNode[meta.getName ()] = meta.getString ();
		ELEKTRA_LOG_DEBUG ("Add metakey “%s: %s”", meta.getName ().c_str (), meta.getString ().c_str ());
	}

	if (metaNode.size () <= 0)
	{
		ELEKTRA_LOG_DEBUG ("Return leaf node with value “%s”",
				   dataNode.IsNull () ? "~" : dataNode.IsSequence () ? "[]" : dataNode.as<string> ().c_str ());
		return dataNode;
	}

	YAML::Node node{ YAML::Node (YAML::NodeType::Sequence) };
	node.SetTag ("!elektra/meta");
	node.push_back (dataNode);
	node.push_back (metaNode);

#ifdef HAVE_LOGGER
	ostringstream data;
	data << node;
	ELEKTRA_LOG_DEBUG ("Return meta leaf node with value “%s”", data.str ().c_str ());
#endif

	return node;
}

/**
 * @brief This function adds `null` elements to the given YAML collection.
 *
 * @param sequence This node stores the collection to which this function adds `numberOfElements` empty elements.
 * @param numberOfElements This parameter specifies the number of empty element this function adds to `sequence`.
 */
void addEmptyArrayElements (YAML::Node & sequence, unsigned long long const numberOfElements)
{
	ELEKTRA_LOG_DEBUG ("Add %llu empty array elements", numberOfElements);
	for (auto missingFields = numberOfElements; missingFields > 0; missingFields--)
	{
		sequence.push_back ({});
	}
}

/**
 * @brief This function adds a key to a YAML node.
 *
 * @param data This node stores the data specified via `keyIterator`.
 * @param keyIterator This iterator specifies the current part of the key name this function adds to `data`.
 * @param key This parameter specifies the key that should be added to `data`.
 * @param converted This partial key specifies the part of `key` that is already part of `data`.
 * @param arrayParent This key stores the (possible) array parent of the current part of `key` this function should add to `data`.
 */
void addKey (YAML::Node & data, NameIterator & keyIterator, Key & key, Key & converted, Key * arrayParent)
{
	if (keyIterator == key.end ())
	{
		ELEKTRA_LOG_DEBUG ("Create leaf node for value “%s”", key.getString ().c_str ());
		data = createLeafNode (key);
		return;
	}

	converted.addBaseName (*keyIterator);
	auto const isArrayElement = data.IsSequence () || (arrayParent && converted.isDirectBelow (*arrayParent));
	auto const arrayIndex = isArrayElement ? getArrayIndex (keyIterator) : 0;

	ELEKTRA_LOG_DEBUG ("Add key part “%s”", (*keyIterator).c_str ());

	if (data.IsScalar ()) data = YAML::Node ();
	if (isArrayElement)
	{
		YAML::Node node = arrayIndex < data.size () ? data[arrayIndex] : YAML::Node ();
		addKey (node, ++keyIterator, key, converted, arrayParent);
		if (arrayIndex > data.size ()) addEmptyArrayElements (data, arrayIndex - data.size ());
		data[arrayIndex] = node;
	}
	else
	{
		string part = *keyIterator;
		YAML::Node node = data[part] ? data[part] : YAML::Node ();
		addKey (node, ++keyIterator, key, converted, arrayParent);
		data[part] = node;
	}
}

/**
 * @brief This function adds a key set to a YAML node.
 *
 * @param data This node stores the data specified via `mappings`.
 * @param mappings This keyset specifies all keys and values this function adds to `data`.
 * @param parent This key is the root of all keys stored in `mappings`.
 */
void addKeys (YAML::Node & data, KeySet const & mappings, Key const & parent)
{
	stack<Key> arrayParents;

	for (auto key : mappings)
	{
		ELEKTRA_LOG_DEBUG ("Convert key “%s”: “%s”", key.getName ().c_str (),
				   key.getBinarySize () == 0 ? "NULL" : key.isString () ? key.getString ().c_str () : "binary value!");
		NameIterator keyIterator = relativeKeyIterator (key, parent);

		if (key.hasMeta ("array"))
		{
			ELEKTRA_LOG_DEBUG ("Add array parent “%s”", key.getName ().c_str ());
			arrayParents.push (key);
		}
		else if (!arrayParents.empty () && !key.isBelow (arrayParents.top ()))
		{
			ELEKTRA_LOG_DEBUG ("Remove array parent “%s”", arrayParents.top ().getName ().c_str ());
			arrayParents.pop ();
		}

		Key converted{ parent.getName (), KEY_END };
		addKey (data, keyIterator, key, converted, arrayParents.empty () ? nullptr : &arrayParents.top ());

#ifdef HAVE_LOGGER
		ostringstream output;
		output << data;

		ELEKTRA_LOG_DEBUG ("Converted Data:");
		ELEKTRA_LOG_DEBUG ("——————————");

		istringstream stream (output.str ());
		for (string line; std::getline (stream, line);)
		{
			ELEKTRA_LOG_DEBUG ("%s", line.c_str ());
		}

		ELEKTRA_LOG_DEBUG ("——————————");
#endif
	}
}

} // end namespace

/**
 * @brief This function saves the key-value pairs stored in `mappings` as YAML data in the location specified via `parent`.
 *
 * @param mappings This key set stores the mappings that should be saved as YAML data.
 * @param parent This key specifies the path to the YAML data file that should be written.
 */
void yamlcpp::yamlWrite (KeySet const & mappings, Key const & parent)
{
	KeySet keys = mappings;
	auto missing = missingKeys (keys, parent);
	keys.append (missing);

	YAML::Node data;
	addKeys (data, keys, parent);

#ifdef HAVE_LOGGER
	ELEKTRA_LOG_DEBUG ("Write Data:");
	ELEKTRA_LOG_DEBUG ("——————————");

	ostringstream outputString;
	outputString << data;
	istringstream stream (outputString.str ());
	for (string line; std::getline (stream, line);)
	{
		ELEKTRA_LOG_DEBUG ("%s", line.c_str ());
	}

	ELEKTRA_LOG_DEBUG ("——————————");
#endif

	ofstream output (parent.getString ());
	output << data << endl;
}
<|endoftext|>


<commit_before>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2015 Artem Pavlenko
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

#ifndef MAPNIK_FILE_IO_HPP
#define MAPNIK_FILE_IO_HPP

// mapnik
#include <mapnik/make_unique.hpp>
#include <mapnik/util/noncopyable.hpp>
#include <mapnik/util/utf_conv_win.hpp>

// stl
#include <cstdio>
#include <memory>
#include <string>

namespace mapnik { namespace util {

class file : public util::noncopyable
{
public:
    using file_ptr = std::unique_ptr<std::FILE, int (*)(std::FILE *)>;
    using data_type = std::unique_ptr<char[]>;

    explicit file(std::string const& filename)
#ifdef _WINDOWS
     : file_(_wfopen(mapnik::utf8_to_utf16(filename).c_str(), L"rb"), std::fclose),
#else
     : file_(std::fopen(filename.c_str(),"rb"), std::fclose),
#endif
       size_(0)

     {
        if (file_)
        {
            std::fseek(file_.get(), 0, SEEK_END);
            size_ = std::ftell(file_.get());
            std::fseek(file_.get(), 0, SEEK_SET);
        }
     }

    inline bool open() const
    {
        return file_ ? true : false;
    }

    inline operator bool() const
    {
        return this->open();
    }

    inline std::FILE * get() const
    {
        return file_.get();
    }

    inline std::size_t size() const
    {
        return size_;
    }

    inline data_type data() const
    {
        if (!size_) return nullptr;
        std::fseek(file_.get(), 0, SEEK_SET);
        data_type buffer(new char[size_]);
        std::fread(buffer.get(), size_, 1, file_.get());
        return buffer;
    }
private:
    file_ptr file_;
    std::size_t size_;
};

}}

#endif // FILE_IO
<commit_msg>file_io - make operator bool() explicit via @lightmare (https://github.com/mapnik/mapnik/commit/0d032c261863b4c1c92f5630a91b0a15dba059c3#commitcomment-16753722)<commit_after>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2015 Artem Pavlenko
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

#ifndef MAPNIK_FILE_IO_HPP
#define MAPNIK_FILE_IO_HPP

// mapnik
#include <mapnik/make_unique.hpp>
#include <mapnik/util/noncopyable.hpp>
#include <mapnik/util/utf_conv_win.hpp>

// stl
#include <cstdio>
#include <memory>
#include <string>

namespace mapnik { namespace util {

class file : public util::noncopyable
{
public:
    using file_ptr = std::unique_ptr<std::FILE, int (*)(std::FILE *)>;
    using data_type = std::unique_ptr<char[]>;

    explicit file(std::string const& filename)
#ifdef _WINDOWS
     : file_(_wfopen(mapnik::utf8_to_utf16(filename).c_str(), L"rb"), std::fclose),
#else
     : file_(std::fopen(filename.c_str(),"rb"), std::fclose),
#endif
       size_(0)

     {
        if (file_)
        {
            std::fseek(file_.get(), 0, SEEK_END);
            size_ = std::ftell(file_.get());
            std::fseek(file_.get(), 0, SEEK_SET);
        }
     }

    inline bool open() const
    {
        return file_ ? true : false;
    }

    explicit operator bool() const
    {
        return this->open();
    }

    inline std::FILE * get() const
    {
        return file_.get();
    }

    inline std::size_t size() const
    {
        return size_;
    }

    inline data_type data() const
    {
        if (!size_) return nullptr;
        std::fseek(file_.get(), 0, SEEK_SET);
        data_type buffer(new char[size_]);
        std::fread(buffer.get(), size_, 1, file_.get());
        return buffer;
    }
private:
    file_ptr file_;
    std::size_t size_;
};

}}

#endif // FILE_IO
<|endoftext|>


<commit_before>/**
 * @file
 *
 * @brief This file contains the implementation of a basic listener.
 *
 * @copyright BSD License (see LICENSE.md or https://www.libelektra.org)
 */

// -- Imports ------------------------------------------------------------------------------------------------------------------------------

#include <stdexcept>

#include "listener.hpp"

using std::overflow_error;
using std::string;
using std::to_string;

using kdb::Key;

// -- Functions ----------------------------------------------------------------------------------------------------------------------------

namespace
{

/**
 * @brief This function converts a given number to an array base name.
 *
 * @param index This number specifies the index of the array entry.
 *
 * @return A string representing the given indices as Elektra array name.
 */
string indexToArrayBaseName (uintmax_t const index)
{
	size_t digits = 1;

	for (uintmax_t value = index; value > 9; digits++)
	{
		value /= 10;
	}

	return "#" + string (digits - 1, '_') + to_string (index);
}

/**
 * @brief This function converts a YAML scalar to a string.
 *
 * @param text This string contains a YAML scalar (including quote
 *             characters).
 *
 * @return A string without leading and trailing quote characters
 */
string scalarToText (string const & text)
{
	if (text.length () == 0)
	{
		return text;
	}
	if (*(text.begin ()) == '"' || *(text.begin ()) == '\'')
	{
		return text.substr (1, text.length () - 2);
	}
	return text;
}

} // namespace

// -- Class --------------------------------------------------------------------

namespace yawn
{

/**
 * @brief This constructor creates a Listener using the given parent key.
 *
 * @param parent This argument specifies the parent key of the key set this
 *               listener produces.
 */
Listener::Listener (Key const & parent)
{
	parents.push (parent);
}

/**
 * @brief This function will be called after the walker exits a value node.
 *
 * @param text This variable contains the text stored in the value.
 */
void Listener::exitValue (string const & text)
{
	Key key = parents.top ();
	key.setString (scalarToText (text));
	keys.append (key);
}

/**
 * @brief This function will be called after the walker exits a key node.
 *
 * @param text This variable contains the text of the key.
 */
void Listener::exitKey (string const & text)
{
	// Entering a mapping such as `part: …` means that we need to add `part` to
	// the key name
	Key child{ parents.top ().getName (), KEY_END };
	child.addBaseName (scalarToText (text));
	parents.push (child);
}

/**
 * @brief This function will be called after the walker exits the node for a
 *        key-value pair.
 *
 * @param matchedValue This variable specifies if the pair contains a value
 *                     or not.
 */
void Listener::exitPair (bool const matchedValue)
{
	if (!matchedValue)
	{
		// Add key with empty value
		keys.append (parents.top ());
	}
	// Returning from a mapping such as `part: …` means that we need need to
	// remove the key for `part` from the stack.
	parents.pop ();
}

/**
 * @brief This function will be called before the walker enters a sequence
 *        node.
 */
void Listener::enterSequence ()
{
	indices.push (0);
	parents.top ().setMeta ("array", ""); // We start with an empty array
}

/**
 * @brief This function will be called after the walker exits a sequence node.
 */
void Listener::exitSequence ()
{
	// We add the parent key of all array elements after we leave the sequence
	keys.append (parents.top ());
	indices.pop ();
}

/**
 * @brief This function will be called before the walker enters an element
 *        node.
 */
void Listener::enterElement ()
{
	Key key{ parents.top ().getName (), KEY_END };
	if (indices.top () >= UINTMAX_MAX) throw overflow_error ("Unable to increase array index for array “" + key.getName () + "”");

	key.addBaseName (indexToArrayBaseName (indices.top ()));

	uintmax_t index = indices.top ();
	indices.pop ();
	index++;
	indices.push (index);

	parents.top ().setMeta ("array", key.getBaseName ());
	parents.push (key);
}

/**
 * @brief This function will be called after the walker exits a sequence node.
 */
void Listener::exitElement ()
{
	parents.pop (); // Remove the key for the current array entry
}

/**
 * @brief This method returns the key set of the listener.
 *
 * @return A key set created by the walker by calling methods of this class
 **/
kdb::KeySet Listener::getKeySet () const
{
	return keys;
}

} // namespace yawn
<commit_msg>YAwn: Do not overwrite original parent key<commit_after>/**
 * @file
 *
 * @brief This file contains the implementation of a basic listener.
 *
 * @copyright BSD License (see LICENSE.md or https://www.libelektra.org)
 */

// -- Imports ------------------------------------------------------------------------------------------------------------------------------

#include <stdexcept>

#include "listener.hpp"

using std::overflow_error;
using std::string;
using std::to_string;

using kdb::Key;

// -- Functions ----------------------------------------------------------------------------------------------------------------------------

namespace
{

/**
 * @brief This function converts a given number to an array base name.
 *
 * @param index This number specifies the index of the array entry.
 *
 * @return A string representing the given indices as Elektra array name.
 */
string indexToArrayBaseName (uintmax_t const index)
{
	size_t digits = 1;

	for (uintmax_t value = index; value > 9; digits++)
	{
		value /= 10;
	}

	return "#" + string (digits - 1, '_') + to_string (index);
}

/**
 * @brief This function converts a YAML scalar to a string.
 *
 * @param text This string contains a YAML scalar (including quote
 *             characters).
 *
 * @return A string without leading and trailing quote characters
 */
string scalarToText (string const & text)
{
	if (text.length () == 0)
	{
		return text;
	}
	if (*(text.begin ()) == '"' || *(text.begin ()) == '\'')
	{
		return text.substr (1, text.length () - 2);
	}
	return text;
}

} // namespace

// -- Class --------------------------------------------------------------------

namespace yawn
{

/**
 * @brief This constructor creates a Listener using the given parent key.
 *
 * @param parent This argument specifies the parent key of the key set this
 *               listener produces.
 */
Listener::Listener (Key const & parent)
{
	parents.push (parent.dup ());
}

/**
 * @brief This function will be called after the walker exits a value node.
 *
 * @param text This variable contains the text stored in the value.
 */
void Listener::exitValue (string const & text)
{
	Key key = parents.top ();
	key.setString (scalarToText (text));
	keys.append (key);
}

/**
 * @brief This function will be called after the walker exits a key node.
 *
 * @param text This variable contains the text of the key.
 */
void Listener::exitKey (string const & text)
{
	// Entering a mapping such as `part: …` means that we need to add `part` to
	// the key name
	Key child{ parents.top ().getName (), KEY_END };
	child.addBaseName (scalarToText (text));
	parents.push (child);
}

/**
 * @brief This function will be called after the walker exits the node for a
 *        key-value pair.
 *
 * @param matchedValue This variable specifies if the pair contains a value
 *                     or not.
 */
void Listener::exitPair (bool const matchedValue)
{
	if (!matchedValue)
	{
		// Add key with empty value
		keys.append (parents.top ());
	}
	// Returning from a mapping such as `part: …` means that we need need to
	// remove the key for `part` from the stack.
	parents.pop ();
}

/**
 * @brief This function will be called before the walker enters a sequence
 *        node.
 */
void Listener::enterSequence ()
{
	indices.push (0);
	parents.top ().setMeta ("array", ""); // We start with an empty array
}

/**
 * @brief This function will be called after the walker exits a sequence node.
 */
void Listener::exitSequence ()
{
	// We add the parent key of all array elements after we leave the sequence
	keys.append (parents.top ());
	indices.pop ();
}

/**
 * @brief This function will be called before the walker enters an element
 *        node.
 */
void Listener::enterElement ()
{
	Key key{ parents.top ().getName (), KEY_END };
	if (indices.top () >= UINTMAX_MAX) throw overflow_error ("Unable to increase array index for array “" + key.getName () + "”");

	key.addBaseName (indexToArrayBaseName (indices.top ()));

	uintmax_t index = indices.top ();
	indices.pop ();
	index++;
	indices.push (index);

	parents.top ().setMeta ("array", key.getBaseName ());
	parents.push (key);
}

/**
 * @brief This function will be called after the walker exits a sequence node.
 */
void Listener::exitElement ()
{
	parents.pop (); // Remove the key for the current array entry
}

/**
 * @brief This method returns the key set of the listener.
 *
 * @return A key set created by the walker by calling methods of this class
 **/
kdb::KeySet Listener::getKeySet () const
{
	return keys;
}

} // namespace yawn
<|endoftext|>


<commit_before>#include "tabwidget.h"

#include <QApplication>
#include <QPainter>
#include <QPaintEvent>

namespace OpenCOR {
namespace Core {

TabWidget::TabWidget(const QString &pLogoFileName, QWidget *pParent) :
    QTabWidget(pParent),
    CommonWidget(pParent)
{
    // Set some properties
    // Note: we give a strong focus policy to the tab widget so that it can also
    //       get focus by being clicked on

    setMovable(true);
    setTabsClosable(true);
    setFocusPolicy(Qt::StrongFocus);

    // Logo settings

    mLogo.load(pLogoFileName);

    mLogoBackgroundColor = QImage(pLogoFileName).pixel(0, 0);

    mLogoWidth  = mLogo.width();
    mLogoHeight = mLogo.height();

    // A connection to handle the change of tab

    connect(this, SIGNAL(currentChanged(int)),
            this, SLOT(tabChanged(const int &)));
    connect(qApp, SIGNAL(focusChanged(QWidget *, QWidget *)),
            this, SLOT(getFocus(QWidget *, QWidget *)));
}

void TabWidget::paintEvent(QPaintEvent *pEvent)
{
    // Display the CellML logo in place of the tab widget itself, in case the
    // tab widget doesn't have any tab associated with it

    if (!count()) {
        // There are no tabs, so display our logo

        QPainter painter(this);

        // Paint the widget with the logo's background colour

        int widgetWidth  = width();
        int widgetHeight = height();

        painter.fillRect(QRect(0, 0, widgetWidth, widgetHeight),
                         mLogoBackgroundColor);

        // Draw the logo itself

        painter.drawPixmap(QRect(0.5*(widgetWidth-mLogoWidth),
                                 0.5*(widgetHeight-mLogoHeight),
                                 mLogoWidth, mLogoHeight),
                           mLogo);

        // Draw a border around the widget which actually consists of two
        // borders. A 'dark' outer border and a 'light' inner border. Note the
        // way the border coordinates were adjusted to get the right effect...

        QPen pen = painter.pen();

        pen.setColor(palette().color(QPalette::Button));

        painter.setPen(pen);

        QRect border = rect();

        border.adjust(0, 0, -1, 0);

        painter.drawRect(border);

        pen.setColor(palette().color(QPalette::Midlight));

        painter.setPen(pen);

        border.adjust(1, 1, -1, -1);

        painter.drawRect(border);

        // Accept the event

        pEvent->accept();
    } else {
        // There are tabs, so revert to the default paint handler

        QTabWidget::paintEvent(pEvent);
    }
}

void TabWidget::tabChanged(const int &pIndex) const
{
    // A new tab has been selected, so give the focus to its widget

    QWidget *crtWidget = widget(pIndex);

    if (crtWidget)
        crtWidget->setFocus();
}

void TabWidget::getFocus(QWidget *, QWidget *pNew) const
{
    // The tab widget (or a part of it) has just received the focus and, here,
    // we want to take advantage of this to give the focus to the widget of the
    // active tab as a result of the user clicking on the active tab (since this
    // won't emit the currentChanged signal). In our case, this means we are
    // after pNew being of QTabBar type and that, more importantly, its parent
    // is this tab widget

    if (pNew && (pNew->parentWidget() == this))
        // The tab widget didn't have the focus, but the user has just clicked
        // on the tab widget's active tab, thus giving the focus to the tab
        // widget, so now we need to give the focus to the active tab's widget

        tabChanged(currentIndex());
}

} }
<commit_msg>Don't add a border to the tab widget (in the central widget) if on Mac OS X.<commit_after>#include "tabwidget.h"

#include <QApplication>
#include <QPainter>
#include <QPaintEvent>

namespace OpenCOR {
namespace Core {

TabWidget::TabWidget(const QString &pLogoFileName, QWidget *pParent) :
    QTabWidget(pParent),
    CommonWidget(pParent)
{
    // Set some properties
    // Note: we give a strong focus policy to the tab widget so that it can also
    //       get focus by being clicked on

    setMovable(true);
    setTabsClosable(true);
    setFocusPolicy(Qt::StrongFocus);

    // Logo settings

    mLogo.load(pLogoFileName);

    mLogoBackgroundColor = QImage(pLogoFileName).pixel(0, 0);

    mLogoWidth  = mLogo.width();
    mLogoHeight = mLogo.height();

    // A connection to handle the change of tab

    connect(this, SIGNAL(currentChanged(int)),
            this, SLOT(tabChanged(const int &)));
    connect(qApp, SIGNAL(focusChanged(QWidget *, QWidget *)),
            this, SLOT(getFocus(QWidget *, QWidget *)));
}

void TabWidget::paintEvent(QPaintEvent *pEvent)
{
    // Display the CellML logo in place of the tab widget itself, in case the
    // tab widget doesn't have any tab associated with it

    if (!count()) {
        // There are no tabs, so display our logo

        QPainter painter(this);

        // Paint the widget with the logo's background colour

        int widgetWidth  = width();
        int widgetHeight = height();

        painter.fillRect(QRect(0, 0, widgetWidth, widgetHeight),
                         mLogoBackgroundColor);

        // Draw the logo itself

        painter.drawPixmap(QRect(0.5*(widgetWidth-mLogoWidth),
                                 0.5*(widgetHeight-mLogoHeight),
                                 mLogoWidth, mLogoHeight),
                           mLogo);

#ifndef Q_WS_MAC
        // Draw a border around the widget
        // Note #1: the border actually consists of two borders. A 'dark' outer
        //          border and a 'light' inner border. Note the way the border
        //          coordinates were adjusted to get the right effect...
        // Note #2: the border doesn't look good on Mac OS X, so...

        QPen pen = painter.pen();

        pen.setColor(palette().color(QPalette::Button));

        painter.setPen(pen);

        QRect border = rect();

        border.adjust(0, 0, -1, 0);

        painter.drawRect(border);

        pen.setColor(palette().color(QPalette::Midlight));

        painter.setPen(pen);

        border.adjust(1, 1, -1, -1);

        painter.drawRect(border);
#endif

        // Accept the event

        pEvent->accept();
    } else {
        // There are tabs, so revert to the default paint handler

        QTabWidget::paintEvent(pEvent);
    }
}

void TabWidget::tabChanged(const int &pIndex) const
{
    // A new tab has been selected, so give the focus to its widget

    QWidget *crtWidget = widget(pIndex);

    if (crtWidget)
        crtWidget->setFocus();
}

void TabWidget::getFocus(QWidget *, QWidget *pNew) const
{
    // The tab widget (or a part of it) has just received the focus and, here,
    // we want to take advantage of this to give the focus to the widget of the
    // active tab as a result of the user clicking on the active tab (since this
    // won't emit the currentChanged signal). In our case, this means we are
    // after pNew being of QTabBar type and that, more importantly, its parent
    // is this tab widget

    if (pNew && (pNew->parentWidget() == this))
        // The tab widget didn't have the focus, but the user has just clicked
        // on the tab widget's active tab, thus giving the focus to the tab
        // widget, so now we need to give the focus to the active tab's widget

        tabChanged(currentIndex());
}

} }
<|endoftext|>


<commit_before>//
// MessagePack for C++ static resolution routine
//
// Copyright (C) 2008-2009 FURUHASHI Sadayuki
//
//    Licensed under the Apache License, Version 2.0 (the "License");
//    you may not use this file except in compliance with the License.
//    You may obtain a copy of the License at
//
//        http://www.apache.org/licenses/LICENSE-2.0
//
//    Unless required by applicable law or agreed to in writing, software
//    distributed under the License is distributed on an "AS IS" BASIS,
//    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//    See the License for the specific language governing permissions and
//    limitations under the License.
//
#ifndef MSGPACK_TYPE_STRING_HPP__
#define MSGPACK_TYPE_STRING_HPP__

#include "msgpack/object.hpp"
#include <string>

namespace msgpack {

template <typename Elem>
inline std::basic_string<Elem>& operator>> (object o, std::basic_string<Elem>& v)
{
	if(o.type != type::RAW) { throw type_error(); }
	v.assign(reinterpret_cast<const Elem*>(o.via.raw.ptr), o.via.raw.size/sizeof(std::basic_string<Elem>::value_type));
	return v;
}

template <typename Stream, typename Elem>
inline packer<Stream>& operator<< (packer<Stream>& o, const std::basic_string<Elem>& v)
{
  auto size = v.size()*sizeof(std::basic_string<Elem>::value_type);
	o.pack_raw(size);
	o.pack_raw_body(reinterpret_cast<const char*>(v.data()), size);
	return o;
}
template <typename Elem>
inline void operator<< (object::with_zone& o, const std::basic_string<Elem>& v)
{
	o.type = type::RAW;
  auto size = v.size()*sizeof(std::basic_string<Elem>::value_type);
	char* ptr = (char*)o.zone->malloc(size);
	o.via.raw.ptr = ptr;
	o.via.raw.size = (uint32_t)size;
	memcpy(ptr, v.data(), size);
}
template <typename Elem>
inline void operator<< (object& o, const std::basic_string<Elem>& v)
{
	o.type = type::RAW;
	o.via.raw.ptr = v.data();
	o.via.raw.size = (uint32_t)(v.size()*sizeof(std::basic_string<Elem>::value_type));
}

}  // namespace msgpack

#endif /* msgpack/type/string.hpp */

<commit_msg>Optimized sizeof in string.hpp<commit_after>//
// MessagePack for C++ static resolution routine
//
// Copyright (C) 2008-2009 FURUHASHI Sadayuki
//
//    Licensed under the Apache License, Version 2.0 (the "License");
//    you may not use this file except in compliance with the License.
//    You may obtain a copy of the License at
//
//        http://www.apache.org/licenses/LICENSE-2.0
//
//    Unless required by applicable law or agreed to in writing, software
//    distributed under the License is distributed on an "AS IS" BASIS,
//    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//    See the License for the specific language governing permissions and
//    limitations under the License.
//
#ifndef MSGPACK_TYPE_STRING_HPP__
#define MSGPACK_TYPE_STRING_HPP__

#include "msgpack/object.hpp"
#include <string>

namespace msgpack {

template <typename Elem>
inline std::basic_string<Elem>& operator>> (object o, std::basic_string<Elem>& v)
{
	if(o.type != type::RAW) { throw type_error(); }
	v.assign(reinterpret_cast<const Elem*>(o.via.raw.ptr), o.via.raw.size/sizeof(Elem));
	return v;
}

template <typename Stream, typename Elem>
inline packer<Stream>& operator<< (packer<Stream>& o, const std::basic_string<Elem>& v)
{
  auto size = v.size()*sizeof(Elem);
	o.pack_raw(size);
	o.pack_raw_body(reinterpret_cast<const char*>(v.data()), size);
	return o;
}
template <typename Elem>
inline void operator<< (object::with_zone& o, const std::basic_string<Elem>& v)
{
	o.type = type::RAW;
  auto size = v.size()*sizeof(std::basic_string<Elem>::value_type);
	char* ptr = (char*)o.zone->malloc(size);
	o.via.raw.ptr = ptr;
	o.via.raw.size = (uint32_t)size;
	memcpy(ptr, v.data(), size);
}
template <typename Elem>
inline void operator<< (object& o, const std::basic_string<Elem>& v)
{
	o.type = type::RAW;
	o.via.raw.ptr = v.data();
	o.via.raw.size = (uint32_t)(v.size()*sizeof(std::basic_string<Elem>::value_type));
}

}  // namespace msgpack

#endif /* msgpack/type/string.hpp */

<|endoftext|>


<commit_before>#include <algorithm>
#include <cassert>
#include <iomanip>
#include <iostream>
#include <sstream>
#include <string>

#include <getopt.h>
#include <sys/time.h>

#include <ast/statement/node.h>
#include <parser/driver.h>
#include <util/filesystem.h>

using namespace std;
using namespace venom;

/**
 * This Timer class taken from cryptdb
 */
class Timer {
private:
  Timer(const Timer &t);  /* no reason to copy timer objects */
public:
  Timer() { lap(); }

  /** microseconds */
  inline uint64_t lap() {
    uint64_t t0 = start;
    uint64_t t1 = cur_usec();
    start = t1;
    return t1 - t0;
  }

  /** milliseconds */
  inline double lap_ms() { return ((double)lap()) / 1000.0; }

private:
  static inline uint64_t cur_usec() {
    struct timeval tv;
    gettimeofday(&tv, 0);
    return ((uint64_t)tv.tv_sec) * 1000000 + tv.tv_usec;
  }
  uint64_t start;
};

inline string pad(const string& orig, size_t s) {
  if (orig.size() > s) return orig;
  stringstream buf;
  buf << orig;
  buf << string(s - orig.size(), ' ');
  return buf.str();
}

void run_test(bool success, const string& srcfile, size_t alignSize) {
  compile_result result;
  Timer t;
  bool res = compile_and_exec(srcfile, result);
  double exec_ms = t.lap_ms();
  cout.setf(ios::fixed, ios::floatfield);
  cout.precision(3);
  if (success) {
    if (res) {
      cout << "File " << pad(srcfile, alignSize) << " (" << exec_ms << " ms) [OK]" << endl;
    } else {
      cout << "File " << pad(srcfile, alignSize) << " (" << exec_ms << " ms) [FAILED]" << endl;
    }
  } else {
    if (!res) {
      cout << "File " << pad(srcfile, alignSize) << " (" << exec_ms << " ms) [OK]" << endl;
    } else {
      cout << "File " << pad(srcfile, alignSize) << " (" << exec_ms << " ms) [FAILED]" << endl;
    }
  }
  cout.unsetf(ios::floatfield);
}

struct max_size_functor_t {
  inline bool operator()(const string& largest, const string& elem) const {
    return elem.size() > largest.size();
  }
} max_size_functor;

void run_tests(bool success, const vector<string>& srcfiles, const string& import_path) {
  global_compile_opts.venom_import_path = import_path;
  global_compile_opts.semantic_check_only = true;
  vector<string>::const_iterator largest =
    max_element(srcfiles.begin(), srcfiles.end(), max_size_functor);
  for (vector<string>::const_iterator it = srcfiles.begin();
       it != srcfiles.end(); ++it) {
    run_test(success, *it, largest->size());
  }
}

int main(int argc, char **argv) {
  string success_dir = "../test/success";
  string failure_dir = "../test/failure";
  while (true) {
    static struct option long_options[] = {
      {"success-dir", required_argument, 0, 's'},
      {"failure-dir", required_argument, 0, 'b'},
      {0, 0, 0, 0}
    };
    int option_index = 0;
    int c = getopt_long(argc, argv, "s:f:",
                        long_options, &option_index);
    if (c == -1) break;
    switch (c) {
    case 's':
      success_dir = optarg;
      break;
    case 'b':
      failure_dir = optarg;
      break;
    case '?':
      /* getopt_long already printed an error message. */
      break;
    default: assert(false);
    }
  }

  vector<string> success_files;
  if (!util::listfiles(success_dir, success_files,
                       util::listfiles_ext_filter("venom"), true)) {
    cerr << "Cannot open directory: " << success_dir << endl;
    return 1;
  }

  vector<string> failure_files;
  if (!util::listfiles(failure_dir, failure_files,
                       util::listfiles_ext_filter("venom"), true)) {
    cerr << "Cannot open directory: " << failure_dir << endl;
    return 1;
  }

  cout << "Running success tests" << endl;
  run_tests(true, success_files, success_dir);

  cout << endl << "Running failure tests" << endl;
  run_tests(false, failure_files, failure_dir);

  return 0;
}
<commit_msg>Use fork() in tests<commit_after>#include <algorithm>
#include <cassert>
#include <cstdlib>
#include <iomanip>
#include <iostream>
#include <sstream>
#include <string>

#include <errno.h>
#include <getopt.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>

#include <ast/statement/node.h>
#include <parser/driver.h>
#include <util/filesystem.h>

using namespace std;
using namespace venom;

/**
 * This Timer class taken from cryptdb
 */
class Timer {
private:
  Timer(const Timer &t);  /* no reason to copy timer objects */
public:
  Timer() { lap(); }

  /** microseconds */
  inline uint64_t lap() {
    uint64_t t0 = start;
    uint64_t t1 = cur_usec();
    start = t1;
    return t1 - t0;
  }

  /** milliseconds */
  inline double lap_ms() { return ((double)lap()) / 1000.0; }

private:
  static inline uint64_t cur_usec() {
    struct timeval tv;
    gettimeofday(&tv, 0);
    return ((uint64_t)tv.tv_sec) * 1000000 + tv.tv_usec;
  }
  uint64_t start;
};

inline string pad(const string& orig, size_t s) {
  if (orig.size() > s) return orig;
  stringstream buf;
  buf << orig;
  buf << string(s - orig.size(), ' ');
  return buf.str();
}

void run_test(bool success, const string& srcfile, size_t alignSize) {
  Timer t;

  // run test in separate process, so that any nasty errors don't
  // break the whole test suite
  pid_t pid = fork();
  int status;
  if (pid == 0) {
    // child
    compile_result result;
    bool res = compile_and_exec(srcfile, result);
    _exit(res ? 0 : 1); // *must* be _exit() *not* exit()
  } else if (pid < 0) {
    // error in fork
    cerr << "Fatal error: could not fork (errno: " << errno << ")" << endl;
    exit(1);
  } else {
    // parent
    pid_t ret = waitpid(pid, &status, 0);
    if (ret == -1) {
      cerr << "Fatal error: waitpid (errno: " << errno << ")" << endl;
      exit(1);
    }
  }

  bool res;
  if (WIFEXITED(status)) {
    res = WEXITSTATUS(status) == 0;
  } else if (WIFSIGNALED(status)) {
    res = false;
  } else VENOM_NOT_REACHED;

  double exec_ms = t.lap_ms();
  cout.setf(ios::fixed, ios::floatfield);
  cout.precision(3);
  if (success) {
    if (res) {
      cout << "File " << pad(srcfile, alignSize) << " (" << exec_ms << " ms) [OK]" << endl;
    } else {
      cout << "File " << pad(srcfile, alignSize) << " (" << exec_ms << " ms) [FAILED]" << endl;
    }
  } else {
    if (!res) {
      cout << "File " << pad(srcfile, alignSize) << " (" << exec_ms << " ms) [OK]" << endl;
    } else {
      cout << "File " << pad(srcfile, alignSize) << " (" << exec_ms << " ms) [FAILED]" << endl;
    }
  }
  cout.unsetf(ios::floatfield);
}

struct max_size_functor_t {
  inline bool operator()(const string& largest, const string& elem) const {
    return elem.size() > largest.size();
  }
} max_size_functor;

void run_tests(bool success, const vector<string>& srcfiles, const string& import_path) {
  global_compile_opts.venom_import_path = import_path;
  global_compile_opts.semantic_check_only = true;
  vector<string>::const_iterator largest =
    max_element(srcfiles.begin(), srcfiles.end(), max_size_functor);
  for (vector<string>::const_iterator it = srcfiles.begin();
       it != srcfiles.end(); ++it) {
    run_test(success, *it, largest->size());
  }
}

int main(int argc, char **argv) {
  string success_dir = "../test/success";
  string failure_dir = "../test/failure";
  while (true) {
    static struct option long_options[] = {
      {"success-dir", required_argument, 0, 's'},
      {"failure-dir", required_argument, 0, 'b'},
      {0, 0, 0, 0}
    };
    int option_index = 0;
    int c = getopt_long(argc, argv, "s:f:",
                        long_options, &option_index);
    if (c == -1) break;
    switch (c) {
    case 's':
      success_dir = optarg;
      break;
    case 'b':
      failure_dir = optarg;
      break;
    case '?':
      /* getopt_long already printed an error message. */
      break;
    default: assert(false);
    }
  }

  vector<string> success_files;
  if (!util::listfiles(success_dir, success_files,
                       util::listfiles_ext_filter("venom"), true)) {
    cerr << "Cannot open directory: " << success_dir << endl;
    return 1;
  }

  vector<string> failure_files;
  if (!util::listfiles(failure_dir, failure_files,
                       util::listfiles_ext_filter("venom"), true)) {
    cerr << "Cannot open directory: " << failure_dir << endl;
    return 1;
  }

  cout << "Running success tests" << endl;
  run_tests(true, success_files, success_dir);

  cout << endl << "Running failure tests" << endl;
  run_tests(false, failure_files, failure_dir);

  return 0;
}
<|endoftext|>


<commit_before>/**
 * @file
 *
 * @brief Tests for yamlcpp plugin
 *
 * @copyright BSD License (see LICENSE.md or https://www.libelektra.org)
 *
 */

// -- Imports ------------------------------------------------------------------------------------------------------------------------------

#include "yamlcpp.hpp"

#include <kdbmodule.h>
#include <kdbprivate.h>

#include <tests.h>
#include <tests.hpp>

using ckdb::keyNew;

using CppKeySet = kdb::KeySet;
using CppKey = kdb::Key;

// -- Macros -------------------------------------------------------------------------------------------------------------------------------

#define OPEN_PLUGIN(parentName, filepath)                                                                                \
	CppKeySet modules{ 0, KS_END };                                                                                \
	CppKeySet config{ 0, KS_END };                                                                                \
	elektraModulesInit (modules.getKeySet (), 0);                                                                                \
	CppKey parent{ parentName, KEY_VALUE, filepath, KEY_END };                                                                         \
	Plugin * plugin = elektraPluginOpen ("yamlcpp", modules.getKeySet (), config.getKeySet (), *parent);                               \
	exit_if_fail (plugin != NULL, "Could not open yamlcpp plugin")

#define CLOSE_PLUGIN()                                                                                \
	elektraPluginClose (plugin, 0);                                                                                \
	elektraModulesClose (modules.getKeySet (), 0);                                                                                \
	ksDel (modules.release ());                                                                                \
	config.release ()

/* We use this prefix in all header files that contain test data. */
#define PREFIX "user/examples/yamlcpp/"

// -- Functions ----------------------------------------------------------------------------------------------------------------------------

TEST (yamlcpp, contract)
{
	OPEN_PLUGIN ("system/elektra/modules/yamlcpp", "file/path");

	CppKeySet keys;
	succeed_if_same (plugin->kdbGet (plugin, keys.getKeySet (), *parent), ELEKTRA_PLUGIN_STATUS_SUCCESS,
			 "Unable to retrieve plugin contract");

	CLOSE_PLUGIN ();
}

void update_parent (CppKeySet expected, string const filepath)
{
	// We replace the value of the parent key of expected keyset, if the header file specifies the value @CONFIG_FILEPATH@.
	// We could also do that via CMake, but the current solution should be easier for now.
	CppKey root = expected.lookup (PREFIX, KDB_O_POP);
	if (root)
	{
		if (root.getString () == "@CONFIG_FILEPATH@") root.setString (filepath);
		expected.append (root);
	}
}

static void test_read (string const & filename, CppKeySet expected, int const status = ELEKTRA_PLUGIN_STATUS_SUCCESS)
#ifdef __llvm__
	__attribute__ ((annotate ("oclint:suppress")))
#endif
{
	string filepath = srcdir_file (filename.c_str ());
	update_parent (expected, filepath);

	OPEN_PLUGIN (PREFIX, filepath.c_str ());

	CppKeySet keys;
	succeed_if_same (plugin->kdbGet (plugin, keys.getKeySet (), *parent), status, parent.getMeta<string> ("error/reason"));
	compare_keyset (keys, expected);

	CLOSE_PLUGIN ();
}

static void test_write_read (CppKeySet expected)
#ifdef __llvm__
	__attribute__ ((annotate ("oclint:suppress")))
#endif
{
	string filepath = elektraFilename ();
	update_parent (expected, filepath);

	OPEN_PLUGIN (PREFIX, filepath.c_str ());

	// Write key set to file
	succeed_if_same (plugin->kdbSet (plugin, expected.getKeySet (), *parent), ELEKTRA_PLUGIN_STATUS_SUCCESS,
			 parent.getMeta<string> ("error/reason"));

	// Read written data
	CppKeySet keySetRead;
	succeed_if_same (plugin->kdbGet (plugin, keySetRead.getKeySet (), *parent), ELEKTRA_PLUGIN_STATUS_SUCCESS,
			 parent.getMeta<string> ("error/reason"));

	// Compare data
	compare_keyset (keySetRead, expected);

	// Clean up
	CLOSE_PLUGIN ();
}

TEST (yamlcpp, flat)
{
	test_read ("yamlcpp/flat_block_mapping.yaml",
#include "yamlcpp/flat_block_mapping.h"
	);
	test_write_read (
#include "yamlcpp/flat_block_mapping.h"
	);

	test_read ("yamlcpp/flat_flow_mapping.yaml",
#include "yamlcpp/flat_flow_mapping.h"
	);
	test_write_read (
#include "yamlcpp/flat_flow_mapping.h"
	);
}

TEST (yamlcpp, nested)
{
	test_read ("yamlcpp/nested_block_mapping.yaml",
#include "yamlcpp/nested_block_mapping.h"
	);
	test_write_read (
#include "yamlcpp/nested_block_mapping.h"
	);
	test_read ("yamlcpp/nested_mixed_mapping.yaml",
#include "yamlcpp/nested_mixed_mapping.h"
	);
	test_write_read (
#include "yamlcpp/nested_mixed_mapping.h"
	);
}

TEST (yamlcpp, array)
{
	test_read ("yamlcpp/simple_sequence.yaml",
#include "yamlcpp/simple_sequence.h"
	);
	test_write_read (
#include "yamlcpp/simple_sequence.h"
	);

	test_read ("yamlcpp/nested_sequences.yaml",
#include "yamlcpp/nested_sequences.h"
	);
	test_write_read (
#include "yamlcpp/nested_sequences.h"
	);
	test_write_read (
#include "yamlcpp/mapping_with_array_key.h"
	);
	test_write_read (
#include "yamlcpp/mixed.h"
	);
}

// -- Main ---------------------------------------------------------------------------------------------------------------------------------

int main (int argc, char * argv[])
{
	init (argc, argv); // Required for `srcdir_file` to work properly
	::testing::InitGoogleTest (&argc, argv);
	return RUN_ALL_TESTS ();
}
<commit_msg>YAML CPP: Remove unnecessary test code<commit_after>/**
 * @file
 *
 * @brief Tests for yamlcpp plugin
 *
 * @copyright BSD License (see LICENSE.md or https://www.libelektra.org)
 *
 */

// -- Imports ------------------------------------------------------------------------------------------------------------------------------

#include "yamlcpp.hpp"

#include <kdbmodule.h>
#include <kdbprivate.h>

#include <tests.h>
#include <tests.hpp>

using ckdb::keyNew;

using CppKeySet = kdb::KeySet;
using CppKey = kdb::Key;

// -- Macros -------------------------------------------------------------------------------------------------------------------------------

#define OPEN_PLUGIN(parentName, filepath)                                                                                \
	CppKeySet modules{ 0, KS_END };                                                                                \
	CppKeySet config{ 0, KS_END };                                                                                \
	elektraModulesInit (modules.getKeySet (), 0);                                                                                \
	CppKey parent{ parentName, KEY_VALUE, filepath, KEY_END };                                                                         \
	Plugin * plugin = elektraPluginOpen ("yamlcpp", modules.getKeySet (), config.getKeySet (), *parent);                               \
	exit_if_fail (plugin != NULL, "Could not open yamlcpp plugin")

#define CLOSE_PLUGIN()                                                                                \
	elektraPluginClose (plugin, 0);                                                                                \
	elektraModulesClose (modules.getKeySet (), 0);                                                                                \
	ksDel (modules.release ());                                                                                \
	config.release ()

/* We use this prefix in all header files that contain test data. */
#define PREFIX "user/examples/yamlcpp/"

// -- Functions ----------------------------------------------------------------------------------------------------------------------------

TEST (yamlcpp, contract)
{
	OPEN_PLUGIN ("system/elektra/modules/yamlcpp", "file/path");

	CppKeySet keys;
	succeed_if_same (plugin->kdbGet (plugin, keys.getKeySet (), *parent), ELEKTRA_PLUGIN_STATUS_SUCCESS,
			 "Unable to retrieve plugin contract");

	CLOSE_PLUGIN ();
}

static void test_read (string const & filename, CppKeySet expected, int const status = ELEKTRA_PLUGIN_STATUS_SUCCESS)
#ifdef __llvm__
	__attribute__ ((annotate ("oclint:suppress")))
#endif
{
	string filepath = srcdir_file (filename.c_str ());

	OPEN_PLUGIN (PREFIX, filepath.c_str ());

	CppKeySet keys;
	succeed_if_same (plugin->kdbGet (plugin, keys.getKeySet (), *parent), status, parent.getMeta<string> ("error/reason"));
	compare_keyset (keys, expected);

	CLOSE_PLUGIN ();
}

static void test_write_read (CppKeySet expected)
#ifdef __llvm__
	__attribute__ ((annotate ("oclint:suppress")))
#endif
{
	string filepath = elektraFilename ();

	OPEN_PLUGIN (PREFIX, filepath.c_str ());

	// Write key set to file
	succeed_if_same (plugin->kdbSet (plugin, expected.getKeySet (), *parent), ELEKTRA_PLUGIN_STATUS_SUCCESS,
			 parent.getMeta<string> ("error/reason"));

	// Read written data
	CppKeySet keySetRead;
	succeed_if_same (plugin->kdbGet (plugin, keySetRead.getKeySet (), *parent), ELEKTRA_PLUGIN_STATUS_SUCCESS,
			 parent.getMeta<string> ("error/reason"));

	// Compare data
	compare_keyset (keySetRead, expected);

	// Clean up
	CLOSE_PLUGIN ();
}

TEST (yamlcpp, flat)
{
	test_read ("yamlcpp/flat_block_mapping.yaml",
#include "yamlcpp/flat_block_mapping.h"
	);
	test_write_read (
#include "yamlcpp/flat_block_mapping.h"
	);

	test_read ("yamlcpp/flat_flow_mapping.yaml",
#include "yamlcpp/flat_flow_mapping.h"
	);
	test_write_read (
#include "yamlcpp/flat_flow_mapping.h"
	);
}

TEST (yamlcpp, nested)
{
	test_read ("yamlcpp/nested_block_mapping.yaml",
#include "yamlcpp/nested_block_mapping.h"
	);
	test_write_read (
#include "yamlcpp/nested_block_mapping.h"
	);
	test_read ("yamlcpp/nested_mixed_mapping.yaml",
#include "yamlcpp/nested_mixed_mapping.h"
	);
	test_write_read (
#include "yamlcpp/nested_mixed_mapping.h"
	);
}

TEST (yamlcpp, array)
{
	test_read ("yamlcpp/simple_sequence.yaml",
#include "yamlcpp/simple_sequence.h"
	);
	test_write_read (
#include "yamlcpp/simple_sequence.h"
	);

	test_read ("yamlcpp/nested_sequences.yaml",
#include "yamlcpp/nested_sequences.h"
	);
	test_write_read (
#include "yamlcpp/nested_sequences.h"
	);
	test_write_read (
#include "yamlcpp/mapping_with_array_key.h"
	);
	test_write_read (
#include "yamlcpp/mixed.h"
	);
}

// -- Main ---------------------------------------------------------------------------------------------------------------------------------

int main (int argc, char * argv[])
{
	init (argc, argv); // Required for `srcdir_file` to work properly
	::testing::InitGoogleTest (&argc, argv);
	return RUN_ALL_TESTS ();
}
<|endoftext|>


<commit_before>#pragma once
// This class
#include <Manager/ExtraDrainSyncManager.hpp>

/// Project specific
// Engine
#include <DoremiEngine/Physics/Include/PhysicsModule.hpp>
#include <DoremiEngine/Physics/Include/RigidBodyManager.hpp>

// Handlers
#include <EntityComponent/EntityHandler.hpp>
// Components
#include <EntityComponent/Components/RigidBodyComponent.hpp>
#include <EntityComponent/Components/TransformComponent.hpp>

// 3rd party
#include <DirectXMath.h>

using namespace DirectX;
namespace Doremi
{
    namespace Core
    {
        ExtraDrainSyncManager::ExtraDrainSyncManager(const DoremiEngine::Core::SharedContext& p_sharedContext)
            : Manager(p_sharedContext, "ExtraDrainSyncManager")
        {
        }

        ExtraDrainSyncManager::~ExtraDrainSyncManager() {}

        void ExtraDrainSyncManager::Update(double p_dt)
        {
            // Update simulation
            m_sharedContext.GetPhysicsModule().Update(p_dt);
            const size_t length = EntityHandler::GetInstance().GetLastEntityIndex();
            int mask = (int)ComponentType::ExtraDrain | (int)ComponentType::RigidBody;
            for(size_t i = 0; i < length; i++)
            {
                if(EntityHandler::GetInstance().HasComponents(i, mask))
                {
                    // Get relevant components
                    TransformComponent* transComp = EntityHandler::GetInstance().GetComponentFromStorage<TransformComponent>(i);

                    // Get rigid body manager
                    DoremiEngine::Physics::RigidBodyManager& rigidManager = m_sharedContext.GetPhysicsModule().GetRigidBodyManager();

                    // Calculate a rotated orientation
                    XMFLOAT4 newOrientation;
                    XMVECTOR rotationModVec = XMQuaternionRotationAxis(XMLoadFloat3(&XMFLOAT3(0, 0, 1)), 3.1415 / 2);

                    XMStoreFloat4(&newOrientation, XMQuaternionMultiply(XMLoadFloat4(&transComp->rotation), rotationModVec));
                    // Set position of drain so it follows us around
                    rigidManager.SetBodyPosition(i, transComp->position, newOrientation);
                }
            }
        }

        void ExtraDrainSyncManager::OnEvent(Event* p_event) {}
    }
}<commit_msg>Changed PI/2 to a precomputed XM PI/2<commit_after>#pragma once
// This class
#include <Manager/ExtraDrainSyncManager.hpp>

/// Project specific
// Engine
#include <DoremiEngine/Physics/Include/PhysicsModule.hpp>
#include <DoremiEngine/Physics/Include/RigidBodyManager.hpp>

// Handlers
#include <EntityComponent/EntityHandler.hpp>
// Components
#include <EntityComponent/Components/RigidBodyComponent.hpp>
#include <EntityComponent/Components/TransformComponent.hpp>

// 3rd party
#include <DirectXMath.h>

using namespace DirectX;
namespace Doremi
{
    namespace Core
    {
        ExtraDrainSyncManager::ExtraDrainSyncManager(const DoremiEngine::Core::SharedContext& p_sharedContext)
            : Manager(p_sharedContext, "ExtraDrainSyncManager")
        {
        }

        ExtraDrainSyncManager::~ExtraDrainSyncManager() {}

        void ExtraDrainSyncManager::Update(double p_dt)
        {
            // Update simulation
            m_sharedContext.GetPhysicsModule().Update(p_dt);
            const size_t length = EntityHandler::GetInstance().GetLastEntityIndex();
            int mask = (int)ComponentType::ExtraDrain | (int)ComponentType::RigidBody;
            for(size_t i = 0; i < length; i++)
            {
                if(EntityHandler::GetInstance().HasComponents(i, mask))
                {
                    // Get relevant components
                    TransformComponent* transComp = EntityHandler::GetInstance().GetComponentFromStorage<TransformComponent>(i);

                    // Get rigid body manager
                    DoremiEngine::Physics::RigidBodyManager& rigidManager = m_sharedContext.GetPhysicsModule().GetRigidBodyManager();

                    // Calculate a rotated orientation
                    XMFLOAT4 newOrientation;
                    XMVECTOR rotationModVec = XMQuaternionRotationAxis(XMLoadFloat3(&XMFLOAT3(0, 0, 1)), XM_PIDIV2);

                    XMStoreFloat4(&newOrientation, XMQuaternionMultiply(XMLoadFloat4(&transComp->rotation), rotationModVec));
                    // Set position of drain so it follows us around
                    rigidManager.SetBodyPosition(i, transComp->position, newOrientation);
                }
            }
        }

        void ExtraDrainSyncManager::OnEvent(Event* p_event) {}
    }
}<|endoftext|>


<commit_before><commit_msg>Update ch_controller.cc<commit_after><|endoftext|>


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

#include "util/codec.h"
#include <boost/assign/list_of.hpp>

#include "util/compress.h"
#include "util/decompress.h"

#include "gen-cpp/Descriptors_types.h"
#include "gen-cpp/Descriptors_constants.h"

using namespace std;
using namespace boost;
using namespace boost::assign;
using namespace impala;

const char* const Codec::DEFAULT_COMPRESSION =
     "org.apache.hadoop.io.compress.DefaultCodec";

const char* const Codec::GZIP_COMPRESSION =
     "org.apache.hadoop.io.compress.GzipCodec";

const char* const Codec::BZIP2_COMPRESSION =
     "org.apache.hadoop.io.compress.BZip2Codec";

const char* const Codec::SNAPPY_COMPRESSION =
     "org.apache.hadoop.io.compress.SnappyCodec";

const Codec::CodecMap Codec::CODEC_MAP = map_list_of
  ("", THdfsCompression::NONE)
  (Codec::DEFAULT_COMPRESSION, THdfsCompression::DEFAULT)
  (Codec::GZIP_COMPRESSION, THdfsCompression::GZIP)
  (Codec::BZIP2_COMPRESSION, THdfsCompression::BZIP2)
  (Codec::SNAPPY_COMPRESSION, THdfsCompression::SNAPPY_BLOCKED);

string Codec::GetCodecName(THdfsCompression::type type) {
  map<const string, THdfsCompression::type>::const_iterator im;
  for (im = g_Descriptors_constants.COMPRESSION_MAP.begin();
       im != g_Descriptors_constants.COMPRESSION_MAP.end(); ++im) {
    if (im->second == type) return im->first;
  }
  DCHECK(im != g_Descriptors_constants.COMPRESSION_MAP.end());
  return "INVALID";
}

Status Codec::CreateCompressor(RuntimeState* runtime_state, MemPool* mem_pool,
                               bool reuse, const string& codec,
                               scoped_ptr<Codec>* compressor) {
  map<const string, const THdfsCompression::type>::const_iterator
      type = CODEC_MAP.find(codec);

  if (type == CODEC_MAP.end()) {
    stringstream ss;
    ss << "Unknown Codec: " << codec;
    return Status(ss.str());
  }
  Codec* comp;
  RETURN_IF_ERROR(
      CreateCompressor(runtime_state, mem_pool, reuse, type->second, &comp));
  compressor->reset(comp);
  return Status::OK;
}

Status Codec::CreateCompressor(RuntimeState* runtime_state, MemPool* mem_pool,
                               bool reuse, THdfsCompression::type format,
                               scoped_ptr<Codec>* compressor) {
  Codec* comp;
  RETURN_IF_ERROR(
      CreateCompressor(runtime_state, mem_pool, reuse, format, &comp));
  compressor->reset(comp);
  return Status::OK;
}

Status Codec::CreateCompressor(RuntimeState* runtime_state, MemPool* mem_pool,
                               bool reuse, THdfsCompression::type format,
                               Codec** compressor) {
  switch (format) {
    case THdfsCompression::NONE:
      *compressor = NULL;
      return Status::OK;
    case THdfsCompression::GZIP:
      *compressor = new GzipCompressor(GzipCompressor::GZIP, mem_pool, reuse);
      break;
    case THdfsCompression::DEFAULT:
      *compressor = new GzipCompressor(GzipCompressor::ZLIB, mem_pool, reuse);
      break;
    case THdfsCompression::DEFLATE:
      *compressor = new GzipCompressor(GzipCompressor::DEFLATE, mem_pool, reuse);
      break;
    case THdfsCompression::BZIP2:
      *compressor = new BzipCompressor(mem_pool, reuse);
      break;
    case THdfsCompression::SNAPPY_BLOCKED:
      *compressor = new SnappyBlockCompressor(mem_pool, reuse);
      break;
    case THdfsCompression::SNAPPY:
      *compressor = new SnappyCompressor(mem_pool, reuse);
      break;
  }

  return (*compressor)->Init();
}

Status Codec::CreateDecompressor(RuntimeState* runtime_state, MemPool* mem_pool,
                                 bool reuse, const string& codec,
                                 scoped_ptr<Codec>* decompressor) {
  map<const string, const THdfsCompression::type>::const_iterator
      type = CODEC_MAP.find(codec);

  if (type == CODEC_MAP.end()) {
    stringstream ss;
    ss << "Unknown Codec: " << codec;
    return Status(ss.str());
  }
  Codec* decom;
  RETURN_IF_ERROR(
      CreateDecompressor(runtime_state, mem_pool, reuse, type->second, &decom));
  decompressor->reset(decom);
  return Status::OK;
}

Status Codec::CreateDecompressor(RuntimeState* runtime_state, MemPool* mem_pool,
                                 bool reuse, THdfsCompression::type format,
                                 scoped_ptr<Codec>* decompressor) {
  Codec* decom;
  RETURN_IF_ERROR(
      CreateDecompressor(runtime_state, mem_pool, reuse, format, &decom));
  decompressor->reset(decom);
  return Status::OK;
}

Status Codec::CreateDecompressor(RuntimeState* runtime_state, MemPool* mem_pool,
                                 bool reuse, THdfsCompression::type format,
                                 Codec** decompressor) {
  switch (format) {
    case THdfsCompression::NONE:
      *decompressor = NULL;
      return Status::OK;
    case THdfsCompression::DEFAULT:
    case THdfsCompression::GZIP:
      *decompressor = new GzipDecompressor(mem_pool, reuse, false);
      break;
    case THdfsCompression::DEFLATE:
      *decompressor = new GzipDecompressor(mem_pool, reuse, true);
      break;
    case THdfsCompression::BZIP2:
      *decompressor = new BzipDecompressor(mem_pool, reuse);
      break;
    case THdfsCompression::SNAPPY_BLOCKED:
      *decompressor = new SnappyBlockDecompressor(mem_pool, reuse);
      break;
    case THdfsCompression::SNAPPY:
      *decompressor = new SnappyDecompressor(mem_pool, reuse);
      break;
  }

  return (*decompressor)->Init();
}

Codec::Codec(MemPool* mem_pool, bool reuse_buffer)
  : memory_pool_(mem_pool),
    reuse_buffer_(reuse_buffer),
    out_buffer_(NULL),
    buffer_length_(0) {
}

<commit_msg>Make unsupported codec message a little clearer.<commit_after>// Copyright 2012 Cloudera Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "util/codec.h"
#include <boost/assign/list_of.hpp>

#include "util/compress.h"
#include "util/decompress.h"

#include "gen-cpp/Descriptors_types.h"
#include "gen-cpp/Descriptors_constants.h"

using namespace std;
using namespace boost;
using namespace boost::assign;
using namespace impala;

const char* const Codec::DEFAULT_COMPRESSION =
    "org.apache.hadoop.io.compress.DefaultCodec";

const char* const Codec::GZIP_COMPRESSION =
    "org.apache.hadoop.io.compress.GzipCodec";

const char* const Codec::BZIP2_COMPRESSION =
    "org.apache.hadoop.io.compress.BZip2Codec";

const char* const Codec::SNAPPY_COMPRESSION =
    "org.apache.hadoop.io.compress.SnappyCodec";

const char* const UNKNOWN_CODEC_ERROR =
    "This compression codec is currently unsupported: ";

const Codec::CodecMap Codec::CODEC_MAP = map_list_of
  ("", THdfsCompression::NONE)
  (Codec::DEFAULT_COMPRESSION, THdfsCompression::DEFAULT)
  (Codec::GZIP_COMPRESSION, THdfsCompression::GZIP)
  (Codec::BZIP2_COMPRESSION, THdfsCompression::BZIP2)
  (Codec::SNAPPY_COMPRESSION, THdfsCompression::SNAPPY_BLOCKED);

string Codec::GetCodecName(THdfsCompression::type type) {
  map<const string, THdfsCompression::type>::const_iterator im;
  for (im = g_Descriptors_constants.COMPRESSION_MAP.begin();
       im != g_Descriptors_constants.COMPRESSION_MAP.end(); ++im) {
    if (im->second == type) return im->first;
  }
  DCHECK(im != g_Descriptors_constants.COMPRESSION_MAP.end());
  return "INVALID";
}

Status Codec::CreateCompressor(RuntimeState* runtime_state, MemPool* mem_pool,
                               bool reuse, const string& codec,
                               scoped_ptr<Codec>* compressor) {
  map<const string, const THdfsCompression::type>::const_iterator
      type = CODEC_MAP.find(codec);

  if (type == CODEC_MAP.end()) {
    stringstream ss;
    ss << UNKNOWN_CODEC_ERROR << codec;
    return Status(ss.str());
  }
  Codec* comp;
  RETURN_IF_ERROR(
      CreateCompressor(runtime_state, mem_pool, reuse, type->second, &comp));
  compressor->reset(comp);
  return Status::OK;
}

Status Codec::CreateCompressor(RuntimeState* runtime_state, MemPool* mem_pool,
                               bool reuse, THdfsCompression::type format,
                               scoped_ptr<Codec>* compressor) {
  Codec* comp;
  RETURN_IF_ERROR(
      CreateCompressor(runtime_state, mem_pool, reuse, format, &comp));
  compressor->reset(comp);
  return Status::OK;
}

Status Codec::CreateCompressor(RuntimeState* runtime_state, MemPool* mem_pool,
                               bool reuse, THdfsCompression::type format,
                               Codec** compressor) {
  switch (format) {
    case THdfsCompression::NONE:
      *compressor = NULL;
      return Status::OK;
    case THdfsCompression::GZIP:
      *compressor = new GzipCompressor(GzipCompressor::GZIP, mem_pool, reuse);
      break;
    case THdfsCompression::DEFAULT:
      *compressor = new GzipCompressor(GzipCompressor::ZLIB, mem_pool, reuse);
      break;
    case THdfsCompression::DEFLATE:
      *compressor = new GzipCompressor(GzipCompressor::DEFLATE, mem_pool, reuse);
      break;
    case THdfsCompression::BZIP2:
      *compressor = new BzipCompressor(mem_pool, reuse);
      break;
    case THdfsCompression::SNAPPY_BLOCKED:
      *compressor = new SnappyBlockCompressor(mem_pool, reuse);
      break;
    case THdfsCompression::SNAPPY:
      *compressor = new SnappyCompressor(mem_pool, reuse);
      break;
  }

  return (*compressor)->Init();
}

Status Codec::CreateDecompressor(RuntimeState* runtime_state, MemPool* mem_pool,
                                 bool reuse, const string& codec,
                                 scoped_ptr<Codec>* decompressor) {
  map<const string, const THdfsCompression::type>::const_iterator
      type = CODEC_MAP.find(codec);

  if (type == CODEC_MAP.end()) {
    stringstream ss;
    ss << UNKNOWN_CODEC_ERROR << codec;
    return Status(ss.str());
  }
  Codec* decom;
  RETURN_IF_ERROR(
      CreateDecompressor(runtime_state, mem_pool, reuse, type->second, &decom));
  decompressor->reset(decom);
  return Status::OK;
}

Status Codec::CreateDecompressor(RuntimeState* runtime_state, MemPool* mem_pool,
                                 bool reuse, THdfsCompression::type format,
                                 scoped_ptr<Codec>* decompressor) {
  Codec* decom;
  RETURN_IF_ERROR(
      CreateDecompressor(runtime_state, mem_pool, reuse, format, &decom));
  decompressor->reset(decom);
  return Status::OK;
}

Status Codec::CreateDecompressor(RuntimeState* runtime_state, MemPool* mem_pool,
                                 bool reuse, THdfsCompression::type format,
                                 Codec** decompressor) {
  switch (format) {
    case THdfsCompression::NONE:
      *decompressor = NULL;
      return Status::OK;
    case THdfsCompression::DEFAULT:
    case THdfsCompression::GZIP:
      *decompressor = new GzipDecompressor(mem_pool, reuse, false);
      break;
    case THdfsCompression::DEFLATE:
      *decompressor = new GzipDecompressor(mem_pool, reuse, true);
      break;
    case THdfsCompression::BZIP2:
      *decompressor = new BzipDecompressor(mem_pool, reuse);
      break;
    case THdfsCompression::SNAPPY_BLOCKED:
      *decompressor = new SnappyBlockDecompressor(mem_pool, reuse);
      break;
    case THdfsCompression::SNAPPY:
      *decompressor = new SnappyDecompressor(mem_pool, reuse);
      break;
  }

  return (*decompressor)->Init();
}

Codec::Codec(MemPool* mem_pool, bool reuse_buffer)
  : memory_pool_(mem_pool),
    reuse_buffer_(reuse_buffer),
    out_buffer_(NULL),
    buffer_length_(0) {
}

<|endoftext|>