<commit_before>/**
@file Cmd/Defs.hpp
@brief Command definitions.

@author Timothy Howard
@copyright 2013-2014 Timothy Howard under the MIT license;
see @ref index or the accompanying LICENSE file for full text.
*/

#ifndef HORD_CMD_DEFS_HPP_
#define HORD_CMD_DEFS_HPP_

#include <Hord/config.hpp>

#include <duct/cc_unique_ptr.hpp>
#include <duct/StateStore.hpp>

namespace Hord {
namespace Cmd {

// Forward declarations
struct IDFields;
struct type_info;
struct type_info_table;
class Stage; // external
enum class Type : uint32_t;
enum class Flags : uint32_t;
enum class StageType : uint8_t;
enum class Status : unsigned;

/**
	@addtogroup cmd
	@{
*/

/**
	%ID.

	@note Value only takes up bits @c 0x3FFFFFFF.
	See @c Cmd::IDFields.
*/
using ID = uint32_t;

/**
	%ID constants.
*/
enum : Cmd::ID {
	/**
		Null %ID.
	*/
	NULL_ID = Cmd::ID{0u},
	/**
		Maximum %ID value.
	*/
	MAX_ID = Cmd::ID{0x3FFFFFFFu}
};

/**
	%ID fields.

	@note @c flag_host is included in the canonical value for %ID
	space separation.
*/
struct IDFields final {
/** @name Properties */ /// @{
	/**
		Base %ID value.
	*/
	Cmd::ID base : 30;

	/**
		Whether the command is being executed by the host.
	*/
	bool flag_host : 1;

	/**
		Whether the stage is an initiator for the command.

		@note This is enabled for the first result stage of a
		local command. It ensures there are no stray command
		initiations, and assists when resolving %ID collisions.
	*/
	bool flag_initiator : 1;

	/**
		Assign fields.

		@param base @c base.
		@param flag_host @c flag_host.
		@param flag_initiator @c flag_initiator.
	*/
	void
	assign(
		Cmd::ID base,
		bool const flag_host,
		bool const flag_initiator
	) noexcept {
		this->base = base;
		this->flag_host = flag_host;
		this->flag_initiator = flag_initiator;
	}

	/**
		Assign.

		@param other Fields.
	*/
	void
	assign(
		IDFields const& other
	) noexcept {
		this->base = other.base;
		this->flag_host = other.flag_host;
		this->flag_initiator = other.flag_initiator;
	}
/// @}
};

/**
	Command type info.
*/
struct type_info final {
/** @name Types */ /// @{
	/** Flag store type. */
	using flag_store_type = duct::StateStore<Cmd::Flags, unsigned>;
/// @}

/** @name Properties */ /// @{
	/**
		Command type.
	*/
	Cmd::Type const type;

	/**
		Command flags.
	*/
	flag_store_type const flags;
/// @}

/** @name Operations */ /// @{
	/**
		Construct stage by type.

		@throws Error{ErrorCode::cmd_construct_stage_type_invalid}
		If @a type is not supplied by the command.

		@throws std::bad_alloc
		If allocation fails.

		@returns Pointer to stage.
		@param type %Stage type.
	*/
	Cmd::Stage*
	(&construct_stage)(
		Cmd::StageType const type
	);
/// @}
};

/**
	Command type info table.

	The type range is [begin, end) such that @c end-begin
	is the number of types in the table in
	sequential order.

	@warning Terrors of abyss await you if the table is not
	sequential and/or the range difference is negative.
*/
struct type_info_table final {
/** @name Properties */ /// @{
	// NB: Goddammit, C++. Just let me assign an unbound array
	// reference to an array of any arity.
	/** Type info array. */
	Cmd::type_info const* const* const array;

	/** First type in the array. */
	Cmd::Type const range_begin;

	/** One past the last type in the array. */
	Cmd::Type const range_end;

	/**
		Get size.

		@warning The result will overflow if the range is degenerate.
	*/
	constexpr std::size_t
	size() const noexcept {
		return
			static_cast<std::size_t>(range_end) -
			static_cast<std::size_t>(range_begin)
		;
	}
/// @}

/** @name Queries */ /// @{
	/**
		Check if the table contains a type.

		@param type Command type.
	*/
	constexpr bool
	contains(
		Cmd::Type const type
	) const noexcept {
		return
			type >= range_begin &&
			type <  range_end
		;
	}

	/**
		Check if the type range intersects with another table.

		@param other Table to test against.
	*/
	constexpr bool
	intersects(
		Cmd::type_info_table const& other
	) const noexcept {
		return
		// end within other
		   ((other.range_end >  this->range_begin &&
			 other.range_end <= this->range_end)  ||
			(this->range_end >  other.range_begin &&
			 this->range_end <= other.range_end))
		// begin within other
		|| ((other.range_begin >= this->range_begin &&
			 other.range_begin <  this->range_end)  ||
			(this->range_begin >= other.range_begin &&
			 this->range_begin <  other.range_end))
		;
	}
/// @}
};

/**
	Owning pointer to command stage.
*/
using StageUPtr = duct::cc_unique_ptr<Cmd::Stage>;

/**
	Command type.

	@remarks The range [0x00, 0xFF] is reserved for stage
	types. The range [0x0100, 0xFFFF] is reserved for
	standard types. Userspace is permitted the range
	[0x00010000, 0xFFFFFFFF].

	@sa Cmd::StageType
*/
enum class Type : uint32_t {
/** @name Standard range */ /// @{
	/** Base standard type. */
	STANDARD_BASE = 0x100,
	/** Maximum standard type. */
	STANDARD_LIMIT = 0xFFFF,
	/** Number of standard types. */
	STANDARD_COUNT = STANDARD_LIMIT - STANDARD_BASE,
/// @}

/** @name Userspace range */ /// @{
	/** Base userspace type. */
	USERSPACE_BASE = 0x00010000,
	/** Maximum userspace type. */
	USERSPACE_LIMIT = 0xFFFFFFFF,
/// @}

/**
	@ref cmd_generic.
	@{
*/
	GenericTerminate = STANDARD_BASE,
/** @} */

/**
	@ref cmd_node.
	@{
*/
	NodeCreate,
	//NodeDestroy,
/** @} */

/**
	@ref cmd_record.
	@{
*/
	//RecordInsert,
	//RecordDestroy,
/** @} */

/** @cond INTERNAL */
	// One-past-end
	STANDARD_END,
	STANDARD_COUNT_DEFINED = STANDARD_END - STANDARD_BASE
/** @endcond */
};

/**
	Command flags.
*/
enum class Flags : uint32_t {
	/**
		No flags.
	*/
	none = 0,

	/**
		Command requires remote result to continue execution.
	*/
	remote = 1 << 1,

	/**
		Command is revertible.

		@note A revision point will only be stored if the command
		has this flag.
	*/
	revertible = 1 << 2
};

/**
	%Stage type.

	@note The range of valid stage types is
	[0x00, 0xFF], with [0x00, 0x0F] being
	reserved for standard stage types.

	@remarks Most commands use only a subset of the standard stages.
*/
enum class StageType : uint8_t {
/** @name Standard range */ /// @{
	/** Base standard type. */
	STANDARD_BASE = 0x00,
	/** Maximum standard type. */
	STANDARD_LIMIT = 0x0F,
/// @}

/** @name Userspace range */ /// @{
	/** Base userspace type. */
	USERSPACE_BASE = 0x10,
	/** Maximum userspace type. */
	USERSPACE_LIMIT = 0xFF,
/// @}

/** @name Standard types */ /// @{
	/**
		Statement stage.

		@remarks If a command uses this stage, it is typically the
		only stage apart from the return stage.
	*/
	Statement = STANDARD_BASE,

	/**
		Error stage.
	*/
	Error,

	/**
		Request stage.
	*/
	Request,

	/**
		Response stage.
	*/
	Response,
/// @}

/** @cond INTERNAL */
	// One-past-end
	STANDARD_END,
	STANDARD_COUNT_DEFINED = STANDARD_END - STANDARD_BASE
/** @endcond */
};

/**
	Command status.
*/
enum class Status : unsigned {
	/**
		Command is waiting for a stage to return.
	*/
	waiting = 1,

	/**
		Command has completed without explicit error.

		@note This will be the command status even if an Error stage
		is emitted.
	*/
	complete,

	/**
		Command has terminated with an error.

		@note Commands which terminate with an error are immediately
		removed from the active group and a @c GenericTerminate
		pseudo-stage is emitted to the remote endpoint.

		@par
		@note This is implicit if stage execution throws an exception.
	*/
	error,

	/**
		Command has terminated because of a remote error.
	*/
	error_remote
};

/** @} */ // end of doc-group cmd

} // namespace Cmd
} // namespace Hord

#endif // HORD_CMD_DEFS_HPP_
<commit_msg>Cmd/Defs: added static assertions to ensure standard type limit conformity.<commit_after>/**
@file Cmd/Defs.hpp
@brief Command definitions.

@author Timothy Howard
@copyright 2013-2014 Timothy Howard under the MIT license;
see @ref index or the accompanying LICENSE file for full text.
*/

#ifndef HORD_CMD_DEFS_HPP_
#define HORD_CMD_DEFS_HPP_

#include <Hord/config.hpp>
#include <Hord/utility.hpp>

#include <duct/cc_unique_ptr.hpp>
#include <duct/StateStore.hpp>

namespace Hord {
namespace Cmd {

// Forward declarations
struct IDFields;
struct type_info;
struct type_info_table;
class Stage; // external
enum class Type : uint32_t;
enum class Flags : uint32_t;
enum class StageType : uint8_t;
enum class Status : unsigned;

/**
	@addtogroup cmd
	@{
*/

/**
	%ID.

	@note Value only takes up bits @c 0x3FFFFFFF.
	See @c Cmd::IDFields.
*/
using ID = uint32_t;

/**
	%ID constants.
*/
enum : Cmd::ID {
	/**
		Null %ID.
	*/
	NULL_ID = Cmd::ID{0u},
	/**
		Maximum %ID value.
	*/
	MAX_ID = Cmd::ID{0x3FFFFFFFu}
};

/**
	%ID fields.

	@note @c flag_host is included in the canonical value for %ID
	space separation.
*/
struct IDFields final {
/** @name Properties */ /// @{
	/**
		Base %ID value.
	*/
	Cmd::ID base : 30;

	/**
		Whether the command is being executed by the host.
	*/
	bool flag_host : 1;

	/**
		Whether the stage is an initiator for the command.

		@note This is enabled for the first result stage of a
		local command. It ensures there are no stray command
		initiations, and assists when resolving %ID collisions.
	*/
	bool flag_initiator : 1;

	/**
		Assign fields.

		@param base @c base.
		@param flag_host @c flag_host.
		@param flag_initiator @c flag_initiator.
	*/
	void
	assign(
		Cmd::ID base,
		bool const flag_host,
		bool const flag_initiator
	) noexcept {
		this->base = base;
		this->flag_host = flag_host;
		this->flag_initiator = flag_initiator;
	}

	/**
		Assign.

		@param other Fields.
	*/
	void
	assign(
		IDFields const& other
	) noexcept {
		this->base = other.base;
		this->flag_host = other.flag_host;
		this->flag_initiator = other.flag_initiator;
	}
/// @}
};

/**
	Command type info.
*/
struct type_info final {
/** @name Types */ /// @{
	/** Flag store type. */
	using flag_store_type = duct::StateStore<Cmd::Flags, unsigned>;
/// @}

/** @name Properties */ /// @{
	/**
		Command type.
	*/
	Cmd::Type const type;

	/**
		Command flags.
	*/
	flag_store_type const flags;
/// @}

/** @name Operations */ /// @{
	/**
		Construct stage by type.

		@throws Error{ErrorCode::cmd_construct_stage_type_invalid}
		If @a type is not supplied by the command.

		@throws std::bad_alloc
		If allocation fails.

		@returns Pointer to stage.
		@param type %Stage type.
	*/
	Cmd::Stage*
	(&construct_stage)(
		Cmd::StageType const type
	);
/// @}
};

/**
	Command type info table.

	The type range is [begin, end) such that @c end-begin
	is the number of types in the table in
	sequential order.

	@warning Terrors of abyss await you if the table is not
	sequential and/or the range difference is negative.
*/
struct type_info_table final {
/** @name Properties */ /// @{
	// NB: Goddammit, C++. Just let me assign an unbound array
	// reference to an array of any arity.
	/** Type info array. */
	Cmd::type_info const* const* const array;

