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

#include "ccode.hpp"

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

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

namespace
{

/**
 * @brief Cast a character to an unsigned character.
 *
 * @param character This parameter specifies the character this function casts to an unsigned value.
 *
 * @return A unsigned character corresponding to the given argument
 */
inline constexpr unsigned char operator"" _uc (char character) noexcept
{
	return static_cast<unsigned char> (character);
}

/**
 * @brief This function maps hex characters to integer numbers.
 *
 * @pre The specified character has to be between
 *
 *      - `'0'`–`'9'`,
 *      - `'a'`-`'f'`, or
 *      - `'A'`-`'F'`
 *
 *     .
 *
 * @param character This argument specifies the (hexadecimal) character this function converts.
 *
 * @return An integer number between `0` and `15` if the precondition is valid or `0` otherwise
 */
inline int elektraHexcodeConvFromHex (char character)
{
	if (character >= '0' && character <= '9') return character - '0';
	if (character >= 'a' && character <= 'f') return character - 'a' + 10;
	if (character >= 'A' && character <= 'F') return character - 'A' + 10;

	return 0; /* Unknown escape char */
}

/**
 * @brief This function returns a key set containing the contract of this plugin.
 *
 * @return A contract describing the functionality of this plugin.
 */
inline KeySet * contract (void)
{
	return ksNew (30, keyNew ("system/elektra/modules/ccode", KEY_VALUE, "ccode plugin waits for your orders", KEY_END),
		      keyNew ("system/elektra/modules/ccode/exports", KEY_END),
		      keyNew ("system/elektra/modules/ccode/exports/open", KEY_FUNC, elektraCcodeOpen, KEY_END),
		      keyNew ("system/elektra/modules/ccode/exports/close", KEY_FUNC, elektraCcodeClose, KEY_END),
		      keyNew ("system/elektra/modules/ccode/exports/get", KEY_FUNC, elektraCcodeGet, KEY_END),
		      keyNew ("system/elektra/modules/ccode/exports/set", KEY_FUNC, elektraCcodeSet, KEY_END),
#include "readme_ccode.c"
		      keyNew ("system/elektra/modules/ccode/infos/version", KEY_VALUE, PLUGINVERSION, KEY_END), KS_END);
}

/**
 * @brief Retrieve the mapping data and initialize the buffer if it is empty.
 *
 * @return The mapping data stored by this plugin.
 */
CCodeData * retrieveMapping (Plugin * handle)
{
	CCodeData * const mapping = static_cast<CCodeData *> (elektraPluginGetData (handle));
	if (!mapping->buffer)
	{
		mapping->bufferSize = 1000;
		mapping->buffer = new unsigned char[mapping->bufferSize];
	}
	return mapping;
}

/**
 * @brief This function sets default values for the encoding and decoding character mapping.
 *
 * @param mapping This parameter stores the encoding and decoding table this function fills with default values.
 */
void setDefaultConfig (CCodeData * const mapping)
{
	unsigned char pairs[][2] = { { '\b'_uc, 'b'_uc }, { '\t'_uc, 't'_uc }, { '\n'_uc, 'n'_uc },  { '\v'_uc, 'v'_uc },
				     { '\f'_uc, 'f'_uc }, { '\r'_uc, 'r'_uc }, { '\\'_uc, '\\'_uc }, { '\''_uc, '\''_uc },
				     { '\"'_uc, '"'_uc }, { '\0'_uc, '0'_uc } };

	for (size_t pair = 0; pair < sizeof (pairs) / sizeof (pairs[0]); pair++)
	{
		unsigned char character = pairs[pair][0];
		unsigned char replacement = pairs[pair][1];

		mapping->encode[character] = replacement;
		mapping->decode[replacement] = character;
	}
}

/**
 * @brief This function sets values for the encoding and decoding character mapping.
 *
 * @param mapping This parameter stores the encoding and decoding table this function fills with the values specified in `config`.
 * @param config This key set stores the character mappings this function stores inside `mappings`.
 * @param root This key stores the root key for the character mapping stored in `config`.
 */
void readConfig (CCodeData * const mapping, KeySet * const config, Key const * const root)
{
	Key const * key = 0;
	while ((key = ksNext (config)) != 0)
	{
		/* Ignore keys that are not directly below the config root key or have an incorrect size */
		if (keyRel (root, key) != 1 || keyGetBaseNameSize (key) != 3 || keyGetValueSize (key) != 3) continue;

		int character = elektraHexcodeConvFromHex (keyBaseName (key)[1]);
		character += elektraHexcodeConvFromHex (keyBaseName (key)[0]) * 16;

		int replacement = elektraHexcodeConvFromHex (keyString (key)[1]);
		replacement += elektraHexcodeConvFromHex (keyString (key)[0]) * 16;

		/* Hexencode this character! */
		mapping->encode[character & 255] = replacement;
		mapping->decode[replacement & 255] = character;
	}
}

/**
 * @brief This function replaces escaped characters in a string with unescaped characters.
 *
 * The function stores the unescaped result in `mapping->buffer`.
 *
 * @pre The variable `mapping->buffer` needs to be as large as `size`.
 *
 * @param value This string stores the string this function decodes.
 * @param size This number specifies the size of `value` including the trailing `'\0'` character.
 * @param mapping This variable stores the buffer and the character mapping this function uses to decode `value`.
 *
 * @return The size of the decoded string including the trailing `'\0'` character
 */
size_t decode (char const * const value, size_t const size, CCodeData * mapping)
{
	size_t out = 0;
	for (size_t in = 0; in < size - 1; ++in)
	{
		unsigned char character = value[in];

		if (character == mapping->escape)
		{
			++in; /* Advance twice */
			character = value[in];

			mapping->buffer[out] = mapping->decode[character & 255];
		}
		else
		{
			mapping->buffer[out] = character;
		}
		++out; /* Only one char is written */
	}

	mapping->buffer[out] = 0; // null termination for keyString()
	return out + 1;
}

/**
 * @brief This function replaces unescaped characters in a string with escaped characters.
 *
 * The function stores the escaped result value in `mapping->buffer`.
 *
 * @pre The variable `mapping->buffer` needs to be twice as large as size.
 *
 * @param value This variable stores the string this function escapes.
 * @param size This number specifies the size of `value` including the trailing `'\0'` character.
 * @param mapping This variable stores the buffer and the character mapping this function uses to encode `value`.
 *
 * @return The size of the encoded string including the trailing `'\0'` character
 */
size_t encode (char const * const value, size_t const size, CCodeData * mapping)
{
	size_t out = 0;
	for (size_t in = 0; in < size - 1; ++in)
	{
		unsigned char character = value[in];

		if (mapping->encode[character])
		{
			mapping->buffer[out + 1] = mapping->encode[character];
			// Escape char
			mapping->buffer[out] = mapping->escape;
			out += 2;
		}
		else
		{
			// just copy one character
			mapping->buffer[out] = value[in];
			// advance out cursor
			out++;
		}
	}

	mapping->buffer[out] = 0; // null termination for keyString()
	return out + 1;
}

} // end namespace

extern "C" {

/**
 * @brief This function replaces escaped character in a key value with unescaped characters.
 *
 * The function stores the unescaped result value both in `mapping->buffer` and the given key.
 *
 * @pre The variable `mapping->buffer` needs to be as large as the key value’s size.
 *
 * @param key This key holds the value this function decodes.
 * @param mapping This variable stores the buffer and the character mapping this function uses to decode the value of the given key.
 */
void elektraCcodeDecode (Key * key, CCodeData * mapping)
{
	const char * value = static_cast<const char *> (keyValue (key));
	if (!value) return;

	keySetRaw (key, mapping->buffer, decode (value, keyGetValueSize (key), mapping));
}

/**
 * @brief This function replaces unescaped character in a key value with escaped characters.
 *
 * The function stores the escaped result value both in `mapping->buffer` and the given key.
 *
 * @pre The variable `mapping->buffer` needs to be twice as large as the key value’s size.
 *
 * @param key This key stores the value this function escapes.
 * @param mapping This variable stores the buffer and the character mapping this function uses to encode the value of the given key.
 */
void elektraCcodeEncode (Key * key, CCodeData * mapping)
{
	const char * value = static_cast<const char *> (keyValue (key));
	if (!value) return;

	keySetRaw (key, mapping->buffer, encode (value, keyGetValueSize (key), mapping));
}

// ====================
// = Plugin Interface =
// ====================

/** @see elektraDocOpen */
int elektraCcodeOpen (Plugin * handle, Key * key ELEKTRA_UNUSED)
{
	CCodeData * const mapping = new CCodeData ();

	/* Store for later use...*/
	elektraPluginSetData (handle, mapping);

	KeySet * const config = elektraPluginGetConfig (handle);

	Key const * const escape = ksLookupByName (config, "/escape", 0);
	mapping->escape = '\\';
	if (escape && keyGetBaseNameSize (escape) && keyGetValueSize (escape) == 3)
	{
		int escapeChar = elektraHexcodeConvFromHex (keyString (escape)[1]);
		escapeChar += elektraHexcodeConvFromHex (keyString (escape)[0]) * 16;

		mapping->escape = escapeChar & 255;
	}
	ELEKTRA_LOG_DEBUG ("Use “%c” as escape character", mapping->escape);

	Key const * const root = ksLookupByName (config, "/chars", 0);

	if (root)
	{
		readConfig (mapping, config, root);
	}
	else
	{
		setDefaultConfig (mapping);
	}

	return ELEKTRA_PLUGIN_STATUS_NO_UPDATE;
}

/** @see elektraDocClose */
int elektraCcodeClose (Plugin * handle, Key * key ELEKTRA_UNUSED)
{
	CCodeData * const mapping = static_cast<CCodeData *> (elektraPluginGetData (handle));

	delete[](mapping->buffer);
	delete (mapping);

	return ELEKTRA_PLUGIN_STATUS_NO_UPDATE;
}

/** @see elektraDocGet */
int elektraCcodeGet (Plugin * handle, KeySet * returned, Key * parentKey)
{
	if (!strcmp (keyName (parentKey), "system/elektra/modules/ccode"))
	{
		KeySet * const pluginConfig = contract ();
		ksAppend (returned, pluginConfig);
		ksDel (pluginConfig);
		return ELEKTRA_PLUGIN_STATUS_SUCCESS;
	}

	CCodeData * const mapping = retrieveMapping (handle);

	Key * key;
	ksRewind (returned);
	while ((key = ksNext (returned)) != 0)
	{
		size_t const size = keyGetValueSize (key);
		if (size > mapping->bufferSize)
		{
			mapping->bufferSize = size;
			mapping->buffer = new unsigned char[mapping->bufferSize];
		}

		elektraCcodeDecode (key, mapping);
	}

	return ELEKTRA_PLUGIN_STATUS_SUCCESS;
}

/** @see elektraDocSet */
int elektraCcodeSet (Plugin * handle, KeySet * returned, Key * parentKey ELEKTRA_UNUSED)
{
	CCodeData * const mapping = retrieveMapping (handle);

	CppKeySet keys{ returned };
	for (auto key : keys)
	{
		size_t const size = key.getBinarySize () * 2;
		if (size > mapping->bufferSize)
		{
			mapping->bufferSize = size;
			mapping->buffer = new unsigned char[mapping->bufferSize];
		}

		elektraCcodeEncode (*key, mapping);
	}

	keys.release ();
	return ELEKTRA_PLUGIN_STATUS_SUCCESS;
}

Plugin * ELEKTRA_PLUGIN_EXPORT (ccode)
{
	// clang-format off
	return elektraPluginExport("ccode",
		ELEKTRA_PLUGIN_OPEN,	&elektraCcodeOpen,
		ELEKTRA_PLUGIN_CLOSE,	&elektraCcodeClose,
		ELEKTRA_PLUGIN_GET,	&elektraCcodeGet,
		ELEKTRA_PLUGIN_SET,	&elektraCcodeSet,
		ELEKTRA_PLUGIN_END);
}

} // end extern "C"
<commit_msg>CCode: Fix minor spelling mistakes in comments<commit_after>/**
 * @file
 *
 * @brief
 *
 * @copyright BSD License (see LICENSE.md or https://www.libelektra.org)
 */

