// Copyright Maciej Sobczak 2008-2019.
// This file is part of YAMI4.
//
// YAMI4 is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// YAMI4 is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with YAMI4. If not, see .
#include "parameters.h"
#include "fatal_errors.h"
#include "parameter_entry.h"
#include "parameter_iterator.h"
#include "parameters-details.h"
#include
#include
using namespace yami;
using namespace yami::core;
parameters::parameters(void * working_area, std::size_t area_size)
: own_allocator_(), allocator_(own_allocator_),
uses_private_area_(area_size > 0),
data_(NULL), num_of_entries_(0)
{
own_allocator_.set_working_area(working_area, area_size);
}
parameters::parameters(details::allocator & alloc, bool private_area)
: own_allocator_(), allocator_(alloc),
uses_private_area_(private_area),
data_(NULL), num_of_entries_(0)
{
}
parameters::~parameters()
{
if (uses_private_area_ == false)
{
// this object uses global dynamic memory
clear();
}
}
void parameters::clear()
{
for (size_t i = 0; i != num_of_entries_; ++i)
{
details::entry & e = data_[i];
if (e.type != unused)
{
e.clear_name(allocator_);
// this is recursive for nested parameters:
e.clear_item(allocator_);
}
}
if (data_ != NULL)
{
allocator_.deallocate(data_);
data_ = NULL;
num_of_entries_ = 0;
}
}
result parameters::set_boolean(const char * name, std::size_t name_length,
bool value)
{
std::size_t index;
const result res = details::prepare_for_set(data_, num_of_entries_,
name, name_length, index, allocator_);
if (res == ok)
{
details::entry & e = data_[index];
e.type = boolean;
e.item.b = value;
}
return res;
}
result parameters::set_boolean(const char * name, bool value)
{
return set_boolean(name, std::strlen(name), value);
}
result parameters::get_boolean(const char * name, std::size_t name_length,
bool & value) const
{
result res;
const std::size_t index = details::find_entry(data_, num_of_entries_,
name, name_length);
if (index != num_of_entries_)
{
const details::entry & e = data_[index];
if (e.type == boolean)
{
value = e.item.b;
res = ok;
}
else
{
res = bad_type;
}
}
else
{
res = no_such_name;
}
return res;
}
result parameters::get_boolean(const char * name, bool & value) const
{
return get_boolean(name, std::strlen(name), value);
}
result parameters::set_integer(const char * name, std::size_t name_length,
int value)
{
std::size_t index;
const result res = details::prepare_for_set(data_, num_of_entries_,
name, name_length, index, allocator_);
if (res == ok)
{
details::entry & e = data_[index];
e.type = integer;
e.item.i = value;
}
return res;
}
result parameters::set_integer(const char * name, int value)
{
return set_integer(name, std::strlen(name), value);
}
result parameters::get_integer(const char * name, std::size_t name_length,
int & value) const
{
result res;
const std::size_t index = details::find_entry(data_, num_of_entries_,
name, name_length);
if (index != num_of_entries_)
{
const details::entry & e = data_[index];
if (e.type == integer)
{
value = e.item.i;
res = ok;
}
else
{
res = bad_type;
}
}
else
{
res = no_such_name;
}
return res;
}
result parameters::get_integer(const char * name, int & value) const
{
return get_integer(name, std::strlen(name), value);
}
result parameters::set_long_long(const char * name, std::size_t name_length,
long long value)
{
std::size_t index;
const result res = details::prepare_for_set(data_, num_of_entries_,
name, name_length, index, allocator_);
if (res == ok)
{
details::entry & e = data_[index];
e.type = long_long;
e.item.L = value;
}
return res;
}
result parameters::set_long_long(const char * name, long long value)
{
return set_long_long(name, std::strlen(name), value);
}
result parameters::get_long_long(const char * name, std::size_t name_length,
long long & value) const
{
result res;
const std::size_t index = details::find_entry(data_, num_of_entries_,
name, name_length);
if (index != num_of_entries_)
{
const details::entry & e = data_[index];
if (e.type == long_long)
{
value = e.item.L;
res = ok;
}
else
{
res = bad_type;
}
}
else
{
res = no_such_name;
}
return res;
}
result parameters::get_long_long(const char * name, long long & value) const
{
return get_long_long(name, std::strlen(name), value);
}
result parameters::set_double_float(
const char * name, std::size_t name_length, double value)
{
std::size_t index;
const result res = details::prepare_for_set(data_, num_of_entries_,
name, name_length, index, allocator_);
if (res == ok)
{
details::entry & e = data_[index];
e.type = double_float;
e.item.d = value;
}
return res;
}
result parameters::set_double_float(const char * name, double value)
{
return set_double_float(name, std::strlen(name), value);
}
result parameters::get_double_float(
const char * name, std::size_t name_length, double & value) const
{
result res;
const std::size_t index = details::find_entry(data_, num_of_entries_,
name, name_length);
if (index != num_of_entries_)
{
const details::entry & e = data_[index];
if (e.type == double_float)
{
value = e.item.d;
res = ok;
}
else
{
res = bad_type;
}
}
else
{
res = no_such_name;
}
return res;
}
result parameters::get_double_float(const char * name, double & value) const
{
return get_double_float(name, std::strlen(name), value);
}
result parameters::set_string(const char * name, std::size_t name_length,
const char * value, std::size_t value_length)
{
result res;
char * new_buffer =
static_cast(allocator_.allocate(value_length));
if (new_buffer != NULL)
{
std::memcpy(new_buffer, value, value_length);
res = details::do_set_string(name, name_length,
new_buffer, value_length,
data_, num_of_entries_, allocator_, true);
if (res != ok)
{
allocator_.deallocate(new_buffer);
}
}
else
{
res = no_memory;
}
return res;
}
result parameters::set_string(const char * name, const char * value)
{
return set_string(name, std::strlen(name), value, std::strlen(value));
}
result parameters::set_string_shallow(
const char * name, std::size_t name_length,
const char * value, std::size_t value_length)
{
const result res = details::do_set_string(name, name_length,
value, value_length,
data_, num_of_entries_, allocator_, false);
return res;
}
result parameters::set_string_shallow(const char * name, const char * value)
{
return set_string_shallow(name, std::strlen(name),
value, std::strlen(value));
}
result parameters::get_string(const char * name, std::size_t name_length,
const char * & value, std::size_t & value_length) const
{
result res;
const std::size_t index = details::find_entry(data_, num_of_entries_,
name, name_length);
if (index != num_of_entries_)
{
const details::entry & e = data_[index];
if (e.type == string)
{
value = e.item.str.value;
value_length = e.item.str.length;
res = ok;
}
else
{
res = bad_type;
}
}
else
{
res = no_such_name;
}
return res;
}
result parameters::get_string(const char * name,
const char * & value, std::size_t & value_length) const
{
return get_string(name, std::strlen(name), value, value_length);
}
result parameters::set_binary(const char * name, std::size_t name_length,
const void * value, std::size_t value_length)
{
result res;
void * new_buffer = allocator_.allocate(value_length);
if (new_buffer != NULL)
{
std::memcpy(new_buffer, value, value_length);
res = details::do_set_binary(name, name_length,
new_buffer, value_length,
data_, num_of_entries_, allocator_, true);
if (res != ok)
{
allocator_.deallocate(new_buffer);
}
}
else
{
res = no_memory;
}
return res;
}
result parameters::set_binary(const char * name,
const void * value, std::size_t value_length)
{
return set_binary(name, std::strlen(name), value, value_length);
}
result parameters::set_binary_shallow(
const char * name, std::size_t name_length,
const void * value, std::size_t value_length)
{
const result res = details::do_set_binary(name, name_length,
value, value_length,
data_, num_of_entries_, allocator_, false);
return res;
}
result parameters::set_binary_shallow(const char * name,
const void * value, std::size_t value_length)
{
return set_binary_shallow(name, std::strlen(name),
value, value_length);
}
result parameters::get_binary(const char * name, std::size_t name_length,
const void * & value, std::size_t & value_length) const
{
result res;
const std::size_t index = details::find_entry(data_, num_of_entries_,
name, name_length);
if (index != num_of_entries_)
{
const details::entry & e = data_[index];
if (e.type == binary)
{
value = e.item.bin.value;
value_length = e.item.bin.length;
res = ok;
}
else
{
res = bad_type;
}
}
else
{
res = no_such_name;
}
return res;
}
result parameters::get_binary(const char * name,
const void * & value, std::size_t & value_length) const
{
return get_binary(name, std::strlen(name), value, value_length);
}
result parameters::set_boolean_array(
const char * name, std::size_t name_length,
const bool * values, std::size_t array_length)
{
result res;
const std::size_t raw_length = array_length * sizeof(bool);
bool * new_array =
static_cast(allocator_.allocate(raw_length));
if (new_array != NULL)
{
std::memcpy(new_array, values, raw_length);
res = details::do_set_boolean_array(name, name_length,
new_array, array_length,
data_, num_of_entries_, allocator_, true);
if (res != ok)
{
allocator_.deallocate(new_array);
}
}
else
{
res = no_memory;
}
return res;
}
result parameters::set_boolean_array(const char * name,
const bool * values, std::size_t array_length)
{
return set_boolean_array(name, std::strlen(name), values, array_length);
}
result parameters::set_boolean_array_shallow(
const char * name, std::size_t name_length,
const bool * values, std::size_t array_length)
{
const result res = details::do_set_boolean_array(name, name_length,
values, array_length,
data_, num_of_entries_, allocator_, false);
return res;
}
result parameters::set_boolean_array_shallow(const char * name,
const bool * values, std::size_t array_length)
{
return set_boolean_array_shallow(name, std::strlen(name),
values, array_length);
}
result parameters::create_boolean_array(
const char * name, std::size_t name_length,
std::size_t array_length, bool * & array)
{
result res;
const std::size_t raw_length = array_length * sizeof(bool);
bool * new_array =
static_cast(allocator_.allocate(raw_length));
if (new_array != NULL)
{
res = details::do_set_boolean_array(name, name_length,
new_array, array_length,
data_, num_of_entries_, allocator_, true);
if (res == ok)
{
array = new_array;
}
else
{
allocator_.deallocate(new_array);
}
}
else
{
res = no_memory;
}
return res;
}
result parameters::create_boolean_array(const char * name,
std::size_t array_length, bool * & array)
{
return create_boolean_array(name, std::strlen(name), array_length, array);
}
result parameters::get_boolean_array(
const char * name, std::size_t name_length,
bool * & values, std::size_t & array_length) const
{
result res;
const std::size_t index = details::find_entry(data_, num_of_entries_,
name, name_length);
if (index != num_of_entries_)
{
const details::entry & e = data_[index];
if (e.type == boolean_array)
{
values = e.item.ba.values;
array_length = e.item.ba.length;
res = ok;
}
else
{
res = bad_type;
}
}
else
{
res = no_such_name;
}
return res;
}
result parameters::get_boolean_array(const char * name,
bool * & values, std::size_t & array_length) const
{
return get_boolean_array(name, std::strlen(name), values, array_length);
}
result parameters::set_integer_array(
const char * name, std::size_t name_length,
const int * values, std::size_t array_length)
{
result res;
const std::size_t raw_length = array_length * sizeof(int);
int * new_array =
static_cast(allocator_.allocate(raw_length));
if (new_array != NULL)
{
std::memcpy(new_array, values, raw_length);
res = details::do_set_integer_array(name, name_length,
new_array, array_length,
data_, num_of_entries_, allocator_, true);
if (res != ok)
{
allocator_.deallocate(new_array);
}
}
else
{
res = no_memory;
}
return res;
}
result parameters::set_integer_array(const char * name,
const int * values, std::size_t array_length)
{
return set_integer_array(name, std::strlen(name), values, array_length);
}
result parameters::set_integer_array_shallow(
const char * name, std::size_t name_length,
const int * values, std::size_t array_length)
{
const result res = details::do_set_integer_array(name, name_length,
values, array_length,
data_, num_of_entries_, allocator_, false);
return res;
}
result parameters::set_integer_array_shallow(const char * name,
const int * values, std::size_t array_length)
{
return set_integer_array_shallow(name, std::strlen(name),
values, array_length);
}
result parameters::create_integer_array(
const char * name, std::size_t name_length,
std::size_t array_length, int * & array)
{
result res;
const std::size_t raw_length = array_length * sizeof(int);
int * new_array =
static_cast(allocator_.allocate(raw_length));
if (new_array != NULL)
{
res = details::do_set_integer_array(name, name_length,
new_array, array_length,
data_, num_of_entries_, allocator_, true);
if (res == ok)
{
array = new_array;
}
else
{
allocator_.deallocate(new_array);
}
}
else
{
res = no_memory;
}
return res;
}
result parameters::create_integer_array(const char * name,
std::size_t array_length, int * & array)
{
return create_integer_array(name, std::strlen(name), array_length, array);
}
result parameters::get_integer_array(
const char * name, std::size_t name_length,
int * & values, std::size_t & array_length) const
{
result res;
const std::size_t index = details::find_entry(data_, num_of_entries_,
name, name_length);
if (index != num_of_entries_)
{
const details::entry & e = data_[index];
if (e.type == integer_array)
{
values = e.item.ia.values;
array_length = e.item.ia.length;
res = ok;
}
else
{
res = bad_type;
}
}
else
{
res = no_such_name;
}
return res;
}
result parameters::get_integer_array(const char * name,
int * & values, std::size_t & array_length) const
{
return get_integer_array(name, std::strlen(name), values, array_length);
}
result parameters::set_long_long_array(
const char * name, std::size_t name_length,
const long long * values, std::size_t array_length)
{
result res;
const std::size_t raw_length = array_length * sizeof(long long);
long long * new_array =
static_cast(allocator_.allocate(raw_length));
if (new_array != NULL)
{
std::memcpy(new_array, values, raw_length);
res = details::do_set_long_long_array(name, name_length,
new_array, array_length,
data_, num_of_entries_, allocator_, true);
if (res != ok)
{
allocator_.deallocate(new_array);
}
}
else
{
res = no_memory;
}
return res;
}
result parameters::set_long_long_array(const char * name,
const long long * values, std::size_t array_length)
{
return set_long_long_array(name, std::strlen(name), values, array_length);
}
result parameters::set_long_long_array_shallow(
const char * name, std::size_t name_length,
const long long * values, std::size_t array_length)
{
const result res = details::do_set_long_long_array(name, name_length,
values, array_length,
data_, num_of_entries_, allocator_, false);
return res;
}
result parameters::set_long_long_array_shallow(const char * name,
const long long * values, std::size_t array_length)
{
return set_long_long_array_shallow(name, std::strlen(name),
values, array_length);
}
result parameters::create_long_long_array(
const char * name, std::size_t name_length,
std::size_t array_length, long long * & array)
{
result res;
const std::size_t raw_length = array_length * sizeof(long long);
long long * new_array =
static_cast(allocator_.allocate(raw_length));
if (new_array != NULL)
{
res = details::do_set_long_long_array(name, name_length,
new_array, array_length,
data_, num_of_entries_, allocator_, true);
if (res == ok)
{
array = new_array;
}
else
{
allocator_.deallocate(new_array);
}
}
else
{
res = no_memory;
}
return res;
}
result parameters::create_long_long_array(const char * name,
std::size_t array_length, long long * & array)
{
return create_long_long_array(name, std::strlen(name),
array_length, array);
}
result parameters::get_long_long_array(
const char * name, std::size_t name_length,
long long * & values, std::size_t & array_length) const
{
result res;
const std::size_t index = details::find_entry(data_, num_of_entries_,
name, name_length);
if (index != num_of_entries_)
{
const details::entry & e = data_[index];
if (e.type == long_long_array)
{
values = e.item.La.values;
array_length = e.item.La.length;
res = ok;
}
else
{
res = bad_type;
}
}
else
{
res = no_such_name;
}
return res;
}
result parameters::get_long_long_array(const char * name,
long long * & values, std::size_t & array_length) const
{
return get_long_long_array(name, std::strlen(name), values, array_length);
}
result parameters::set_double_float_array(
const char * name, std::size_t name_length,
const double * values, std::size_t array_length)
{
result res;
const std::size_t raw_length = array_length * sizeof(double);
double * new_array =
static_cast(allocator_.allocate(raw_length));
if (new_array != NULL)
{
std::memcpy(new_array, values, raw_length);
res = details::do_set_double_float_array(name, name_length,
new_array, array_length,
data_, num_of_entries_, allocator_, true);
if (res != ok)
{
allocator_.deallocate(new_array);
}
}
else
{
res = no_memory;
}
return res;
}
result parameters::set_double_float_array(const char * name,
const double * values, std::size_t array_length)
{
return set_double_float_array(
name, std::strlen(name), values, array_length);
}
result parameters::set_double_float_array_shallow(
const char * name, std::size_t name_length,
const double * values, std::size_t array_length)
{
const result res = details::do_set_double_float_array(name, name_length,
values, array_length,
data_, num_of_entries_, allocator_, false);
return res;
}
result parameters::set_double_float_array_shallow(const char * name,
const double * values, std::size_t array_length)
{
return set_double_float_array_shallow(name, std::strlen(name),
values, array_length);
}
result parameters::create_double_float_array(
const char * name, std::size_t name_length,
std::size_t array_length, double * & array)
{
result res;
const std::size_t raw_length = array_length * sizeof(double);
double * new_array =
static_cast(allocator_.allocate(raw_length));
if (new_array != NULL)
{
res = details::do_set_double_float_array(name, name_length,
new_array, array_length,
data_, num_of_entries_, allocator_, true);
if (res == ok)
{
array = new_array;
}
else
{
allocator_.deallocate(new_array);
}
}
else
{
res = no_memory;
}
return res;
}
result parameters::create_double_float_array(const char * name,
std::size_t array_length, double * & array)
{
return create_double_float_array(name, std::strlen(name),
array_length, array);
}
result parameters::get_double_float_array(
const char * name, std::size_t name_length,
double * & values, std::size_t & array_length) const
{
result res;
const std::size_t index = details::find_entry(data_, num_of_entries_,
name, name_length);
if (index != num_of_entries_)
{
const details::entry & e = data_[index];
if (e.type == double_float_array)
{
values = e.item.da.values;
array_length = e.item.da.length;
res = ok;
}
else
{
res = bad_type;
}
}
else
{
res = no_such_name;
}
return res;
}
result parameters::get_double_float_array(const char * name,
double * & values, std::size_t & array_length) const
{
return get_double_float_array(
name, std::strlen(name), values, array_length);
}
result parameters::create_string_array(
const char * name, std::size_t name_length,
std::size_t array_length)
{
std::size_t dummy_index;
const result res = details::do_create_string_array(
name, name_length, array_length, dummy_index,
data_, num_of_entries_, allocator_);
return res;
}
result parameters::create_string_array(
const char * name, std::size_t array_length)
{
return create_string_array(name, std::strlen(name), array_length);
}
result parameters::set_string_in_array(
const char * name, std::size_t name_length,
std::size_t index, const char * value, std::size_t value_length)
{
result res;
const std::size_t item_index = details::find_entry(
data_, num_of_entries_, name, name_length);
if (item_index != num_of_entries_)
{
res = details::do_set_string_in_array(item_index, index,
value, value_length, data_, allocator_);
}
else
{
res = no_such_name;
}
return res;
}
result parameters::set_string_in_array(const char * name,
std::size_t index, const char * value)
{
return set_string_in_array(name, std::strlen(name),
index, value, std::strlen(value));
}
result parameters::get_string_array_length(
const char * name, std::size_t name_length,
std::size_t & array_length) const
{
result res;
const std::size_t index = details::find_entry(data_, num_of_entries_,
name, name_length);
if (index != num_of_entries_)
{
const details::entry & e = data_[index];
if (e.type == string_array)
{
array_length = e.item.sa.length;
res = ok;
}
else
{
res = bad_type;
}
}
else
{
res = no_such_name;
}
return res;
}
result parameters::get_string_array_length(const char * name,
std::size_t & array_length) const
{
return get_string_array_length(name, std::strlen(name), array_length);
}
result parameters::get_string_in_array(
const char * name, std::size_t name_length,
std::size_t index,
const char * & value, std::size_t & value_length) const
{
result res;
const std::size_t item_index = details::find_entry(
data_, num_of_entries_, name, name_length);
if (item_index != num_of_entries_)
{
const details::entry & e = data_[item_index];
if (e.type == string_array)
{
if (index < e.item.sa.length)
{
value = e.item.sa.values[index].value;
value_length = e.item.sa.values[index].length;
res = ok;
}
else
{
res = no_such_index;
}
}
else
{
res = bad_type;
}
}
else
{
res = no_such_name;
}
return res;
}
result parameters::get_string_in_array(const char * name, std::size_t index,
const char * & value, std::size_t & value_length) const
{
return get_string_in_array(name, std::strlen(name),
index, value, value_length);
}
result parameters::create_binary_array(
const char * name, std::size_t name_length,
std::size_t array_length)
{
std::size_t dummy_index;
const result res = details::do_create_binary_array(
name, name_length, array_length, dummy_index,
data_, num_of_entries_, allocator_);
return res;
}
result parameters::create_binary_array(
const char * name, std::size_t array_length)
{
return create_binary_array(name, std::strlen(name), array_length);
}
result parameters::set_binary_in_array(
const char * name, std::size_t name_length,
std::size_t index, const void * value, std::size_t value_length)
{
result res;
const std::size_t item_index = details::find_entry(
data_, num_of_entries_, name, name_length);
if (item_index != num_of_entries_)
{
res = details::do_set_binary_in_array(item_index, index,
value, value_length, data_, allocator_);
}
else
{
res = no_such_name;
}
return res;
}
result parameters::set_binary_in_array(const char * name,
std::size_t index, const void * value, std::size_t value_length)
{
return set_binary_in_array(name, std::strlen(name),
index, value, value_length);
}
result parameters::get_binary_array_length(
const char * name, std::size_t name_length,
std::size_t & array_length) const
{
result res;
const std::size_t index = details::find_entry(data_, num_of_entries_,
name, name_length);
if (index != num_of_entries_)
{
const details::entry & e = data_[index];
if (e.type == binary_array)
{
array_length = e.item.bina.length;
res = ok;
}
else
{
res = bad_type;
}
}
else
{
res = no_such_name;
}
return res;
}
result parameters::get_binary_array_length(const char * name,
std::size_t & array_length) const
{
return get_binary_array_length(name, std::strlen(name), array_length);
}
result parameters::get_binary_in_array(
const char * name, std::size_t name_length,
std::size_t index,
const void * & value, std::size_t & value_length) const
{
result res;
const std::size_t item_index = details::find_entry(
data_, num_of_entries_, name, name_length);
if (item_index != num_of_entries_)
{
const details::entry & e = data_[item_index];
if (e.type == binary_array)
{
if (index < e.item.bina.length)
{
value = e.item.bina.values[index].value;
value_length = e.item.bina.values[index].length;
res = ok;
}
else
{
res = no_such_index;
}
}
else
{
res = bad_type;
}
}
else
{
res = no_such_name;
}
return res;
}
result parameters::get_binary_in_array(const char * name, std::size_t index,
const void * & value, std::size_t & value_length) const
{
return get_binary_in_array(name, std::strlen(name),
index, value, value_length);
}
result parameters::create_nested_parameters(
const char * name, std::size_t name_length, parameters * & params)
{
result res;
void * new_buffer = allocator_.allocate(sizeof(parameters));
if (new_buffer != NULL)
{
std::size_t index;
res = details::prepare_for_set(data_, num_of_entries_,
name, name_length, index, allocator_);
if (res == ok)
{
parameters * nested =
new (new_buffer) parameters(allocator_, uses_private_area_);
details::entry & e = data_[index];
e.type = nested_parameters;
e.item.nested = nested;
params = nested;
}
else
{
allocator_.deallocate(new_buffer);
}
}
else
{
res = no_memory;
}
return res;
}
result parameters::create_nested_parameters(
const char * name, parameters * & params)
{
return create_nested_parameters(name, std::strlen(name), params);
}
result parameters::get_nested_parameters(
const char * name, std::size_t name_length, parameters * & params) const
{
result res;
const std::size_t index = details::find_entry(
data_, num_of_entries_, name, name_length);
if (index != num_of_entries_)
{
const details::entry & e = data_[index];
if (e.type == nested_parameters)
{
params = e.item.nested;
res = ok;
}
else
{
res = bad_type;
}
}
else
{
res = no_such_name;
}
return res;
}
result parameters::get_nested_parameters(
const char * name, parameters * & params) const
{
return get_nested_parameters(name, std::strlen(name), params);
}
result parameters::create_nested_array(
const char * name, std::size_t name_length,
std::size_t array_length)
{
std::size_t dummy_index;
const result res = details::do_create_nested_array(
name, name_length, array_length, dummy_index,
data_, num_of_entries_, allocator_);
return res;
}
result parameters::create_nested_array(
const char * name, std::size_t array_length)
{
return create_nested_array(name, std::strlen(name), array_length);
}
result parameters::get_nested_array_length(
const char * name, std::size_t name_length,
std::size_t & array_length) const
{
result res;
const std::size_t index = details::find_entry(data_, num_of_entries_,
name, name_length);
if (index != num_of_entries_)
{
const details::entry & e = data_[index];
if (e.type == nested_parameters_array)
{
array_length = e.item.nesteda.length;
res = ok;
}
else
{
res = bad_type;
}
}
else
{
res = no_such_name;
}
return res;
}
result parameters::get_nested_array_length(const char * name,
std::size_t & array_length) const
{
return get_nested_array_length(name, std::strlen(name), array_length);
}
result parameters::get_nested_in_array(
const char * name, std::size_t name_length,
std::size_t index,
parameters * & nested) const
{
result res;
const std::size_t item_index = details::find_entry(
data_, num_of_entries_, name, name_length);
if (item_index != num_of_entries_)
{
const details::entry & e = data_[item_index];
if (e.type == nested_parameters_array)
{
if (index < e.item.nesteda.length)
{
nested = &e.item.nesteda.values[index];
res = ok;
}
else
{
res = no_such_index;
}
}
else
{
res = bad_type;
}
}
else
{
res = no_such_name;
}
return res;
}
result parameters::get_nested_in_array(
const char * name, std::size_t index,
parameters * & nested) const
{
return get_nested_in_array(name, std::strlen(name), index, nested);
}
result parameters::remove(const char * name, std::size_t name_length)
{
result res;
const std::size_t index = details::find_entry(
data_, num_of_entries_, name, name_length);
if (index != num_of_entries_)
{
details::entry & e = data_[index];
e.clear_name(allocator_);
e.clear_item(allocator_);
e.type = unused;
res = ok;
}
else
{
res = no_such_name;
}
return res;
}
result parameters::remove(const char * name)
{
return remove(name, std::strlen(name));
}
std::size_t parameters::size() const
{
std::size_t count = 0;
for (std::size_t i = 0; i != num_of_entries_; ++i)
{
if (data_[i].type != unused)
{
++count;
}
}
return count;
}
result parameters::get_type(const char * name, std::size_t name_length,
parameter_type & t) const
{
result res;
const std::size_t index = details::find_entry(
data_, num_of_entries_, name, name_length);
if (index != num_of_entries_)
{
t = data_[index].type;
res = ok;
}
else
{
res = no_such_name;
}
return res;
}
result parameters::get_type(const char * name, parameter_type & t) const
{
return get_type(name, std::strlen(name), t);
}
result parameters::get_iterator(parameter_iterator & it) const
{
result res;
std::size_t first_used_index = num_of_entries_;
for (std::size_t i = 0; i != num_of_entries_; ++i)
{
if (data_[i].type != unused)
{
first_used_index = i;
break;
}
}
if (first_used_index != num_of_entries_)
{
it.data_ = data_;
it.current_index_ = first_used_index;
it.num_of_entries_ = num_of_entries_;
it.allocator_ = &allocator_;
res = ok;
}
else
{
res = no_entries;
}
return res;
}
result parameters::find(const char * name, std::size_t name_length,
parameter_entry & entry) const
{
result res;
const std::size_t index = details::find_entry(
data_, num_of_entries_, name, name_length);
if (index != num_of_entries_)
{
entry.e_ = data_ + index;
res = ok;
}
else
{
res = no_such_name;
}
return res;
}
result parameters::find(const char * name, parameter_entry & entry) const
{
return find(name, std::strlen(name), entry);
}
result parameters::merge_from(const parameters & other)
{
// merge is performed as serialize of other
// followed by deserialize into this
result res = ok;
if (other.size() != 0)
{
std::size_t buffer_size;
res = other.get_serialize_buffer_size(buffer_size);
if (res == ok)
{
char * buffer = static_cast(
allocator_.allocate(buffer_size));
if (buffer != NULL)
{
res = other.serialize(&buffer, &buffer_size, 1);
if (res == ok)
{
const char * buffers[1];
buffers[0] = buffer;
std::size_t buffer_sizes[1];
buffer_sizes[0] = buffer_size;
res = deserialize(buffers, buffer_sizes, 1);
}
allocator_.deallocate(buffer);
}
else
{
res = no_memory;
}
}
}
return res;
}
result parameters::get_serialize_buffer_size(std::size_t & buffer_size) const
{
// the serialized format is:
// 1. number of entries
// 2. for each entry:
// 1. name length
// 2. name
// 3. type
// 4. value
// depending on type, value is:
// - boolean: 0 or 1 in 4 bytes
// - integer: as is 4 bytets
// - long_long: as is 8 bytes
// - double_float: as is 8 bytes
// - string: length followed by value
// - boolean_array: length followed by packed (per bit) values
// - integer_array: length followed by values
// - long_long_array: length followed by values
// - double_float_array: length followed by values
// - string_array: length followed by values as for string
// - nested: as the whole
// recurively for nested parameters:
buffer_size = 0;
details::get_serialize_buffer_size(*this, buffer_size);
return ok;
}
result parameters::serialize(char * * buffers,
const std::size_t * buffer_sizes,
std::size_t num_of_buffers) const
{
std::size_t current_buffer = 0;
char * buffer_position = &buffers[0][0];
return details::serialize(*this,
buffers, buffer_sizes, num_of_buffers,
current_buffer, buffer_position);
}
result parameters::deserialize(
const char * * buffers, const std::size_t * buffer_sizes,
std::size_t num_of_buffers)
{
std::size_t current_buffer = 0;
const char * buffer_position = &buffers[0][0];
return details::deserialize(*this,
buffers, buffer_sizes, num_of_buffers,
current_buffer, buffer_position);
}
void parameters::dump(
details::dump_sink & sink, std::size_t indent_length) const
{
for (std::size_t i = 0; i != num_of_entries_; ++i)
{
bool add_newline = true;
sink.indent(indent_length);
sink.dump("entry ");
sink.dump(i);
sink.dump(":\n");
switch (data_[i].type)
{
case unused:
sink.indent(indent_length);
sink.dump("unused");
break;
case boolean:
sink.indent(indent_length);
sink.dump("name: ");
data_[i].name.dump(sink);
sink.dump("\n");
sink.indent(indent_length);
sink.dump("boolean: ");
sink.dump(data_[i].item.b);
break;
case integer:
sink.indent(indent_length);
sink.dump("name: ");
data_[i].name.dump(sink);
sink.dump("\n");
sink.indent(indent_length);
sink.dump("integer: ");
sink.dump(data_[i].item.i);
break;
case long_long:
sink.indent(indent_length);
sink.dump("name: ");
data_[i].name.dump(sink);
sink.dump("\n");
sink.indent(indent_length);
sink.dump("long_long: ");
sink.dump(data_[i].item.L);
break;
case double_float:
sink.indent(indent_length);
sink.dump("name: ");
data_[i].name.dump(sink);
sink.dump("\n");
sink.indent(indent_length);
sink.dump("double: ");
sink.dump(data_[i].item.d);
break;
case string:
sink.indent(indent_length);
sink.dump("name: ");
data_[i].name.dump(sink);
sink.dump("\n");
sink.indent(indent_length);
sink.dump("string: ");
sink.dump(data_[i].item.str.value,
data_[i].item.str.length);
break;
case binary:
sink.indent(indent_length);
sink.dump("name: ");
data_[i].name.dump(sink);
sink.dump("\n");
sink.indent(indent_length);
sink.dump("binary of length ");
sink.dump(data_[i].item.bin.length);
break;
case boolean_array:
sink.indent(indent_length);
sink.dump("name: ");
data_[i].name.dump(sink);
sink.dump("\n");
sink.indent(indent_length);
sink.dump("boolean array:");
for (std::size_t j = 0; j != data_[i].item.ba.length; ++j)
{
sink.dump(" ");
sink.dump(data_[i].item.ba.values[j]);
}
break;
case integer_array:
sink.indent(indent_length);
sink.dump("name: ");
data_[i].name.dump(sink);
sink.dump("\n");
sink.indent(indent_length);
sink.dump("integer array:");
for (std::size_t j = 0; j != data_[i].item.ia.length; ++j)
{
sink.dump(" ");
sink.dump(data_[i].item.ia.values[j]);
}
break;
case long_long_array:
sink.indent(indent_length);
sink.dump("name: ");
data_[i].name.dump(sink);
sink.dump("\n");
sink.indent(indent_length);
sink.dump("long_long array:");
for (std::size_t j = 0; j != data_[i].item.La.length; ++j)
{
sink.dump(" ");
sink.dump(data_[i].item.La.values[j]);
}
break;
case double_float_array:
sink.indent(indent_length);
sink.dump("name: ");
data_[i].name.dump(sink);
sink.dump("\n");
sink.indent(indent_length);
sink.dump("double array:");
for (std::size_t j = 0; j != data_[i].item.da.length; ++j)
{
sink.dump(" ");
sink.dump(data_[i].item.da.values[j]);
}
break;
case string_array:
sink.indent(indent_length);
sink.dump("name: ");
data_[i].name.dump(sink);
sink.dump("\n");
sink.indent(indent_length);
sink.dump("string array:");
for (std::size_t j = 0; j != data_[i].item.sa.length; ++j)
{
sink.dump(" ");
sink.dump(data_[i].item.sa.values[j].value,
data_[i].item.sa.values[j].length);
}
break;
case binary_array:
sink.indent(indent_length);
sink.dump("name: ");
data_[i].name.dump(sink);
sink.dump("\n");
sink.indent(indent_length);
sink.dump("binary array of length ");
sink.dump(data_[i].item.bina.length);
break;
case nested_parameters:
sink.indent(indent_length);
sink.dump("name: ");
data_[i].name.dump(sink);
sink.dump("\n");
sink.indent(indent_length);
sink.dump("nested parameters:\n");
data_[i].item.nested->dump(sink, indent_length + 2);
add_newline = false;
break;
case nested_parameters_array:
sink.indent(indent_length);
sink.dump("name: ");
data_[i].name.dump(sink);
sink.dump("\n");
sink.indent(indent_length);
sink.dump("nested parameters array of length ");
sink.dump(data_[i].item.nesteda.length);
sink.dump(":\n");
for (std::size_t j = 0; j != data_[i].item.nesteda.length; ++j)
{
sink.indent(indent_length);
sink.dump(" nested at index ");
sink.dump(j);
sink.dump(":\n");
data_[i].item.nesteda.values[j].dump(sink, indent_length + 4);
}
add_newline = false;
break;
default:
details::fatal_failure(__FILE__, __LINE__);
}
if (add_newline)
{
sink.dump("\n");
}
}
}