	/** First type in the array. */
	Cmd::Type const range_begin;

	/** One past the last type in the array. */
	Cmd::Type const range_end;

	/**
		Get size.

		@warning The result will overflow if the range is degenerate.
	*/
	constexpr std::size_t
	size() const noexcept {
		return
			static_cast<std::size_t>(range_end) -
			static_cast<std::size_t>(range_begin)
		;
	}
/// @}

/** @name Queries */ /// @{
	/**
		Check if the table contains a type.

		@param type Command type.
	*/
	constexpr bool
	contains(
		Cmd::Type const type
	) const noexcept {
		return
			type >= range_begin &&
			type <  range_end
		;
	}

	/**
		Check if the type range intersects with another table.

		@param other Table to test against.
	*/
	constexpr bool
	intersects(
		Cmd::type_info_table const& other
	) const noexcept {
		return
		// end within other
		   ((other.range_end >  this->range_begin &&
			 other.range_end <= this->range_end)  ||
			(this->range_end >  other.range_begin &&
			 this->range_end <= other.range_end))
		// begin within other
		|| ((other.range_begin >= this->range_begin &&
			 other.range_begin <  this->range_end)  ||
			(this->range_begin >= other.range_begin &&
			 this->range_begin <  other.range_end))
		;
	}
/// @}
};

/**
	Owning pointer to command stage.
*/
using StageUPtr = duct::cc_unique_ptr<Cmd::Stage>;

/**
	Command type.

	@remarks The range [0x00, 0xFF] is reserved for stage
	types. The range [0x0100, 0xFFFF] is reserved for
	standard types. Userspace is permitted the range
	[0x00010000, 0xFFFFFFFF].

	@sa Cmd::StageType
*/
enum class Type : uint32_t {
/** @name Standard range */ /// @{
	/** Base standard type. */
	STANDARD_BASE = 0x100,
	/** Maximum standard type. */
	STANDARD_LIMIT = 0xFFFF,
	/** Number of standard types. */
	STANDARD_COUNT = STANDARD_LIMIT - STANDARD_BASE,
/// @}

/** @name Userspace range */ /// @{
	/** Base userspace type. */
	USERSPACE_BASE = 0x00010000,
	/** Maximum userspace type. */
	USERSPACE_LIMIT = 0xFFFFFFFF,
/// @}

/**
	@ref cmd_generic.
	@{
*/
	GenericTerminate = STANDARD_BASE,
/** @} */

/**
	@ref cmd_node.
	@{
*/
	NodeCreate,
	//NodeDestroy,
/** @} */

/**
	@ref cmd_record.
	@{
*/
	//RecordInsert,
	//RecordDestroy,
/** @} */

/** @cond INTERNAL */
	// One-past-end
	STANDARD_END,
	STANDARD_COUNT_DEFINED = STANDARD_END - STANDARD_BASE
/** @endcond */
};

/** @cond INTERNAL */
static_assert(
	enum_cast(Cmd::Type::STANDARD_LIMIT) >=
	enum_cast(Cmd::Type::STANDARD_END) - 1,
	"standard command types exceed the limit for standard types"
);
/** @endcond */

/**
	Command flags.
*/
enum class Flags : uint32_t {
	/**
		No flags.
	*/
	none = 0,

	/**
		Command requires remote result to continue execution.
	*/
	remote = 1 << 1,

	/**
		Command is revertible.

		@note A revision point will only be stored if the command
		has this flag.
	*/
	revertible = 1 << 2
};

/**
	%Stage type.

	@note The range of valid stage types is
	[0x00, 0xFF], with [0x00, 0x0F] being
	reserved for standard stage types.

	@remarks Most commands use only a subset of the standard stages.
*/
enum class StageType : uint8_t {
/** @name Standard range */ /// @{
	/** Base standard type. */
	STANDARD_BASE = 0x00,
	/** Maximum standard type. */
	STANDARD_LIMIT = 0x0F,
/// @}

/** @name Userspace range */ /// @{
	/** Base userspace type. */
	USERSPACE_BASE = 0x10,
	/** Maximum userspace type. */
	USERSPACE_LIMIT = 0xFF,
/// @}

/** @name Standard types */ /// @{
	/**
		Statement stage.

		@remarks If a command uses this stage, it is typically the
		only stage apart from the return stage.
	*/
	Statement = STANDARD_BASE,

	/**
		Error stage.
	*/
	Error,

	/**
		Request stage.
	*/
	Request,

	/**
		Response stage.
	*/
	Response,
/// @}

/** @cond INTERNAL */
	// One-past-end
	STANDARD_END,
	STANDARD_COUNT_DEFINED = STANDARD_END - STANDARD_BASE
/** @endcond */
};

/** @cond INTERNAL */
static_assert(
	enum_cast(Cmd::StageType::STANDARD_LIMIT) >=
	enum_cast(Cmd::StageType::STANDARD_END) - 1,
	"standard stage types exceed the limit for standard types"
);
/** @endcond */

/**
	Command status.
*/
enum class Status : unsigned {
	/**
		Command is waiting for a stage to return.
	*/
	waiting = 1,

	/**
		Command has completed without explicit error.

		@note This will be the command status even if an Error stage
		is emitted.
	*/
	complete,

	/**
		Command has terminated with an error.

		@note Commands which terminate with an error are immediately
		removed from the active group and a @c GenericTerminate
		pseudo-stage is emitted to the remote endpoint.

		@par
		@note This is implicit if stage execution throws an exception.
	*/
	error,

	/**
		Command has terminated because of a remote error.
	*/
	error_remote
};

/** @} */ // end of doc-group cmd

} // namespace Cmd
} // namespace Hord

#endif // HORD_CMD_DEFS_HPP_
<|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 "../client/gles2_lib.h"
#include "../common/thread_local.h"

namespace gles2 {
namespace {
gpu::ThreadLocalKey g_gl_context_key;
}  // namespace anonymous

void Initialize() {
  g_gl_context_key = gpu::ThreadLocalAlloc();
}

void Terminate() {
  gpu::ThreadLocalFree(g_gl_context_key);
  g_gl_context_key = 0;
}

gpu::gles2::GLES2Implementation* GetGLContext() {
  return static_cast<gpu::gles2::GLES2Implementation*>(
    gpu::ThreadLocalGetValue(g_gl_context_key));
}

void SetGLContext(gpu::gles2::GLES2Implementation* context) {
  gpu::ThreadLocalSetValue(g_gl_context_key, context);
}
}  // namespace gles2

<commit_msg>Work around bug in gcc's name mangling causing linker to crash on Mac OS X.<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 "../client/gles2_lib.h"
#include "../common/thread_local.h"

namespace gles2 {
// TODO(kbr): the use of this anonymous namespace core dumps the
// linker on Mac OS X 10.6 when the symbol ordering file is used
// namespace {
static gpu::ThreadLocalKey g_gl_context_key;
// }  // namespace anonymous

void Initialize() {
  g_gl_context_key = gpu::ThreadLocalAlloc();
}

void Terminate() {
  gpu::ThreadLocalFree(g_gl_context_key);
  g_gl_context_key = 0;
}

gpu::gles2::GLES2Implementation* GetGLContext() {
  return static_cast<gpu::gles2::GLES2Implementation*>(
    gpu::ThreadLocalGetValue(g_gl_context_key));
}

void SetGLContext(gpu::gles2::GLES2Implementation* context) {
  gpu::ThreadLocalSetValue(g_gl_context_key, context);
}
}  // namespace gles2

<|endoftext|>