#include "ccode.hpp"

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

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

namespace
{

/**
 * @brief Cast a character to an unsigned character.
 *
 * @param character This parameter specifies the character this function casts to an unsigned value.
 *
 * @return A unsigned character corresponding to the given argument
 */
inline constexpr unsigned char operator"" _uc (char character) noexcept
{
	return static_cast<unsigned char> (character);
}

/**
 * @brief This function maps hex characters to integer numbers.
 *
 * @pre The specified character has to be between
 *
 *      - `'0'`–`'9'`,
 *      - `'a'`-`'f'`, or
 *      - `'A'`-`'F'`
 *
 *     .
 *
 * @param character This argument specifies the (hexadecimal) character this function converts.
 *
 * @return An integer number between `0` and `15` if the precondition is valid or `0` otherwise
 */
inline int elektraHexcodeConvFromHex (char character)
{
	if (character >= '0' && character <= '9') return character - '0';
	if (character >= 'a' && character <= 'f') return character - 'a' + 10;
	if (character >= 'A' && character <= 'F') return character - 'A' + 10;

	return 0; /* Unknown escape char */
}

/**
 * @brief This function returns a key set containing the contract of this plugin.
 *
 * @return A contract describing the functionality of this plugin.
 */
inline KeySet * contract (void)
{
	return ksNew (30, keyNew ("system/elektra/modules/ccode", KEY_VALUE, "ccode plugin waits for your orders", KEY_END),
		      keyNew ("system/elektra/modules/ccode/exports", KEY_END),
		      keyNew ("system/elektra/modules/ccode/exports/open", KEY_FUNC, elektraCcodeOpen, KEY_END),
		      keyNew ("system/elektra/modules/ccode/exports/close", KEY_FUNC, elektraCcodeClose, KEY_END),
		      keyNew ("system/elektra/modules/ccode/exports/get", KEY_FUNC, elektraCcodeGet, KEY_END),
		      keyNew ("system/elektra/modules/ccode/exports/set", KEY_FUNC, elektraCcodeSet, KEY_END),
#include "readme_ccode.c"
		      keyNew ("system/elektra/modules/ccode/infos/version", KEY_VALUE, PLUGINVERSION, KEY_END), KS_END);
}

/**
 * @brief Retrieve the mapping data and initialize the buffer if it is empty.
 *
 * @return The mapping data stored by this plugin.
 */
CCodeData * retrieveMapping (Plugin * handle)
{
	CCodeData * const mapping = static_cast<CCodeData *> (elektraPluginGetData (handle));
	if (!mapping->buffer)
	{
		mapping->bufferSize = 1000;
		mapping->buffer = new unsigned char[mapping->bufferSize];
	}
	return mapping;
}

/**
 * @brief This function sets default values for the encoding and decoding character mapping.
 *
 * @param mapping This parameter stores the encoding and decoding table this function fills with default values.
 */
void setDefaultConfig (CCodeData * const mapping)
{
	unsigned char pairs[][2] = { { '\b'_uc, 'b'_uc }, { '\t'_uc, 't'_uc }, { '\n'_uc, 'n'_uc },  { '\v'_uc, 'v'_uc },
				     { '\f'_uc, 'f'_uc }, { '\r'_uc, 'r'_uc }, { '\\'_uc, '\\'_uc }, { '\''_uc, '\''_uc },
				     { '\"'_uc, '"'_uc }, { '\0'_uc, '0'_uc } };

	for (size_t pair = 0; pair < sizeof (pairs) / sizeof (pairs[0]); pair++)
	{
		unsigned char character = pairs[pair][0];
		unsigned char replacement = pairs[pair][1];

		mapping->encode[character] = replacement;
		mapping->decode[replacement] = character;
	}
}

/**
 * @brief This function sets values for the encoding and decoding character mapping.
 *
 * @param mapping This parameter stores the encoding and decoding table this function fills with the values specified in `config`.
 * @param config This key set stores the character mappings this function stores inside `mappings`.
 * @param root This key stores the root key for the character mapping stored in `config`.
 */
void readConfig (CCodeData * const mapping, KeySet * const config, Key const * const root)
{
	Key const * key = 0;
	while ((key = ksNext (config)) != 0)
	{
		/* Ignore keys that are not directly below the config root key or have an incorrect size */
		if (keyRel (root, key) != 1 || keyGetBaseNameSize (key) != 3 || keyGetValueSize (key) != 3) continue;

		int character = elektraHexcodeConvFromHex (keyBaseName (key)[1]);
		character += elektraHexcodeConvFromHex (keyBaseName (key)[0]) * 16;

		int replacement = elektraHexcodeConvFromHex (keyString (key)[1]);
		replacement += elektraHexcodeConvFromHex (keyString (key)[0]) * 16;

		/* Hexencode this character! */
		mapping->encode[character & 255] = replacement;
		mapping->decode[replacement & 255] = character;
	}
}

/**
 * @brief This function replaces escaped characters in a string with unescaped characters.
 *
 * The function stores the unescaped result in `mapping->buffer`.
 *
 * @pre The variable `mapping->buffer` needs to be as large as `size`.
 *
 * @param value This string stores the string this function decodes.
 * @param size This number specifies the size of `value` including the trailing `'\0'` character.
 * @param mapping This variable stores the buffer and the character mapping this function uses to decode `value`.
 *
 * @return The size of the decoded string including the trailing `'\0'` character
 */
size_t decode (char const * const value, size_t const size, CCodeData * mapping)
{
	size_t out = 0;
	for (size_t in = 0; in < size - 1; ++in)
	{
		unsigned char character = value[in];

		if (character == mapping->escape)
		{
			++in; /* Advance twice */
			character = value[in];

			mapping->buffer[out] = mapping->decode[character & 255];
		}
		else
		{
			mapping->buffer[out] = character;
		}
		++out; /* Only one char is written */
	}

	mapping->buffer[out] = 0; // null termination for keyString()
	return out + 1;
}

/**
 * @brief This function replaces unescaped characters in a string with escaped characters.
 *
 * The function stores the escaped result value in `mapping->buffer`.
 *
 * @pre The variable `mapping->buffer` needs to be twice as large as size.
 *
 * @param value This variable stores the string this function escapes.
 * @param size This number specifies the size of `value` including the trailing `'\0'` character.
 * @param mapping This variable stores the buffer and the character mapping this function uses to encode `value`.
 *
 * @return The size of the encoded string including the trailing `'\0'` character
 */
size_t encode (char const * const value, size_t const size, CCodeData * mapping)
{
	size_t out = 0;
	for (size_t in = 0; in < size - 1; ++in)
	{
		unsigned char character = value[in];

		if (mapping->encode[character])
		{
			mapping->buffer[out + 1] = mapping->encode[character];
			// Escape char
			mapping->buffer[out] = mapping->escape;
			out += 2;
		}
		else
		{
			// just copy one character
			mapping->buffer[out] = value[in];
			// advance out cursor
			out++;
		}
	}

	mapping->buffer[out] = 0; // null termination for keyString()
	return out + 1;
}

} // end namespace

extern "C" {

/**
 * @brief This function replaces escaped characters in a key value with unescaped characters.
 *
 * The function stores the unescaped result value both in `mapping->buffer` and the given key.
 *
 * @pre The variable `mapping->buffer` needs to be as large as the key value’s size.
 *
 * @param key This key holds the value this function decodes.
 * @param mapping This variable stores the buffer and the character mapping this function uses to decode the value of the given key.
 */
void elektraCcodeDecode (Key * key, CCodeData * mapping)
{
	const char * value = static_cast<const char *> (keyValue (key));
	if (!value) return;

	keySetRaw (key, mapping->buffer, decode (value, keyGetValueSize (key), mapping));
}

/**
 * @brief This function replaces unescaped characters in a key value with escaped characters.
 *
 * The function stores the escaped result value both in `mapping->buffer` and the given key.
 *
 * @pre The variable `mapping->buffer` needs to be twice as large as the key value’s size.
 *
 * @param key This key stores the value this function escapes.
 * @param mapping This variable stores the buffer and the character mapping this function uses to encode the value of the given key.
 */
void elektraCcodeEncode (Key * key, CCodeData * mapping)
{
	const char * value = static_cast<const char *> (keyValue (key));
	if (!value) return;

	keySetRaw (key, mapping->buffer, encode (value, keyGetValueSize (key), mapping));
}

// ====================
// = Plugin Interface =
// ====================

/** @see elektraDocOpen */
int elektraCcodeOpen (Plugin * handle, Key * key ELEKTRA_UNUSED)
{
	CCodeData * const mapping = new CCodeData ();

	/* Store for later use...*/
	elektraPluginSetData (handle, mapping);

	KeySet * const config = elektraPluginGetConfig (handle);

	Key const * const escape = ksLookupByName (config, "/escape", 0);
	mapping->escape = '\\';
	if (escape && keyGetBaseNameSize (escape) && keyGetValueSize (escape) == 3)
	{
		int escapeChar = elektraHexcodeConvFromHex (keyString (escape)[1]);
		escapeChar += elektraHexcodeConvFromHex (keyString (escape)[0]) * 16;

		mapping->escape = escapeChar & 255;
	}
	ELEKTRA_LOG_DEBUG ("Use “%c” as escape character", mapping->escape);

	Key const * const root = ksLookupByName (config, "/chars", 0);

	if (root)
	{
		readConfig (mapping, config, root);
	}
	else
	{
		setDefaultConfig (mapping);
	}

	return ELEKTRA_PLUGIN_STATUS_NO_UPDATE;
}

/** @see elektraDocClose */
int elektraCcodeClose (Plugin * handle, Key * key ELEKTRA_UNUSED)
{
	CCodeData * const mapping = static_cast<CCodeData *> (elektraPluginGetData (handle));

	delete[](mapping->buffer);
	delete (mapping);

	return ELEKTRA_PLUGIN_STATUS_NO_UPDATE;
}

/** @see elektraDocGet */
int elektraCcodeGet (Plugin * handle, KeySet * returned, Key * parentKey)
{
	if (!strcmp (keyName (parentKey), "system/elektra/modules/ccode"))
	{
		KeySet * const pluginConfig = contract ();
		ksAppend (returned, pluginConfig);
		ksDel (pluginConfig);
		return ELEKTRA_PLUGIN_STATUS_SUCCESS;
	}

	CCodeData * const mapping = retrieveMapping (handle);

	Key * key;
	ksRewind (returned);
	while ((key = ksNext (returned)) != 0)
	{
		size_t const size = keyGetValueSize (key);
		if (size > mapping->bufferSize)
		{
			mapping->bufferSize = size;
			mapping->buffer = new unsigned char[mapping->bufferSize];
		}

		elektraCcodeDecode (key, mapping);
	}

	return ELEKTRA_PLUGIN_STATUS_SUCCESS;
}

/** @see elektraDocSet */
int elektraCcodeSet (Plugin * handle, KeySet * returned, Key * parentKey ELEKTRA_UNUSED)
{
	CCodeData * const mapping = retrieveMapping (handle);

	CppKeySet keys{ returned };
	for (auto key : keys)
	{
		size_t const size = key.getBinarySize () * 2;
		if (size > mapping->bufferSize)
		{
			mapping->bufferSize = size;
			mapping->buffer = new unsigned char[mapping->bufferSize];
		}

		elektraCcodeEncode (*key, mapping);
	}

	keys.release ();
	return ELEKTRA_PLUGIN_STATUS_SUCCESS;
}

Plugin * ELEKTRA_PLUGIN_EXPORT (ccode)
{
	// clang-format off
	return elektraPluginExport("ccode",
		ELEKTRA_PLUGIN_OPEN,	&elektraCcodeOpen,
		ELEKTRA_PLUGIN_CLOSE,	&elektraCcodeClose,
		ELEKTRA_PLUGIN_GET,	&elektraCcodeGet,
		ELEKTRA_PLUGIN_SET,	&elektraCcodeSet,
		ELEKTRA_PLUGIN_END);
}

} // end extern "C"
<|endoftext|>


<commit_before>/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * 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.
 */

/*
 * Copyright (C) 2015 ScyllaDB
 *
 * Modified by ScyllaDB
 */

/*
 * This file is part of Scylla.
 *
 * Scylla is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Scylla is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Scylla.  If not, see <http://www.gnu.org/licenses/>.
 */

#pragma once

#include "db/consistency_level_type.hh"
#include "db/write_type.hh"
#include <stdexcept>
#include <seastar/core/sstring.hh>
#include <seastar/core/print.hh>
#include "bytes.hh"

namespace exceptions {

enum class exception_code : int32_t {
    SERVER_ERROR    = 0x0000,
    PROTOCOL_ERROR  = 0x000A,

    BAD_CREDENTIALS = 0x0100,

    // 1xx: problem during request execution
    UNAVAILABLE     = 0x1000,
    OVERLOADED      = 0x1001,
    IS_BOOTSTRAPPING= 0x1002,
    TRUNCATE_ERROR  = 0x1003,
    WRITE_TIMEOUT   = 0x1100,
    WRITE_FAILURE   = 0x1500,
    READ_TIMEOUT    = 0x1200,
    READ_FAILURE    = 0x1300,

    // 2xx: problem validating the request
    SYNTAX_ERROR    = 0x2000,
    UNAUTHORIZED    = 0x2100,
    INVALID         = 0x2200,
    CONFIG_ERROR    = 0x2300,
    ALREADY_EXISTS  = 0x2400,
    UNPREPARED      = 0x2500
};

class cassandra_exception : public std::exception {
private:
    exception_code _code;
    sstring _msg;
protected:
    template<typename... Args>
    static inline sstring prepare_message(const char* fmt, Args&&... args) noexcept {
        try {
            return sprint(fmt, std::forward<Args>(args)...);
        } catch (...) {
            return sstring();
        }
    }
public:
    cassandra_exception(exception_code code, sstring msg) noexcept
        : _code(code)
        , _msg(std::move(msg))
    { }
    virtual const char* what() const noexcept override { return _msg.begin(); }
    exception_code code() const { return _code; }
    sstring get_message() const { return what(); }
};

class protocol_exception : public cassandra_exception {
public:
    protocol_exception(sstring msg) noexcept
        : exceptions::cassandra_exception{exceptions::exception_code::PROTOCOL_ERROR, std::move(msg)}
    { }
};

struct unavailable_exception : cassandra_exception {
    db::consistency_level consistency;
    int32_t required;
    int32_t alive;

    unavailable_exception(sstring msg, db::consistency_level cl, int32_t required, int32_t alive) noexcept
        : exceptions::cassandra_exception(exceptions::exception_code::UNAVAILABLE, std::move(msg))
        , consistency(cl)
        , required(required)
        , alive(alive)
    {}

    unavailable_exception(db::consistency_level cl, int32_t required, int32_t alive) noexcept
        : unavailable_exception(prepare_message("Cannot achieve consistency level for cl %s. Requires %ld, alive %ld", cl, required, alive),
                cl, required, alive)
    {}
};

class request_execution_exception : public cassandra_exception {
public:
    request_execution_exception(exception_code code, sstring msg) noexcept
        : cassandra_exception(code, std::move(msg))
    { }
};

class truncate_exception : public request_execution_exception
{
public:
    truncate_exception(std::exception_ptr ep);
};

class request_timeout_exception : public cassandra_exception {
public:
    db::consistency_level consistency;
    int32_t received;
    int32_t block_for;

    request_timeout_exception(exception_code code, const sstring& ks, const sstring& cf, db::consistency_level consistency, int32_t received, int32_t block_for) noexcept
        : cassandra_exception{code, prepare_message("Operation timed out for %s.%s - received only %d responses from %d CL=%s.", ks, cf, received, block_for, consistency)}
        , consistency{consistency}
        , received{received}
        , block_for{block_for}
    { }
};

class read_timeout_exception : public request_timeout_exception {
public:
    bool data_present;

    read_timeout_exception(const sstring& ks, const sstring& cf, db::consistency_level consistency, int32_t received, int32_t block_for, bool data_present) noexcept
        : request_timeout_exception{exception_code::READ_TIMEOUT, ks, cf, consistency, received, block_for}
        , data_present{data_present}
    { }
};

struct mutation_write_timeout_exception : public request_timeout_exception {
    db::write_type type;
    mutation_write_timeout_exception(const sstring& ks, const sstring& cf, db::consistency_level consistency, int32_t received, int32_t block_for, db::write_type type) noexcept :
        request_timeout_exception(exception_code::WRITE_TIMEOUT, ks, cf, consistency, received, block_for)
        , type{std::move(type)}
    { }
};

class request_failure_exception : public cassandra_exception {
public:
    db::consistency_level consistency;
    int32_t received;
    int32_t failures;
    int32_t block_for;

protected:
    request_failure_exception(exception_code code, const sstring& ks, const sstring& cf, db::consistency_level consistency_, int32_t received_, int32_t failures_, int32_t block_for_) noexcept
        : cassandra_exception{code, prepare_message("Operation failed for %s.%s - received %d responses and %d failures from %d CL=%s.", ks, cf, received_, failures_, block_for_, consistency_)}
        , consistency{consistency_}
        , received{received_}
        , failures{failures_}
        , block_for{block_for_}
    {}
};

struct mutation_write_failure_exception : public request_failure_exception {
    db::write_type type;
    mutation_write_failure_exception(const sstring& ks, const sstring& cf, db::consistency_level consistency_, int32_t received_, int32_t failures_, int32_t block_for_, db::write_type type_) noexcept :
        request_failure_exception(exception_code::WRITE_FAILURE, ks, cf, consistency_, received_, failures_, block_for_)
        , type{std::move(type_)}
    { }
};

struct read_failure_exception : public request_failure_exception {
    bool data_present;

    read_failure_exception(const sstring& ks, const sstring& cf, db::consistency_level consistency_, int32_t received_, int32_t failures_, int32_t block_for_, bool data_present_) noexcept
        : request_failure_exception{exception_code::READ_FAILURE, ks, cf, consistency_, received_, failures_, block_for_}
        , data_present{data_present_}
    { }
};

struct overloaded_exception : public cassandra_exception {
    overloaded_exception(size_t c) noexcept :
        cassandra_exception(exception_code::OVERLOADED, prepare_message("Too many in flight hints: %lu", c)) {}
};

class request_validation_exception : public cassandra_exception {
public:
    using cassandra_exception::cassandra_exception;
};

class invalidated_prepared_usage_attempt_exception : public exceptions::request_validation_exception {
public:
    invalidated_prepared_usage_attempt_exception() : request_validation_exception{exception_code::UNPREPARED, "Attempt to execute the invalidated prepared statement."} {}
};

class unauthorized_exception: public request_validation_exception {
public:
    unauthorized_exception(sstring msg) noexcept
                    : request_validation_exception(exception_code::UNAUTHORIZED,
                                    std::move(msg)) {
    }
};

class authentication_exception: public request_validation_exception {
public:
    authentication_exception(sstring msg) noexcept
                    : request_validation_exception(exception_code::BAD_CREDENTIALS,
                                    std::move(msg)) {
    }
};

class invalid_request_exception : public request_validation_exception {
public:
    invalid_request_exception(sstring cause) noexcept
        : request_validation_exception(exception_code::INVALID, std::move(cause))
    { }
};

class keyspace_not_defined_exception : public invalid_request_exception {
public:
    keyspace_not_defined_exception(std::string cause) noexcept
        : invalid_request_exception(std::move(cause))
    { }
};

class prepared_query_not_found_exception : public request_validation_exception {
public:
    bytes id;

    prepared_query_not_found_exception(bytes id) noexcept
        : request_validation_exception{exception_code::UNPREPARED, prepare_message("No prepared statement with ID %s found.", id)}
        , id{id}
    { }
};

class syntax_exception : public request_validation_exception {
public:
    syntax_exception(sstring msg) noexcept
        : request_validation_exception(exception_code::SYNTAX_ERROR, std::move(msg))
    { }
};

class configuration_exception : public request_validation_exception {
public:
    configuration_exception(sstring msg) noexcept
        : request_validation_exception{exception_code::CONFIG_ERROR, std::move(msg)}
    { }

    configuration_exception(exception_code code, sstring msg) noexcept
        : request_validation_exception{code, std::move(msg)}
    { }
};

class already_exists_exception : public configuration_exception {
public:
    const sstring ks_name;
    const sstring cf_name;
private:
    already_exists_exception(sstring ks_name_, sstring cf_name_, sstring msg)
        : configuration_exception{exception_code::ALREADY_EXISTS, msg}
        , ks_name{ks_name_}
        , cf_name{cf_name_}
    { }
public:
    already_exists_exception(sstring ks_name_, sstring cf_name_)
        : already_exists_exception{ks_name_, cf_name_, format("Cannot add already existing table \"{}\" to keyspace \"{}\"", cf_name_, ks_name_)}
    { }

    already_exists_exception(sstring ks_name_)
        : already_exists_exception{ks_name_, "", format("Cannot add existing keyspace \"{}\"", ks_name_)}
    { }
};

class recognition_exception : public std::runtime_error {
public:
    recognition_exception(const std::string& msg) : std::runtime_error(msg) {};
};

class unsupported_operation_exception : public std::runtime_error {
public:
    unsupported_operation_exception() : std::runtime_error("unsupported operation") {}
    unsupported_operation_exception(const sstring& msg) : std::runtime_error("unsupported operation: " + msg) {}
};

}
<commit_msg>exceptions: define additional cassandra CQL exceptions codes<commit_after>/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * 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.
 */