<commit_before>/* Copyright 2020 The TensorFlow Authors. All Rights Reserved.

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 "tensorflow/lite/micro/kernels/fully_connected.h"

#include "tensorflow/lite/c/builtin_op_data.h"
#include "tensorflow/lite/c/common.h"
#include "tensorflow/lite/kernels/internal/common.h"
#include "tensorflow/lite/kernels/internal/quantization_util.h"
#include "tensorflow/lite/kernels/internal/reference/fully_connected.h"
#include "tensorflow/lite/kernels/internal/reference/integer_ops/fully_connected.h"
#include "tensorflow/lite/kernels/internal/tensor_ctypes.h"
#include "tensorflow/lite/kernels/kernel_util.h"
#include "tensorflow/lite/micro/kernels/kernel_util.h"
#include "tensorflow/lite/micro/kernels/xtensa/fixedpoint_utils.h"
#include "tensorflow/lite/micro/kernels/xtensa/xtensa.h"

namespace tflite {
namespace {

#if defined(HIFIMINI)
void FullyConnected(const FullyConnectedParams& params,
                    const RuntimeShape& input_shape, const int8_t* input_data,
                    const RuntimeShape& filter_shape, const int8_t* filter_data,
                    const RuntimeShape& bias_shape, const int32_t* bias_data,
                    const RuntimeShape& output_shape, int8_t* output_data) {
  // TODO(b/154032858): Investigate removing extra copies.
  const int32_t input_offset = params.input_offset;
  const int32_t filter_offset = params.weights_offset;
  const int32_t output_offset = params.output_offset;
  const int32_t output_multiplier = params.output_multiplier;
  const int output_shift = params.output_shift;
  const int32_t output_activation_min = params.quantized_activation_min;
  const int32_t output_activation_max = params.quantized_activation_max;

  const int filter_dim_count = filter_shape.DimensionsCount();
  const int batches = output_shape.Dims(0);
  const int output_depth = output_shape.Dims(1);
  const int accum_depth = filter_shape.Dims(filter_dim_count - 1);
  const int accum_depth_iters = accum_depth / 2;

  ae_p24x2s offsets_input_24x2 = AE_MOVPA24(input_offset);
  ae_p24x2s offsets_filter_24x2 = AE_MOVPA24(filter_offset);
  ae_q56s output_offset_56 = AE_CVTQ48A32S(output_offset);
  ae_q56s output_activation_max_56 = AE_CVTQ48A32S(output_activation_max);
  ae_q56s output_activation_min_56 = AE_CVTQ48A32S(output_activation_min);

  for (int b = 0; b < batches; ++b) {
    for (int out_c = 0; out_c < output_depth; ++out_c) {
      // Load intrinsics advance pointer before loading so backoff data pointers
      // by two before loading:
      const int8_t* input_ptr = (input_data + b * accum_depth) - 2;
      const int8_t* filter_ptr = (filter_data + out_c * accum_depth) - 2;

      // Main accumulator register entry for loop:
      ae_q56s sum_56 = AE_ZEROQ56();

      for (int d = 0; d < accum_depth_iters; d++) {
        // Load the signed 8bit values into the PR register:
        ae_p24x2s input_24x2;
        ae_p24x2s filter_24x2;
        AE_LP8X2F_IU(input_24x2, input_ptr, 2);
        AE_LP8X2F_IU(filter_24x2, filter_ptr, 2);

        // Right shift the signed 8bit values to expand to signed 24bit values:
        input_24x2 = AE_P24X2S_SRAI(input_24x2, 16);
        filter_24x2 = AE_P24X2S_SRAI(filter_24x2, 16);

        // Add offsets to data values (24 bit aligned):
        input_24x2 = AE_P24S_ADDS_P24X2S(offsets_input_24x2, input_24x2);
        filter_24x2 = AE_P24S_ADDS_P24X2S(offsets_filter_24x2, filter_24x2);

        // 24x2 signed integer dual MAC w/ addition into 56bit accumulator (48
        // bit aligned):
        AE_MULAAP24S_HH_LL(sum_56, input_24x2, filter_24x2);
      }

      // Left shift to get back into 32bit space (right padded to 48bit):
      sum_56 = AE_Q56S_SLAI(sum_56, 16);

      // Add bias data if needed:
      if (bias_data) {
        ae_q56s bias_56 = AE_CVTQ48A32S(bias_data[out_c]);
        sum_56 = AE_ADDQ56(sum_56, bias_56);
      }

      // Shift left into 24bit space and place back on PR register:
      sum_56 = AE_Q56S_SLAI(sum_56, 8);
      ae_p24x2s sum_24x2 = AE_TRUNCP24Q48(sum_56);

      // MultiplyByQuantizedMultiplier returns a 48bit aligned value
      sum_56 = MultiplyByQuantizedMultiplier(sum_24x2, output_multiplier,
                                             output_shift);

      // Add output_offset and cap min/max values:
      sum_56 = AE_ADDQ56(sum_56, output_offset_56);
      sum_56 = AE_MINQ56S(sum_56, output_activation_max_56);
      sum_56 = AE_MAXQ56S(sum_56, output_activation_min_56);

      output_data[out_c + output_depth * b] =
          static_cast<int8_t>(AE_TRUNCA32Q48(sum_56));
    }
  }
}
#endif

TfLiteStatus CalculateOpData(TfLiteContext* context,
                             TfLiteFusedActivation activation,
                             TfLiteType data_type, const TfLiteTensor* input,
                             const TfLiteTensor* filter,
                             const TfLiteTensor* bias, TfLiteTensor* output,
                             OpDataFullyConnected* data) {
  double real_multiplier = 0.0;
  TF_LITE_ENSURE_STATUS(GetQuantizedConvolutionMultipler(
      context, input, filter, bias, output, &real_multiplier));
#if defined(HIFIMINI)
  QuantizeMultiplierForInt24(real_multiplier, &data->output_multiplier,
                             &data->output_shift);
#else
  QuantizeMultiplier(real_multiplier, &data->output_multiplier,
                     &data->output_shift);
#endif
  data->input_zero_point = input->params.zero_point;
  data->filter_zero_point = filter->params.zero_point;
  data->output_zero_point = output->params.zero_point;

  return CalculateActivationRangeQuantized(context, activation, output,
                                           &data->output_activation_min,
                                           &data->output_activation_max);
}

void* Init(TfLiteContext* context, const char* buffer, size_t length) {
  TFLITE_DCHECK(context->AllocatePersistentBuffer != nullptr);
  return context->AllocatePersistentBuffer(context,
                                           sizeof(OpDataFullyConnected));
}

TfLiteStatus Prepare(TfLiteContext* context, TfLiteNode* node) {
  TFLITE_DCHECK(node->user_data != nullptr);
  TFLITE_DCHECK(node->builtin_data != nullptr);

  auto* data = static_cast<OpDataFullyConnected*>(node->user_data);
  const auto* params =
      reinterpret_cast<TfLiteFullyConnectedParams*>(node->builtin_data);

  const TfLiteTensor* input =
      GetInput(context, node, kFullyConnectedInputTensor);
  const TfLiteTensor* filter =
      GetInput(context, node, kFullyConnectedWeightsTensor);
  const TfLiteTensor* bias =
      GetOptionalInputTensor(context, node, kFullyConnectedBiasTensor);
  TfLiteTensor* output = GetOutput(context, node, kFullyConnectedOutputTensor);

  if (input->type != kTfLiteInt8) {
    TF_LITE_KERNEL_LOG(context, "Type %s (%d) not supported.",
                       TfLiteTypeGetName(input->type), input->type);
    return kTfLiteError;
  }

  return CalculateOpData(context, params->activation, input->type, input,
                         filter, bias, output, data);
}

TfLiteStatus EvalQuantizedInt8(TfLiteContext* context, TfLiteNode* node,
                               const OpDataFullyConnected& data,
                               const TfLiteEvalTensor* input,
                               const TfLiteEvalTensor* filter,
                               const TfLiteEvalTensor* bias,
                               TfLiteEvalTensor* output) {
  // TODO(b/154032858): Investigate removing extra copies (i.e.
  // data.ToQuantizedParams), and also passing by value.
  //
  // TODO(b/155656675): Consider passing OpDataFullyConnected by value
  // once it is also passed to the FullyConnected function. Until it is copied
  // to a local op_param variable, we do not get any latency improvements from
  // passing by value.
#if defined(HIFIMINI)
  FullyConnected(FullyConnectedParamsQuantized(data),
                 tflite::micro::GetTensorShape(input),
                 tflite::micro::GetTensorData<int8_t>(input),
                 tflite::micro::GetTensorShape(filter),
                 tflite::micro::GetTensorData<int8_t>(filter),
                 tflite::micro::GetTensorShape(bias),
                 tflite::micro::GetTensorData<int32_t>(bias),
                 tflite::micro::GetTensorShape(output),
                 tflite::micro::GetTensorData<int8_t>(output));
#elif defined(FUSION_F1)
  FullyConnectedParams op_params = FullyConnectedParamsQuantized(data);
  // Weights will always be symmetric quantized since we only support int
  // quantization.
  TFLITE_DCHECK(op_params.weights_offset == 0);

  const RuntimeShape& output_shape = tflite::micro::GetTensorShape(output);
  const int num_batches = output_shape.Dims(0);
  const int output_depth = output_shape.Dims(1);

  const RuntimeShape& filter_shape = tflite::micro::GetTensorShape(filter);
  const int filter_dim_count = filter_shape.DimensionsCount();
  const int accum_depth = filter_shape.Dims(filter_dim_count - 1);

  for (int b = 0; b < num_batches; ++b) {
    TF_LITE_ENSURE_EQ(
        context,
        xa_nn_fully_connected_sym8sxasym8s_asym8s(
            (tflite::micro::GetTensorData<int8_t>(output) + b * output_depth),
            tflite::micro::GetTensorData<int8_t>(filter),
            (tflite::micro::GetTensorData<int8_t>(input) + b * accum_depth),
            tflite::micro::GetTensorData<int32_t>(bias), accum_depth,
            output_depth, op_params.input_offset, op_params.output_multiplier,
            op_params.output_shift, op_params.output_offset),
        0);
  }

  int8_t* output_arr = tflite::micro::GetTensorData<int8_t>(output);
  TF_LITE_ENSURE_EQ(context,
                    xa_nn_vec_activation_min_max_8_8(
                        output_arr, output_arr, data.output_activation_min,
                        data.output_activation_max, num_batches * output_depth),
                    0);
  return kTfLiteOk;
#else
  reference_integer_ops::FullyConnected(
      FullyConnectedParamsQuantized(data), tflite::micro::GetTensorShape(input),
      tflite::micro::GetTensorData<int8_t>(input),
      tflite::micro::GetTensorShape(filter),
      tflite::micro::GetTensorData<int8_t>(filter),
      tflite::micro::GetTensorShape(bias),
      tflite::micro::GetTensorData<int32_t>(bias),
      tflite::micro::GetTensorShape(output),
      tflite::micro::GetTensorData<int8_t>(output));
#endif

  return kTfLiteOk;
}

TfLiteStatus Eval(TfLiteContext* context, TfLiteNode* node) {
  TFLITE_DCHECK(node->user_data != nullptr);
  const auto& data =
      *(static_cast<const OpDataFullyConnected*>(node->user_data));

  const TfLiteEvalTensor* input =
      tflite::micro::GetEvalInput(context, node, kFullyConnectedInputTensor);
  const TfLiteEvalTensor* filter =
      tflite::micro::GetEvalInput(context, node, kFullyConnectedWeightsTensor);
  const TfLiteEvalTensor* bias =
      (NumInputs(node) == 3) ? tflite::micro::GetEvalInput(
                                   context, node, kFullyConnectedBiasTensor)
                             : nullptr;

  TfLiteEvalTensor* output =
      tflite::micro::GetEvalOutput(context, node, kFullyConnectedOutputTensor);

  return EvalQuantizedInt8(context, node, data, input, filter, bias, output);
}

}  // namespace

TfLiteRegistration Register_FULLY_CONNECTED() {
  return {/*init=*/Init,
          /*free=*/nullptr,
          /*prepare=*/Prepare,
          /*invoke=*/Eval,
          /*profiling_string=*/nullptr,
          /*builtin_code=*/0,
          /*custom_name=*/nullptr,
          /*version=*/0};
}

}  // namespace tflite
<commit_msg>address review comments.<commit_after>/* Copyright 2020 The TensorFlow Authors. All Rights Reserved.

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 "tensorflow/lite/micro/kernels/fully_connected.h"

#include "tensorflow/lite/c/builtin_op_data.h"
#include "tensorflow/lite/c/common.h"
#include "tensorflow/lite/kernels/internal/common.h"
#include "tensorflow/lite/kernels/internal/quantization_util.h"
#include "tensorflow/lite/kernels/internal/reference/fully_connected.h"
#include "tensorflow/lite/kernels/internal/reference/integer_ops/fully_connected.h"
#include "tensorflow/lite/kernels/internal/tensor_ctypes.h"
#include "tensorflow/lite/kernels/kernel_util.h"
#include "tensorflow/lite/micro/kernels/kernel_util.h"
#include "tensorflow/lite/micro/kernels/xtensa/fixedpoint_utils.h"
#include "tensorflow/lite/micro/kernels/xtensa/xtensa.h"

namespace tflite {
namespace {

#if defined(HIFIMINI)
void FullyConnected(const FullyConnectedParams& params,
                    const RuntimeShape& input_shape, const int8_t* input_data,
                    const RuntimeShape& filter_shape, const int8_t* filter_data,
                    const RuntimeShape& bias_shape, const int32_t* bias_data,
                    const RuntimeShape& output_shape, int8_t* output_data) {
  // TODO(b/154032858): Investigate removing extra copies.
  const int32_t input_offset = params.input_offset;
  const int32_t filter_offset = params.weights_offset;
  const int32_t output_offset = params.output_offset;
  const int32_t output_multiplier = params.output_multiplier;
  const int output_shift = params.output_shift;
  const int32_t output_activation_min = params.quantized_activation_min;
  const int32_t output_activation_max = params.quantized_activation_max;

  const int filter_dim_count = filter_shape.DimensionsCount();
  const int batches = output_shape.Dims(0);
  const int output_depth = output_shape.Dims(1);
  const int accum_depth = filter_shape.Dims(filter_dim_count - 1);
  const int accum_depth_iters = accum_depth / 2;

  ae_p24x2s offsets_input_24x2 = AE_MOVPA24(input_offset);
  ae_p24x2s offsets_filter_24x2 = AE_MOVPA24(filter_offset);
  ae_q56s output_offset_56 = AE_CVTQ48A32S(output_offset);
  ae_q56s output_activation_max_56 = AE_CVTQ48A32S(output_activation_max);
  ae_q56s output_activation_min_56 = AE_CVTQ48A32S(output_activation_min);

  for (int b = 0; b < batches; ++b) {
    for (int out_c = 0; out_c < output_depth; ++out_c) {
      // Load intrinsics advance pointer before loading so backoff data pointers
      // by two before loading:
      const int8_t* input_ptr = (input_data + b * accum_depth) - 2;
      const int8_t* filter_ptr = (filter_data + out_c * accum_depth) - 2;

      // Main accumulator register entry for loop:
      ae_q56s sum_56 = AE_ZEROQ56();

      for (int d = 0; d < accum_depth_iters; d++) {
        // Load the signed 8bit values into the PR register:
        ae_p24x2s input_24x2;
        ae_p24x2s filter_24x2;
        AE_LP8X2F_IU(input_24x2, input_ptr, 2);
        AE_LP8X2F_IU(filter_24x2, filter_ptr, 2);

        // Right shift the signed 8bit values to expand to signed 24bit values:
        input_24x2 = AE_P24X2S_SRAI(input_24x2, 16);
        filter_24x2 = AE_P24X2S_SRAI(filter_24x2, 16);

        // Add offsets to data values (24 bit aligned):
        input_24x2 = AE_P24S_ADDS_P24X2S(offsets_input_24x2, input_24x2);
        filter_24x2 = AE_P24S_ADDS_P24X2S(offsets_filter_24x2, filter_24x2);

        // 24x2 signed integer dual MAC w/ addition into 56bit accumulator (48
        // bit aligned):
        AE_MULAAP24S_HH_LL(sum_56, input_24x2, filter_24x2);
      }

      // Left shift to get back into 32bit space (right padded to 48bit):
      sum_56 = AE_Q56S_SLAI(sum_56, 16);

      // Add bias data if needed:
      if (bias_data) {
        ae_q56s bias_56 = AE_CVTQ48A32S(bias_data[out_c]);
        sum_56 = AE_ADDQ56(sum_56, bias_56);
      }

      // Shift left into 24bit space and place back on PR register:
      sum_56 = AE_Q56S_SLAI(sum_56, 8);
      ae_p24x2s sum_24x2 = AE_TRUNCP24Q48(sum_56);

      // MultiplyByQuantizedMultiplier returns a 48bit aligned value
      sum_56 = MultiplyByQuantizedMultiplier(sum_24x2, output_multiplier,
                                             output_shift);

      // Add output_offset and cap min/max values:
      sum_56 = AE_ADDQ56(sum_56, output_offset_56);
      sum_56 = AE_MINQ56S(sum_56, output_activation_max_56);
      sum_56 = AE_MAXQ56S(sum_56, output_activation_min_56);

      output_data[out_c + output_depth * b] =
          static_cast<int8_t>(AE_TRUNCA32Q48(sum_56));
    }
  }
}
#endif

TfLiteStatus CalculateOpData(TfLiteContext* context,
                             TfLiteFusedActivation activation,
                             TfLiteType data_type, const TfLiteTensor* input,
                             const TfLiteTensor* filter,
                             const TfLiteTensor* bias, TfLiteTensor* output,
                             OpDataFullyConnected* data) {
  double real_multiplier = 0.0;
  TF_LITE_ENSURE_STATUS(GetQuantizedConvolutionMultipler(
      context, input, filter, bias, output, &real_multiplier));
#if defined(HIFIMINI)
  QuantizeMultiplierForInt24(real_multiplier, &data->output_multiplier,
                             &data->output_shift);
#else
  QuantizeMultiplier(real_multiplier, &data->output_multiplier,
                     &data->output_shift);
#endif
  data->input_zero_point = input->params.zero_point;
  data->filter_zero_point = filter->params.zero_point;
  data->output_zero_point = output->params.zero_point;

  return CalculateActivationRangeQuantized(context, activation, output,
                                           &data->output_activation_min,
                                           &data->output_activation_max);
}

void* Init(TfLiteContext* context, const char* buffer, size_t length) {
  TFLITE_DCHECK(context->AllocatePersistentBuffer != nullptr);
  return context->AllocatePersistentBuffer(context,
                                           sizeof(OpDataFullyConnected));
}

TfLiteStatus Prepare(TfLiteContext* context, TfLiteNode* node) {
  TFLITE_DCHECK(node->user_data != nullptr);
  TFLITE_DCHECK(node->builtin_data != nullptr);

  auto* data = static_cast<OpDataFullyConnected*>(node->user_data);
  const auto* params =
      reinterpret_cast<TfLiteFullyConnectedParams*>(node->builtin_data);

  const TfLiteTensor* input =
      GetInput(context, node, kFullyConnectedInputTensor);
  const TfLiteTensor* filter =
      GetInput(context, node, kFullyConnectedWeightsTensor);
  const TfLiteTensor* bias =
      GetOptionalInputTensor(context, node, kFullyConnectedBiasTensor);
  TfLiteTensor* output = GetOutput(context, node, kFullyConnectedOutputTensor);

  if (input->type != kTfLiteInt8) {
    TF_LITE_KERNEL_LOG(context, "Type %s (%d) not supported.",
                       TfLiteTypeGetName(input->type), input->type);
    return kTfLiteError;
  }

  // Filter weights will always be symmetric quantized since we only support
  // int8 quantization.
  TFLITE_DCHECK(filter->params.zero_point == 0);

  TFLITE_DCHECK(GetTensorShape(output).DimensionsCount() == 2);

  return CalculateOpData(context, params->activation, input->type, input,
                         filter, bias, output, data);
}

TfLiteStatus EvalQuantizedInt8(TfLiteContext* context, TfLiteNode* node,
                               const OpDataFullyConnected& data,
                               const TfLiteEvalTensor* input,
                               const TfLiteEvalTensor* filter,
                               const TfLiteEvalTensor* bias,
                               TfLiteEvalTensor* output) {
  // TODO(b/154032858): Investigate removing extra copies (i.e.
  // data.ToQuantizedParams), and also passing by value.
  //
  // TODO(b/155656675): Consider passing OpDataFullyConnected by value
  // once it is also passed to the FullyConnected function. Until it is copied
  // to a local op_param variable, we do not get any latency improvements from
  // passing by value.
#if defined(HIFIMINI)
  FullyConnected(FullyConnectedParamsQuantized(data),
                 tflite::micro::GetTensorShape(input),
                 tflite::micro::GetTensorData<int8_t>(input),
                 tflite::micro::GetTensorShape(filter),
                 tflite::micro::GetTensorData<int8_t>(filter),
                 tflite::micro::GetTensorShape(bias),
                 tflite::micro::GetTensorData<int32_t>(bias),
                 tflite::micro::GetTensorShape(output),
                 tflite::micro::GetTensorData<int8_t>(output));
#elif defined(FUSION_F1)
  const RuntimeShape& output_shape = tflite::micro::GetTensorShape(output);
  const int num_batches = output_shape.Dims(0);
  const int output_depth = output_shape.Dims(1);

  const RuntimeShape& filter_shape = tflite::micro::GetTensorShape(filter);
  const int filter_dim_count = filter_shape.DimensionsCount();
  const int accum_depth = filter_shape.Dims(filter_dim_count - 1);

  FullyConnectedParams op_params = FullyConnectedParamsQuantized(data);
  for (int b = 0; b < num_batches; ++b) {
    TF_LITE_ENSURE_EQ(
        context,
        xa_nn_fully_connected_sym8sxasym8s_asym8s(
            (tflite::micro::GetTensorData<int8_t>(output) + b * output_depth),
            tflite::micro::GetTensorData<int8_t>(filter),
            (tflite::micro::GetTensorData<int8_t>(input) + b * accum_depth),
            tflite::micro::GetTensorData<int32_t>(bias), accum_depth,
            output_depth, op_params.input_offset, op_params.output_multiplier,
            op_params.output_shift, op_params.output_offset),
        0);
  }

  int8_t* output_arr = tflite::micro::GetTensorData<int8_t>(output);
  TF_LITE_ENSURE_EQ(context,
                    xa_nn_vec_activation_min_max_8_8(
                        output_arr, output_arr, data.output_activation_min,
                        data.output_activation_max, num_batches * output_depth),
                    0);
  return kTfLiteOk;
#else
  reference_integer_ops::FullyConnected(
      FullyConnectedParamsQuantized(data), tflite::micro::GetTensorShape(input),
      tflite::micro::GetTensorData<int8_t>(input),
      tflite::micro::GetTensorShape(filter),
      tflite::micro::GetTensorData<int8_t>(filter),
      tflite::micro::GetTensorShape(bias),
      tflite::micro::GetTensorData<int32_t>(bias),
      tflite::micro::GetTensorShape(output),
      tflite::micro::GetTensorData<int8_t>(output));
#endif

  return kTfLiteOk;
}

TfLiteStatus Eval(TfLiteContext* context, TfLiteNode* node) {
  TFLITE_DCHECK(node->user_data != nullptr);
  const auto& data =
      *(static_cast<const OpDataFullyConnected*>(node->user_data));

  const TfLiteEvalTensor* input =
      tflite::micro::GetEvalInput(context, node, kFullyConnectedInputTensor);
  const TfLiteEvalTensor* filter =
      tflite::micro::GetEvalInput(context, node, kFullyConnectedWeightsTensor);
  const TfLiteEvalTensor* bias =
      (NumInputs(node) == 3) ? tflite::micro::GetEvalInput(
                                   context, node, kFullyConnectedBiasTensor)
                             : nullptr;

  TfLiteEvalTensor* output =
      tflite::micro::GetEvalOutput(context, node, kFullyConnectedOutputTensor);

  return EvalQuantizedInt8(context, node, data, input, filter, bias, output);
}

}  // namespace

TfLiteRegistration Register_FULLY_CONNECTED() {
  return {/*init=*/Init,
          /*free=*/nullptr,
          /*prepare=*/Prepare,
          /*invoke=*/Eval,
          /*profiling_string=*/nullptr,
          /*builtin_code=*/0,
          /*custom_name=*/nullptr,
          /*version=*/0};
}

}  // namespace tflite
<|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 2015 Cloudius Systems
 *
 * Modified by Cloudius Systems
 */