/*
 * Copyright (C) 2015 ScyllaDB
 *
 * Modified by ScyllaDB
 */

/*
 * This file is part of Scylla.
 *
 * Scylla is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Scylla is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Scylla.  If not, see <http://www.gnu.org/licenses/>.
 */

#pragma once

#include "db/consistency_level_type.hh"
#include "db/write_type.hh"
#include <stdexcept>
#include <seastar/core/sstring.hh>
#include <seastar/core/print.hh>
#include "bytes.hh"

namespace exceptions {

enum class exception_code : int32_t {
    SERVER_ERROR    = 0x0000,
    PROTOCOL_ERROR  = 0x000A,

    BAD_CREDENTIALS = 0x0100,

    // 1xx: problem during request execution
    UNAVAILABLE     = 0x1000,
    OVERLOADED      = 0x1001,
    IS_BOOTSTRAPPING= 0x1002,
    TRUNCATE_ERROR  = 0x1003,
    WRITE_TIMEOUT   = 0x1100,
    WRITE_FAILURE   = 0x1500,
    READ_TIMEOUT    = 0x1200,
    READ_FAILURE    = 0x1300,
    FUNCTION_FAILURE= 0x1400,
    CDC_WRITE_FAILURE = 0x1600,

    // 2xx: problem validating the request
    SYNTAX_ERROR    = 0x2000,
    UNAUTHORIZED    = 0x2100,
    INVALID         = 0x2200,
    CONFIG_ERROR    = 0x2300,
    ALREADY_EXISTS  = 0x2400,
    UNPREPARED      = 0x2500
};

class cassandra_exception : public std::exception {
private:
    exception_code _code;
    sstring _msg;
protected:
    template<typename... Args>
    static inline sstring prepare_message(const char* fmt, Args&&... args) noexcept {
        try {
            return sprint(fmt, std::forward<Args>(args)...);
        } catch (...) {
            return sstring();
        }
    }
public:
    cassandra_exception(exception_code code, sstring msg) noexcept
        : _code(code)
        , _msg(std::move(msg))
    { }
    virtual const char* what() const noexcept override { return _msg.begin(); }
    exception_code code() const { return _code; }
    sstring get_message() const { return what(); }
};

class protocol_exception : public cassandra_exception {
public:
    protocol_exception(sstring msg) noexcept
        : exceptions::cassandra_exception{exceptions::exception_code::PROTOCOL_ERROR, std::move(msg)}
    { }
};

struct unavailable_exception : cassandra_exception {
    db::consistency_level consistency;
    int32_t required;
    int32_t alive;

    unavailable_exception(sstring msg, db::consistency_level cl, int32_t required, int32_t alive) noexcept
        : exceptions::cassandra_exception(exceptions::exception_code::UNAVAILABLE, std::move(msg))
        , consistency(cl)
        , required(required)
        , alive(alive)
    {}

    unavailable_exception(db::consistency_level cl, int32_t required, int32_t alive) noexcept
        : unavailable_exception(prepare_message("Cannot achieve consistency level for cl %s. Requires %ld, alive %ld", cl, required, alive),
                cl, required, alive)
    {}
};

class request_execution_exception : public cassandra_exception {
public:
    request_execution_exception(exception_code code, sstring msg) noexcept
        : cassandra_exception(code, std::move(msg))
    { }
};

class truncate_exception : public request_execution_exception
{
public:
    truncate_exception(std::exception_ptr ep);
};

class request_timeout_exception : public cassandra_exception {
public:
    db::consistency_level consistency;
    int32_t received;
    int32_t block_for;

    request_timeout_exception(exception_code code, const sstring& ks, const sstring& cf, db::consistency_level consistency, int32_t received, int32_t block_for) noexcept
        : cassandra_exception{code, prepare_message("Operation timed out for %s.%s - received only %d responses from %d CL=%s.", ks, cf, received, block_for, consistency)}
        , consistency{consistency}
        , received{received}
        , block_for{block_for}
    { }
};

class read_timeout_exception : public request_timeout_exception {
public:
    bool data_present;

    read_timeout_exception(const sstring& ks, const sstring& cf, db::consistency_level consistency, int32_t received, int32_t block_for, bool data_present) noexcept
        : request_timeout_exception{exception_code::READ_TIMEOUT, ks, cf, consistency, received, block_for}
        , data_present{data_present}
    { }
};

struct mutation_write_timeout_exception : public request_timeout_exception {
    db::write_type type;
    mutation_write_timeout_exception(const sstring& ks, const sstring& cf, db::consistency_level consistency, int32_t received, int32_t block_for, db::write_type type) noexcept :
        request_timeout_exception(exception_code::WRITE_TIMEOUT, ks, cf, consistency, received, block_for)
        , type{std::move(type)}
    { }
};

class request_failure_exception : public cassandra_exception {
public:
    db::consistency_level consistency;
    int32_t received;
    int32_t failures;
    int32_t block_for;

protected:
    request_failure_exception(exception_code code, const sstring& ks, const sstring& cf, db::consistency_level consistency_, int32_t received_, int32_t failures_, int32_t block_for_) noexcept
        : cassandra_exception{code, prepare_message("Operation failed for %s.%s - received %d responses and %d failures from %d CL=%s.", ks, cf, received_, failures_, block_for_, consistency_)}
        , consistency{consistency_}
        , received{received_}
        , failures{failures_}
        , block_for{block_for_}
    {}
};

struct mutation_write_failure_exception : public request_failure_exception {
    db::write_type type;
    mutation_write_failure_exception(const sstring& ks, const sstring& cf, db::consistency_level consistency_, int32_t received_, int32_t failures_, int32_t block_for_, db::write_type type_) noexcept :
        request_failure_exception(exception_code::WRITE_FAILURE, ks, cf, consistency_, received_, failures_, block_for_)
        , type{std::move(type_)}
    { }
};

struct read_failure_exception : public request_failure_exception {
    bool data_present;

    read_failure_exception(const sstring& ks, const sstring& cf, db::consistency_level consistency_, int32_t received_, int32_t failures_, int32_t block_for_, bool data_present_) noexcept
        : request_failure_exception{exception_code::READ_FAILURE, ks, cf, consistency_, received_, failures_, block_for_}
        , data_present{data_present_}
    { }
};

struct overloaded_exception : public cassandra_exception {
    overloaded_exception(size_t c) noexcept :
        cassandra_exception(exception_code::OVERLOADED, prepare_message("Too many in flight hints: %lu", c)) {}
};

class request_validation_exception : public cassandra_exception {
public:
    using cassandra_exception::cassandra_exception;
};

class invalidated_prepared_usage_attempt_exception : public exceptions::request_validation_exception {
public:
    invalidated_prepared_usage_attempt_exception() : request_validation_exception{exception_code::UNPREPARED, "Attempt to execute the invalidated prepared statement."} {}
};

class unauthorized_exception: public request_validation_exception {
public:
    unauthorized_exception(sstring msg) noexcept
                    : request_validation_exception(exception_code::UNAUTHORIZED,
                                    std::move(msg)) {
    }
};

class authentication_exception: public request_validation_exception {
public:
    authentication_exception(sstring msg) noexcept
                    : request_validation_exception(exception_code::BAD_CREDENTIALS,
                                    std::move(msg)) {
    }
};

class invalid_request_exception : public request_validation_exception {
public:
    invalid_request_exception(sstring cause) noexcept
        : request_validation_exception(exception_code::INVALID, std::move(cause))
    { }
};

class keyspace_not_defined_exception : public invalid_request_exception {
public:
    keyspace_not_defined_exception(std::string cause) noexcept
        : invalid_request_exception(std::move(cause))
    { }
};

class prepared_query_not_found_exception : public request_validation_exception {
public:
    bytes id;

    prepared_query_not_found_exception(bytes id) noexcept
        : request_validation_exception{exception_code::UNPREPARED, prepare_message("No prepared statement with ID %s found.", id)}
        , id{id}
    { }
};

class syntax_exception : public request_validation_exception {
public:
    syntax_exception(sstring msg) noexcept
        : request_validation_exception(exception_code::SYNTAX_ERROR, std::move(msg))
    { }
};

class configuration_exception : public request_validation_exception {
public:
    configuration_exception(sstring msg) noexcept
        : request_validation_exception{exception_code::CONFIG_ERROR, std::move(msg)}
    { }

    configuration_exception(exception_code code, sstring msg) noexcept
        : request_validation_exception{code, std::move(msg)}
    { }
};

class already_exists_exception : public configuration_exception {
public:
    const sstring ks_name;
    const sstring cf_name;
private:
    already_exists_exception(sstring ks_name_, sstring cf_name_, sstring msg)
        : configuration_exception{exception_code::ALREADY_EXISTS, msg}
        , ks_name{ks_name_}
        , cf_name{cf_name_}
    { }
public:
    already_exists_exception(sstring ks_name_, sstring cf_name_)
        : already_exists_exception{ks_name_, cf_name_, format("Cannot add already existing table \"{}\" to keyspace \"{}\"", cf_name_, ks_name_)}
    { }

    already_exists_exception(sstring ks_name_)
        : already_exists_exception{ks_name_, "", format("Cannot add existing keyspace \"{}\"", ks_name_)}
    { }
};

class recognition_exception : public std::runtime_error {
public:
    recognition_exception(const std::string& msg) : std::runtime_error(msg) {};
};

class unsupported_operation_exception : public std::runtime_error {
public:
    unsupported_operation_exception() : std::runtime_error("unsupported operation") {}
    unsupported_operation_exception(const sstring& msg) : std::runtime_error("unsupported operation: " + msg) {}
};

}
<|endoftext|>


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

#include "yanlr.hpp"
#include "YAMLLexer.h"
#include "YAMLParser.h"
#include "antlr4-runtime.h"

#include <kdbhelper.h>

using namespace ckdb;
using namespace antlr;
using namespace antlr4;

extern "C" {

int elektraYanlrGet (Plugin * handle ELEKTRA_UNUSED, KeySet * returned, Key * parentKey)
{
	if (!elektraStrCmp (keyName (parentKey), "system/elektra/modules/yanlr"))
	{
		KeySet * contract =
			ksNew (30, keyNew ("system/elektra/modules/yanlr", KEY_VALUE, "yanlr plugin waits for your orders", KEY_END),
			       keyNew ("system/elektra/modules/yanlr/exports", KEY_END),
			       keyNew ("system/elektra/modules/yanlr/exports/get", KEY_FUNC, elektraYanlrGet, KEY_END),
			       keyNew ("system/elektra/modules/yanlr/exports/set", KEY_FUNC, elektraYanlrSet, KEY_END),
#include ELEKTRA_README (yanlr)
			       keyNew ("system/elektra/modules/yanlr/infos/version", KEY_VALUE, PLUGINVERSION, KEY_END), KS_END);
		ksAppend (returned, contract);
		ksDel (contract);

		return ELEKTRA_PLUGIN_STATUS_SUCCESS;
	}
	return ELEKTRA_PLUGIN_STATUS_NO_UPDATE;
}

int elektraYanlrSet (Plugin * handle ELEKTRA_UNUSED, KeySet * returned ELEKTRA_UNUSED, Key * parentKey ELEKTRA_UNUSED)
{
	return ELEKTRA_PLUGIN_STATUS_NO_UPDATE;
}

Plugin * ELEKTRA_PLUGIN_EXPORT (yanlr)
{
	return elektraPluginExport ("yanlr", ELEKTRA_PLUGIN_GET, &elektraYanlrGet, ELEKTRA_PLUGIN_SET, &elektraYanlrSet,
				    ELEKTRA_PLUGIN_END);
}

} // end extern "C"
<commit_msg>Yan LR: Add comment banners<commit_after>/**
 * @file
 *
 * @brief Source for yanlr plugin
 *
 * @copyright BSD License (see LICENSE.md or https://www.libelektra.org)
 *
 */

#include "yanlr.hpp"
#include "YAMLLexer.h"
#include "YAMLParser.h"
#include "antlr4-runtime.h"

#include <kdbhelper.h>

using namespace ckdb;
using namespace antlr;
using namespace antlr4;

extern "C" {

// ====================
// = Plugin Interface =
// ====================

/** @see elektraDocGet */
int elektraYanlrGet (Plugin * handle ELEKTRA_UNUSED, KeySet * returned, Key * parentKey)
{
	if (!elektraStrCmp (keyName (parentKey), "system/elektra/modules/yanlr"))
	{
		KeySet * contract =
			ksNew (30, keyNew ("system/elektra/modules/yanlr", KEY_VALUE, "yanlr plugin waits for your orders", KEY_END),
			       keyNew ("system/elektra/modules/yanlr/exports", KEY_END),
			       keyNew ("system/elektra/modules/yanlr/exports/get", KEY_FUNC, elektraYanlrGet, KEY_END),
			       keyNew ("system/elektra/modules/yanlr/exports/set", KEY_FUNC, elektraYanlrSet, KEY_END),
#include ELEKTRA_README (yanlr)
			       keyNew ("system/elektra/modules/yanlr/infos/version", KEY_VALUE, PLUGINVERSION, KEY_END), KS_END);
		ksAppend (returned, contract);
		ksDel (contract);

		return ELEKTRA_PLUGIN_STATUS_SUCCESS;
	}
	return ELEKTRA_PLUGIN_STATUS_NO_UPDATE;
}

/** @see elektraDocSet */
int elektraYanlrSet (Plugin * handle ELEKTRA_UNUSED, KeySet * returned ELEKTRA_UNUSED, Key * parentKey ELEKTRA_UNUSED)
{
	return ELEKTRA_PLUGIN_STATUS_NO_UPDATE;
}

Plugin * ELEKTRA_PLUGIN_EXPORT (yanlr)
{
	return elektraPluginExport ("yanlr", ELEKTRA_PLUGIN_GET, &elektraYanlrGet, ELEKTRA_PLUGIN_SET, &elektraYanlrSet,
				    ELEKTRA_PLUGIN_END);
}

} // end extern "C"
<|endoftext|>


<commit_before>/**
 * @file py_sql_well.cpp
 * @brief python wraper for well fracture storage
 * @author Oleg Borschuk
 * @version
 * @date 2011-07-29
 */

#include "py_sql_well.h"
#include "sql_well.h"
#include "bs_serialize.h"

using namespace boost::python;
#ifdef BSPY_EXPORTING_PLUGIN

namespace blue_sky {
namespace python {
  void py_export_compdat_ident();

  //////////////////////////////////////////////////////////////////////////

  //////////////////////////////////////////////////////////////////////////
  //! export matrices to python
  void py_export_sql_well ()
  {
    using namespace boost::python;

    base_exporter <well_pool_iface, py_sql_well_exporter>::export_class ("well_pool_iface");

    class_exporter <sql_well, well_pool_iface, py_sql_well_exporter>::export_class ("sql_well");

    py_export_compdat_ident();

    def("serialize_to_str", &blue_sky::serialize_to_str< well_pool_iface >);
    def("serialize_from_str", &blue_sky::serialize_from_str< well_pool_iface >);

    // register implicit conversion to interface
    implicitly_convertible<
      smart_ptr< sql_well >,
      smart_ptr< well_pool_iface >
    >();
  }

}	// namespace python
}	// namespace blue_sky
#endif // #ifdef BSPY_EXPORTING_PLUGIN
<commit_msg>SQW: add helper serialize_to_str_fname that accepts proj path & fname<commit_after>/**
 * @file py_sql_well.cpp
 * @brief python wraper for well fracture storage
 * @author Oleg Borschuk
 * @version
 * @date 2011-07-29
 */

#include "py_sql_well.h"
#include "sql_well.h"
#include "bs_serialize.h"
#include "bs_prop_base.h"

using namespace boost::python;
#ifdef BSPY_EXPORTING_PLUGIN

namespace blue_sky {
namespace python {
  void py_export_compdat_ident();

  //////////////////////////////////////////////////////////////////////////

  // helper function to write well_pool to given fname
  std::string serialize_to_str_fname(
      smart_ptr< well_pool_iface > wp,
      const std::string& prj_path,
      const std::string& prj_name
  ) {
    // save project path for serialization code
    kernel::idx_dt_ptr p_dt = BS_KERNEL.pert_idx_dt(BS_KERNEL.find_type("hdm").td_);
    //std::string well_pool_filename = prj_name + "_well_pool.db";
    p_dt->insert< std::string >(prj_path);
    // and project name
    p_dt->insert< std::string >(prj_name);

    // invoke serializetion
    std::string res = serialize_to_str< well_pool_iface >(wp);
    // clear table
    p_dt->clear< std::string >();

    return res;
  }

  //////////////////////////////////////////////////////////////////////////
  //! export matrices to python
  void py_export_sql_well ()
  {
    using namespace boost::python;

    base_exporter <well_pool_iface, py_sql_well_exporter>::export_class ("well_pool_iface");

    class_exporter <sql_well, well_pool_iface, py_sql_well_exporter>::export_class ("sql_well");

    py_export_compdat_ident();

    def("serialize_to_str", &blue_sky::serialize_to_str< well_pool_iface >);
    def("serialize_from_str", &blue_sky::serialize_from_str< well_pool_iface >);
    def("serialize_to_str_fname", &serialize_to_str_fname);

    // register implicit conversion to interface
    implicitly_convertible<
      smart_ptr< sql_well >,
      smart_ptr< well_pool_iface >
    >();
  }

}	// namespace python
}	// namespace blue_sky
#endif // #ifdef BSPY_EXPORTING_PLUGIN
<|endoftext|>


<commit_before>///
/// @file   popcount.cpp
/// @brief  Fast algorithm to count the number of 1 bits in an array
///         using only integer operations.
///
/// Copyright (C) 2017 Kim Walisch, <kim.walisch@gmail.com>
///
/// This file is distributed under the BSD License. See the COPYING
/// file in the top level directory.
///

#include <stdint.h>

namespace {

/// This uses fewer arithmetic operations than any other known
/// implementation on machines with fast multiplication.
/// It uses 12 arithmetic operations, one of which is a multiply.
/// http://en.wikipedia.org/wiki/Hamming_weight#Efficient_implementation
///
uint64_t popcount64c(uint64_t x)
{
  const uint64_t m1 = 0x5555555555555555ull;
  const uint64_t m2 = 0x3333333333333333ull;
  const uint64_t m4 = 0x0F0F0F0F0F0F0F0Full;
  const uint64_t h01 = 0x0101010101010101ull;

  x -= (x >> 1) & m1;
  x = (x & m2) + ((x >> 2) & m2);
  x = (x + (x >> 4)) & m4;
  return (x * h01) >> 56;
}

/// Carry-save adder (CSA).
/// @see Chapter 5 in "Hacker's Delight".
///
void CSA(uint64_t& h, uint64_t& l, uint64_t a, uint64_t b, uint64_t c)
{
  uint64_t u = a ^ b;
  h = (a & b) | (u & c);
  l = u ^ c;
}

} // namespace

namespace primesieve {

/// Harley-Seal popcount (4th iteration).
/// The Harley-Seal popcount algorithm is one of the fastest algorithms
/// for counting 1 bits in an array using only integer operations.
/// This implementation uses only 5.69 instructions per 64-bit word.
/// @see Chapter 5 in "Hacker's Delight" 2nd edition.
///
uint64_t popcount(const uint64_t* array, uint64_t size)
{
  uint64_t total = 0;
  uint64_t ones = 0, twos = 0, fours = 0, eights = 0, sixteens = 0;
  uint64_t twosA, twosB, foursA, foursB, eightsA, eightsB;
  uint64_t limit = size - size % 16;
  uint64_t i = 0;

  for(; i < limit; i += 16)
  {
    CSA(twosA, ones, ones, array[i+0], array[i+1]);
    CSA(twosB, ones, ones, array[i+2], array[i+3]);
    CSA(foursA, twos, twos, twosA, twosB);
    CSA(twosA, ones, ones, array[i+4], array[i+5]);
    CSA(twosB, ones, ones, array[i+6], array[i+7]);
    CSA(foursB, twos, twos, twosA, twosB);
    CSA(eightsA,fours, fours, foursA, foursB);
    CSA(twosA, ones, ones, array[i+8], array[i+9]);
    CSA(twosB, ones, ones, array[i+10], array[i+11]);
    CSA(foursA, twos, twos, twosA, twosB);
    CSA(twosA, ones, ones, array[i+12], array[i+13]);
    CSA(twosB, ones, ones, array[i+14], array[i+15]);
    CSA(foursB, twos, twos, twosA, twosB);
    CSA(eightsB, fours, fours, foursA, foursB);
    CSA(sixteens, eights, eights, eightsA, eightsB);

    total += popcount64c(sixteens);
  }

  total *= 16;
  total += 8 * popcount64c(eights);
  total += 4 * popcount64c(fours);
  total += 2 * popcount64c(twos);
  total += 1 * popcount64c(ones);

  for(; i < size; i++)
    total += popcount64c(array[i]);

  return total;
}

} // namespace
<commit_msg>Rename popcount64c() to popcount64()<commit_after>///
/// @file   popcount.cpp
/// @brief  Fast algorithm to count the number of 1 bits in an array
///         using only integer operations.
///
/// Copyright (C) 2017 Kim Walisch, <kim.walisch@gmail.com>
///
/// This file is distributed under the BSD License. See the COPYING
/// file in the top level directory.
///

#include <stdint.h>

namespace {

/// This uses fewer arithmetic operations than any other known
/// implementation on machines with fast multiplication.
/// It uses 12 arithmetic operations, one of which is a multiply.
/// http://en.wikipedia.org/wiki/Hamming_weight#Efficient_implementation
///
uint64_t popcount64(uint64_t x)
{
  const uint64_t m1 = 0x5555555555555555ull;
  const uint64_t m2 = 0x3333333333333333ull;
  const uint64_t m4 = 0x0F0F0F0F0F0F0F0Full;
  const uint64_t h01 = 0x0101010101010101ull;

  x -= (x >> 1) & m1;
  x = (x & m2) + ((x >> 2) & m2);
  x = (x + (x >> 4)) & m4;
  return (x * h01) >> 56;
}

/// Carry-save adder (CSA).
/// @see Chapter 5 in "Hacker's Delight".
///
void CSA(uint64_t& h, uint64_t& l, uint64_t a, uint64_t b, uint64_t c)
{
  uint64_t u = a ^ b;
  h = (a & b) | (u & c);
  l = u ^ c;
}

} // namespace