#ifndef CQL3_CONSTANTS_HH
#define CQL3_CONSTANTS_HH

#include "cql3/abstract_marker.hh"
#include "cql3/update_parameters.hh"
#include "cql3/operation.hh"
#include "cql3/term.hh"
#include "core/shared_ptr.hh"

namespace cql3 {

#if 0
package org.apache.cassandra.cql3;

import java.nio.ByteBuffer;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import org.apache.cassandra.config.ColumnDefinition;
import org.apache.cassandra.db.*;
import org.apache.cassandra.db.composites.CellName;
import org.apache.cassandra.db.composites.Composite;
import org.apache.cassandra.db.marshal.AbstractType;
import org.apache.cassandra.db.marshal.BytesType;
import org.apache.cassandra.db.marshal.CounterColumnType;
import org.apache.cassandra.db.marshal.LongType;
import org.apache.cassandra.db.marshal.ReversedType;
import org.apache.cassandra.exceptions.InvalidRequestException;
import org.apache.cassandra.serializers.MarshalException;
import org.apache.cassandra.utils.ByteBufferUtil;
#endif

/**
 * Static helper methods and classes for constants.
 */
class constants {
public:
#if 0
    private static final Logger logger = LoggerFactory.getLogger(Constants.class);
#endif
public:
    enum class type {
        STRING, INTEGER, UUID, FLOAT, BOOLEAN, HEX
    };

    /**
    * A constant value, i.e. a ByteBuffer.
    */
    class value : public terminal {
    public:
        bytes_opt _bytes;
        value(bytes_opt bytes_) : _bytes(std::move(bytes_)) {}
        virtual bytes_opt get(const query_options& options) override { return _bytes; }
        virtual bytes_opt bind_and_get(const query_options& options) override { return _bytes; }
        virtual sstring to_string() const override { return to_hex(*_bytes); }
    };

    class null_literal final : public term::raw {
    private:
        class null_value final : public value {
        public:
            null_value() : value({}) {}
            virtual ::shared_ptr<terminal> bind(const query_options& options) override { return {}; }
            virtual sstring to_string() const override { return "null"; }
        };
        static const ::shared_ptr<terminal> NULL_VALUE;
    public:
        virtual ::shared_ptr<term> prepare(database& db, const sstring& keyspace, ::shared_ptr<column_specification> receiver) override {
            if (!is_assignable(test_assignment(db, keyspace, receiver))) {
                throw exceptions::invalid_request_exception("Invalid null value for counter increment/decrement");
            }
            return NULL_VALUE;
        }

        virtual assignment_testable::test_result test_assignment(database& db,
            const sstring& keyspace,
            ::shared_ptr<column_specification> receiver) override {
                return receiver->type->is_counter()
                    ? assignment_testable::test_result::NOT_ASSIGNABLE
                    : assignment_testable::test_result::WEAKLY_ASSIGNABLE;
        }

        virtual sstring to_string() const override {
            return "null";
        }
    };

    static const ::shared_ptr<term::raw> NULL_LITERAL;

    class literal : public term::raw {
    private:
        const type _type;
        const sstring _text;
    public:
        literal(type type_, sstring text)
            : _type{type_}
            , _text{text}
        { }

        static ::shared_ptr<literal> string(sstring text) {
            return ::make_shared<literal>(type::STRING, text);
        }

        static ::shared_ptr<literal> integer(sstring text) {
            return ::make_shared<literal>(type::INTEGER, text);
        }