namespace primesieve {

/// Harley-Seal popcount (4th iteration).
/// The Harley-Seal popcount algorithm is one of the fastest algorithms
/// for counting 1 bits in an array using only integer operations.
/// This implementation uses only 5.69 instructions per 64-bit word.
/// @see Chapter 5 in "Hacker's Delight" 2nd edition.
///
uint64_t popcount(const uint64_t* array, uint64_t size)
{
  uint64_t total = 0;
  uint64_t ones = 0, twos = 0, fours = 0, eights = 0, sixteens = 0;
  uint64_t twosA, twosB, foursA, foursB, eightsA, eightsB;
  uint64_t limit = size - size % 16;
  uint64_t i = 0;

  for(; i < limit; i += 16)
  {
    CSA(twosA, ones, ones, array[i+0], array[i+1]);
    CSA(twosB, ones, ones, array[i+2], array[i+3]);
    CSA(foursA, twos, twos, twosA, twosB);
    CSA(twosA, ones, ones, array[i+4], array[i+5]);
    CSA(twosB, ones, ones, array[i+6], array[i+7]);
    CSA(foursB, twos, twos, twosA, twosB);
    CSA(eightsA,fours, fours, foursA, foursB);
    CSA(twosA, ones, ones, array[i+8], array[i+9]);
    CSA(twosB, ones, ones, array[i+10], array[i+11]);
    CSA(foursA, twos, twos, twosA, twosB);
    CSA(twosA, ones, ones, array[i+12], array[i+13]);
    CSA(twosB, ones, ones, array[i+14], array[i+15]);
    CSA(foursB, twos, twos, twosA, twosB);
    CSA(eightsB, fours, fours, foursA, foursB);
    CSA(sixteens, eights, eights, eightsA, eightsB);

    total += popcount64(sixteens);
  }

  total *= 16;
  total += 8 * popcount64(eights);
  total += 4 * popcount64(fours);
  total += 2 * popcount64(twos);
  total += 1 * popcount64(ones);

  for(; i < size; i++)
    total += popcount64(array[i]);

  return total;
}

} // namespace
<|endoftext|>


<commit_before>// Copyright (c) 2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <algorithm>

#include "app/gfx/canvas.h"
#include "app/menus/simple_menu_model.h"
#include "app/theme_provider.h"
#include "base/command_line.h"
#include "chrome/app/chrome_dll_resource.h"
#include "chrome/browser/chromeos/compact_location_bar.h"
#include "chrome/browser/chromeos/compact_navigation_bar.h"
#include "chrome/browser/chromeos/main_menu.h"
#include "chrome/browser/chromeos/status_area_view.h"
#include "chrome/browser/chromeos/panel_controller.h"
#include "chrome/browser/views/frame/browser_extender.h"
#include "chrome/browser/views/frame/browser_frame_gtk.h"
#include "chrome/browser/views/frame/browser_view.h"
#include "chrome/browser/views/tabs/tab_overview_types.h"
#include "chrome/browser/views/tabs/tab_strip.h"
#include "chrome/browser/views/toolbar_view.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/x11_util.h"
#include "grit/generated_resources.h"
#include "grit/theme_resources.h"
#include "views/controls/button/button.h"
#include "views/controls/button/image_button.h"
#include "views/controls/menu/menu_2.h"
#include "views/window/window.h"

namespace {

const char* kChromeOsWindowManagerName = "chromeos-wm";
const int kCompactNavbarSpaceHeight = 3;

class Spacer : public views::View {
  SkBitmap* background_;
 public:
  explicit Spacer(SkBitmap* bitmap) : background_(bitmap) {}

  void Paint(gfx::Canvas* canvas) {
    canvas->TileImageInt(*background_, 0, 0, width(), height());
  }
};

// NormalExtender adds ChromeOS specific controls and menus to a BrowserView
// created with Browser::TYPE_NORMAL. This extender adds controls to
// the title bar as follows:
//                  ____  __ __
//      [MainMenu] /    \   \  \     [StatusArea]
//
// and adds the system context menu to the remaining arae of the titlebar.
//
// For Browser::TYPE_POPUP type of BrowserView, see PopupExtender class below.
class NormalExtender : public BrowserExtender,
                       public views::ButtonListener,
                       public views::ContextMenuController {
 public:
  explicit NormalExtender(BrowserView* browser_view)
      : BrowserExtender(browser_view),
        main_menu_(NULL),
        status_area_(NULL),
        compact_navigation_bar_(NULL),
        // CompactNavigationBar is disabled by default.
        // TODO(oshima): Get this info from preference.
        compact_navigation_bar_enabled_(false),
        force_maximized_window_(false) {
  }
  virtual ~NormalExtender() {}

 protected:
  // BrowserExtender overrides.
  virtual void Init() {
    main_menu_ = new views::ImageButton(this);
    ThemeProvider* theme_provider =
        browser_view()->frame()->GetThemeProviderForFrame();
    SkBitmap* image = theme_provider->GetBitmapNamed(IDR_MAIN_MENU_BUTTON);
    main_menu_->SetImage(views::CustomButton::BS_NORMAL, image);
    main_menu_->SetImage(views::CustomButton::BS_HOT, image);
    main_menu_->SetImage(views::CustomButton::BS_PUSHED, image);
    browser_view()->AddChildView(main_menu_);

    Browser* browser = browser_view()->browser();
    compact_location_bar_.reset(
        new chromeos::CompactLocationBar(browser_view()));
    compact_navigation_bar_ = new chromeos::CompactNavigationBar(browser);
    browser_view()->AddChildView(compact_navigation_bar_);
    compact_navigation_bar_->Init();
    status_area_ = new chromeos::StatusAreaView(
        browser,
        browser_view()->GetWindow()->GetNativeWindow());
    browser_view()->AddChildView(status_area_);
    status_area_->Init();

    SkBitmap* theme_toolbar = theme_provider->GetBitmapNamed(IDR_THEME_TOOLBAR);
    spacer_ = new Spacer(theme_toolbar);
    browser_view()->AddChildView(spacer_);

    InitSystemMenu();
    chromeos::MainMenu::ScheduleCreation();

    // The ContextMenuController has to be set to a NonClientView but
    // not to a NonClientFrameView because a TabStrip is not a child of
    // a NonClientFrameView even though visually a TabStrip is over a
    // NonClientFrameView.
    BrowserFrameGtk* gtk_frame =
        static_cast<BrowserFrameGtk*>(browser_view()->frame());
    gtk_frame->GetNonClientView()->SetContextMenuController(this);

    if (browser->type() == Browser::TYPE_NORMAL) {
      std::string wm_name;
      bool wm_name_valid = x11_util::GetWindowManagerName(&wm_name);
      // NOTE: On Chrome OS the wm and Chrome are started in parallel. This
      // means it's possible for us not to be able to get the name of the window
      // manager. We assume that when this happens we're on Chrome OS.
      force_maximized_window_ = (!wm_name_valid ||
                                 wm_name == kChromeOsWindowManagerName ||
                                 CommandLine::ForCurrentProcess()->HasSwitch(
                                     switches::kChromeosFrame));
    }
  }

  virtual void Layout(const gfx::Rect& bounds,
                      gfx::Rect* tabstrip_bounds,
                      int* bottom) {
    if (browser_view()->IsTabStripVisible()) {
      *bottom = bounds.bottom();
    } else {
      *bottom = 0;
    }
    // Skip if there is no space to layout, or if the browser is in
    // fullscreen mode.
    if (bounds.IsEmpty() || browser_view()->IsFullscreen()) {
      main_menu_->SetVisible(false);
      compact_navigation_bar_->SetVisible(false);
      status_area_->SetVisible(false);
      tabstrip_bounds->SetRect(bounds.x(), bounds.y(),
                               bounds.width(), bounds.height());
      return;
    } else {
      main_menu_->SetVisible(true);
      compact_navigation_bar_->SetVisible(compact_navigation_bar_enabled_);
      status_area_->SetVisible(true);
    }
    /* TODO(oshima):
     * Disabling the ability to update location bar on re-layout bacause
     * tabstrip state may not be in sync with the browser's state when
     * new tab is added. We should decide when we know more about this
     * feature. May be we should simply hide the location?
     * Filed a bug: http://crbug.com/30612.
    if (compact_navigation_bar_->IsVisible()) {
      // Update the size and location of the compact location bar.
      compact_location_bar_->UpdateBounds(
          browser_view()->tabstrip()->GetSelectedTab());
    }
    */

    // Layout main menu before tab strip.
    gfx::Size main_menu_size = main_menu_->GetPreferredSize();

    // TODO(oshima): Use 0 for x position for now as this is
    // sufficient for chromeos where the window is always
    // maximized. The correct value is
    // OpaqueBrowserFrameView::NonClientBorderThickness() and we will
    // consider exposing it once we settle on the UI.
    main_menu_->SetBounds(0, bounds.y(),
                          main_menu_size.width(), bounds.height());

    // Layout status area after tab strip.
    status_area_->Update();
    gfx::Size status_size = status_area_->GetPreferredSize();
    status_area_->SetBounds(bounds.x() + bounds.width() - status_size.width(),
                            bounds.y(), status_size.width(),
                            status_size.height());
    int curx = bounds.x();
    int width = bounds.width() - status_size.width();

    if (compact_navigation_bar_->IsVisible()) {
      gfx::Size cnb_bounds = compact_navigation_bar_->GetPreferredSize();
      // This (+1/-1) is a quick hack for the bug
      // http://code.google.com/p/chromium-os/issues/detail?id=1010
      // while investigating the issue. It could be in gtk or around
      // NativeViewHostGtk::CreateFixed, but it will take some time.
      compact_navigation_bar_->SetBounds(curx, bounds.y() + 1,
                                         cnb_bounds.width(),
                                         bounds.height() - 1);
      curx += cnb_bounds.width();
      width -= cnb_bounds.width();

      spacer_->SetVisible(true);
      spacer_->SetBounds(0, *bottom, browser_view()->width(),
                         kCompactNavbarSpaceHeight);
      *bottom += kCompactNavbarSpaceHeight;
    } else {
      spacer_->SetVisible(false);
    }
    width = std::max(0, width);  // In case there is no space left.
    tabstrip_bounds->SetRect(curx, bounds.y(), width, bounds.height());
  }

  virtual bool NonClientHitTest(const gfx::Point& point) {
    gfx::Point point_in_main_menu_coords(point);
    views::View::ConvertPointToView(browser_view(), main_menu_,
                                    &point_in_main_menu_coords);
    if (main_menu_->HitTest(point_in_main_menu_coords))
      return true;

    gfx::Point point_in_status_area_coords(point);
    views::View::ConvertPointToView(browser_view(), status_area_,
                                    &point_in_status_area_coords);
    if (status_area_->HitTest(point_in_status_area_coords))
      return true;

    if (compact_navigation_bar_->IsVisible()) {
      gfx::Point point_in_cnb_coords(point);
      views::View::ConvertPointToView(browser_view(),
                                      compact_navigation_bar_,
                                      &point_in_cnb_coords);
      return compact_navigation_bar_->HitTest(point_in_cnb_coords);
    }
    return false;
  }

  virtual void UpdateTitleBar() {}

  virtual void Show() {
    TabOverviewTypes::instance()->SetWindowType(
        GTK_WIDGET(GetBrowserWindow()->GetNativeWindow()),
        TabOverviewTypes::WINDOW_TYPE_CHROME_TOPLEVEL,
        NULL);
  }

  virtual void Close() {}

  virtual void ActivationChanged() {}

  virtual bool ShouldForceHideToolbar() {
    return compact_navigation_bar_enabled_;
  }

  virtual bool SetFocusToCompactNavigationBar() {
    if (compact_navigation_bar_->IsFocusable()) {
      compact_navigation_bar_->FocusLocation();
      return true;
    } else {
      return false;
    }
  }

  virtual void ToggleCompactNavigationBar() {
    compact_navigation_bar_enabled_ = !compact_navigation_bar_enabled_;
    compact_navigation_bar_->SetFocusable(compact_navigation_bar_enabled_);
  }

  virtual void OnMouseEnteredToTab(Tab* tab) {
    ShowCompactLocationBarUnderSelectedTab();
  }

  virtual void OnMouseMovedOnTab(Tab* tab) {
    ShowCompactLocationBarUnderSelectedTab();
  }

  virtual void OnMouseExitedFromTab(Tab* tab) {
    compact_location_bar_->StartPopupTimer();
  }

  virtual bool ShouldForceMaximizedWindow() {
    return force_maximized_window_;
  }

  virtual int GetMainMenuWidth() const {
    return main_menu_->GetPreferredSize().width();
  }

 private:
  // Shows the compact location bar under the selected tab.
  void ShowCompactLocationBarUnderSelectedTab() {
    if (!compact_navigation_bar_enabled_)
      return;
    compact_location_bar_->Update(
        browser_view()->tabstrip()->GetSelectedTab(),
        browser_view()->browser()->GetSelectedTabContents());
  }

  // Creates system menu.
  void InitSystemMenu() {
    system_menu_contents_.reset(new menus::SimpleMenuModel(browser_view()));
    system_menu_contents_->AddItemWithStringId(IDC_RESTORE_TAB,
                                               IDS_RESTORE_TAB);
    system_menu_contents_->AddItemWithStringId(IDC_NEW_TAB, IDS_NEW_TAB);
    system_menu_contents_->AddSeparator();
    system_menu_contents_->AddItemWithStringId(IDC_TASK_MANAGER,
                                               IDS_TASK_MANAGER);
    system_menu_menu_.reset(new views::Menu2(system_menu_contents_.get()));
  }

  // views::ButtonListener overrides.
  virtual void ButtonPressed(views::Button* sender, const views::Event& event) {
    chromeos::MainMenu::Show(browser_view()->browser());
  }

  // views::ContextMenuController overrides.
  virtual void ShowContextMenu(views::View* source,
                               int x,
                               int y,
                               bool is_mouse_gesture) {
    system_menu_menu_->RunMenuAt(gfx::Point(x, y), views::Menu2::ALIGN_TOPLEFT);
  }

  // Main menu button.
  views::ImageButton* main_menu_;

  // Status Area view.
  chromeos::StatusAreaView* status_area_;

  // System menus.
  scoped_ptr<menus::SimpleMenuModel> system_menu_contents_;
  scoped_ptr<views::Menu2> system_menu_menu_;

  // CompactNavigationBar view.
  chromeos::CompactNavigationBar* compact_navigation_bar_;

  // A toggle flag to show/hide the compact navigation bar.
  bool compact_navigation_bar_enabled_;

  // CompactLocationBar view.
  scoped_ptr<chromeos::CompactLocationBar> compact_location_bar_;

  // A flag to specify if the browser window should be maximized.
  bool force_maximized_window_;

  // A spacer under the tap strip used when the compact navigation bar
  // is active.
  Spacer* spacer_;

  DISALLOW_COPY_AND_ASSIGN(NormalExtender);
};

// PopupExtender class creates dedicated title window for popup window.
// The size and location of the created title window is controlled by
// by window manager.
class PopupExtender : public BrowserExtender {
 public:
  explicit PopupExtender(BrowserView* browser_view)
      : BrowserExtender(browser_view) {
  }
  virtual ~PopupExtender() {}