        static ::shared_ptr<literal> floating_point(sstring text) {
            return ::make_shared<literal>(type::FLOAT, text);
        }

        static ::shared_ptr<literal> uuid(sstring text) {
            return ::make_shared<literal>(type::UUID, text);
        }

        static ::shared_ptr<literal> bool_(sstring text) {
            return ::make_shared<literal>(type::BOOLEAN, text);
        }

        static ::shared_ptr<literal> hex(sstring text) {
            return ::make_shared<literal>(type::HEX, text);
        }

        virtual ::shared_ptr<term> prepare(database& db, const sstring& keyspace, ::shared_ptr<column_specification> receiver);
    private:
        bytes parsed_value(::shared_ptr<abstract_type> validator);
    public:
        const sstring& get_raw_text() {
            return _text;
        }

        virtual assignment_testable::test_result test_assignment(database& db, const sstring& keyspace, ::shared_ptr<column_specification> receiver);

        virtual sstring to_string() const override {
            return _type == type::STRING ? sstring(sprint("'%s'", _text)) : _text;
        }
    };

    class marker : public abstract_marker {
    public:
        marker(int32_t bind_index, ::shared_ptr<column_specification> receiver)
            : abstract_marker{bind_index, std::move(receiver)}
        {
            assert(!_receiver->type->is_collection());
        }

        virtual bytes_opt bind_and_get(const query_options& options) override {
            try {
                auto value = options.get_values().at(_bind_index);
                if (value) {
                    _receiver->type->validate(value.value());
                }
                return value;
            } catch (const exceptions::marshal_exception& e) {
                throw exceptions::invalid_request_exception(e.what());
            }
        }

        virtual ::shared_ptr<terminal> bind(const query_options& options) override {
            auto bytes = bind_and_get(options);
            if (!bytes) {
                return ::shared_ptr<terminal>{};
            }
            return ::make_shared<constants::value>(std::move(bytes));
        }
    };

    class setter : public operation {
    public:
        using operation::operation;

        virtual void execute(mutation& m, const exploded_clustering_prefix& prefix, const update_parameters& params) override {
            bytes_opt value = _t->bind_and_get(params._options);
            auto cell = value ? params.make_cell(*value) : params.make_dead_cell();
            m.set_cell(prefix, column, std::move(cell));
        }
    };

#if 0
    public static class Adder extends Operation
    {
        public Adder(ColumnDefinition column, Term t)
        {
            super(column, t);
        }

        public void execute(ByteBuffer rowKey, ColumnFamily cf, Composite prefix, UpdateParameters params) throws InvalidRequestException
        {
            ByteBuffer bytes = t.bindAndGet(params.options);
            if (bytes == null)
                throw new InvalidRequestException("Invalid null value for counter increment");
            long increment = ByteBufferUtil.toLong(bytes);
            CellName cname = cf.getComparator().create(prefix, column);
            cf.addColumn(params.makeCounter(cname, increment));
        }
    }

    public static class Substracter extends Operation
    {
        public Substracter(ColumnDefinition column, Term t)
        {
            super(column, t);
        }

        public void execute(ByteBuffer rowKey, ColumnFamily cf, Composite prefix, UpdateParameters params) throws InvalidRequestException
        {
            ByteBuffer bytes = t.bindAndGet(params.options);
            if (bytes == null)
                throw new InvalidRequestException("Invalid null value for counter increment");

            long increment = ByteBufferUtil.toLong(bytes);
            if (increment == Long.MIN_VALUE)
                throw new InvalidRequestException("The negation of " + increment + " overflows supported counter precision (signed 8 bytes integer)");

            CellName cname = cf.getComparator().create(prefix, column);
            cf.addColumn(params.makeCounter(cname, -increment));
        }
    }
#endif

    class deleter : public operation {
    public:
        deleter(const column_definition& column)
            : operation(column, {})
        { }

        virtual void execute(mutation& m, const exploded_clustering_prefix& prefix, const update_parameters& params) override;
    };
};

std::ostream& operator<<(std::ostream&out, constants::type t);

}

#endif
<commit_msg>cql3: remove gunk from constants.hh<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 2015 Cloudius Systems
 *
 * Modified by Cloudius Systems
 */

#ifndef CQL3_CONSTANTS_HH
#define CQL3_CONSTANTS_HH

#include "cql3/abstract_marker.hh"
#include "cql3/update_parameters.hh"
#include "cql3/operation.hh"
#include "cql3/term.hh"
#include "core/shared_ptr.hh"

namespace cql3 {

/**
 * Static helper methods and classes for constants.
 */
class constants {
public:
#if 0
    private static final Logger logger = LoggerFactory.getLogger(Constants.class);
#endif
public:
    enum class type {
        STRING, INTEGER, UUID, FLOAT, BOOLEAN, HEX
    };

    /**
    * A constant value, i.e. a ByteBuffer.
    */
    class value : public terminal {
    public:
        bytes_opt _bytes;
        value(bytes_opt bytes_) : _bytes(std::move(bytes_)) {}
        virtual bytes_opt get(const query_options& options) override { return _bytes; }
        virtual bytes_opt bind_and_get(const query_options& options) override { return _bytes; }
        virtual sstring to_string() const override { return to_hex(*_bytes); }
    };

    class null_literal final : public term::raw {
    private:
        class null_value final : public value {
        public:
            null_value() : value({}) {}
            virtual ::shared_ptr<terminal> bind(const query_options& options) override { return {}; }
            virtual sstring to_string() const override { return "null"; }
        };
        static const ::shared_ptr<terminal> NULL_VALUE;
    public:
        virtual ::shared_ptr<term> prepare(database& db, const sstring& keyspace, ::shared_ptr<column_specification> receiver) override {
            if (!is_assignable(test_assignment(db, keyspace, receiver))) {
                throw exceptions::invalid_request_exception("Invalid null value for counter increment/decrement");
            }
            return NULL_VALUE;
        }

        virtual assignment_testable::test_result test_assignment(database& db,
            const sstring& keyspace,
            ::shared_ptr<column_specification> receiver) override {
                return receiver->type->is_counter()
                    ? assignment_testable::test_result::NOT_ASSIGNABLE
                    : assignment_testable::test_result::WEAKLY_ASSIGNABLE;
        }

        virtual sstring to_string() const override {
            return "null";
        }
    };

    static const ::shared_ptr<term::raw> NULL_LITERAL;

    class literal : public term::raw {
    private:
        const type _type;
        const sstring _text;
    public:
        literal(type type_, sstring text)
            : _type{type_}
            , _text{text}
        { }

        static ::shared_ptr<literal> string(sstring text) {
            return ::make_shared<literal>(type::STRING, text);
        }

        static ::shared_ptr<literal> integer(sstring text) {
            return ::make_shared<literal>(type::INTEGER, text);
        }

        static ::shared_ptr<literal> floating_point(sstring text) {
            return ::make_shared<literal>(type::FLOAT, text);
        }

        static ::shared_ptr<literal> uuid(sstring text) {
            return ::make_shared<literal>(type::UUID, text);
        }

        static ::shared_ptr<literal> bool_(sstring text) {
            return ::make_shared<literal>(type::BOOLEAN, text);
        }

        static ::shared_ptr<literal> hex(sstring text) {
            return ::make_shared<literal>(type::HEX, text);
        }

        virtual ::shared_ptr<term> prepare(database& db, const sstring& keyspace, ::shared_ptr<column_specification> receiver);
    private:
        bytes parsed_value(::shared_ptr<abstract_type> validator);
    public:
        const sstring& get_raw_text() {
            return _text;
        }

        virtual assignment_testable::test_result test_assignment(database& db, const sstring& keyspace, ::shared_ptr<column_specification> receiver);

        virtual sstring to_string() const override {
            return _type == type::STRING ? sstring(sprint("'%s'", _text)) : _text;
        }
    };

    class marker : public abstract_marker {
    public:
        marker(int32_t bind_index, ::shared_ptr<column_specification> receiver)
            : abstract_marker{bind_index, std::move(receiver)}
        {
            assert(!_receiver->type->is_collection());
        }

        virtual bytes_opt bind_and_get(const query_options& options) override {
            try {
                auto value = options.get_values().at(_bind_index);
                if (value) {
                    _receiver->type->validate(value.value());
                }
                return value;
            } catch (const exceptions::marshal_exception& e) {
                throw exceptions::invalid_request_exception(e.what());
            }
        }

        virtual ::shared_ptr<terminal> bind(const query_options& options) override {
            auto bytes = bind_and_get(options);
            if (!bytes) {
                return ::shared_ptr<terminal>{};
            }
            return ::make_shared<constants::value>(std::move(bytes));
        }
    };

    class setter : public operation {
    public:
        using operation::operation;

        virtual void execute(mutation& m, const exploded_clustering_prefix& prefix, const update_parameters& params) override {
            bytes_opt value = _t->bind_and_get(params._options);
            auto cell = value ? params.make_cell(*value) : params.make_dead_cell();
            m.set_cell(prefix, column, std::move(cell));
        }
    };

#if 0
    public static class Adder extends Operation
    {
        public Adder(ColumnDefinition column, Term t)
        {
            super(column, t);
        }

        public void execute(ByteBuffer rowKey, ColumnFamily cf, Composite prefix, UpdateParameters params) throws InvalidRequestException
        {
            ByteBuffer bytes = t.bindAndGet(params.options);
            if (bytes == null)
                throw new InvalidRequestException("Invalid null value for counter increment");
            long increment = ByteBufferUtil.toLong(bytes);
            CellName cname = cf.getComparator().create(prefix, column);
            cf.addColumn(params.makeCounter(cname, increment));
        }
    }

    public static class Substracter extends Operation
    {
        public Substracter(ColumnDefinition column, Term t)
        {
            super(column, t);
        }

        public void execute(ByteBuffer rowKey, ColumnFamily cf, Composite prefix, UpdateParameters params) throws InvalidRequestException
        {
            ByteBuffer bytes = t.bindAndGet(params.options);
            if (bytes == null)
                throw new InvalidRequestException("Invalid null value for counter increment");

            long increment = ByteBufferUtil.toLong(bytes);
            if (increment == Long.MIN_VALUE)
                throw new InvalidRequestException("The negation of " + increment + " overflows supported counter precision (signed 8 bytes integer)");

            CellName cname = cf.getComparator().create(prefix, column);
            cf.addColumn(params.makeCounter(cname, -increment));
        }
    }
#endif

    class deleter : public operation {
    public:
        deleter(const column_definition& column)
            : operation(column, {})
        { }

        virtual void execute(mutation& m, const exploded_clustering_prefix& prefix, const update_parameters& params) override;
    };
};

std::ostream& operator<<(std::ostream&out, constants::type t);

}

#endif
<|endoftext|>


<commit_before>/*
 *  Copyright (C) 2015 Samsung Electronics Co., Ltd All Rights Reserved
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1 as published by the Free Software Foundation.
 *
 *  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 Street, Fifth Floor, Boston, MA  02110-1301  USA
 */

/**
 * @file
 * @author  Mateusz Malicki (m.malicki2@samsung.com)
 * @brief   Container interface
 */

#ifndef LXCPP_CONTAINER_HPP
#define LXCPP_CONTAINER_HPP

#include "lxcpp/network-config.hpp"
#include "lxcpp/provision-config.hpp"
#include "lxcpp/cgroups/cgroup-config.hpp"
#include "lxcpp/logger-config.hpp"

#include <sys/types.h>

#include <string>
#include <functional>
#include <vector>

namespace lxcpp {

struct NetworkInterfaceInfo {
    const std::string ifname;
    const NetStatus status;
    const std::string macaddr;
    const int mtu;
    const int flags;
    const std::vector<InetAddr> addrs;
};

class Container {
public:
    typedef std::function<void(void)> Callback;

    enum class State: int {
        STOPPED,   //< Init isn't running
        STOPPING,  //< Init's stop is triggered
        STARTING,  //< Container is being set up
        RUNNING,   //< Init in container is running
        CONNECTING //< Synchronizing with existing Guard
    };

    virtual ~Container() {};