 private:
  // BrowserExtender overrides.
  virtual void Init() {
    // The visibility of toolbar is controlled in
    // the BrowserView::IsToolbarVisible method.

    views::Window* window = GetBrowserWindow();
    gfx::NativeWindow native_window = window->GetNativeWindow();
    // The window manager needs the min size for popups.
    gfx::Rect bounds = window->GetBounds();
    gtk_widget_set_size_request(
        GTK_WIDGET(native_window), bounds.width(), bounds.height());
    // If we don't explicitly resize here there is a race condition between
    // the X Server and the window manager. Windows will appear with a default
    // size of 200x200 if this happens.
    gtk_window_resize(native_window, bounds.width(), bounds.height());
  }

  virtual void Layout(const gfx::Rect& bounds,
                      gfx::Rect* tabstrip_bounds,
                      int* bottom) {
    *bottom = 0;
    tabstrip_bounds->SetRect(0, 0, 0, 0);
  }

  virtual bool NonClientHitTest(const gfx::Point& point) {
    return false;
  }

  virtual void Show() {
    panel_controller_.reset(new chromeos::PanelController(browser_view()));
  }

  virtual void Close() {
    if (panel_controller_.get())
      panel_controller_->Close();
  }

  virtual void UpdateTitleBar() {
    if (panel_controller_.get())
      panel_controller_->UpdateTitleBar();
  }

  virtual void ActivationChanged() {
    if (panel_controller_.get()) {
      if (GetBrowserWindow()->IsActive())
        panel_controller_->OnFocusIn();
      else
        panel_controller_->OnFocusOut();
    }
  }

  virtual bool ShouldForceHideToolbar() {
    // Always hide toolbar for popups.
    return true;
  }

  virtual bool SetFocusToCompactNavigationBar() {
    return false;
  }

  virtual void ToggleCompactNavigationBar() {}

  virtual void OnMouseEnteredToTab(Tab* tab) {}

  virtual void OnMouseMovedOnTab(Tab* tab) {}

  virtual void OnMouseExitedFromTab(Tab* tab) {}

  virtual bool ShouldForceMaximizedWindow() {
    return false;
  }

  virtual int GetMainMenuWidth() const {
    return 0;
  }

  // Controls interactions with the window manager for popup panels.
  scoped_ptr<chromeos::PanelController> panel_controller_;

  DISALLOW_COPY_AND_ASSIGN(PopupExtender);
};

}  // namespace

////////////////////////////////////////////////////////////////////////////////
// BrowserExtender, public:

// static
BrowserExtender* BrowserExtender::Create(BrowserView* browser_view) {
  if (browser_view->browser()->type() & Browser::TYPE_POPUP)
    return new PopupExtender(browser_view);
  else
    return new NormalExtender(browser_view);
}
<commit_msg>Reverting workaround for focus issue in WidgetGtk.<commit_after>// Copyright (c) 2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <algorithm>

#include "app/gfx/canvas.h"
#include "app/menus/simple_menu_model.h"
#include "app/theme_provider.h"
#include "base/command_line.h"
#include "chrome/app/chrome_dll_resource.h"
#include "chrome/browser/chromeos/compact_location_bar.h"
#include "chrome/browser/chromeos/compact_navigation_bar.h"
#include "chrome/browser/chromeos/main_menu.h"
#include "chrome/browser/chromeos/status_area_view.h"
#include "chrome/browser/chromeos/panel_controller.h"
#include "chrome/browser/views/frame/browser_extender.h"
#include "chrome/browser/views/frame/browser_frame_gtk.h"
#include "chrome/browser/views/frame/browser_view.h"
#include "chrome/browser/views/tabs/tab_overview_types.h"
#include "chrome/browser/views/tabs/tab_strip.h"
#include "chrome/browser/views/toolbar_view.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/x11_util.h"
#include "grit/generated_resources.h"
#include "grit/theme_resources.h"
#include "views/controls/button/button.h"
#include "views/controls/button/image_button.h"
#include "views/controls/menu/menu_2.h"
#include "views/window/window.h"

namespace {

const char* kChromeOsWindowManagerName = "chromeos-wm";
const int kCompactNavbarSpaceHeight = 3;

class Spacer : public views::View {
  SkBitmap* background_;
 public:
  explicit Spacer(SkBitmap* bitmap) : background_(bitmap) {}