    /**
     * Configuration
     */
    virtual const std::string& getName() const = 0;
    virtual const std::string& getRootPath() const = 0;
    virtual void setHostName(const std::string& hostname) = 0;

    virtual pid_t getGuardPid() const = 0;
    virtual pid_t getInitPid() const = 0;

    virtual const std::vector<std::string>& getInit() = 0;
    virtual void setInit(const std::vector<std::string> &init) = 0;

    virtual void setLogger(const logger::LogType type,
                           const logger::LogLevel level,
                           const std::string &arg = "") = 0;

    virtual void setTerminalCount(const unsigned int count) = 0;

    virtual void addUIDMap(unsigned min, unsigned max, unsigned num) = 0;
    virtual void addGIDMap(unsigned min, unsigned max, unsigned num) = 0;

    /**
     * Execution actions
     */
    virtual void start() = 0;
    virtual void stop() = 0;
    virtual void freeze() = 0;
    virtual void unfreeze() = 0;
    virtual void reboot() = 0;
    virtual bool connect() = 0;

    /**
     * States
     */
    virtual State getState() = 0;
    virtual void setStartedCallback(const Callback& callback) = 0;
    virtual void setStoppedCallback(const Callback& callback) = 0;

    /**
     * Other
     */
    virtual int attach(const std::vector<std::string>& argv,
                       const uid_t uid,
                       const gid_t gid,
                       const std::string& ttyPath,
                       const std::vector<gid_t>& supplementaryGids,
                       const int capsToKeep,
                       const std::string& workDirInContainer,
                       const std::vector<std::string>& envToKeep,
                       const std::vector<std::pair<std::string, std::string>>& envToSet) = 0;
    virtual void console() = 0;

    // Network interfaces setup/config
    virtual void addInterfaceConfig(InterfaceConfigType type,
                                    const std::string& hostif,
                                    const std::string& zoneif = "",
                                    const std::vector<InetAddr>& addrs = std::vector<InetAddr>(),
                                    MacVLanMode mode = MacVLanMode::PRIVATE) = 0;
    virtual void addInetConfig(const std::string& ifname, const InetAddr& addr) = 0;

    /**
     * Network interfaces (runtime)
     */
    virtual std::vector<std::string> getInterfaces() const = 0;
    virtual NetworkInterfaceInfo getInterfaceInfo(const std::string& ifname) const = 0;
    virtual void createInterface(const std::string& hostif,
                                 const std::string& zoneif,
                                 InterfaceType type,
                                 MacVLanMode mode) = 0;
    virtual void destroyInterface(const std::string& ifname) = 0;
    virtual void moveInterface(const std::string& ifname) = 0;
    virtual void setUpInterface(const std::string& ifname) = 0;
    virtual void setDownInterface(const std::string& ifname) = 0;
    virtual void addInetAddr(const std::string& ifname, const InetAddr& addr) = 0;
    virtual void delInetAddr(const std::string& ifname, const InetAddr& addr) = 0;

    /**
     * Provisioning
     */
    virtual void declareFile(const provision::File::Type type,
                             const std::string& path,
                             const int32_t flags,
                             const int32_t mode) = 0;
    virtual const FileVector& getFiles() const = 0;
    virtual void removeFile(const provision::File& item) = 0;

    virtual void declareMount(const std::string& source,
                              const std::string& target,
                              const std::string& type,
                              const int64_t flags,
                              const std::string& data) = 0;
    virtual const MountVector& getMounts() const = 0;
    virtual void removeMount(const provision::Mount& item) = 0;

    virtual void declareLink(const std::string& source,
                             const std::string& target) = 0;
    virtual const LinkVector& getLinks() const = 0;
    virtual void removeLink(const provision::Link& item) = 0;

    /**
     * CGroups
     */
    virtual void addSubsystem(const std::string& name, const std::string& path) = 0;
    virtual void addCGroup(const std::string& subsys,
                           const std::string& grpname,
                           const std::vector<CGroupParam>& comm,
                           const std::vector<CGroupParam>& params) = 0;

    /**
     * Environment variables
     */
    virtual void setEnv(const std::vector<std::pair<std::string, std::string>>& variables) = 0;

    /**
     * Linux capabilities
     */
    virtual void setCaps(const int caps) = 0;

    /**
     * System Property (sysctl)
     */
    virtual void setSystemProperty(const std::string& name, const std::string& value) = 0;

    /**
     * Rlimit
     */
    virtual void setRlimit(const std::string& type, const uint64_t hard, const uint64_t soft) = 0;

    /**
     * Namespaces
     * TODO Needed to implement application container.
     */
    virtual void setNamespaces(const int namespaces) = 0;

    /**
     * UID/GIDS
     * TODO Needed to implement application container.
     */
    virtual void setUser(const int uid, const int gid, const std::vector<int> additionalGids) = 0;

    /**
     * Device
     */
    virtual void addDevice(const std::string& path,
                           const char type,
                           const int64_t major,
                           const int64_t minor,
                           const std::string& permissions,
                           const uint32_t fileMode,
                           const uint32_t uid,
                           const uint32_t gid) = 0;

    /**
     * Hooks
     */
    virtual void addHook(const std::string& type,
                         const std::vector<std::string>& hook,
                         const std::vector<std::pair<std::string, std::string>>& env) = 0;

};

} // namespace lxcpp

#endif // LXCPP_CONTAINER_HPP
<commit_msg>lxcpp: Fixed comments<commit_after>/*
 *  Copyright (C) 2015 Samsung Electronics Co., Ltd All Rights Reserved
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1 as published by the Free Software Foundation.
 *
 *  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 Street, Fifth Floor, Boston, MA  02110-1301  USA
 */

/**
 * @file
 * @author  Mateusz Malicki (m.malicki2@samsung.com)
 * @brief   Container interface
 */

#ifndef LXCPP_CONTAINER_HPP
#define LXCPP_CONTAINER_HPP

#include "lxcpp/network-config.hpp"
#include "lxcpp/provision-config.hpp"
#include "lxcpp/cgroups/cgroup-config.hpp"
#include "lxcpp/logger-config.hpp"

#include <sys/types.h>

#include <string>
#include <functional>
#include <vector>

namespace lxcpp {

struct NetworkInterfaceInfo {
    const std::string ifname;
    const NetStatus status;
    const std::string macaddr;
    const int mtu;
    const int flags;
    const std::vector<InetAddr> addrs;
};

class Container {
public:
    typedef std::function<void(void)> Callback;

    enum class State: int {
        STOPPED,   ///< Init isn't running
        STOPPING,  ///< Init's stop is triggered
        STARTING,  ///< Container is being set up
        RUNNING,   ///< Init in container is running
        CONNECTING ///< Synchronizing with existing Guard
    };

    virtual ~Container() {};

    /**
     * Configuration
     */
    virtual const std::string& getName() const = 0;
    virtual const std::string& getRootPath() const = 0;
    virtual void setHostName(const std::string& hostname) = 0;

    virtual pid_t getGuardPid() const = 0;
    virtual pid_t getInitPid() const = 0;

    virtual const std::vector<std::string>& getInit() = 0;
    virtual void setInit(const std::vector<std::string> &init) = 0;

    virtual void setLogger(const logger::LogType type,
                           const logger::LogLevel level,
                           const std::string &arg = "") = 0;

    virtual void setTerminalCount(const unsigned int count) = 0;

    virtual void addUIDMap(unsigned min, unsigned max, unsigned num) = 0;
    virtual void addGIDMap(unsigned min, unsigned max, unsigned num) = 0;

    /**
     * Execution actions
     */
    virtual void start() = 0;
    virtual void stop() = 0;
    virtual void freeze() = 0;
    virtual void unfreeze() = 0;
    virtual void reboot() = 0;
    virtual bool connect() = 0;

    /**
     * States
     */
    virtual State getState() = 0;
    virtual void setStartedCallback(const Callback& callback) = 0;
    virtual void setStoppedCallback(const Callback& callback) = 0;

    /**
     * Other
     */
    virtual int attach(const std::vector<std::string>& argv,
                       const uid_t uid,
                       const gid_t gid,
                       const std::string& ttyPath,
                       const std::vector<gid_t>& supplementaryGids,
                       const int capsToKeep,
                       const std::string& workDirInContainer,
                       const std::vector<std::string>& envToKeep,
                       const std::vector<std::pair<std::string, std::string>>& envToSet) = 0;
    virtual void console() = 0;

    // Network interfaces setup/config
    virtual void addInterfaceConfig(InterfaceConfigType type,
                                    const std::string& hostif,
                                    const std::string& zoneif = "",
                                    const std::vector<InetAddr>& addrs = std::vector<InetAddr>(),
                                    MacVLanMode mode = MacVLanMode::PRIVATE) = 0;
    virtual void addInetConfig(const std::string& ifname, const InetAddr& addr) = 0;

    /**
     * Network interfaces (runtime)
     */
    virtual std::vector<std::string> getInterfaces() const = 0;
    virtual NetworkInterfaceInfo getInterfaceInfo(const std::string& ifname) const = 0;
    virtual void createInterface(const std::string& hostif,
                                 const std::string& zoneif,
                                 InterfaceType type,
                                 MacVLanMode mode) = 0;
    virtual void destroyInterface(const std::string& ifname) = 0;
    virtual void moveInterface(const std::string& ifname) = 0;
    virtual void setUpInterface(const std::string& ifname) = 0;
    virtual void setDownInterface(const std::string& ifname) = 0;
    virtual void addInetAddr(const std::string& ifname, const InetAddr& addr) = 0;
    virtual void delInetAddr(const std::string& ifname, const InetAddr& addr) = 0;

    /**
     * Provisioning
     */
    virtual void declareFile(const provision::File::Type type,
                             const std::string& path,
                             const int32_t flags,
                             const int32_t mode) = 0;
    virtual const FileVector& getFiles() const = 0;
    virtual void removeFile(const provision::File& item) = 0;

    virtual void declareMount(const std::string& source,
                              const std::string& target,
                              const std::string& type,
                              const int64_t flags,
                              const std::string& data) = 0;
    virtual const MountVector& getMounts() const = 0;
    virtual void removeMount(const provision::Mount& item) = 0;

    virtual void declareLink(const std::string& source,
                             const std::string& target) = 0;
    virtual const LinkVector& getLinks() const = 0;
    virtual void removeLink(const provision::Link& item) = 0;

    /**
     * CGroups
     */
    virtual void addSubsystem(const std::string& name, const std::string& path) = 0;
    virtual void addCGroup(const std::string& subsys,
                           const std::string& grpname,
                           const std::vector<CGroupParam>& comm,
                           const std::vector<CGroupParam>& params) = 0;

    /**
     * Environment variables
     */
    virtual void setEnv(const std::vector<std::pair<std::string, std::string>>& variables) = 0;

    /**
     * Linux capabilities
     */
    virtual void setCaps(const int caps) = 0;

    /**
     * System Property (sysctl)
     */
    virtual void setSystemProperty(const std::string& name, const std::string& value) = 0;

    /**
     * Rlimit
     */
    virtual void setRlimit(const std::string& type, const uint64_t hard, const uint64_t soft) = 0;

    /**
     * Namespaces
     * TODO Needed to implement application container.
     */
    virtual void setNamespaces(const int namespaces) = 0;

    /**
     * UID/GIDS
     * TODO Needed to implement application container.
     */
    virtual void setUser(const int uid, const int gid, const std::vector<int> additionalGids) = 0;

    /**
     * Device
     */
    virtual void addDevice(const std::string& path,
                           const char type,
                           const int64_t major,
                           const int64_t minor,
                           const std::string& permissions,
                           const uint32_t fileMode,
                           const uint32_t uid,
                           const uint32_t gid) = 0;

    /**
     * Hooks
     */
    virtual void addHook(const std::string& type,
                         const std::vector<std::string>& hook,
                         const std::vector<std::pair<std::string, std::string>>& env) = 0;

};

} // namespace lxcpp

#endif // LXCPP_CONTAINER_HPP
<|endoftext|>


<commit_before>#ifndef LIBBITCOIN_TYPES_H
#define LIBBITCOIN_TYPES_H

#include <boost/detail/endian.hpp>
#include <boost/asio.hpp>
#include <array>
#include <memory>
#include <sstream>
#include <iomanip>
#include <vector>

#include <bitcoin/network/types.hpp>

namespace libbitcoin {

using std::shared_ptr;
using boost::asio::io_service;
using boost::asio::ip::tcp;
using boost::asio::deadline_timer;

class dialect;
class blockchain;
class kernel;
class network;
class clock;

typedef shared_ptr<dialect> dialect_ptr;
typedef shared_ptr<blockchain> blockchain_ptr;
typedef shared_ptr<kernel> kernel_ptr;
typedef shared_ptr<network> network_ptr;
typedef shared_ptr<clock> clock_ptr;

typedef shared_ptr<io_service> service_ptr;
typedef shared_ptr<io_service::work> work_ptr;
typedef shared_ptr<io_service::strand> strand_ptr;
typedef shared_ptr<deadline_timer> deadline_timer_ptr;

typedef std::array<uint8_t, 32> hash_digest;
typedef std::array<uint8_t, 20> short_hash;

typedef unsigned char byte;
typedef std::vector<byte> data_chunk;

template<typename D, typename T>
void extend_data(D& chunk, const T& other)
{
    chunk.insert(end(chunk), begin(other), end(other));
}

template<typename T>
T cast_chunk(data_chunk chunk, bool reverse=false)
{
    #ifdef BOOST_LITTLE_ENDIAN
        reverse = !reverse;
    #elif BOOST_BIG_ENDIAN
        // do nothing
    #else
        #error "Endian isn't defined!"
    #endif

    if (reverse)
        std::reverse(begin(chunk), end(chunk));

    T val = 0;
    for (size_t i = 0; i < sizeof(T) && i < chunk.size(); ++i)
        val += static_cast<T>(chunk[i]) << (i*8);
    return val;
}

template<typename T>
data_chunk uncast_type(T val, bool reverse=false)
{
    data_chunk chunk;
    for (size_t i = 0; i < sizeof(T); ++i)
        chunk.push_back(reinterpret_cast<byte*>(&val)[i]);
    if (reverse)
        std::reverse(begin(chunk), end(chunk));
    return chunk;
}

template<typename T>
std::string pretty_hex(T data)
{
    std::stringstream ss;
    ss << std::hex;
    for (int val: data)
        ss << std::setw(2) << std::setfill('0') << val << ' ';
    // Remove end ' '
    std::string ret = ss.str();
    if (ret.size() == 0)
        return "";
    ret.resize(ret.size() - 1);
    return ret;
}

data_chunk bytes_from_pretty(std::string byte_stream);
hash_digest hash_from_pretty(std::string byte_stream);

} // libbitcoin

#endif

<commit_msg>hash_digest / short_hash std::hash implementations for std::*map variants.<commit_after>#ifndef LIBBITCOIN_TYPES_H
#define LIBBITCOIN_TYPES_H

#include <boost/detail/endian.hpp>
#include <boost/asio.hpp>
#include <array>
#include <memory>
#include <sstream>
#include <iomanip>
#include <vector>

#include <bitcoin/network/types.hpp>

namespace libbitcoin {

using std::shared_ptr;
using boost::asio::io_service;
using boost::asio::ip::tcp;
using boost::asio::deadline_timer;

class dialect;
class blockchain;
class kernel;
class network;
class clock;

typedef shared_ptr<dialect> dialect_ptr;
typedef shared_ptr<blockchain> blockchain_ptr;
typedef shared_ptr<kernel> kernel_ptr;
typedef shared_ptr<network> network_ptr;
typedef shared_ptr<clock> clock_ptr;

typedef shared_ptr<io_service> service_ptr;
typedef shared_ptr<io_service::work> work_ptr;
typedef shared_ptr<io_service::strand> strand_ptr;
typedef shared_ptr<deadline_timer> deadline_timer_ptr;

typedef std::array<uint8_t, 32> hash_digest;
typedef std::array<uint8_t, 20> short_hash;

typedef unsigned char byte;
typedef std::vector<byte> data_chunk;

template<typename D, typename T>
void extend_data(D& chunk, const T& other)
{
    chunk.insert(end(chunk), begin(other), end(other));
}

template<typename T>
T cast_chunk(data_chunk chunk, bool reverse=false)
{
    #ifdef BOOST_LITTLE_ENDIAN
        reverse = !reverse;
    #elif BOOST_BIG_ENDIAN
        // do nothing
    #else
        #error "Endian isn't defined!"
    #endif

    if (reverse)
        std::reverse(begin(chunk), end(chunk));

    T val = 0;
    for (size_t i = 0; i < sizeof(T) && i < chunk.size(); ++i)
        val += static_cast<T>(chunk[i]) << (i*8);
    return val;
}

template<typename T>
data_chunk uncast_type(T val, bool reverse=false)
{
    data_chunk chunk;
    for (size_t i = 0; i < sizeof(T); ++i)
        chunk.push_back(reinterpret_cast<byte*>(&val)[i]);
    if (reverse)
        std::reverse(begin(chunk), end(chunk));
    return chunk;
}

template<typename T>
std::string pretty_hex(T data)
{
    std::stringstream ss;
    ss << std::hex;
    for (int val: data)
        ss << std::setw(2) << std::setfill('0') << val << ' ';
    // Remove end ' '
    std::string ret = ss.str();
    if (ret.size() == 0)
        return "";
    ret.resize(ret.size() - 1);
    return ret;
}

data_chunk bytes_from_pretty(std::string byte_stream);
hash_digest hash_from_pretty(std::string byte_stream);

// Make hash_digest and short_hash hashable for std::*map variants
template <typename HashType>
struct std_hash_wrapper
{
    size_t operator()(const HashType& h) const
    {
        std::hash<std::string> functor;
        return functor(std::string(std::begin(h), std::end(h)));
    }
};

} // libbitcoin

// Extend std namespace with our hash wrappers
namespace std
{
    using libbitcoin::std_hash_wrapper;
    using libbitcoin::hash_digest;
    using libbitcoin::short_hash;

    template <>
    struct hash<hash_digest> : public std_hash_wrapper<hash_digest>
    {
    };

    template <>
    struct hash<short_hash> : public std_hash_wrapper<short_hash>
    {
    };
}

#endif

<|endoftext|>