  void Paint(gfx::Canvas* canvas) {
    canvas->TileImageInt(*background_, 0, 0, width(), height());
  }
};

// NormalExtender adds ChromeOS specific controls and menus to a BrowserView
// created with Browser::TYPE_NORMAL. This extender adds controls to
// the title bar as follows:
//                  ____  __ __
//      [MainMenu] /    \   \  \     [StatusArea]
//
// and adds the system context menu to the remaining arae of the titlebar.
//
// For Browser::TYPE_POPUP type of BrowserView, see PopupExtender class below.
class NormalExtender : public BrowserExtender,
                       public views::ButtonListener,
                       public views::ContextMenuController {
 public:
  explicit NormalExtender(BrowserView* browser_view)
      : BrowserExtender(browser_view),
        main_menu_(NULL),
        status_area_(NULL),
        compact_navigation_bar_(NULL),
        // CompactNavigationBar is disabled by default.
        // TODO(oshima): Get this info from preference.
        compact_navigation_bar_enabled_(false),
        force_maximized_window_(false) {
  }
  virtual ~NormalExtender() {}

 protected:
  // BrowserExtender overrides.
  virtual void Init() {
    main_menu_ = new views::ImageButton(this);
    ThemeProvider* theme_provider =
        browser_view()->frame()->GetThemeProviderForFrame();
    SkBitmap* image = theme_provider->GetBitmapNamed(IDR_MAIN_MENU_BUTTON);
    main_menu_->SetImage(views::CustomButton::BS_NORMAL, image);
    main_menu_->SetImage(views::CustomButton::BS_HOT, image);
    main_menu_->SetImage(views::CustomButton::BS_PUSHED, image);
    browser_view()->AddChildView(main_menu_);

    Browser* browser = browser_view()->browser();
    compact_location_bar_.reset(
        new chromeos::CompactLocationBar(browser_view()));
    compact_navigation_bar_ = new chromeos::CompactNavigationBar(browser);
    browser_view()->AddChildView(compact_navigation_bar_);
    compact_navigation_bar_->Init();
    status_area_ = new chromeos::StatusAreaView(
        browser,
        browser_view()->GetWindow()->GetNativeWindow());
    browser_view()->AddChildView(status_area_);
    status_area_->Init();

    SkBitmap* theme_toolbar = theme_provider->GetBitmapNamed(IDR_THEME_TOOLBAR);
    spacer_ = new Spacer(theme_toolbar);
    browser_view()->AddChildView(spacer_);

    InitSystemMenu();
    chromeos::MainMenu::ScheduleCreation();

    // The ContextMenuController has to be set to a NonClientView but
    // not to a NonClientFrameView because a TabStrip is not a child of
    // a NonClientFrameView even though visually a TabStrip is over a
    // NonClientFrameView.
    BrowserFrameGtk* gtk_frame =
        static_cast<BrowserFrameGtk*>(browser_view()->frame());
    gtk_frame->GetNonClientView()->SetContextMenuController(this);

    if (browser->type() == Browser::TYPE_NORMAL) {
      std::string wm_name;
      bool wm_name_valid = x11_util::GetWindowManagerName(&wm_name);
      // NOTE: On Chrome OS the wm and Chrome are started in parallel. This
      // means it's possible for us not to be able to get the name of the window
      // manager. We assume that when this happens we're on Chrome OS.
      force_maximized_window_ = (!wm_name_valid ||
                                 wm_name == kChromeOsWindowManagerName ||
                                 CommandLine::ForCurrentProcess()->HasSwitch(
                                     switches::kChromeosFrame));
    }
  }

  virtual void Layout(const gfx::Rect& bounds,
                      gfx::Rect* tabstrip_bounds,
                      int* bottom) {
    if (browser_view()->IsTabStripVisible()) {
      *bottom = bounds.bottom();
    } else {
      *bottom = 0;
    }
    // Skip if there is no space to layout, or if the browser is in
    // fullscreen mode.
    if (bounds.IsEmpty() || browser_view()->IsFullscreen()) {
      main_menu_->SetVisible(false);
      compact_navigation_bar_->SetVisible(false);
      status_area_->SetVisible(false);
      tabstrip_bounds->SetRect(bounds.x(), bounds.y(),
                               bounds.width(), bounds.height());
      return;
    } else {
      main_menu_->SetVisible(true);
      compact_navigation_bar_->SetVisible(compact_navigation_bar_enabled_);
      status_area_->SetVisible(true);
    }
    /* TODO(oshima):
     * Disabling the ability to update location bar on re-layout bacause
     * tabstrip state may not be in sync with the browser's state when
     * new tab is added. We should decide when we know more about this
     * feature. May be we should simply hide the location?
     * Filed a bug: http://crbug.com/30612.
    if (compact_navigation_bar_->IsVisible()) {
      // Update the size and location of the compact location bar.
      compact_location_bar_->UpdateBounds(
          browser_view()->tabstrip()->GetSelectedTab());
    }
    */

    // Layout main menu before tab strip.
    gfx::Size main_menu_size = main_menu_->GetPreferredSize();

    // TODO(oshima): Use 0 for x position for now as this is
    // sufficient for chromeos where the window is always
    // maximized. The correct value is
    // OpaqueBrowserFrameView::NonClientBorderThickness() and we will
    // consider exposing it once we settle on the UI.
    main_menu_->SetBounds(0, bounds.y(),
                          main_menu_size.width(), bounds.height());

    // Layout status area after tab strip.
    status_area_->Update();
    gfx::Size status_size = status_area_->GetPreferredSize();
    status_area_->SetBounds(bounds.x() + bounds.width() - status_size.width(),
                            bounds.y(), status_size.width(),
                            status_size.height());
    int curx = bounds.x();
    int width = bounds.width() - status_size.width();

    if (compact_navigation_bar_->IsVisible()) {
      gfx::Size cnb_bounds = compact_navigation_bar_->GetPreferredSize();
      compact_navigation_bar_->SetBounds(curx, bounds.y(),
                                         cnb_bounds.width(),
                                         bounds.height());
      curx += cnb_bounds.width();
      width -= cnb_bounds.width();

      spacer_->SetVisible(true);
      spacer_->SetBounds(0, *bottom, browser_view()->width(),
                         kCompactNavbarSpaceHeight);
      *bottom += kCompactNavbarSpaceHeight;
    } else {
      spacer_->SetVisible(false);
    }
    width = std::max(0, width);  // In case there is no space left.
    tabstrip_bounds->SetRect(curx, bounds.y(), width, bounds.height());
  }

  virtual bool NonClientHitTest(const gfx::Point& point) {
    gfx::Point point_in_main_menu_coords(point);
    views::View::ConvertPointToView(browser_view(), main_menu_,
                                    &point_in_main_menu_coords);
    if (main_menu_->HitTest(point_in_main_menu_coords))
      return true;

    gfx::Point point_in_status_area_coords(point);
    views::View::ConvertPointToView(browser_view(), status_area_,
                                    &point_in_status_area_coords);
    if (status_area_->HitTest(point_in_status_area_coords))
      return true;

    if (compact_navigation_bar_->IsVisible()) {
      gfx::Point point_in_cnb_coords(point);
      views::View::ConvertPointToView(browser_view(),
                                      compact_navigation_bar_,
                                      &point_in_cnb_coords);
      return compact_navigation_bar_->HitTest(point_in_cnb_coords);
    }
    return false;
  }

  virtual void UpdateTitleBar() {}

  virtual void Show() {
    TabOverviewTypes::instance()->SetWindowType(
        GTK_WIDGET(GetBrowserWindow()->GetNativeWindow()),
        TabOverviewTypes::WINDOW_TYPE_CHROME_TOPLEVEL,
        NULL);
  }

  virtual void Close() {}

  virtual void ActivationChanged() {}

  virtual bool ShouldForceHideToolbar() {
    return compact_navigation_bar_enabled_;
  }

  virtual bool SetFocusToCompactNavigationBar() {
    if (compact_navigation_bar_->IsFocusable()) {
      compact_navigation_bar_->FocusLocation();
      return true;
    } else {
      return false;
    }
  }

  virtual void ToggleCompactNavigationBar() {
    compact_navigation_bar_enabled_ = !compact_navigation_bar_enabled_;
    compact_navigation_bar_->SetFocusable(compact_navigation_bar_enabled_);
  }

  virtual void OnMouseEnteredToTab(Tab* tab) {
    ShowCompactLocationBarUnderSelectedTab();
  }

  virtual void OnMouseMovedOnTab(Tab* tab) {
    ShowCompactLocationBarUnderSelectedTab();
  }

  virtual void OnMouseExitedFromTab(Tab* tab) {
    compact_location_bar_->StartPopupTimer();
  }

  virtual bool ShouldForceMaximizedWindow() {
    return force_maximized_window_;
  }

  virtual int GetMainMenuWidth() const {
    return main_menu_->GetPreferredSize().width();
  }

 private:
  // Shows the compact location bar under the selected tab.
  void ShowCompactLocationBarUnderSelectedTab() {
    if (!compact_navigation_bar_enabled_)
      return;
    compact_location_bar_->Update(
        browser_view()->tabstrip()->GetSelectedTab(),
        browser_view()->browser()->GetSelectedTabContents());
  }

  // Creates system menu.
  void InitSystemMenu() {
    system_menu_contents_.reset(new menus::SimpleMenuModel(browser_view()));
    system_menu_contents_->AddItemWithStringId(IDC_RESTORE_TAB,
                                               IDS_RESTORE_TAB);
    system_menu_contents_->AddItemWithStringId(IDC_NEW_TAB, IDS_NEW_TAB);
    system_menu_contents_->AddSeparator();
    system_menu_contents_->AddItemWithStringId(IDC_TASK_MANAGER,
                                               IDS_TASK_MANAGER);
    system_menu_menu_.reset(new views::Menu2(system_menu_contents_.get()));
  }

  // views::ButtonListener overrides.
  virtual void ButtonPressed(views::Button* sender, const views::Event& event) {
    chromeos::MainMenu::Show(browser_view()->browser());
  }

  // views::ContextMenuController overrides.
  virtual void ShowContextMenu(views::View* source,
                               int x,
                               int y,
                               bool is_mouse_gesture) {
    system_menu_menu_->RunMenuAt(gfx::Point(x, y), views::Menu2::ALIGN_TOPLEFT);
  }

  // Main menu button.
  views::ImageButton* main_menu_;

  // Status Area view.
  chromeos::StatusAreaView* status_area_;

  // System menus.
  scoped_ptr<menus::SimpleMenuModel> system_menu_contents_;
  scoped_ptr<views::Menu2> system_menu_menu_;

  // CompactNavigationBar view.
  chromeos::CompactNavigationBar* compact_navigation_bar_;

  // A toggle flag to show/hide the compact navigation bar.
  bool compact_navigation_bar_enabled_;

  // CompactLocationBar view.
  scoped_ptr<chromeos::CompactLocationBar> compact_location_bar_;

  // A flag to specify if the browser window should be maximized.
  bool force_maximized_window_;

  // A spacer under the tap strip used when the compact navigation bar
  // is active.
  Spacer* spacer_;

  DISALLOW_COPY_AND_ASSIGN(NormalExtender);
};

// PopupExtender class creates dedicated title window for popup window.
// The size and location of the created title window is controlled by
// by window manager.
class PopupExtender : public BrowserExtender {
 public:
  explicit PopupExtender(BrowserView* browser_view)
      : BrowserExtender(browser_view) {
  }
  virtual ~PopupExtender() {}

 private:
  // BrowserExtender overrides.
  virtual void Init() {
    // The visibility of toolbar is controlled in
    // the BrowserView::IsToolbarVisible method.

    views::Window* window = GetBrowserWindow();
    gfx::NativeWindow native_window = window->GetNativeWindow();
    // The window manager needs the min size for popups.
    gfx::Rect bounds = window->GetBounds();
    gtk_widget_set_size_request(
        GTK_WIDGET(native_window), bounds.width(), bounds.height());
    // If we don't explicitly resize here there is a race condition between
    // the X Server and the window manager. Windows will appear with a default
    // size of 200x200 if this happens.
    gtk_window_resize(native_window, bounds.width(), bounds.height());
  }

  virtual void Layout(const gfx::Rect& bounds,
                      gfx::Rect* tabstrip_bounds,
                      int* bottom) {
    *bottom = 0;
    tabstrip_bounds->SetRect(0, 0, 0, 0);
  }

  virtual bool NonClientHitTest(const gfx::Point& point) {
    return false;
  }

  virtual void Show() {
    panel_controller_.reset(new chromeos::PanelController(browser_view()));
  }

  virtual void Close() {
    if (panel_controller_.get())
      panel_controller_->Close();
  }

  virtual void UpdateTitleBar() {
    if (panel_controller_.get())
      panel_controller_->UpdateTitleBar();
  }

  virtual void ActivationChanged() {
    if (panel_controller_.get()) {
      if (GetBrowserWindow()->IsActive())
        panel_controller_->OnFocusIn();
      else
        panel_controller_->OnFocusOut();
    }
  }

  virtual bool ShouldForceHideToolbar() {
    // Always hide toolbar for popups.
    return true;
  }

  virtual bool SetFocusToCompactNavigationBar() {
    return false;
  }

  virtual void ToggleCompactNavigationBar() {}

  virtual void OnMouseEnteredToTab(Tab* tab) {}

  virtual void OnMouseMovedOnTab(Tab* tab) {}

  virtual void OnMouseExitedFromTab(Tab* tab) {}

  virtual bool ShouldForceMaximizedWindow() {
    return false;
  }

  virtual int GetMainMenuWidth() const {
    return 0;
  }

  // Controls interactions with the window manager for popup panels.
  scoped_ptr<chromeos::PanelController> panel_controller_;

  DISALLOW_COPY_AND_ASSIGN(PopupExtender);
};

}  // namespace

////////////////////////////////////////////////////////////////////////////////
// BrowserExtender, public:

// static
BrowserExtender* BrowserExtender::Create(BrowserView* browser_view) {
  if (browser_view->browser()->type() & Browser::TYPE_POPUP)
    return new PopupExtender(browser_view);
  else
    return new NormalExtender(browser_view);
}
<|endoftext|>