<commit_before>/*
 * callbacks.hpp - Framework support of callback functions
 *
 *   Copyright 2010-2011 Jesús Torres <jmtorres@ull.es>
 *
 * 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 CALLBACKS_HPP_
#define CALLBACKS_HPP_

#include <string>
#include <vector>

#include <boost/function.hpp>
#include <boost/mpl/assert.hpp>
#include <boost/preprocessor/seq/for_each.hpp>
#include <boost/preprocessor/tuple/elem.hpp>
#include <boost/type_traits.hpp>

#include <cli/exceptions.hpp>

//
// Macro CLI_DECLARE_CALLBACKS & CLI_DECLARE_CALLBACKS_TPL
//
// Helps to add the support for callbacks to a class declaration.
//

#define CLI_DECLARE_CALLBACKS_FILLER_0(X, Y)    \
    ((X, Y)) CLI_DECLARE_CALLBACKS_FILLER_1
#define CLI_DECLARE_CALLBACKS_FILLER_1(X, Y)    \
    ((X, Y)) CLI_DECLARE_CALLBACKS_FILLER_0
#define CLI_DECLARE_CALLBACKS_FILLER_0_END
#define CLI_DECLARE_CALLBACKS_FILLER_1_END

#define CLI_DECLARE_CALLBACK_MEMBER(r, TYPE, DECLARATION_TUPLE)     \
    typedef cli::callback::                                         \
        BOOST_PP_TUPLE_ELEM(2, 0, DECLARATION_TUPLE)<TYPE>::Type    \
        BOOST_PP_TUPLE_ELEM(2, 0, DECLARATION_TUPLE);               \
    boost::function<BOOST_PP_TUPLE_ELEM(2, 0, DECLARATION_TUPLE)>   \
        BOOST_PP_TUPLE_ELEM(2, 1, DECLARATION_TUPLE);

#define CLI_DECLARE_CALLBACK_MEMBER_TPL(r, TYPE, DECLARATION_TUPLE) \
    typedef typename cli::callback::                                \
        BOOST_PP_TUPLE_ELEM(2, 0, DECLARATION_TUPLE)<TYPE>::Type    \
        BOOST_PP_TUPLE_ELEM(2, 0, DECLARATION_TUPLE);               \
    boost::function<BOOST_PP_TUPLE_ELEM(2, 0, DECLARATION_TUPLE)>   \
        BOOST_PP_TUPLE_ELEM(2, 1, DECLARATION_TUPLE);

#define CLI_DECLARE_CALLBACKS(TYPE, DECLARATIONS_SEQ)               \
    BOOST_PP_SEQ_FOR_EACH(                                          \
        CLI_DECLARE_CALLBACK_MEMBER,                                \
        TYPE,                                                       \
        BOOST_PP_CAT(                                               \
            CLI_DECLARE_CALLBACKS_FILLER_0 DECLARATIONS_SEQ, _END)) \
    template <template <typename> class Callback>                   \
    friend class cli::callback::SetCallbackImpl;

#define CLI_DECLARE_CALLBACKS_TPL(TYPE, DECLARATIONS_SEQ)           \
    BOOST_PP_SEQ_FOR_EACH(                                          \
        CLI_DECLARE_CALLBACK_MEMBER_TPL,                            \
        TYPE,                                                       \
        BOOST_PP_CAT(                                               \
            CLI_DECLARE_CALLBACKS_FILLER_0 DECLARATIONS_SEQ, _END)) \
    template <template <typename> class Callback>                   \
    friend class cli::callback::SetCallbackImpl;

//
// Macro CLI_CALLBACK_SIGNATURE_ASSERT & CLI_CALLBACK_SIGNATURE_ASSERT_TPL
//
// Tests if the function signature of FUNCTOR match the expected by CALLBACK.
//

#define CLI_CALLBACK_SIGNATURE_ASSERT(CALLBACK, FUNCTOR)                \
    BOOST_MPL_ASSERT((boost::is_convertible<FUNCTOR,                    \
        boost::function<CALLBACK<Type>::Type> >))

#define CLI_CALLBACK_SIGNATURE_ASSERT_TPL(CALLBACK, FUNCTOR)            \
    BOOST_MPL_ASSERT((boost::is_convertible<FUNCTOR,                    \
        boost::function<typename CALLBACK<Type>::Type> >))

namespace cli { namespace callback
{
    //
    // Base template for callback function setter implementation
    //

    template <template <typename> class Callback>
    struct SetCallbackImpl
    {
        template <typename T, typename Functor>
        static void setCallback(T& interpreter, Functor function)
        {
            throw cli::exception::UnknownCallbackException(
                Callback<T>::name());
        }
    };

    //
    // DoCommandCallback
    //

    template <typename T>
    struct DoCommandCallback
    {
        typedef bool (Type)(const std::string&,
            typename T::CommandArgumentsType const&);
        static const char* name() { return "DoCommandCallback"; }
    };

    template <>
    struct SetCallbackImpl<DoCommandCallback>
    {
        template <typename T, typename Functor>
        static void setCallback(T& interpreter, Functor function)
            { interpreter.defaultDoCommandCallback_ = function; }
        template <typename T, typename Functor>
        static void setCallback(T& interpreter, Functor function,
            const std::string& command)
            { interpreter.doCommandCallbacks_[command] = function; }
    };

    //
    // EmptyLineCallback
    //

    template <typename T>
    struct EmptyLineCallback
    {
        typedef bool (Type)();
        static const char* name() { return "EmptyLineCallback"; }
    };

    template <>
    struct SetCallbackImpl<EmptyLineCallback>
    {
        template <typename T, typename Functor>
        static void setCallback(T& interpreter, Functor function)
            { interpreter.emptyLineCallback_ = function; }
    };

    //
    // PreDoCommandCallback
    //

    template <typename T>
    struct PreDoCommandCallback
    {
        typedef void (Type)(std::string&);
        static const char* name() { return "PreDoCommandCallback"; }
    };

    template <>
    struct SetCallbackImpl<PreDoCommandCallback>
    {
        template <typename T, typename Functor>
        static void setCallback(T& interpreter, Functor function)
            { interpreter.preDoCommandCallback_ = function; }
    };

    //
    // PostDoCommandCallback
    //

    template <typename T>
    struct PostDoCommandCallback
    {
        typedef bool (Type)(bool, const std::string&);
        static const char* name() { return "PostDoCommandCallback"; }
    };

    template <>
    struct SetCallbackImpl<PostDoCommandCallback>
    {
        template <typename T, typename Functor>
        static void setCallback(T& interpreter, Functor function)
            { interpreter.postDoCommandCallback_ = function; }
    };

    //
    // ParserErrorCallback
    //

    template <typename T>
    struct ParserErrorCallback
    {
            typedef bool (Type)(typename T::ParserErrorType const&,
                const std::string&);
            static const char* name() { return "ParserErrorCallback"; }
    };

    template <>
    struct SetCallbackImpl<ParserErrorCallback>
    {
            template <typename T, typename Functor>
            static void setCallback(T& interpreter, Functor function)
            { interpreter.parserErrorCallback_ = function; }
    };

    //
    // PreLoopCallback
    //

    template <typename T>
    struct PreLoopCallback
    {
        typedef void (Type)();
        static const char* name() { return "PreLoopCallback"; }
    };

    template <>
    struct SetCallbackImpl<PreLoopCallback>
    {
        template <typename T, typename Functor>
        static void setCallback(T& interpreter, Functor function)
            { interpreter.preLoopCallback_ = function; }
    };

    //
    // PostLoopCallback
    //

    template <typename T>
    struct PostLoopCallback
    {
        typedef void (Type)();
        static const char* name() { return "PostLoopCallback"; }
    };

    template <>
    struct SetCallbackImpl<PostLoopCallback>
    {
        template <typename T, typename Functor>
        static void setCallback(T& interpreter, Functor function)
            { interpreter.postLoopCallback_ = function; }
    };

    //
    // VariableLookupCallback
    //

    template <typename T>
    struct VariableLookupCallback
    {
        typedef std::string (Type)(const std::string&);
        static const char* name() { return "VariableLookupCallback"; }
    };

    template <>
    struct SetCallbackImpl<VariableLookupCallback>
    {
        template <typename T, typename Functor>
        static void setCallback(T& interpreter, Functor function)
            { interpreter.lineParser_->variableLookupCallback_ = function; }
    };

    //
    // PathnameExpansionCallback
    //

    template <typename T>
    struct PathnameExpansionCallback
    {
        typedef std::vector<std::string> (Type)(const std::string&);
        static const char* name() { return "PathnameExpansionCallback"; }
    };

    template <>
    struct SetCallbackImpl<PathnameExpansionCallback>
    {
        template <typename T, typename Functor>
        static void setCallback(T& interpreter, Functor function)
            { interpreter.lineParser_->PathnameExpansionCallback_ = function; }
    };
}}

#endif /* CALLBACKS_HPP_ */
<commit_msg>fix error in setCallback for PathnameExpansion callback<commit_after>/*
 * callbacks.hpp - Framework support of callback functions
 *
 *   Copyright 2010-2011 Jesús Torres <jmtorres@ull.es>
 *
 * 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 CALLBACKS_HPP_
#define CALLBACKS_HPP_

#include <string>
#include <vector>

#include <boost/function.hpp>
#include <boost/mpl/assert.hpp>
#include <boost/preprocessor/seq/for_each.hpp>
#include <boost/preprocessor/tuple/elem.hpp>
#include <boost/type_traits.hpp>

#include <cli/exceptions.hpp>

//
// Macro CLI_DECLARE_CALLBACKS & CLI_DECLARE_CALLBACKS_TPL
//
// Helps to add the support for callbacks to a class declaration.
//

#define CLI_DECLARE_CALLBACKS_FILLER_0(X, Y)    \
    ((X, Y)) CLI_DECLARE_CALLBACKS_FILLER_1
#define CLI_DECLARE_CALLBACKS_FILLER_1(X, Y)    \
    ((X, Y)) CLI_DECLARE_CALLBACKS_FILLER_0
#define CLI_DECLARE_CALLBACKS_FILLER_0_END
#define CLI_DECLARE_CALLBACKS_FILLER_1_END

#define CLI_DECLARE_CALLBACK_MEMBER(r, TYPE, DECLARATION_TUPLE)     \
    typedef cli::callback::                                         \
        BOOST_PP_TUPLE_ELEM(2, 0, DECLARATION_TUPLE)<TYPE>::Type    \
        BOOST_PP_TUPLE_ELEM(2, 0, DECLARATION_TUPLE);               \
    boost::function<BOOST_PP_TUPLE_ELEM(2, 0, DECLARATION_TUPLE)>   \
        BOOST_PP_TUPLE_ELEM(2, 1, DECLARATION_TUPLE);

#define CLI_DECLARE_CALLBACK_MEMBER_TPL(r, TYPE, DECLARATION_TUPLE) \
    typedef typename cli::callback::                                \
        BOOST_PP_TUPLE_ELEM(2, 0, DECLARATION_TUPLE)<TYPE>::Type    \
        BOOST_PP_TUPLE_ELEM(2, 0, DECLARATION_TUPLE);               \
    boost::function<BOOST_PP_TUPLE_ELEM(2, 0, DECLARATION_TUPLE)>   \
        BOOST_PP_TUPLE_ELEM(2, 1, DECLARATION_TUPLE);

#define CLI_DECLARE_CALLBACKS(TYPE, DECLARATIONS_SEQ)               \
    BOOST_PP_SEQ_FOR_EACH(                                          \
        CLI_DECLARE_CALLBACK_MEMBER,                                \
        TYPE,                                                       \
        BOOST_PP_CAT(                                               \
            CLI_DECLARE_CALLBACKS_FILLER_0 DECLARATIONS_SEQ, _END)) \
    template <template <typename> class Callback>                   \
    friend class cli::callback::SetCallbackImpl;

#define CLI_DECLARE_CALLBACKS_TPL(TYPE, DECLARATIONS_SEQ)           \
    BOOST_PP_SEQ_FOR_EACH(                                          \
        CLI_DECLARE_CALLBACK_MEMBER_TPL,                            \
        TYPE,                                                       \
        BOOST_PP_CAT(                                               \
            CLI_DECLARE_CALLBACKS_FILLER_0 DECLARATIONS_SEQ, _END)) \
    template <template <typename> class Callback>                   \
    friend class cli::callback::SetCallbackImpl;

//
// Macro CLI_CALLBACK_SIGNATURE_ASSERT & CLI_CALLBACK_SIGNATURE_ASSERT_TPL
//
// Tests if the function signature of FUNCTOR match the expected by CALLBACK.
//

#define CLI_CALLBACK_SIGNATURE_ASSERT(CALLBACK, FUNCTOR)                \
    BOOST_MPL_ASSERT((boost::is_convertible<FUNCTOR,                    \
        boost::function<CALLBACK<Type>::Type> >))

#define CLI_CALLBACK_SIGNATURE_ASSERT_TPL(CALLBACK, FUNCTOR)            \
    BOOST_MPL_ASSERT((boost::is_convertible<FUNCTOR,                    \
        boost::function<typename CALLBACK<Type>::Type> >))

namespace cli { namespace callback
{
    //
    // Base template for callback function setter implementation
    //

    template <template <typename> class Callback>
    struct SetCallbackImpl
    {
        template <typename T, typename Functor>
        static void setCallback(T& interpreter, Functor function)
        {
            throw cli::exception::UnknownCallbackException(
                Callback<T>::name());
        }
    };

    //
    // DoCommandCallback
    //

    template <typename T>
    struct DoCommandCallback
    {
        typedef bool (Type)(const std::string&,
            typename T::CommandArgumentsType const&);
        static const char* name() { return "DoCommandCallback"; }
    };

    template <>
    struct SetCallbackImpl<DoCommandCallback>
    {
        template <typename T, typename Functor>
        static void setCallback(T& interpreter, Functor function)
            { interpreter.defaultDoCommandCallback_ = function; }
        template <typename T, typename Functor>
        static void setCallback(T& interpreter, Functor function,
            const std::string& command)
            { interpreter.doCommandCallbacks_[command] = function; }
    };

    //
    // EmptyLineCallback
    //

    template <typename T>
    struct EmptyLineCallback
    {
        typedef bool (Type)();
        static const char* name() { return "EmptyLineCallback"; }
    };

    template <>
    struct SetCallbackImpl<EmptyLineCallback>
    {
        template <typename T, typename Functor>
        static void setCallback(T& interpreter, Functor function)
            { interpreter.emptyLineCallback_ = function; }
    };

    //
    // PreDoCommandCallback
    //

    template <typename T>
    struct PreDoCommandCallback
    {
        typedef void (Type)(std::string&);
        static const char* name() { return "PreDoCommandCallback"; }
    };

    template <>
    struct SetCallbackImpl<PreDoCommandCallback>
    {
        template <typename T, typename Functor>
        static void setCallback(T& interpreter, Functor function)
            { interpreter.preDoCommandCallback_ = function; }
    };

    //
    // PostDoCommandCallback
    //

    template <typename T>
    struct PostDoCommandCallback
    {
        typedef bool (Type)(bool, const std::string&);
        static const char* name() { return "PostDoCommandCallback"; }
    };

    template <>
    struct SetCallbackImpl<PostDoCommandCallback>
    {
        template <typename T, typename Functor>
        static void setCallback(T& interpreter, Functor function)
            { interpreter.postDoCommandCallback_ = function; }
    };

    //
    // ParserErrorCallback
    //

    template <typename T>
    struct ParserErrorCallback
    {
            typedef bool (Type)(typename T::ParserErrorType const&,
                const std::string&);
            static const char* name() { return "ParserErrorCallback"; }
    };

    template <>
    struct SetCallbackImpl<ParserErrorCallback>
    {
            template <typename T, typename Functor>
            static void setCallback(T& interpreter, Functor function)
            { interpreter.parserErrorCallback_ = function; }
    };

    //
    // PreLoopCallback
    //

    template <typename T>
    struct PreLoopCallback
    {
        typedef void (Type)();
        static const char* name() { return "PreLoopCallback"; }
    };

    template <>
    struct SetCallbackImpl<PreLoopCallback>
    {
        template <typename T, typename Functor>
        static void setCallback(T& interpreter, Functor function)
            { interpreter.preLoopCallback_ = function; }
    };

    //
    // PostLoopCallback
    //

    template <typename T>
    struct PostLoopCallback
    {
        typedef void (Type)();
        static const char* name() { return "PostLoopCallback"; }
    };

    template <>
    struct SetCallbackImpl<PostLoopCallback>
    {
        template <typename T, typename Functor>
        static void setCallback(T& interpreter, Functor function)
            { interpreter.postLoopCallback_ = function; }
    };

    //
    // VariableLookupCallback
    //

    template <typename T>
    struct VariableLookupCallback
    {
        typedef std::string (Type)(const std::string&);
        static const char* name() { return "VariableLookupCallback"; }
    };

    template <>
    struct SetCallbackImpl<VariableLookupCallback>
    {
        template <typename T, typename Functor>
        static void setCallback(T& interpreter, Functor function)
            { interpreter.lineParser_->variableLookupCallback_ = function; }
    };

    //
    // PathnameExpansionCallback
    //

    template <typename T>
    struct PathnameExpansionCallback
    {
        typedef std::vector<std::string> (Type)(const std::string&);
        static const char* name() { return "PathnameExpansionCallback"; }
    };

    template <>
    struct SetCallbackImpl<PathnameExpansionCallback>
    {
        template <typename T, typename Functor>
        static void setCallback(T& interpreter, Functor function)
            { interpreter.lineParser_->pathnameExpansionCallback_ = function; }
    };
}}

#endif /* CALLBACKS_HPP_ */
<|endoftext|>