mirror of
https://github.com/signalwire/freeswitch.git
synced 2026-10-29 22:54:18 +00:00
Added mod_khomp Endpoint.
This module has been developed to make a nice, affordable brazilian board called Khomp (http://www.khomp.com.br) compatible with FreeSWITCH. Supported boards: - FXS - FXO - E1 - GSM (boards and usb devices) - Passive record - kommuter
This commit is contained in:
1 parent
f8d8a395cc
commit
5fea197b78
96 files changed
+42128
No files matched your search
@@ -0,0 +1,189 @@
|
||||
/*
|
||||
KHOMP generic endpoint/channel library.
|
||||
|
||||
This code was based on FreeBSD 7.X SVN (sys/i386/include/atomic.h),
|
||||
with changes regarding optimizations and generalizations, and a
|
||||
remake of the interface to fit use C++ features.
|
||||
|
||||
Code is distributed under original license.
|
||||
Original copyright follows:
|
||||
|
||||
* Copyright (c) 1998 Doug Rabson
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef _ATOMIC_HPP_
|
||||
#define _ATOMIC_HPP_
|
||||
|
||||
namespace Atomic
|
||||
{
|
||||
// Macros used to insert compare and exchange instructions easily into functions.
|
||||
|
||||
#define MAKE_CMPXCHG_FUNCTION(INS, PTR, EXP, VAL, TYPE) \
|
||||
PunnedType pexp; pexp.valtype = EXP; \
|
||||
PunnedType pval; pval.valtype = VAL; \
|
||||
TYPE vexp = *(pexp.podtype); \
|
||||
TYPE vval = *(pval.podtype); \
|
||||
TYPE res; \
|
||||
unsigned char chg = 0; \
|
||||
asm volatile("lock;" INS "sete %1;" \
|
||||
: "=a" (res), /* 0 */ \
|
||||
"=q" (chg), /* 1 */ \
|
||||
"=m" (*(unsigned char **)(PTR)) /* 2 */ \
|
||||
: "r" (vval), /* 3 */ \
|
||||
"a" (vexp), /* 4 */ \
|
||||
"m" (*(unsigned char **)(PTR)) /* 5 */ \
|
||||
: "memory"); \
|
||||
*(pexp.podtype) = res; \
|
||||
return (chg != 0 ? true : false);
|
||||
|
||||
#define MAKE_CMPXCHG8B_FUNCTION(PTR,EXP,VAL) \
|
||||
PunnedType pexp; pexp.valtype = EXP; \
|
||||
PunnedType pval; pval.valtype = VAL; \
|
||||
unsigned long long vexp = *(pexp.podtype); \
|
||||
unsigned long long vval = *(pval.podtype); \
|
||||
unsigned long long res = (unsigned long long)exp; \
|
||||
unsigned char chg = 0; \
|
||||
asm volatile("lock; cmpxchg8b %2; sete %1;" \
|
||||
: "+A" (vexp), /* 0 (result) */ \
|
||||
"=q" (chg) /* 1 */ \
|
||||
: "m" (*(unsigned char**)(PTR)), /* 2 */ \
|
||||
"b" ((unsigned long)(vval)), \
|
||||
"c" ((unsigned long)(vval >> 32))); \
|
||||
*(pexp.podtype) = vexp; \
|
||||
return (chg != 0 ? true : false);
|
||||
|
||||
// Types used for making CMPXCHG instructions independent from base type.
|
||||
|
||||
template < typename ValType, typename PodType >
|
||||
union PunnedTypeTemplate
|
||||
{
|
||||
ValType * valtype;
|
||||
PodType * podtype;
|
||||
};
|
||||
|
||||
template < int SizeOfType, typename ReturnType >
|
||||
struct HelperCreateCAS;
|
||||
|
||||
template < typename ValType >
|
||||
struct HelperCreateCAS<4, ValType>
|
||||
{
|
||||
#if !defined(__LP64__) && !defined(__LP64)
|
||||
typedef unsigned long BaseType;
|
||||
#else
|
||||
typedef unsigned int BaseType;
|
||||
#endif
|
||||
|
||||
typedef PunnedTypeTemplate< ValType, BaseType > PunnedType;
|
||||
|
||||
inline static bool apply(volatile void *p, ValType * exp, ValType now)
|
||||
{
|
||||
#if !defined(__LP64__) && !defined(__LP64)
|
||||
MAKE_CMPXCHG_FUNCTION("cmpxchgl %3,%5;", p, exp, &now, BaseType);
|
||||
#else
|
||||
MAKE_CMPXCHG_FUNCTION("cmpxchgl %k3,%5;", p, exp, &now, BaseType);
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
template < typename ValType >
|
||||
struct HelperCreateCAS<8, ValType>
|
||||
{
|
||||
#if !defined(__LP64__) && !defined(__LP64)
|
||||
typedef unsigned long long BaseType;
|
||||
#else
|
||||
typedef unsigned long BaseType;
|
||||
#endif
|
||||
|
||||
typedef PunnedTypeTemplate< ValType, BaseType > PunnedType;
|
||||
|
||||
inline static volatile ValType apply(volatile void *p, ValType * exp, ValType now)
|
||||
{
|
||||
#if !defined(__LP64__) && !defined(__LP64)
|
||||
MAKE_CMPXCHG8B_FUNCTION(p, exp, &now);
|
||||
#else
|
||||
MAKE_CMPXCHG_FUNCTION("cmpxchgq %3,%5;", p, exp, &now, BaseType);
|
||||
#endif
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
// The CAS function itself.
|
||||
|
||||
template < typename ValType >
|
||||
inline bool doCAS(volatile ValType * p, ValType * o, ValType n)
|
||||
{
|
||||
return HelperCreateCAS<sizeof(ValType), ValType>::apply(static_cast<volatile void *>(p), o, n);
|
||||
};
|
||||
|
||||
template < typename ValType >
|
||||
inline bool doCAS(volatile ValType * p, ValType o, ValType n)
|
||||
{
|
||||
return HelperCreateCAS<sizeof(ValType), ValType>::apply(static_cast<volatile void *>(p), &o, n);
|
||||
};
|
||||
|
||||
#undef MAKE_CMPXCHG_32_FUNCTION
|
||||
#undef MAKE_CMPXCHG_64_FUNCTION
|
||||
|
||||
#define MAKE_LOCKED_TEMPLATE(NAME) \
|
||||
template < typename ValType > inline void do##NAME(volatile ValType * p, ValType v); \
|
||||
template < typename ValType > inline void do##NAME(volatile ValType * p);
|
||||
|
||||
#define MAKE_LOCKED_FUNCTION(NAME, TYPE, INS, CONS, VAL) \
|
||||
template < > inline void do##NAME < TYPE > (volatile TYPE * p, TYPE v){ asm volatile("lock;" INS : "=m" (*p) : CONS (VAL), "m" (*p)); } \
|
||||
template < > inline void do##NAME < TYPE > (volatile TYPE * p) { asm volatile("lock;" INS : "=m" (*p) : CONS (1), "m" (*p)); }
|
||||
|
||||
#define MAKE_LOCKED_FUNCTIONS(NAME, TYPE, INS, CONS, VAL) \
|
||||
MAKE_LOCKED_FUNCTION(NAME, TYPE, INS, CONS, VAL) \
|
||||
MAKE_LOCKED_FUNCTION(NAME, unsigned TYPE, INS, CONS, VAL)
|
||||
|
||||
MAKE_LOCKED_TEMPLATE(Add);
|
||||
MAKE_LOCKED_TEMPLATE(Sub);
|
||||
MAKE_LOCKED_TEMPLATE(SetBits);
|
||||
MAKE_LOCKED_TEMPLATE(ClearBits);
|
||||
|
||||
MAKE_LOCKED_FUNCTIONS(Add, int, "addl %1,%0", "ir", v);
|
||||
MAKE_LOCKED_FUNCTIONS(Sub, int, "subl %1,%0", "ir", v);
|
||||
MAKE_LOCKED_FUNCTIONS(SetBits, int, "orl %1,%0", "ir", v);
|
||||
MAKE_LOCKED_FUNCTIONS(ClearBits, int, "andl %1,%0", "ir", ~v);
|
||||
|
||||
#if !defined(__LP64__) && !defined(__LP64)
|
||||
|
||||
MAKE_LOCKED_FUNCTIONS(Add, long, "addl %1,%0", "ir", v);
|
||||
MAKE_LOCKED_FUNCTIONS(Sub, long, "subl %1,%0", "ir", v);
|
||||
MAKE_LOCKED_FUNCTIONS(SetBits, long, "orl %1,%0", "ir", v);
|
||||
MAKE_LOCKED_FUNCTIONS(ClearBits, long, "andl %1,%0", "ir", ~v);
|
||||
|
||||
#else
|
||||
|
||||
MAKE_LOCKED_FUNCTIONS(Add, long, "addq %1,%0", "ir", v);
|
||||
MAKE_LOCKED_FUNCTIONS(Sub, long, "subq %1,%0", "ir", v);
|
||||
MAKE_LOCKED_FUNCTIONS(SetBits, long, "orq %1,%0", "ir", v);
|
||||
MAKE_LOCKED_FUNCTIONS(ClearBits, long, "andq %1,%0", "ir", ~v);
|
||||
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif /* _ATOMIC_HPP_ */
|
||||
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
KHOMP generic endpoint/channel library.
|
||||
Copyright (C) 2007-2009 Khomp Ind. & Com.
|
||||
|
||||
The contents of this file are subject to the Mozilla Public License Version 1.1
|
||||
(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.mozilla.org/MPL/
|
||||
|
||||
Software distributed under the License is distributed on an "AS IS" basis,
|
||||
WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
|
||||
the specific language governing rights and limitations under the License.
|
||||
|
||||
Alternatively, the contents of this file may be used under the terms of the
|
||||
"GNU Lesser General Public License 2.1" license (the “LGPL" License), in which
|
||||
case the provisions of "LGPL License" are applicable instead of those above.
|
||||
|
||||
If you wish to allow use of your version of this file only under the terms of
|
||||
the LGPL License and not to allow others to use your version of this file under
|
||||
the MPL, indicate your decision by deleting the provisions above and replace them
|
||||
with the notice and other provisions required by the LGPL License. If you do not
|
||||
delete the provisions above, a recipient may use your version of this file under
|
||||
either the MPL or the LGPL License.
|
||||
|
||||
The LGPL header follows below:
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this library; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
*/
|
||||
|
||||
#ifndef _CONFIG_COMMONS_HPP_
|
||||
#define _CONFIG_COMMONS_HPP_
|
||||
|
||||
/****************************************************************************/
|
||||
/* ASTERISK */
|
||||
#if defined(COMMONS_LIBRARY_USING_ASTERISK)
|
||||
#define COMMONS_IMPLEMENTATION asterisk
|
||||
/****************************************************************************/
|
||||
/* CALLWEAVER */
|
||||
#elif defined(COMMONS_LIBRARY_USING_CALLWEAVER)
|
||||
#define COMMONS_IMPLEMENTATION callweaver
|
||||
/****************************************************************************/
|
||||
/* FREESWITCH */
|
||||
#elif defined(COMMONS_LIBRARY_USING_FREESWITCH)
|
||||
#define COMMONS_IMPLEMENTATION freeswitch
|
||||
/****************************************************************************/
|
||||
/* GNU/LINUX (generic) */
|
||||
#elif defined(COMMONS_LIBRARY_USING_GNU_LINUX)
|
||||
#define COMMONS_IMPLEMENTATION gnulinux
|
||||
/****************************************************************************/
|
||||
#else
|
||||
#error Unknown implementation selected. Please define COMMONS_LIBRARY_USING_* correctly.
|
||||
#endif
|
||||
|
||||
#define COMMONS_INCLUDE(file) <COMMONS_IMPLEMENTATION/file>
|
||||
|
||||
#endif /* _CONFIG_COMMONS_HPP_ */
|
||||
|
||||
@@ -0,0 +1,710 @@
|
||||
/*
|
||||
KHOMP generic endpoint/channel library.
|
||||
Copyright (C) 2007-2009 Khomp Ind. & Com.
|
||||
|
||||
The contents of this file are subject to the Mozilla Public License Version 1.1
|
||||
(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.mozilla.org/MPL/
|
||||
|
||||
Software distributed under the License is distributed on an "AS IS" basis,
|
||||
WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
|
||||
the specific language governing rights and limitations under the License.
|
||||
|
||||
Alternatively, the contents of this file may be used under the terms of the
|
||||
"GNU Lesser General Public License 2.1" license (the “LGPL" License), in which
|
||||
case the provisions of "LGPL License" are applicable instead of those above.
|
||||
|
||||
If you wish to allow use of your version of this file only under the terms of
|
||||
the LGPL License and not to allow others to use your version of this file under
|
||||
the MPL, indicate your decision by deleting the provisions above and replace them
|
||||
with the notice and other provisions required by the LGPL License. If you do not
|
||||
delete the provisions above, a recipient may use your version of this file under
|
||||
either the MPL or the LGPL License.
|
||||
|
||||
The LGPL header follows below:
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this library; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
*/
|
||||
|
||||
#include <config_options.hpp>
|
||||
|
||||
ConfigOption::ConfigOption(std::string name, const ConfigOption::StringType & value, const ConfigOption::StringType defvalue, string_allowed_type allowed, bool list_me)
|
||||
: _my_name(name), _value_data(new StringData(const_cast<StringType &>(value), defvalue, allowed), true),
|
||||
_list_me(list_me), _values(NULL), _loaded(false)
|
||||
{};
|
||||
|
||||
ConfigOption::ConfigOption(std::string name, const ConfigOption::StringType & value, const ConfigOption::StringType defvalue, bool list_me)
|
||||
: _my_name(name), _value_data(new StringData(const_cast<StringType &>(value), defvalue, string_allowed_type()), true),
|
||||
_list_me(list_me), _values(NULL), _loaded(false)
|
||||
{};
|
||||
|
||||
ConfigOption::ConfigOption(std::string name, const ConfigOption::SignedIntType & value, const ConfigOption::SignedIntType defvalue,
|
||||
ConfigOption::SignedIntType min, ConfigOption::SignedIntType max, ConfigOption::SignedIntType step, bool list_me)
|
||||
: _my_name(name), _value_data(new SignedIntData(const_cast<SignedIntType &>(value), defvalue, Range<SignedIntType>(min, max, step)), true),
|
||||
_list_me(list_me), _values(NULL), _loaded(false)
|
||||
{};
|
||||
|
||||
ConfigOption::ConfigOption(std::string name, const ConfigOption::UnsignedIntType & value, const ConfigOption::UnsignedIntType defvalue,
|
||||
ConfigOption::UnsignedIntType min, ConfigOption::UnsignedIntType max, ConfigOption::UnsignedIntType step, bool list_me)
|
||||
: _my_name(name), _value_data(new UnsignedIntData(const_cast<UnsignedIntType &>(value), defvalue, Range<UnsignedIntType>(min, max, step)), true),
|
||||
_list_me(list_me), _values(NULL), _loaded(false)
|
||||
{};
|
||||
|
||||
ConfigOption::ConfigOption(std::string name, const ConfigOption::BooleanType & value, const ConfigOption::BooleanType defvalue, bool list_me)
|
||||
: _my_name(name), _value_data(new BooleanData(const_cast<BooleanType &>(value), defvalue), true),
|
||||
_list_me(list_me), _values(NULL), _loaded(false)
|
||||
{};
|
||||
|
||||
ConfigOption::ConfigOption(std::string name, ConfigOption::FunctionType fun, std::string defvalue, string_allowed_type allowed, bool list_me)
|
||||
: _my_name(name), _value_data(new FunctionData(fun, defvalue, allowed), true),
|
||||
_list_me(list_me), _values(NULL), _loaded(false)
|
||||
{};
|
||||
|
||||
ConfigOption::ConfigOption(std::string name, ConfigOption::FunctionType fun, std::string defvalue, bool list_me)
|
||||
: _my_name(name), _value_data(new FunctionData(fun, defvalue, string_allowed_type()), true),
|
||||
_list_me(list_me), _values(NULL), _loaded(false)
|
||||
{};
|
||||
|
||||
ConfigOption::ConfigOption(const ConfigOption & o)
|
||||
: _my_name(o._my_name), _value_data(o._value_data),
|
||||
_list_me(o._list_me), _values(o._values), _loaded(o._loaded)
|
||||
{};
|
||||
|
||||
ConfigOption::~ConfigOption(void)
|
||||
{
|
||||
if (_values)
|
||||
{
|
||||
for (unsigned int i = 0; _values[i] != NULL; i++)
|
||||
delete _values[i];
|
||||
|
||||
delete[] _values;
|
||||
_values = NULL;
|
||||
}
|
||||
};
|
||||
|
||||
void ConfigOption::set(ConfigOption::StringType value)
|
||||
{
|
||||
switch (_value_data.which())
|
||||
{
|
||||
case ID_STRING:
|
||||
{
|
||||
try
|
||||
{
|
||||
StringData & tmp = _value_data.get<StringData>();
|
||||
|
||||
if (tmp.string_allowed.empty())
|
||||
{
|
||||
tmp.string_val = value;
|
||||
_loaded = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (tmp.string_allowed.find(value) != tmp.string_allowed.end())
|
||||
{
|
||||
tmp.string_val = value;
|
||||
_loaded = true;
|
||||
return;
|
||||
}
|
||||
|
||||
std::string allowed_string;
|
||||
|
||||
for (string_allowed_type::iterator i = tmp.string_allowed.begin(); i != tmp.string_allowed.end(); i++)
|
||||
{
|
||||
allowed_string += " '";
|
||||
allowed_string += (*i);
|
||||
allowed_string += "'";
|
||||
}
|
||||
|
||||
throw ConfigProcessFailure(STG(FMT("value '%s' not allowed for option '%s' (allowed values:%s)")
|
||||
% value % _my_name % allowed_string));
|
||||
}
|
||||
break;
|
||||
}
|
||||
catch(ValueType::InvalidType & e)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
case ID_FUN:
|
||||
{
|
||||
try
|
||||
{
|
||||
FunctionData & tmp = _value_data.get<FunctionData>();
|
||||
tmp.fun_val(value);
|
||||
_loaded = true;
|
||||
break;
|
||||
}
|
||||
catch(ValueType::InvalidType & e)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
throw ConfigProcessFailure(STG(FMT("option '%s' is not of type string, nor function defined") % _my_name));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ConfigOption::set(ConfigOption::SignedIntType value)
|
||||
{
|
||||
try
|
||||
{
|
||||
SignedIntData & tmp = _value_data.get<SignedIntData>();
|
||||
|
||||
if (value < tmp.sint_Range.minimum)
|
||||
throw ConfigProcessFailure(STG(FMT("value '%d' out-of-Range for option '%s' (too low)") % value % _my_name));
|
||||
|
||||
if (value > tmp.sint_Range.maximum)
|
||||
throw ConfigProcessFailure(STG(FMT("value '%d' out-of-Range for option '%s' (too high)") % value % _my_name));
|
||||
|
||||
if (((value - tmp.sint_Range.minimum) % tmp.sint_Range.step) != 0)
|
||||
throw ConfigProcessFailure(STG(FMT("value '%d' out-of-Range for option '%s' (outside allowed step)") % value % _my_name));
|
||||
|
||||
tmp.sint_val = value;
|
||||
_loaded = true;
|
||||
}
|
||||
catch(ValueType::InvalidType & e)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
void ConfigOption::set(ConfigOption::UnsignedIntType value)
|
||||
{
|
||||
try
|
||||
{
|
||||
UnsignedIntData & tmp = _value_data.get<UnsignedIntData>();
|
||||
|
||||
if (value < tmp.uint_Range.minimum)
|
||||
throw ConfigProcessFailure(STG(FMT("value '%d' out-of-Range for option '%s' (too low)") % value % _my_name));
|
||||
|
||||
if (value > tmp.uint_Range.maximum)
|
||||
throw ConfigProcessFailure(STG(FMT("value '%d' out-of-Range for option '%s' (too high)") % value % _my_name));
|
||||
|
||||
if (((value - tmp.uint_Range.minimum) % tmp.uint_Range.step) != 0)
|
||||
throw ConfigProcessFailure(STG(FMT("value '%d' out-of-Range for option '%s' (outside allowed step)") % value % _my_name));
|
||||
|
||||
tmp.uint_val = value;
|
||||
_loaded = true;
|
||||
}
|
||||
catch(ValueType::InvalidType & e)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
void ConfigOption::set(ConfigOption::BooleanType value)
|
||||
{
|
||||
try
|
||||
{
|
||||
BooleanData & tmp = _value_data.get<BooleanData>();
|
||||
tmp.bool_val = value;
|
||||
_loaded = true;
|
||||
}
|
||||
catch(ValueType::InvalidType & e)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
std::string & ConfigOption::name(void) { return _my_name; };
|
||||
|
||||
ConfigOption::value_id_type ConfigOption::type(void)
|
||||
{
|
||||
return (value_id_type) _value_data.which();
|
||||
};
|
||||
|
||||
const char ** ConfigOption::values(void)
|
||||
{
|
||||
if (_values != NULL)
|
||||
return _values;
|
||||
|
||||
switch ((value_id_type) _value_data.which())
|
||||
{
|
||||
case ConfigOption::ID_BOOL:
|
||||
{
|
||||
_values = new const char*[3];
|
||||
|
||||
_values[0] = strdup("yes");
|
||||
_values[1] = strdup("no");
|
||||
_values[2] = NULL;
|
||||
|
||||
return _values;
|
||||
}
|
||||
|
||||
case ConfigOption::ID_SINT:
|
||||
{
|
||||
try
|
||||
{
|
||||
SignedIntData & tmp = _value_data.get<SignedIntData>();
|
||||
|
||||
|
||||
unsigned int count = ((tmp.sint_Range.maximum - tmp.sint_Range.minimum) / tmp.sint_Range.step) + 1;
|
||||
unsigned int index = 0;
|
||||
|
||||
_values = new const char*[count + 1];
|
||||
|
||||
for (SignedIntType i = tmp.sint_Range.minimum; i <= tmp.sint_Range.maximum; i += tmp.sint_Range.step, index++)
|
||||
_values[index] = strdup(STG(FMT("%d") % i).c_str());
|
||||
|
||||
_values[index] = NULL;
|
||||
|
||||
return _values;
|
||||
}
|
||||
catch(ValueType::InvalidType & e)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
case ConfigOption::ID_UINT:
|
||||
{
|
||||
try
|
||||
{
|
||||
UnsignedIntData & tmp = _value_data.get<UnsignedIntData>();
|
||||
|
||||
unsigned int count = ((tmp.uint_Range.maximum - tmp.uint_Range.minimum) / tmp.uint_Range.step) + 1;
|
||||
unsigned int index = 0;
|
||||
|
||||
_values = new const char*[count + 1];
|
||||
|
||||
for (UnsignedIntType i = tmp.uint_Range.minimum; i <= tmp.uint_Range.maximum; i += tmp.uint_Range.step, index++)
|
||||
_values[index] = strdup(STG(FMT("%d") % i).c_str());
|
||||
|
||||
_values[index] = NULL;
|
||||
|
||||
return _values;
|
||||
}
|
||||
catch(ValueType::InvalidType & e)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
case ConfigOption::ID_STRING:
|
||||
{
|
||||
try
|
||||
{
|
||||
StringData & tmp = _value_data.get<StringData>();
|
||||
|
||||
_values = new const char*[ tmp.string_allowed.size() + 1 ];
|
||||
|
||||
unsigned int index = 0;
|
||||
|
||||
for (string_allowed_type::iterator i = tmp.string_allowed.begin(); i != tmp.string_allowed.end(); i++, index++)
|
||||
_values[index] = strdup((*i).c_str());
|
||||
|
||||
_values[index] = NULL;
|
||||
|
||||
return _values;
|
||||
}
|
||||
catch(ValueType::InvalidType & e)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
case ConfigOption::ID_FUN:
|
||||
{
|
||||
try
|
||||
{
|
||||
FunctionData & tmp = _value_data.get<FunctionData>();
|
||||
|
||||
_values = new const char*[ tmp.fun_allowed.size() + 1 ];
|
||||
|
||||
unsigned int index = 0;
|
||||
|
||||
for (string_allowed_type::iterator i = tmp.fun_allowed.begin(); i != tmp.fun_allowed.end(); i++, index++)
|
||||
_values[index] = strdup((*i).c_str());
|
||||
|
||||
_values[index] = NULL;
|
||||
return _values;
|
||||
}
|
||||
catch(ValueType::InvalidType & e)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
default:
|
||||
throw ConfigProcessFailure(STG(FMT("unknown type identifier '%d'") % _value_data.which()));
|
||||
}
|
||||
};
|
||||
|
||||
void ConfigOption::reset(void)
|
||||
{
|
||||
_loaded = false;
|
||||
};
|
||||
|
||||
void ConfigOption::commit(void)
|
||||
{
|
||||
if (_loaded)
|
||||
return;
|
||||
|
||||
switch ((value_id_type) _value_data.which())
|
||||
{
|
||||
case ConfigOption::ID_BOOL:
|
||||
{
|
||||
try
|
||||
{
|
||||
BooleanData & tmp = _value_data.get<BooleanData>();
|
||||
tmp.bool_val = tmp.bool_default;
|
||||
}
|
||||
catch(ValueType::InvalidType & e)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case ConfigOption::ID_SINT:
|
||||
{
|
||||
try
|
||||
{
|
||||
SignedIntData & tmp = _value_data.get<SignedIntData>();
|
||||
tmp.sint_val = tmp.sint_default;
|
||||
}
|
||||
catch(ValueType::InvalidType & e)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case ConfigOption::ID_UINT:
|
||||
{
|
||||
try
|
||||
{
|
||||
UnsignedIntData & tmp = _value_data.get<UnsignedIntData>();
|
||||
tmp.uint_val = tmp.uint_default;
|
||||
}
|
||||
catch(ValueType::InvalidType & e)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case ConfigOption::ID_STRING:
|
||||
{
|
||||
try
|
||||
{
|
||||
StringData & tmp = _value_data.get<StringData>();
|
||||
tmp.string_val = tmp.string_default;
|
||||
}
|
||||
catch(ValueType::InvalidType & e)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case ConfigOption::ID_FUN:
|
||||
{
|
||||
try
|
||||
{
|
||||
FunctionData & tmp = _value_data.get<FunctionData>();
|
||||
tmp.fun_val(tmp.fun_default);
|
||||
}
|
||||
catch(ValueType::InvalidType & e)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
throw ConfigProcessFailure(STG(FMT("unknown type identifier '%d'") % _value_data.which()));
|
||||
}
|
||||
|
||||
_loaded = true;
|
||||
};
|
||||
|
||||
void ConfigOption::copy_from(ConfigOption & src)
|
||||
{
|
||||
if (src._value_data.which() != _value_data.which())
|
||||
throw ConfigProcessFailure(STG(FMT("unable to copy options, source type differs from destination.")));
|
||||
|
||||
if (!src._loaded)
|
||||
return;
|
||||
|
||||
switch ((value_id_type) _value_data.which())
|
||||
{
|
||||
case ConfigOption::ID_BOOL:
|
||||
{
|
||||
try
|
||||
{
|
||||
BooleanData & stmp = src._value_data.get<BooleanData>();
|
||||
BooleanData & dtmp = _value_data.get<BooleanData>();
|
||||
/* do not copy references, but values.. */
|
||||
bool tmpval = stmp.bool_val;
|
||||
dtmp.bool_val = tmpval;
|
||||
}
|
||||
catch(ValueType::InvalidType & e)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case ConfigOption::ID_SINT:
|
||||
{
|
||||
try
|
||||
{
|
||||
SignedIntData & stmp = src._value_data.get<SignedIntData>();
|
||||
SignedIntData & dtmp = _value_data.get<SignedIntData>();
|
||||
/* do not copy references, but values.. */
|
||||
int tmpval = stmp.sint_val;
|
||||
dtmp.sint_val = tmpval;
|
||||
}
|
||||
catch(ValueType::InvalidType & e)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case ConfigOption::ID_UINT:
|
||||
{
|
||||
try
|
||||
{
|
||||
UnsignedIntData & stmp = src._value_data.get<UnsignedIntData>();
|
||||
UnsignedIntData & dtmp = _value_data.get<UnsignedIntData>();
|
||||
/* do not copy references, but values.. */
|
||||
unsigned int tmpval = stmp.uint_val;
|
||||
dtmp.uint_val = tmpval;
|
||||
}
|
||||
catch(ValueType::InvalidType & e)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case ConfigOption::ID_STRING:
|
||||
{
|
||||
try
|
||||
{
|
||||
StringData & stmp = src._value_data.get<StringData>();
|
||||
StringData & dtmp = _value_data.get<StringData>();
|
||||
/* do not copy references, but values.. */
|
||||
std::string tmpval = stmp.string_val;
|
||||
dtmp.string_val = tmpval;
|
||||
}
|
||||
catch(ValueType::InvalidType & e)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case ConfigOption::ID_FUN:
|
||||
{
|
||||
/* TO IMPLEMENT (NEEDS ANOTHER METHOD ON FUNCTION FOR GETTING VALUE) */
|
||||
|
||||
// FunctionData & tmp = boost::get<FunctionData>(_value_data);
|
||||
//
|
||||
// if (!tmp.loaded)
|
||||
// {
|
||||
// tmp.fun_val(tmp.fun_default);
|
||||
// tmp.loaded = true;
|
||||
// }
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
throw ConfigProcessFailure(STG(FMT("unknown type identifier '%d'") % _value_data.which()));
|
||||
}
|
||||
|
||||
_loaded = true;
|
||||
};
|
||||
|
||||
/*********************************/
|
||||
|
||||
bool ConfigOptions::add(ConfigOption option)
|
||||
{
|
||||
//option_map_type::iterator iter2 = _map.begin();
|
||||
|
||||
//boost::tie(iter2, ok2)
|
||||
std::pair<option_map_type::iterator, bool> ret = _map.insert(option_pair_type(option.name(), option));
|
||||
|
||||
return ret.second;
|
||||
}
|
||||
|
||||
bool ConfigOptions::synonym(std::string equiv_opt, std::string main_opt)
|
||||
{
|
||||
//syn_option_map_type::iterator iter = _syn_map.begin();
|
||||
|
||||
//boost::tie(iter, ok)
|
||||
std::pair<syn_option_map_type::iterator, bool> ret = _syn_map.insert(syn_option_pair_type(equiv_opt, main_opt));
|
||||
|
||||
return ret.second;
|
||||
}
|
||||
|
||||
ConfigOptions::string_set ConfigOptions::options(void)
|
||||
{
|
||||
string_set res;
|
||||
|
||||
for (option_map_type::iterator i = _map.begin(); i != _map.end(); i++)
|
||||
res.insert((*i).first);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
void ConfigOptions::process(const char * name, const char * value)
|
||||
{
|
||||
option_map_type::iterator iter = find_option(name);
|
||||
|
||||
if (iter == _map.end())
|
||||
throw ConfigProcessFailure(STG(FMT("unknown option '%s'") % name));
|
||||
|
||||
try
|
||||
{
|
||||
switch ((*iter).second.type())
|
||||
{
|
||||
case ConfigOption::ID_SINT:
|
||||
set<ConfigOption::SignedIntType>((*iter).first, Strings::toulong(value));
|
||||
return;
|
||||
case ConfigOption::ID_UINT:
|
||||
set<ConfigOption::UnsignedIntType>((*iter).first, Strings::tolong(value));
|
||||
return;
|
||||
case ConfigOption::ID_BOOL:
|
||||
set<ConfigOption::BooleanType>((*iter).first, Strings::toboolean(value));
|
||||
return;
|
||||
case ConfigOption::ID_STRING:
|
||||
case ConfigOption::ID_FUN:
|
||||
set<ConfigOption::StringType>((*iter).first, std::string(value));
|
||||
return;
|
||||
default:
|
||||
throw ConfigProcessFailure(STG(FMT("unknown type identifier '%d'") % (*iter).second.type()));
|
||||
}
|
||||
}
|
||||
catch (Strings::invalid_value & e)
|
||||
{
|
||||
throw ConfigProcessFailure(STG(FMT("invalid value '%s' for option '%s'") % value % name));
|
||||
}
|
||||
}
|
||||
|
||||
const char ** ConfigOptions::values(const char * name)
|
||||
{
|
||||
option_map_type::iterator iter = find_option(name);
|
||||
|
||||
if (iter == _map.end())
|
||||
throw ConfigProcessFailure(STG(FMT("unknown option '%s'") % name));
|
||||
|
||||
return (*iter).second.values();
|
||||
}
|
||||
|
||||
const char ** ConfigOptions::values(void)
|
||||
{
|
||||
if (_values != NULL)
|
||||
return _values;
|
||||
|
||||
unsigned int count = 0;
|
||||
|
||||
for (option_map_type::iterator i = _map.begin(); i != _map.end(); i++)
|
||||
if ((*i).second.list_me())
|
||||
++count;
|
||||
|
||||
_values = new const char*[ count + 1 ];
|
||||
|
||||
unsigned int index = 0;
|
||||
|
||||
for (option_map_type::iterator i = _map.begin(); i != _map.end(); i++)
|
||||
{
|
||||
if ((*i).second.list_me())
|
||||
{
|
||||
_values[index] = strdup((*i).first.c_str());
|
||||
++index;
|
||||
}
|
||||
}
|
||||
|
||||
_values[index] = NULL;
|
||||
|
||||
return _values;
|
||||
}
|
||||
|
||||
void ConfigOptions::reset(void)
|
||||
{
|
||||
for (option_map_type::iterator i = _map.begin(); i != _map.end(); i++)
|
||||
(*i).second.reset();
|
||||
}
|
||||
|
||||
ConfigOptions::messages_type ConfigOptions::commit(void)
|
||||
{
|
||||
messages_type msgs;
|
||||
|
||||
for (option_map_type::iterator i = _map.begin(); i != _map.end(); i++)
|
||||
{
|
||||
try
|
||||
{
|
||||
(*i).second.commit();
|
||||
}
|
||||
catch (ConfigProcessFailure & e)
|
||||
{
|
||||
msgs.push_back(e.msg);
|
||||
}
|
||||
}
|
||||
|
||||
return msgs;
|
||||
}
|
||||
|
||||
bool ConfigOptions::loaded(std::string name)
|
||||
{
|
||||
option_map_type::iterator iter = find_option(name);
|
||||
|
||||
if (iter == _map.end())
|
||||
return false;
|
||||
|
||||
return iter->second.loaded();
|
||||
}
|
||||
|
||||
void ConfigOptions::copy_from(ConfigOptions & source, std::string name)
|
||||
{
|
||||
option_map_type::iterator iter_src = source.find_option(name);
|
||||
option_map_type::iterator iter_dst = find_option(name);
|
||||
|
||||
if (iter_src == source._map.end())
|
||||
throw ConfigProcessFailure(STG(FMT("unknown option '%s' on source") % name));
|
||||
|
||||
if (iter_dst == _map.end())
|
||||
throw ConfigProcessFailure(STG(FMT("unknown option '%s' on destination") % name));
|
||||
|
||||
iter_dst->second.copy_from(iter_src->second);
|
||||
}
|
||||
|
||||
ConfigOptions::option_map_type::iterator ConfigOptions::find_option(std::string name)
|
||||
{
|
||||
syn_option_map_type::iterator syn_iter = _syn_map.find(name);
|
||||
|
||||
if (syn_iter != _syn_map.end())
|
||||
name = syn_iter->second;
|
||||
|
||||
option_map_type::iterator iter = _map.find(name);
|
||||
|
||||
return iter;
|
||||
}
|
||||
@@ -0,0 +1,286 @@
|
||||
/*
|
||||
KHOMP generic endpoint/channel library.
|
||||
Copyright (C) 2007-2009 Khomp Ind. & Com.
|
||||
|
||||
The contents of this file are subject to the Mozilla Public License Version 1.1
|
||||
(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.mozilla.org/MPL/
|
||||
|
||||
Software distributed under the License is distributed on an "AS IS" basis,
|
||||
WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
|
||||
the specific language governing rights and limitations under the License.
|
||||
|
||||
Alternatively, the contents of this file may be used under the terms of the
|
||||
"GNU Lesser General Public License 2.1" license (the “LGPL" License), in which
|
||||
case the provisions of "LGPL License" are applicable instead of those above.
|
||||
|
||||
If you wish to allow use of your version of this file only under the terms of
|
||||
the LGPL License and not to allow others to use your version of this file under
|
||||
the MPL, indicate your decision by deleting the provisions above and replace them
|
||||
with the notice and other provisions required by the LGPL License. If you do not
|
||||
delete the provisions above, a recipient may use your version of this file under
|
||||
either the MPL or the LGPL License.
|
||||
|
||||
The LGPL header follows below:
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this library; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
*/
|
||||
|
||||
#include <set>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
#include <strings.hpp>
|
||||
|
||||
#include <function.hpp>
|
||||
#include <variant.hpp>
|
||||
#include <format.hpp>
|
||||
|
||||
#ifndef _CONFIG_OPTIONS_HPP_
|
||||
#define _CONFIG_OPTIONS_HPP_
|
||||
|
||||
struct ConfigProcessFailure
|
||||
{
|
||||
ConfigProcessFailure(std::string _msg): msg(_msg) {};
|
||||
std::string msg;
|
||||
};
|
||||
|
||||
struct ConfigOption
|
||||
{
|
||||
typedef int SignedIntType;
|
||||
typedef unsigned int UnsignedIntType;
|
||||
typedef bool BooleanType;
|
||||
typedef std::string StringType;
|
||||
|
||||
typedef Function::Function1 < void, std::string > FunctionType;
|
||||
|
||||
typedef std::set < StringType > string_allowed_type;
|
||||
|
||||
/* this should reflect 'variant.which()'! */
|
||||
typedef enum
|
||||
{
|
||||
ID_SINT = 0,
|
||||
ID_UINT = 1,
|
||||
ID_BOOL = 2,
|
||||
ID_STRING = 3,
|
||||
ID_FUN = 4,
|
||||
}
|
||||
value_id_type;
|
||||
|
||||
template < typename number_type >
|
||||
struct Range
|
||||
{
|
||||
Range(number_type _minimum, number_type _maximum, number_type _step)
|
||||
: minimum(_minimum), maximum(_maximum), step(_step) {};
|
||||
|
||||
number_type minimum, maximum, step;
|
||||
};
|
||||
|
||||
struct SignedIntData : public VariantBaseType < void >
|
||||
{
|
||||
SignedIntData(SignedIntType & _sint_val, SignedIntType _sint_default, Range< SignedIntType > _sint_Range)
|
||||
: sint_val(_sint_val), sint_default(_sint_default), sint_Range(_sint_Range) {};
|
||||
|
||||
int which()
|
||||
{
|
||||
return ID_SINT;
|
||||
}
|
||||
|
||||
SignedIntType & sint_val;
|
||||
SignedIntType sint_default;
|
||||
Range<SignedIntType> sint_Range;
|
||||
};
|
||||
|
||||
struct UnsignedIntData : public VariantBaseType < void >
|
||||
{
|
||||
UnsignedIntData(UnsignedIntType & _uint_val, UnsignedIntType _uint_default, Range< UnsignedIntType > _uint_Range)
|
||||
: uint_val(_uint_val), uint_default(_uint_default), uint_Range(_uint_Range) {};
|
||||
|
||||
int which()
|
||||
{
|
||||
return ID_UINT;
|
||||
}
|
||||
|
||||
UnsignedIntType & uint_val;
|
||||
UnsignedIntType uint_default;
|
||||
Range<UnsignedIntType> uint_Range;
|
||||
};
|
||||
|
||||
struct BooleanData : public VariantBaseType < void >
|
||||
{
|
||||
BooleanData(BooleanType & _bool_val, BooleanType _bool_default)
|
||||
: bool_val(_bool_val), bool_default(_bool_default) {};
|
||||
|
||||
int which()
|
||||
{
|
||||
return ID_BOOL;
|
||||
}
|
||||
|
||||
BooleanType & bool_val;
|
||||
BooleanType bool_default;
|
||||
};
|
||||
|
||||
struct StringData : public VariantBaseType < void >
|
||||
{
|
||||
StringData(std::string & _string_val, std::string _string_default, string_allowed_type _string_allowed)
|
||||
: string_val(_string_val), string_default(_string_default), string_allowed(_string_allowed) {};
|
||||
|
||||
int which()
|
||||
{
|
||||
return ID_STRING;
|
||||
}
|
||||
|
||||
std::string & string_val;
|
||||
std::string string_default;
|
||||
string_allowed_type string_allowed;
|
||||
};
|
||||
|
||||
struct FunctionData : public VariantBaseType < void >
|
||||
{
|
||||
FunctionData(FunctionType _fun_val, std::string _fun_default, string_allowed_type _fun_allowed)
|
||||
: fun_val(_fun_val), fun_default(_fun_default), fun_allowed(_fun_allowed) {};
|
||||
|
||||
int which()
|
||||
{
|
||||
return ID_FUN;
|
||||
}
|
||||
|
||||
FunctionType fun_val;
|
||||
std::string fun_default;
|
||||
string_allowed_type fun_allowed;
|
||||
};
|
||||
|
||||
|
||||
typedef Variant < VariantBaseType < void > > ValueType;
|
||||
|
||||
ConfigOption(std::string, const StringType &, const StringType, string_allowed_type allowed, bool list_me = true);
|
||||
ConfigOption(std::string, const StringType &, const StringType = "", bool list_me = true);
|
||||
ConfigOption(std::string, const SignedIntType &, const SignedIntType = 0, SignedIntType min = -INT_MAX, SignedIntType max = INT_MAX, SignedIntType step = 1, bool list_me = true);
|
||||
ConfigOption(std::string, const UnsignedIntType &, const UnsignedIntType = 0, UnsignedIntType min = 0, UnsignedIntType max = UINT_MAX, UnsignedIntType step = 1, bool list_me = true);
|
||||
ConfigOption(std::string, const BooleanType &, const BooleanType = false, bool list_me = true);
|
||||
ConfigOption(std::string, FunctionType, std::string defvalue, string_allowed_type allowed, bool list_me = true);
|
||||
ConfigOption(std::string, FunctionType, std::string defvalue = "", bool list_me = true);
|
||||
|
||||
ConfigOption(const ConfigOption & o);
|
||||
|
||||
~ConfigOption(void);
|
||||
|
||||
void set(StringType value);
|
||||
|
||||
void set(SignedIntType value);
|
||||
void set(UnsignedIntType value);
|
||||
void set(BooleanType value);
|
||||
|
||||
BooleanType get_bool(){ return _value_data.get<BooleanData>().bool_val; }
|
||||
std::string get_str(){ return _value_data.get<StringData>().string_val; }
|
||||
SignedIntType get_sint(){ return _value_data.get<SignedIntData>().sint_val; }
|
||||
UnsignedIntType get_uint(){ return _value_data.get<UnsignedIntData>().uint_val; }
|
||||
|
||||
std::string & name(void);
|
||||
value_id_type type(void);
|
||||
|
||||
const char ** values(void);
|
||||
|
||||
void reset(void);
|
||||
void commit(void);
|
||||
|
||||
bool list_me(void) { return _list_me; };
|
||||
bool loaded(void) { return _loaded; };
|
||||
|
||||
void copy_from(ConfigOption &);
|
||||
|
||||
protected:
|
||||
std::string _my_name;
|
||||
ValueType _value_data;
|
||||
|
||||
bool _list_me;
|
||||
const char ** _values;
|
||||
bool _loaded;
|
||||
};
|
||||
|
||||
struct ConfigOptions
|
||||
{
|
||||
typedef std::vector < std::string > messages_type;
|
||||
|
||||
ConfigOptions(void): _values(NULL) {};
|
||||
|
||||
typedef std::set < std::string > string_set;
|
||||
|
||||
typedef std::map < std::string, ConfigOption > option_map_type;
|
||||
typedef std::pair < std::string, ConfigOption > option_pair_type;
|
||||
|
||||
typedef std::map < std::string, std::string > syn_option_map_type;
|
||||
typedef std::pair < std::string, std::string > syn_option_pair_type;
|
||||
|
||||
bool add(ConfigOption option);
|
||||
|
||||
/* only valid in "process" (for backwards compatibility config files) */
|
||||
bool synonym(std::string, std::string);
|
||||
|
||||
template <typename ValueType>
|
||||
void set(std::string name, ValueType value)
|
||||
{
|
||||
option_map_type::iterator iter = _map.find(name);
|
||||
|
||||
if (iter == _map.end())
|
||||
throw ConfigProcessFailure(STG(FMT("unknown option: %s") % name));
|
||||
|
||||
(*iter).second.set(value);
|
||||
}
|
||||
|
||||
std::string get(std::string name)
|
||||
{
|
||||
option_map_type::iterator iter = _map.find(name);
|
||||
|
||||
if (iter == _map.end())
|
||||
throw ConfigProcessFailure(STG(FMT("unknown option: %s") % name));
|
||||
|
||||
switch((*iter).second.type())
|
||||
{
|
||||
case ConfigOption::ID_BOOL: return (*iter).second.get_bool() ? "yes" : "no";
|
||||
case ConfigOption::ID_STRING: return (*iter).second.get_str();
|
||||
case ConfigOption::ID_UINT: return STG(FMT("%d") % (*iter).second.get_uint());
|
||||
case ConfigOption::ID_SINT: return STG(FMT("%d") % (*iter).second.get_sint());
|
||||
case ConfigOption::ID_FUN: return "";
|
||||
}
|
||||
}
|
||||
|
||||
string_set options(void);
|
||||
|
||||
void process(const char *, const char *); /* process option from file */
|
||||
|
||||
void reset(void); /* reset loaded opts */
|
||||
messages_type commit(void); /* set defaults */
|
||||
|
||||
const char ** values(const char *); /* option value */
|
||||
const char ** values(void); /* values from options */
|
||||
|
||||
bool loaded(std::string); /* return if config was loaded */
|
||||
|
||||
void copy_from(ConfigOptions &, std::string);
|
||||
|
||||
protected:
|
||||
option_map_type::iterator find_option(std::string);
|
||||
|
||||
protected:
|
||||
option_map_type _map;
|
||||
syn_option_map_type _syn_map;
|
||||
|
||||
const char ** _values;
|
||||
};
|
||||
|
||||
#endif /* _CONFIG_OPTIONS_HPP_ */
|
||||
|
||||
@@ -0,0 +1,241 @@
|
||||
/*
|
||||
KHOMP generic endpoint/channel library.
|
||||
Copyright (C) 2007-2009 Khomp Ind. & Com.
|
||||
|
||||
The contents of this file are subject to the Mozilla Public License Version 1.1
|
||||
(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.mozilla.org/MPL/
|
||||
|
||||
Software distributed under the License is distributed on an "AS IS" basis,
|
||||
WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
|
||||
the specific language governing rights and limitations under the License.
|
||||
|
||||
Alternatively, the contents of this file may be used under the terms of the
|
||||
"GNU Lesser General Public License 2.1" license (the “LGPL" License), in which
|
||||
case the provisions of "LGPL License" are applicable instead of those above.
|
||||
|
||||
If you wish to allow use of your version of this file only under the terms of
|
||||
the LGPL License and not to allow others to use your version of this file under
|
||||
the MPL, indicate your decision by deleting the provisions above and replace them
|
||||
with the notice and other provisions required by the LGPL License. If you do not
|
||||
delete the provisions above, a recipient may use your version of this file under
|
||||
either the MPL or the LGPL License.
|
||||
|
||||
The LGPL header follows below:
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this library; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
*/
|
||||
#include <errno.h>
|
||||
|
||||
#include <configurator/configfile.hpp>
|
||||
|
||||
#if _MSC_VER >= 1400
|
||||
#undef close
|
||||
#endif
|
||||
|
||||
void Configfile::ignore(std::string str)
|
||||
{
|
||||
_ignores.insert(str);
|
||||
};
|
||||
|
||||
bool Configfile::select(Section **ptr, std::string str)
|
||||
{
|
||||
/* default section == this! */
|
||||
*ptr = this;
|
||||
|
||||
/* always success by default */
|
||||
return true;
|
||||
};
|
||||
|
||||
bool Configfile::adjust(Section * section, std::string & opt, std::string & val)
|
||||
{
|
||||
return section->load(opt, val);
|
||||
};
|
||||
|
||||
bool Configfile::deserialize(std::ifstream& fd)
|
||||
{
|
||||
Section * section = NULL;
|
||||
|
||||
/* default selection! */
|
||||
if (!select(§ion))
|
||||
{
|
||||
_errors.push_back("default selection has failed!");
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t count = 0;
|
||||
|
||||
while (fd.good())
|
||||
{
|
||||
std::string str;
|
||||
|
||||
/* read one line! */
|
||||
std::getline(fd, str);
|
||||
|
||||
size_t lst = str.size() - 1;
|
||||
|
||||
if (str.size() >= 1 && str[lst] == '\r') //cuida das quebras de linha do tipo \r\n
|
||||
{
|
||||
str.erase(lst,1);
|
||||
--lst;
|
||||
}
|
||||
|
||||
/* empty line! */
|
||||
if (str.size() == 0)
|
||||
continue;
|
||||
|
||||
/* comment! */
|
||||
if (str[0] == '#')
|
||||
continue;
|
||||
|
||||
++count;
|
||||
|
||||
if (str[0] == '[' && str[lst] == ']')
|
||||
{
|
||||
str.erase(0,1); --lst;
|
||||
str.erase(lst,1); --lst;
|
||||
|
||||
if (!select(§ion, str))
|
||||
{
|
||||
_errors.push_back(STG(FMT("erroneous section '%s'") % str));
|
||||
|
||||
/* ignore this section */
|
||||
section = NULL;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string::size_type pos = str.find('=');
|
||||
|
||||
if (pos == std::string::npos)
|
||||
{
|
||||
_errors.push_back(STG(FMT("erroneous separator '%s'") % str));
|
||||
continue;
|
||||
};
|
||||
|
||||
if (section == NULL)
|
||||
{
|
||||
_errors.push_back(STG(FMT("no section for option '%s'") % str));
|
||||
continue;
|
||||
}
|
||||
|
||||
std::string opt(str.substr(0,pos));
|
||||
std::string val(str.substr(pos+1));
|
||||
|
||||
if (_ignores.find(opt) != _ignores.end())
|
||||
continue;
|
||||
|
||||
if (val == "@") val = "";
|
||||
|
||||
if (adjust(section, opt, val))
|
||||
continue;
|
||||
|
||||
_errors.push_back(STG(FMT("option '%s' does "
|
||||
"not exist or '%s' is not a valid value (at section '%s')")
|
||||
% opt % val % section->name()));
|
||||
}
|
||||
}
|
||||
|
||||
// retorna 'true' se arquivo tinha alguma coisa valida.
|
||||
return (count != 0);
|
||||
}
|
||||
|
||||
bool Configfile::obtain()
|
||||
{
|
||||
std::ifstream fd(_filename.c_str());
|
||||
|
||||
if (!fd.is_open())
|
||||
{
|
||||
_errors.push_back(STG(FMT("unable to open file '%s': %s")
|
||||
% _filename % strerror(errno)));
|
||||
return false;
|
||||
};
|
||||
|
||||
if (!deserialize(fd))
|
||||
{
|
||||
fd.close();
|
||||
return false;
|
||||
}
|
||||
|
||||
fd.close();
|
||||
return true;
|
||||
};
|
||||
|
||||
void Configfile::recurse(std::ofstream& fd, Section * section)
|
||||
{
|
||||
typedef Section::SectionMap::iterator section_iter;
|
||||
typedef Section::OptionMap::iterator option_iter;
|
||||
|
||||
for (option_iter i = section->option_begin(); i != section->option_end(); i++)
|
||||
{
|
||||
std::string res;
|
||||
|
||||
if ((*i).second.store(res))
|
||||
{
|
||||
if (res == "") res = "@";
|
||||
fd << (*i).first << "=" << res << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
if (!section->recursive())
|
||||
return;
|
||||
|
||||
for (section_iter j = section->section_begin(); j != section->section_end(); j++)
|
||||
recurse(fd, (*j).second);
|
||||
}
|
||||
|
||||
bool Configfile::serialize(std::ofstream& fd)
|
||||
{
|
||||
recurse(fd, this);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Configfile::provide()
|
||||
{
|
||||
std::string tmp(_filename);
|
||||
tmp += ".new";
|
||||
|
||||
std::ofstream fd(tmp.c_str());
|
||||
|
||||
if (!fd.good())
|
||||
{
|
||||
_errors.push_back(STG(FMT("unable to open file '%s': %s")
|
||||
% tmp % strerror(errno)));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!serialize(fd))
|
||||
{
|
||||
fd.close();
|
||||
return false;
|
||||
}
|
||||
|
||||
fd.close();
|
||||
|
||||
if (rename(tmp.c_str(), _filename.c_str()) != 0)
|
||||
{
|
||||
_errors.push_back(STG(FMT("unable to replace config file '%s': %s")
|
||||
% _filename % strerror(errno)));
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#if _MSC_VER >= 1400
|
||||
#define close _close
|
||||
#endif
|
||||
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
KHOMP generic endpoint/channel library.
|
||||
Copyright (C) 2007-2009 Khomp Ind. & Com.
|
||||
|
||||
The contents of this file are subject to the Mozilla Public License Version 1.1
|
||||
(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.mozilla.org/MPL/
|
||||
|
||||
Software distributed under the License is distributed on an "AS IS" basis,
|
||||
WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
|
||||
the specific language governing rights and limitations under the License.
|
||||
|
||||
Alternatively, the contents of this file may be used under the terms of the
|
||||
"GNU Lesser General Public License 2.1" license (the “LGPL" License), in which
|
||||
case the provisions of "LGPL License" are applicable instead of those above.
|
||||
|
||||
If you wish to allow use of your version of this file only under the terms of
|
||||
the LGPL License and not to allow others to use your version of this file under
|
||||
the MPL, indicate your decision by deleting the provisions above and replace them
|
||||
with the notice and other provisions required by the LGPL License. If you do not
|
||||
delete the provisions above, a recipient may use your version of this file under
|
||||
either the MPL or the LGPL License.
|
||||
|
||||
The LGPL header follows below:
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this library; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
*/
|
||||
|
||||
#include <vector>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <set>
|
||||
|
||||
#include <format.hpp>
|
||||
|
||||
#include <configurator/section.hpp>
|
||||
|
||||
#ifndef _CONFIG_CONFIGFILE_HPP_
|
||||
#define _CONFIG_CONFIGFILE_HPP_
|
||||
|
||||
struct Configfile: public Section
|
||||
{
|
||||
typedef std::list < std::string > ErrorVector;
|
||||
typedef std::set < std::string > NameSet;
|
||||
|
||||
Configfile(std::string name, std::string desc)
|
||||
: Section(name, desc), _good(false) {};
|
||||
|
||||
virtual ~Configfile() {};
|
||||
|
||||
bool good() { return _good; };
|
||||
std::string & filename() { return _filename; };
|
||||
|
||||
ErrorVector & errors() { return _errors; };
|
||||
|
||||
void ignore(std::string);
|
||||
|
||||
virtual bool obtain();
|
||||
virtual bool provide();
|
||||
|
||||
protected:
|
||||
virtual bool select(Section **, std::string str = "");
|
||||
virtual bool adjust(Section *, std::string & opt, std::string & val);
|
||||
|
||||
virtual bool deserialize(std::ifstream &);
|
||||
virtual bool serialize(std::ofstream &);
|
||||
|
||||
void recurse(std::ofstream &, Section *);
|
||||
|
||||
protected:
|
||||
bool _good;
|
||||
ErrorVector _errors;
|
||||
NameSet _ignores;
|
||||
std::string _filename;
|
||||
};
|
||||
|
||||
#endif /* _CONFIG_CONFIGFILE_HPP_ */
|
||||
@@ -0,0 +1,185 @@
|
||||
/*
|
||||
KHOMP generic endpoint/channel library.
|
||||
Copyright (C) 2007-2009 Khomp Ind. & Com.
|
||||
|
||||
The contents of this file are subject to the Mozilla Public License Version 1.1
|
||||
(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.mozilla.org/MPL/
|
||||
|
||||
Software distributed under the License is distributed on an "AS IS" basis,
|
||||
WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
|
||||
the specific language governing rights and limitations under the License.
|
||||
|
||||
Alternatively, the contents of this file may be used under the terms of the
|
||||
"GNU Lesser General Public License 2.1" license (the “LGPL" License), in which
|
||||
case the provisions of "LGPL License" are applicable instead of those above.
|
||||
|
||||
If you wish to allow use of your version of this file only under the terms of
|
||||
the LGPL License and not to allow others to use your version of this file under
|
||||
the MPL, indicate your decision by deleting the provisions above and replace them
|
||||
with the notice and other provisions required by the LGPL License. If you do not
|
||||
delete the provisions above, a recipient may use your version of this file under
|
||||
either the MPL or the LGPL License.
|
||||
|
||||
The LGPL header follows below:
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this library; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
*/
|
||||
|
||||
#include <configurator/option.hpp>
|
||||
|
||||
bool Option::equals(std::string & value)
|
||||
{
|
||||
switch (_restriction.numeral())
|
||||
{
|
||||
case Restriction::N_UNIQUE:
|
||||
{
|
||||
Restriction::Value my_value;
|
||||
|
||||
if (!_restriction.get(Restriction::F_USER, my_value))
|
||||
return false;
|
||||
|
||||
return (my_value == value);
|
||||
}
|
||||
case Restriction::N_MULTIPLE:
|
||||
{
|
||||
Restriction::Vector my_values;
|
||||
|
||||
if (!_restriction.get(Restriction::F_USER, my_values))
|
||||
return false;
|
||||
|
||||
for (Restriction::Vector::iterator i = my_values.begin(); i != my_values.end(); i++)
|
||||
{
|
||||
if ((*i) == value)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Option::load(std::string & value)
|
||||
{
|
||||
bool ret = _restriction.set(Restriction::F_FILE, value);
|
||||
|
||||
if (ret) _modified = false;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool Option::change(std::string & value)
|
||||
{
|
||||
bool ret = _restriction.set(Restriction::F_FILE, value);
|
||||
|
||||
if (ret) _modified = true;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool Option::store(std::string & value)
|
||||
{
|
||||
switch (_restriction.numeral())
|
||||
{
|
||||
case Restriction::N_UNIQUE:
|
||||
return _restriction.get(Restriction::F_FILE, value);
|
||||
|
||||
case Restriction::N_MULTIPLE:
|
||||
{
|
||||
Restriction::Vector values;
|
||||
|
||||
if (!_restriction.get(Restriction::F_FILE, values))
|
||||
return false;
|
||||
|
||||
Strings::Merger strs;
|
||||
|
||||
for (Restriction::Vector::iterator i = values.begin(); i != values.end(); i++)
|
||||
strs.add(*i);
|
||||
|
||||
value = strs.merge(",");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
Option::Flags Option::set(const char * value)
|
||||
{
|
||||
std::string str_value(value);
|
||||
return set(str_value);
|
||||
}
|
||||
|
||||
|
||||
Option::Flags Option::set(Restriction::Value & value)
|
||||
{
|
||||
Restriction::Value last_value, curr_value;
|
||||
Flags flags;
|
||||
|
||||
bool ret1 = _restriction.get(Restriction::F_USER, last_value);
|
||||
|
||||
if (!_restriction.set(Restriction::F_USER, value))
|
||||
return flags;
|
||||
|
||||
flags[F_ADJUSTED] = true;
|
||||
|
||||
bool ret2 = _restriction.get(Restriction::F_USER, curr_value);
|
||||
|
||||
if (!ret1 || (ret2 && (last_value != curr_value)))
|
||||
{
|
||||
flags[F_MODIFIED] = true;
|
||||
_modified = true;
|
||||
}
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
||||
Option::Flags Option::set(Restriction::Vector & values)
|
||||
{
|
||||
Restriction::Vector last_values, curr_values;
|
||||
Flags flags;
|
||||
|
||||
bool ret1 = _restriction.get(Restriction::F_USER, last_values);
|
||||
|
||||
if (!_restriction.set(Restriction::F_USER, values))
|
||||
return flags;
|
||||
|
||||
flags[F_ADJUSTED] = true;
|
||||
|
||||
bool ret2 = _restriction.get(Restriction::F_USER, curr_values);
|
||||
|
||||
if (!ret1 || (ret2 && (last_values != curr_values)))
|
||||
{
|
||||
flags[F_MODIFIED] = true;
|
||||
_modified = true;
|
||||
}
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
||||
bool Option::get(Restriction::Value & value)
|
||||
{
|
||||
return _restriction.get(Restriction::F_USER, value);
|
||||
}
|
||||
|
||||
bool Option::get(Restriction::Vector & values)
|
||||
{
|
||||
return _restriction.get(Restriction::F_USER, values);
|
||||
}
|
||||
@@ -0,0 +1,122 @@
|
||||
/*
|
||||
KHOMP generic endpoint/channel library.
|
||||
Copyright (C) 2007-2009 Khomp Ind. & Com.
|
||||
|
||||
The contents of this file are subject to the Mozilla Public License Version 1.1
|
||||
(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.mozilla.org/MPL/
|
||||
|
||||
Software distributed under the License is distributed on an "AS IS" basis,
|
||||
WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
|
||||
the specific language governing rights and limitations under the License.
|
||||
|
||||
Alternatively, the contents of this file may be used under the terms of the
|
||||
"GNU Lesser General Public License 2.1" license (the “LGPL" License), in which
|
||||
case the provisions of "LGPL License" are applicable instead of those above.
|
||||
|
||||
If you wish to allow use of your version of this file only under the terms of
|
||||
the LGPL License and not to allow others to use your version of this file under
|
||||
the MPL, indicate your decision by deleting the provisions above and replace them
|
||||
with the notice and other provisions required by the LGPL License. If you do not
|
||||
delete the provisions above, a recipient may use your version of this file under
|
||||
either the MPL or the LGPL License.
|
||||
|
||||
The LGPL header follows below:
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this library; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include <string>
|
||||
#include <list>
|
||||
#include <vector>
|
||||
|
||||
#include <strings.hpp>
|
||||
|
||||
#include <configurator/restriction.hpp>
|
||||
|
||||
#ifndef _CONFIG_OPTION_HPP_
|
||||
#define _CONFIG_OPTION_HPP_
|
||||
|
||||
struct Option
|
||||
{
|
||||
enum FlagTypes
|
||||
{
|
||||
F_MODIFIED = 0x0, /* if option was modified */
|
||||
F_ADJUSTED = 0x1, /* if option was correctly formated */
|
||||
};
|
||||
|
||||
struct Flags: public std::vector<bool>
|
||||
{
|
||||
Flags(): std::vector<bool>(2) {};
|
||||
};
|
||||
|
||||
typedef Restriction::Value Value;
|
||||
typedef Restriction::Vector Vector;
|
||||
|
||||
/* exception */
|
||||
struct InvalidDefaultValue
|
||||
{
|
||||
InvalidDefaultValue(std::string name, std::string value)
|
||||
: _name(name), _value(value) {};
|
||||
|
||||
std::string & name() { return _name; };
|
||||
std::string & value() { return _value; };
|
||||
|
||||
protected:
|
||||
std::string _name;
|
||||
std::string _value;
|
||||
};
|
||||
|
||||
Option(std::string name, std::string desc, std::string defvalue, Restriction restriction)
|
||||
: _name(name), _desc(desc), _restriction(restriction), _modified(true)
|
||||
{
|
||||
std::string value(defvalue);
|
||||
|
||||
if (!(set(value)[F_ADJUSTED]))
|
||||
throw InvalidDefaultValue(name, defvalue);
|
||||
}
|
||||
|
||||
const std::string & name() { return _name; };
|
||||
const std::string & description() { return _desc; };
|
||||
|
||||
Restriction & restriction() { return _restriction; };
|
||||
bool modified() { return _modified; };
|
||||
|
||||
public:
|
||||
bool load(std::string &);
|
||||
bool change(std::string &);
|
||||
bool store(std::string &);
|
||||
|
||||
Flags set(const char *);
|
||||
Flags set(Value &);
|
||||
Flags set(Vector &);
|
||||
|
||||
bool get(Value &);
|
||||
bool get(Vector &);
|
||||
|
||||
bool equals(std::string &);
|
||||
|
||||
protected:
|
||||
std::string _name;
|
||||
std::string _desc;
|
||||
|
||||
Restriction _restriction;
|
||||
bool _modified;
|
||||
};
|
||||
|
||||
#endif /* _CONFIG_OPTION_HPP_ */
|
||||
@@ -0,0 +1,353 @@
|
||||
/*
|
||||
KHOMP generic endpoint/channel library.
|
||||
Copyright (C) 2007-2009 Khomp Ind. & Com.
|
||||
|
||||
The contents of this file are subject to the Mozilla Public License Version 1.1
|
||||
(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.mozilla.org/MPL/
|
||||
|
||||
Software distributed under the License is distributed on an "AS IS" basis,
|
||||
WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
|
||||
the specific language governing rights and limitations under the License.
|
||||
|
||||
Alternatively, the contents of this file may be used under the terms of the
|
||||
"GNU Lesser General Public License 2.1" license (the “LGPL" License), in which
|
||||
case the provisions of "LGPL License" are applicable instead of those above.
|
||||
|
||||
If you wish to allow use of your version of this file only under the terms of
|
||||
the LGPL License and not to allow others to use your version of this file under
|
||||
the MPL, indicate your decision by deleting the provisions above and replace them
|
||||
with the notice and other provisions required by the LGPL License. If you do not
|
||||
delete the provisions above, a recipient may use your version of this file under
|
||||
either the MPL or the LGPL License.
|
||||
|
||||
The LGPL header follows below:
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this library; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
*/
|
||||
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <iostream>
|
||||
#include <strings.hpp>
|
||||
|
||||
#include <configurator/restriction.hpp>
|
||||
|
||||
/* internal helper! */
|
||||
bool Restriction::equalNumber(const double a, const double b)
|
||||
{
|
||||
char tmp1[64];
|
||||
char tmp2[64];
|
||||
|
||||
snprintf(tmp1, sizeof(tmp1), "%.3f", a);
|
||||
snprintf(tmp2, sizeof(tmp2), "%.3f", b);
|
||||
|
||||
if (strncmp(tmp1, tmp2, sizeof(tmp1)))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* process value to our internal representation */
|
||||
|
||||
bool Restriction::process(Restriction::Format fmt,
|
||||
const Restriction::Value & value, Restriction::Value & final)
|
||||
{
|
||||
switch (_bounds)
|
||||
{
|
||||
case B_RANGE:
|
||||
{
|
||||
if (_kind != K_NUMBER)
|
||||
return false;
|
||||
|
||||
std::string tmpvalue;
|
||||
|
||||
Restriction::Value::const_iterator itr = value.begin();
|
||||
Restriction::Value::const_iterator end = value.end();
|
||||
|
||||
tmpvalue.reserve(value.size());
|
||||
|
||||
// f*cking dot/comma notation!
|
||||
for (; itr != end; ++itr)
|
||||
tmpvalue += ((*itr) != ',' ? (*itr) : '.');
|
||||
|
||||
try
|
||||
{
|
||||
double newvalue = Strings::todouble(tmpvalue);
|
||||
|
||||
if (newvalue < _init && newvalue > _fini)
|
||||
return false;
|
||||
|
||||
double res = (newvalue - _init) / _step;
|
||||
|
||||
if (!equalNumber(res, rint(res)))
|
||||
return false;
|
||||
|
||||
final = value;
|
||||
return true;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
case B_LIST:
|
||||
for (List::iterator i = _list.begin(); i != _list.end(); i++)
|
||||
{
|
||||
Value & tmp = (*i);
|
||||
|
||||
if (tmp == value)
|
||||
{
|
||||
final = value;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
||||
case B_MAPS:
|
||||
switch (fmt)
|
||||
{
|
||||
case F_USER:
|
||||
{
|
||||
Map::iterator i = _map_from_usr.find(std::string(value));
|
||||
|
||||
if (i == _map_from_usr.end())
|
||||
return false;
|
||||
|
||||
Value & tmp = (*i).second;
|
||||
|
||||
final = tmp;
|
||||
return true;
|
||||
}
|
||||
|
||||
case F_FILE:
|
||||
{
|
||||
Map::iterator i = _map_from_cfg.find(std::string(value));
|
||||
|
||||
if (i == _map_from_cfg.end())
|
||||
return false;
|
||||
|
||||
final = value;
|
||||
return true;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
|
||||
case B_FREE:
|
||||
final = value;
|
||||
return true;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/* unprocess the value (outputs the external representation) */
|
||||
|
||||
bool Restriction::unprocess(Restriction::Format fmt,
|
||||
const Restriction::Value & value, Restriction::Value & final)
|
||||
{
|
||||
switch (_bounds)
|
||||
{
|
||||
case B_MAPS:
|
||||
|
||||
switch (fmt)
|
||||
{
|
||||
case F_USER:
|
||||
{
|
||||
Map::iterator i = _map_from_cfg.find(std::string(value));
|
||||
|
||||
if (i == _map_from_cfg.end())
|
||||
return false;
|
||||
|
||||
final = (*i).second;
|
||||
return true;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
final = value;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/***************************** *****************************/
|
||||
|
||||
bool Restriction::get(Restriction::Format fmt, Restriction::Value & value)
|
||||
{
|
||||
if (_numeral != N_UNIQUE)
|
||||
return false;
|
||||
|
||||
if (!unprocess(fmt, _value._unique, value))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Restriction::get(Restriction::Format fmt, Restriction::Vector & values)
|
||||
{
|
||||
if (_numeral != N_MULTIPLE)
|
||||
return false;
|
||||
|
||||
List & my_values = _value._multiple;
|
||||
|
||||
for (List::iterator i = my_values.begin(); i != my_values.end(); i++)
|
||||
{
|
||||
Value & value = (*i);
|
||||
Value final;
|
||||
|
||||
if (!unprocess(fmt, value, final))
|
||||
return false;
|
||||
|
||||
values.push_back(final);
|
||||
};
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/***************************** *****************************/
|
||||
|
||||
bool Restriction::set(Restriction::Format fmt, Restriction::Value &value)
|
||||
{
|
||||
switch (_numeral)
|
||||
{
|
||||
case N_UNIQUE:
|
||||
{
|
||||
Value final;
|
||||
|
||||
if (!process(fmt, value, final))
|
||||
return false;
|
||||
|
||||
_value._unique = final;
|
||||
return true;
|
||||
}
|
||||
|
||||
case N_MULTIPLE:
|
||||
{
|
||||
if (value == "@" || value == "#" || value == "")
|
||||
{
|
||||
_value._multiple.clear();
|
||||
return true;
|
||||
}
|
||||
|
||||
Strings::vector_type values;
|
||||
Strings::tokenize(value, values, ",");
|
||||
|
||||
return set(fmt, values);
|
||||
}
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool Restriction::set(Restriction::Format fmt, Restriction::Vector & values)
|
||||
{
|
||||
if (_numeral != N_MULTIPLE)
|
||||
return false;
|
||||
|
||||
if (values.empty())
|
||||
{
|
||||
_value._multiple.clear();
|
||||
}
|
||||
else
|
||||
{
|
||||
/* list needed to store temporary values */
|
||||
List finals;
|
||||
|
||||
for (Vector::iterator i = values.begin(); i != values.end(); i++)
|
||||
{
|
||||
Value & value = (*i);
|
||||
Value final;
|
||||
|
||||
if (!process(fmt, value, final))
|
||||
return false;
|
||||
|
||||
finals.push_back(final);
|
||||
}
|
||||
|
||||
List & lst = _value._multiple;
|
||||
|
||||
/* need to clear values set before */
|
||||
lst.clear();
|
||||
|
||||
for (List::iterator i = finals.begin(); i != finals.end(); i++)
|
||||
{
|
||||
Value value = (*i);
|
||||
lst.push_back(value);
|
||||
}
|
||||
};
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/***************************** *****************************/
|
||||
|
||||
void Restriction::allowed(Restriction::Vector &vals)
|
||||
{
|
||||
switch (_bounds)
|
||||
{
|
||||
case B_FREE:
|
||||
return;
|
||||
|
||||
case B_LIST:
|
||||
for (List::iterator i = _list.begin(); i != _list.end(); i++)
|
||||
vals.push_back((*i));
|
||||
break;
|
||||
|
||||
case B_MAPS:
|
||||
for (Map::iterator i = _map_from_usr.begin(); i != _map_from_usr.end(); i++)
|
||||
vals.push_back((*i).first);
|
||||
break;
|
||||
|
||||
case B_RANGE:
|
||||
{
|
||||
if (_kind != K_NUMBER)
|
||||
return;
|
||||
|
||||
// is there any fraction?
|
||||
bool has_fraction = (!equalNumber(_init, rint(_init))) || (!equalNumber(_fini, rint(_fini))) || (!equalNumber(_step, rint(_step)));
|
||||
|
||||
const char * format = (has_fraction ? "%.2f" : "%02.0f");
|
||||
|
||||
for (double i = _init; i <= _fini; i += _step)
|
||||
{
|
||||
char tmp[32];
|
||||
snprintf(tmp, sizeof(tmp), format, i);
|
||||
vals.push_back(std::string(tmp));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void Restriction::init_class()
|
||||
{
|
||||
_value._unique.clear();
|
||||
_value._multiple.clear();
|
||||
}
|
||||
@@ -0,0 +1,321 @@
|
||||
/*
|
||||
KHOMP generic endpoint/channel library.
|
||||
Copyright (C) 2007-2009 Khomp Ind. & Com.
|
||||
|
||||
The contents of this file are subject to the Mozilla Public License Version 1.1
|
||||
(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.mozilla.org/MPL/
|
||||
|
||||
Software distributed under the License is distributed on an "AS IS" basis,
|
||||
WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
|
||||
the specific language governing rights and limitations under the License.
|
||||
|
||||
Alternatively, the contents of this file may be used under the terms of the
|
||||
"GNU Lesser General Public License 2.1" license (the “LGPL" License), in which
|
||||
case the provisions of "LGPL License" are applicable instead of those above.
|
||||
|
||||
If you wish to allow use of your version of this file only under the terms of
|
||||
the LGPL License and not to allow others to use your version of this file under
|
||||
the MPL, indicate your decision by deleting the provisions above and replace them
|
||||
with the notice and other provisions required by the LGPL License. If you do not
|
||||
delete the provisions above, a recipient may use your version of this file under
|
||||
either the MPL or the LGPL License.
|
||||
|
||||
The LGPL header follows below:
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this library; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
*/
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
#include <string>
|
||||
#include <list>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
|
||||
#ifndef _CONFIG_RESTRICTION_HPP_
|
||||
#define _CONFIG_RESTRICTION_HPP_
|
||||
|
||||
struct Restriction
|
||||
{
|
||||
/* generic types */
|
||||
enum Format
|
||||
{
|
||||
F_USER,
|
||||
F_FILE
|
||||
};
|
||||
|
||||
enum Kind
|
||||
{
|
||||
// K_INTEGER,
|
||||
// K_FLOAT,
|
||||
K_STRING,
|
||||
K_NUMBER // = K_INTEGER // compatibility
|
||||
};
|
||||
|
||||
enum Bounds
|
||||
{
|
||||
B_FREE,
|
||||
B_RANGE,
|
||||
B_LIST,
|
||||
B_MAPS
|
||||
};
|
||||
|
||||
enum Numeral
|
||||
{
|
||||
N_UNIQUE,
|
||||
N_MULTIPLE
|
||||
};
|
||||
|
||||
typedef std::string Value;
|
||||
|
||||
/* types used for data input */
|
||||
struct Pair
|
||||
{
|
||||
const char *pretty;
|
||||
const char *value;
|
||||
};
|
||||
|
||||
typedef std::pair < Value, Value > PairMap;
|
||||
typedef std::list < PairMap > ListMap;
|
||||
|
||||
/* types used internally */
|
||||
typedef std::map < Value, Value > Map;
|
||||
typedef std::vector < Value > Vector;
|
||||
|
||||
typedef std::list < Value > List;
|
||||
typedef std::pair < Value, Value > MapPair;
|
||||
|
||||
struct Generic
|
||||
{
|
||||
Value _unique;
|
||||
List _multiple;
|
||||
};
|
||||
|
||||
Restriction(Kind kind, Numeral num)
|
||||
: _kind(kind), _bounds(B_FREE), _numeral(num), _unit(""),
|
||||
_init(-1), _fini(-1), _step(-1)
|
||||
{
|
||||
init_class();
|
||||
}
|
||||
|
||||
/*
|
||||
Restriction(Kind kind, Numeral num,
|
||||
int init, int fini, int step = 1)
|
||||
: _kind(kind), _bounds(B_RANGE), _numeral(num), _unit(unit),
|
||||
_iinit(init), _ifini(fini), _istep(step),
|
||||
_finit(-1), _ffini(-1), _fstep(-1)
|
||||
{
|
||||
init_class();
|
||||
}
|
||||
|
||||
Restriction(Kind kind, Numeral num,
|
||||
const char *unit, int init, int fini, int step = 1)
|
||||
: _kind(kind), _bounds(B_RANGE), _numeral(num), _unit(unit),
|
||||
_iinit(init), _ifini(fini), _istep(step),
|
||||
_finit(-1), _ffini(-1), _fstep(-1)
|
||||
{
|
||||
init_class();
|
||||
}
|
||||
|
||||
Restriction(Kind kind, Numeral num,
|
||||
std::string unit, int init, int fini, int step = 1)
|
||||
: _kind(kind), _bounds(B_RANGE), _numeral(num), _unit(unit),
|
||||
_iinit(init), _ifini(fini), _istep(step),
|
||||
_finit(-1), _ffini(-1), _fstep(-1)
|
||||
{
|
||||
init_class();
|
||||
}
|
||||
|
||||
Restriction(Kind kind, Numeral num,
|
||||
float init, float fini, float step = 1)
|
||||
: _kind(kind), _bounds(B_RANGE), _numeral(num), _unit(unit),
|
||||
_iinit(-1), _ifini(-1), _istep(-1)
|
||||
_finit(init), _ffini(fini), _fstep(step),
|
||||
{
|
||||
init_class();
|
||||
}
|
||||
|
||||
Restriction(Kind kind, Numeral num,
|
||||
const char *unit, float init, float fini, float step = 1.0)
|
||||
: _kind(kind), _bounds(B_RANGE), _numeral(num), _unit(unit),
|
||||
_iinit(-1), _ifini(-1), _istep(-1)
|
||||
_finit(init), _ffini(fini), _fstep(step),
|
||||
{
|
||||
init_class();
|
||||
}
|
||||
|
||||
Restriction(Kind kind, Numeral num,
|
||||
std::string unit, float init, float fini, float step = 1.0)
|
||||
: _kind(kind), _bounds(B_RANGE), _numeral(num), _unit(unit),
|
||||
_iinit(-1), _ifini(-1), _istep(-1)
|
||||
_finit(init), _ffini(fini), _fstep(step),
|
||||
{
|
||||
init_class();
|
||||
}
|
||||
*/
|
||||
|
||||
Restriction(Kind kind, Numeral num,
|
||||
double init, double fini, double step = 1)
|
||||
: _kind(kind), _bounds(B_RANGE), _numeral(num), _unit(""),
|
||||
_init(init), _fini(fini), _step(step)
|
||||
{
|
||||
init_class();
|
||||
}
|
||||
|
||||
Restriction(Kind kind, Numeral num,
|
||||
const char *unit, double init, double fini, double step = 1.0)
|
||||
: _kind(kind), _bounds(B_RANGE), _numeral(num), _unit(unit),
|
||||
_init(init), _fini(fini), _step(step)
|
||||
{
|
||||
init_class();
|
||||
}
|
||||
|
||||
Restriction(Kind kind, Numeral num,
|
||||
std::string unit, double init, double fini, double step = 1.0)
|
||||
: _kind(kind), _bounds(B_RANGE), _numeral(num), _unit(unit),
|
||||
_init(init), _fini(fini), _step(step)
|
||||
{
|
||||
init_class();
|
||||
}
|
||||
|
||||
Restriction(Kind kind, Numeral num,
|
||||
const char *first, ...)
|
||||
: _kind(kind), _bounds(B_LIST), _numeral(num), _unit(""),
|
||||
_init(-1), _fini(-1), _step(-1)
|
||||
{
|
||||
_list.push_back(std::string(first));
|
||||
|
||||
va_list ap;
|
||||
va_start(ap, first);
|
||||
|
||||
while (true)
|
||||
{
|
||||
const char *arg = va_arg(ap, const char *);
|
||||
|
||||
if (arg == NULL) break;
|
||||
|
||||
_list.push_back(std::string(arg));
|
||||
}
|
||||
|
||||
init_class();
|
||||
}
|
||||
|
||||
Restriction(Kind kind, const char *unit, Numeral num,
|
||||
const char *first, ...)
|
||||
: _kind(kind), _bounds(B_LIST), _numeral(num), _unit(unit),
|
||||
_init(-1), _fini(-1), _step(-1)
|
||||
{
|
||||
_list.push_back(std::string(first));
|
||||
|
||||
va_list ap;
|
||||
va_start(ap, first);
|
||||
|
||||
while (true)
|
||||
{
|
||||
const char *arg = va_arg(ap, const char *);
|
||||
|
||||
if (arg == NULL) break;
|
||||
|
||||
_list.push_back(std::string(arg));
|
||||
}
|
||||
|
||||
init_class();
|
||||
}
|
||||
|
||||
Restriction(Kind kind, Numeral num,
|
||||
const struct Pair first, ...)
|
||||
: _kind(kind), _bounds(B_MAPS), _numeral(num), _unit(""),
|
||||
_init(-1), _fini(-1), _step(-1)
|
||||
{
|
||||
_map_from_usr.insert(MapPair(Value(first.pretty), Value(first.value)));
|
||||
_map_from_cfg.insert(MapPair(Value(first.value), Value(first.pretty)));
|
||||
|
||||
va_list ap;
|
||||
va_start(ap, first);
|
||||
|
||||
while (true)
|
||||
{
|
||||
Pair arg = va_arg(ap, Pair);
|
||||
|
||||
if (arg.pretty == NULL) break;
|
||||
|
||||
_map_from_usr.insert(MapPair(Value(arg.pretty), Value(arg.value)));
|
||||
_map_from_cfg.insert(MapPair(Value(arg.value), Value(arg.pretty)));
|
||||
}
|
||||
|
||||
init_class();
|
||||
}
|
||||
|
||||
Restriction(Kind kind, Numeral num, List list)
|
||||
: _kind(kind), _bounds(B_LIST), _numeral(num), _unit(""),
|
||||
_init(-1), _fini(-1), _step(-1), _list(list)
|
||||
{
|
||||
init_class();
|
||||
}
|
||||
|
||||
Restriction(Kind kind, Numeral num, ListMap map)
|
||||
: _kind(kind), _bounds(B_MAPS), _numeral(num), _unit(""),
|
||||
_init(-1), _fini(-1), _step(-1)
|
||||
{
|
||||
for (ListMap::iterator i = map.begin(); i != map.end(); i++)
|
||||
{
|
||||
_map_from_usr.insert(MapPair(Value((*i).first), Value((*i).second)));
|
||||
_map_from_cfg.insert(MapPair(Value((*i).second), Value((*i).first)));
|
||||
}
|
||||
|
||||
init_class();
|
||||
}
|
||||
|
||||
Kind kind() { return _kind; };
|
||||
Bounds bounds() { return _bounds; };
|
||||
Numeral numeral() { return _numeral; };
|
||||
|
||||
Value unit() { return _unit; };
|
||||
|
||||
bool set(Format, Vector &);
|
||||
bool set(Format, Value &);
|
||||
|
||||
bool get(Format, Vector &);
|
||||
bool get(Format, Value &);
|
||||
|
||||
void allowed(Vector &);
|
||||
|
||||
private:
|
||||
bool process(Format, const Value &, Value &);
|
||||
bool unprocess(Format, const Value &, Value &);
|
||||
void init_class();
|
||||
|
||||
bool equalNumber(const double, const double);
|
||||
|
||||
protected:
|
||||
Kind _kind;
|
||||
Bounds _bounds;
|
||||
Numeral _numeral;
|
||||
|
||||
Value _unit;
|
||||
|
||||
double _init, _fini, _step;
|
||||
|
||||
Map _map_from_usr,
|
||||
_map_from_cfg;
|
||||
|
||||
List _list;
|
||||
|
||||
Generic _value;
|
||||
};
|
||||
|
||||
#endif /* _CONFIG_RESTRICTION_HPP_ */
|
||||
@@ -0,0 +1,130 @@
|
||||
/*
|
||||
KHOMP generic endpoint/channel library.
|
||||
Copyright (C) 2007-2009 Khomp Ind. & Com.
|
||||
|
||||
The contents of this file are subject to the Mozilla Public License Version 1.1
|
||||
(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.mozilla.org/MPL/
|
||||
|
||||
Software distributed under the License is distributed on an "AS IS" basis,
|
||||
WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
|
||||
the specific language governing rights and limitations under the License.
|
||||
|
||||
Alternatively, the contents of this file may be used under the terms of the
|
||||
"GNU Lesser General Public License 2.1" license (the “LGPL" License), in which
|
||||
case the provisions of "LGPL License" are applicable instead of those above.
|
||||
|
||||
If you wish to allow use of your version of this file only under the terms of
|
||||
the LGPL License and not to allow others to use your version of this file under
|
||||
the MPL, indicate your decision by deleting the provisions above and replace them
|
||||
with the notice and other provisions required by the LGPL License. If you do not
|
||||
delete the provisions above, a recipient may use your version of this file under
|
||||
either the MPL or the LGPL License.
|
||||
|
||||
The LGPL header follows below:
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this library; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
*/
|
||||
|
||||
#include <configurator/section.hpp>
|
||||
|
||||
void Section::options(Section::OptionVector & vec)
|
||||
{
|
||||
for (OptionMap::iterator it = _options.begin(); it != _options.end();)
|
||||
{
|
||||
vec.push_back(&((*it).second));
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
void Section::sections(Section::SectionVector & vec)
|
||||
{
|
||||
for (SectionMap::iterator it = _sections.begin(); it != _sections.end();)
|
||||
{
|
||||
vec.push_back((*it).second);
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
/*********/
|
||||
|
||||
Option * Section::option_find(std::string & str, bool recurse)
|
||||
{
|
||||
OptionMap::iterator i = _options.find(str);
|
||||
|
||||
if (i == _options.end())
|
||||
{
|
||||
if (!recurse)
|
||||
throw not_found();
|
||||
|
||||
for (SectionMap::iterator i = _sections.begin(); i != _sections.end(); i++)
|
||||
{
|
||||
try
|
||||
{
|
||||
return i->second->option_find(str, recurse);
|
||||
}
|
||||
catch (not_found & e)
|
||||
{
|
||||
/* keep looping! */
|
||||
};
|
||||
}
|
||||
|
||||
throw not_found();
|
||||
}
|
||||
|
||||
return &((*i).second);
|
||||
}
|
||||
|
||||
Option * Section::option_find(const char * str, bool recurse)
|
||||
{
|
||||
std::string sstr(str);
|
||||
return option_find(sstr, recurse);
|
||||
}
|
||||
|
||||
/*********/
|
||||
|
||||
Section * Section::section_find(std::string & str, bool recurse)
|
||||
{
|
||||
SectionMap::iterator i = _sections.find(str);
|
||||
|
||||
if (i == _sections.end())
|
||||
{
|
||||
if (!recurse)
|
||||
throw not_found();
|
||||
|
||||
for (SectionMap::iterator i = _sections.begin(); i != _sections.end(); i++)
|
||||
{
|
||||
try
|
||||
{
|
||||
return i->second->section_find(str, recurse);
|
||||
}
|
||||
catch (not_found & e)
|
||||
{
|
||||
/* keep looping! */
|
||||
};
|
||||
}
|
||||
|
||||
throw not_found();
|
||||
}
|
||||
|
||||
return ((*i).second);
|
||||
}
|
||||
|
||||
Section * Section::section_find(const char * str, bool recurse)
|
||||
{
|
||||
std::string sstr(str);
|
||||
return section_find(sstr, recurse);
|
||||
}
|
||||
@@ -0,0 +1,226 @@
|
||||
/*
|
||||
KHOMP generic endpoint/channel library.
|
||||
Copyright (C) 2007-2009 Khomp Ind. & Com.
|
||||
|
||||
The contents of this file are subject to the Mozilla Public License Version 1.1
|
||||
(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.mozilla.org/MPL/
|
||||
|
||||
Software distributed under the License is distributed on an "AS IS" basis,
|
||||
WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
|
||||
the specific language governing rights and limitations under the License.
|
||||
|
||||
Alternatively, the contents of this file may be used under the terms of the
|
||||
"GNU Lesser General Public License 2.1" license (the “LGPL" License), in which
|
||||
case the provisions of "LGPL License" are applicable instead of those above.
|
||||
|
||||
If you wish to allow use of your version of this file only under the terms of
|
||||
the LGPL License and not to allow others to use your version of this file under
|
||||
the MPL, indicate your decision by deleting the provisions above and replace them
|
||||
with the notice and other provisions required by the LGPL License. If you do not
|
||||
delete the provisions above, a recipient may use your version of this file under
|
||||
either the MPL or the LGPL License.
|
||||
|
||||
The LGPL header follows below:
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this library; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
*/
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
|
||||
#include <configurator/option.hpp>
|
||||
|
||||
#ifndef _CONFIG_SECTION_HPP_
|
||||
#define _CONFIG_SECTION_HPP_
|
||||
|
||||
struct Section
|
||||
{
|
||||
typedef std::map < std::string, Option > OptionMap;
|
||||
typedef std::vector< Option * > OptionVector;
|
||||
|
||||
typedef std::map < std::string, Section * > SectionMap;
|
||||
typedef std::vector < Section * > SectionVector;
|
||||
|
||||
struct not_found {}; /* exception */
|
||||
|
||||
// protected:
|
||||
Section(std::string name, std::string desc, bool recursive = true)
|
||||
: _name(name), _description(desc), _recursive(recursive) {};
|
||||
|
||||
void add(Option o)
|
||||
{
|
||||
_options.insert(std::pair<std::string,Option>(o.name(), o));
|
||||
};
|
||||
|
||||
void del(std::string name)
|
||||
{
|
||||
_options.erase(name);
|
||||
};
|
||||
|
||||
void add(Section *s)
|
||||
{
|
||||
_sections.insert(std::pair<std::string,Section*>(s->name(), s));
|
||||
};
|
||||
|
||||
public:
|
||||
const std::string & name() { return _name; };
|
||||
const std::string & description() { return _description; };
|
||||
const bool & recursive() { return _recursive; };
|
||||
|
||||
OptionMap::iterator option_begin() { return _options.begin(); };
|
||||
OptionMap::iterator option_end() { return _options.end(); };
|
||||
|
||||
SectionMap::iterator section_begin() { return _sections.begin(); };
|
||||
SectionMap::iterator section_end() { return _sections.end(); };
|
||||
|
||||
/**/
|
||||
|
||||
Option * option_find(const char *, bool recurse = false);
|
||||
Section * section_find(const char *, bool recurse = false);
|
||||
|
||||
Option * option_find(std::string &, bool recurse = false);
|
||||
Section * section_find(std::string &, bool recurse = false);
|
||||
|
||||
/**/
|
||||
|
||||
void options(OptionVector &);
|
||||
void sections(SectionVector &);
|
||||
|
||||
/**/
|
||||
|
||||
template <typename F>
|
||||
bool search_and_apply(std::string &key, std::string &value, F f)
|
||||
{
|
||||
OptionMap::iterator i = _options.find(key);
|
||||
|
||||
if (i != _options.end())
|
||||
return f((*i).second);
|
||||
|
||||
if (!_recursive)
|
||||
return false;
|
||||
|
||||
return (find_if(_sections.begin(), _sections.end(), f) != _sections.end());
|
||||
}
|
||||
|
||||
private:
|
||||
struct key_value
|
||||
{
|
||||
key_value(std::string &k, std::string &v): _k(k), _v(v) {};
|
||||
std::string & _k, & _v;
|
||||
};
|
||||
|
||||
struct load_section: protected key_value
|
||||
{
|
||||
load_section(std::string &k, std::string &v): key_value(k,v) {};
|
||||
|
||||
bool operator()(Option &o) { return o.load(_v); };
|
||||
bool operator()(SectionMap::value_type &v) { return v.second->load(_k,_v); };
|
||||
};
|
||||
|
||||
struct change_section: protected key_value
|
||||
{
|
||||
change_section(std::string &k, std::string &v): key_value(k,v) {};
|
||||
|
||||
bool operator()(Option &o) { return o.change(_v); };
|
||||
bool operator()(SectionMap::value_type &v) { return v.second->change(_k,_v); };
|
||||
};
|
||||
|
||||
struct store_section: protected key_value
|
||||
{
|
||||
store_section(std::string &k, std::string &v): key_value(k,v) {};
|
||||
|
||||
bool operator()(Option &o) { return o.store(_v); };
|
||||
bool operator()(SectionMap::value_type &v) { return v.second->store(_k,_v); };
|
||||
};
|
||||
|
||||
struct set_section: protected key_value
|
||||
{
|
||||
set_section(std::string &k, std::string &v): key_value(k,v) {};
|
||||
|
||||
bool operator()(Option &o) { return (o.set(_v))[Option::F_ADJUSTED]; };
|
||||
bool operator()(SectionMap::value_type &v) { return v.second->set(_k,_v); };
|
||||
};
|
||||
|
||||
struct get_section: protected key_value
|
||||
{
|
||||
get_section(std::string &k, std::string &v): key_value(k,v) {};
|
||||
|
||||
bool operator()(Option &o) { return o.get(_v); };
|
||||
bool operator()(SectionMap::value_type &v) { return v.second->get(_k,_v); };
|
||||
};
|
||||
|
||||
struct modified_section
|
||||
{
|
||||
bool operator()(OptionMap::value_type &v) { return v.second.modified(); };
|
||||
bool operator()(SectionMap::value_type &v) { return v.second->modified(); };
|
||||
};
|
||||
|
||||
public:
|
||||
bool load(const char * key, std::string value)
|
||||
{
|
||||
std::string skey(key);
|
||||
return search_and_apply(skey, value, load_section(skey, value));
|
||||
}
|
||||
|
||||
bool load(std::string &key, std::string &value)
|
||||
{
|
||||
return search_and_apply(key, value, load_section(key, value));
|
||||
}
|
||||
|
||||
bool change(std::string &key, std::string &value)
|
||||
{
|
||||
return search_and_apply(key, value, change_section(key, value));
|
||||
}
|
||||
|
||||
bool store(std::string &key, std::string &value)
|
||||
{
|
||||
return search_and_apply(key, value, store_section(key, value));
|
||||
}
|
||||
|
||||
bool set(std::string &key, std::string &value)
|
||||
{
|
||||
return search_and_apply(key, value, set_section(key, value));
|
||||
}
|
||||
|
||||
bool get(std::string &key, std::string &value)
|
||||
{
|
||||
return search_and_apply(key, value, get_section(key, value));
|
||||
}
|
||||
|
||||
bool modified()
|
||||
{
|
||||
return ((find_if(_options.begin(), _options.end(), modified_section()) != _options.end()) ||
|
||||
(find_if(_sections.begin(), _sections.end(), modified_section()) != _sections.end()));
|
||||
}
|
||||
|
||||
private:
|
||||
Section() {};
|
||||
|
||||
protected:
|
||||
std::string _name;
|
||||
std::string _description;
|
||||
|
||||
OptionMap _options;
|
||||
SectionMap _sections;
|
||||
|
||||
bool _recursive;
|
||||
};
|
||||
|
||||
#endif /* _CONFIG_SECTION_HPP_ */
|
||||
@@ -0,0 +1,102 @@
|
||||
/*
|
||||
KHOMP generic endpoint/channel library.
|
||||
Copyright (C) 2007-2009 Khomp Ind. & Com.
|
||||
|
||||
The contents of this file are subject to the Mozilla Public License Version 1.1
|
||||
(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.mozilla.org/MPL/
|
||||
|
||||
Software distributed under the License is distributed on an "AS IS" basis,
|
||||
WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
|
||||
the specific language governing rights and limitations under the License.
|
||||
|
||||
Alternatively, the contents of this file may be used under the terms of the
|
||||
"GNU Lesser General Public License 2.1" license (the “LGPL" License), in which
|
||||
case the provisions of "LGPL License" are applicable instead of those above.
|
||||
|
||||
If you wish to allow use of your version of this file only under the terms of
|
||||
the LGPL License and not to allow others to use your version of this file under
|
||||
the MPL, indicate your decision by deleting the provisions above and replace them
|
||||
with the notice and other provisions required by the LGPL License. If you do not
|
||||
delete the provisions above, a recipient may use your version of this file under
|
||||
either the MPL or the LGPL License.
|
||||
|
||||
The LGPL header follows below:
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this library; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
*/
|
||||
|
||||
#include <map>
|
||||
|
||||
#include <initializer.hpp>
|
||||
|
||||
#ifndef _FLAGGER_HPP_
|
||||
#define _FLAGGER_HPP_
|
||||
|
||||
template < typename Flag >
|
||||
struct Flagger
|
||||
{
|
||||
protected:
|
||||
struct Bool
|
||||
{
|
||||
Bool(): value(false) {};
|
||||
Bool(bool &v): value(v) {};
|
||||
|
||||
bool value;
|
||||
};
|
||||
|
||||
typedef std::map< Flag, Bool > Map;
|
||||
|
||||
public:
|
||||
typedef Initializer< Flag > InitFlags;
|
||||
|
||||
Flagger() {};
|
||||
|
||||
Flagger(InitFlags flags)
|
||||
{
|
||||
for (typename InitFlags::iterator i = flags.begin(); i != flags.end(); i++)
|
||||
{
|
||||
Flag & flag = (*i);
|
||||
_map[flag].value = true;
|
||||
};
|
||||
};
|
||||
|
||||
void set(Flag elt, bool value = true)
|
||||
{
|
||||
_map[elt].value = value;
|
||||
}
|
||||
|
||||
bool is_set(Flag elt)
|
||||
{
|
||||
return _map[elt].value;
|
||||
}
|
||||
|
||||
Flagger & operator&(Flag elt)
|
||||
{
|
||||
set(elt);
|
||||
return *this;
|
||||
};
|
||||
|
||||
bool operator[](Flag elt)
|
||||
{
|
||||
return is_set(elt);
|
||||
};
|
||||
|
||||
protected:
|
||||
Map _map;
|
||||
};
|
||||
|
||||
#endif /* _FLAGGER_HPP_ */
|
||||
@@ -0,0 +1,331 @@
|
||||
/*
|
||||
KHOMP generic endpoint/channel library.
|
||||
Copyright (C) 2007-2009 Khomp Ind. & Com.
|
||||
|
||||
The contents of this file are subject to the Mozilla Public License Version 1.1
|
||||
(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.mozilla.org/MPL/
|
||||
|
||||
Software distributed under the License is distributed on an "AS IS" basis,
|
||||
WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
|
||||
the specific language governing rights and limitations under the License.
|
||||
|
||||
Alternatively, the contents of this file may be used under the terms of the
|
||||
"GNU Lesser General Public License 2.1" license (the “LGPL" License), in which
|
||||
case the provisions of "LGPL License" are applicable instead of those above.
|
||||
|
||||
If you wish to allow use of your version of this file only under the terms of
|
||||
the LGPL License and not to allow others to use your version of this file under
|
||||
the MPL, indicate your decision by deleting the provisions above and replace them
|
||||
with the notice and other provisions required by the LGPL License. If you do not
|
||||
delete the provisions above, a recipient may use your version of this file under
|
||||
either the MPL or the LGPL License.
|
||||
|
||||
The LGPL header follows below:
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this library; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
*/
|
||||
|
||||
#include "format.hpp"
|
||||
//#include <iostream>
|
||||
|
||||
Format::Format(const char * format_string, bool raise_exception)
|
||||
: _format(format_string), _valid(true), _raise(raise_exception)
|
||||
{
|
||||
initialize(format_string);
|
||||
}
|
||||
|
||||
/*
|
||||
Format::Format(std::string & format_string, bool raise_exception)
|
||||
: _format(NULL), _valid(true), _raise(raise_exception)
|
||||
{
|
||||
initialize(format_string.c_str());
|
||||
}
|
||||
*/
|
||||
|
||||
Format::Format(std::string format_string, bool raise_exception)
|
||||
: _format(format_string), _valid(true), _raise(raise_exception)
|
||||
{
|
||||
initialize(format_string.c_str());
|
||||
}
|
||||
|
||||
void Format::initialize(const char * format_string)
|
||||
{
|
||||
std::string txt;
|
||||
|
||||
const char * ptr = format_string;
|
||||
|
||||
while (*ptr != '\0')
|
||||
{
|
||||
if (*ptr != '%')
|
||||
{
|
||||
txt += *ptr;
|
||||
++ptr;
|
||||
continue;
|
||||
}
|
||||
|
||||
const char * ptr2 = ptr+1;
|
||||
|
||||
if (*ptr2 == '%')
|
||||
{
|
||||
txt += *ptr;
|
||||
|
||||
ptr += 2;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!txt.empty())
|
||||
push_argument(txt, T_LITERAL);
|
||||
|
||||
std::string arg(1, *ptr);
|
||||
|
||||
++ptr;
|
||||
|
||||
bool finished = false;
|
||||
|
||||
short long_count = 0;
|
||||
short short_count = 0;
|
||||
|
||||
while(*ptr != '\0' && !finished)
|
||||
{
|
||||
switch (*ptr)
|
||||
{
|
||||
case ' ':
|
||||
// uncomplete format with ' ', make it a literal.
|
||||
arg += *ptr;
|
||||
push_argument(arg, T_LITERAL);
|
||||
finished = true;
|
||||
break;
|
||||
|
||||
case '%':
|
||||
// uncomplete format with '%', make it a literal and start a new format.
|
||||
push_argument(arg, T_LITERAL);
|
||||
arg += *ptr;
|
||||
break;
|
||||
|
||||
case 'h':
|
||||
short_count = std::min<short>(short_count+1, 2);
|
||||
long_count = 0;
|
||||
arg += *ptr;
|
||||
break;
|
||||
|
||||
case 'l':
|
||||
long_count = std::min<short>(long_count+1, 2);
|
||||
short_count = 0;
|
||||
arg += *ptr;
|
||||
break;
|
||||
|
||||
case 'd':
|
||||
case 'i':
|
||||
arg += *ptr;
|
||||
switch (long_count - short_count)
|
||||
{
|
||||
case 2:
|
||||
push_argument(arg, T_SIGNED_LONG_LONG);
|
||||
break;
|
||||
case 1:
|
||||
push_argument(arg, T_SIGNED_LONG);
|
||||
break;
|
||||
case 0:
|
||||
push_argument(arg, T_SIGNED_INT);
|
||||
break;
|
||||
case -1:
|
||||
push_argument(arg, T_SIGNED_SHORT);
|
||||
break;
|
||||
case -2:
|
||||
push_argument(arg, T_SIGNED_SHORT_SHORT);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
finished = true;
|
||||
break;
|
||||
|
||||
case 'o':
|
||||
case 'u':
|
||||
case 'x':
|
||||
case 'X':
|
||||
arg += *ptr;
|
||||
switch (long_count - short_count)
|
||||
{
|
||||
case 2:
|
||||
push_argument(arg, T_UNSIGNED_LONG_LONG);
|
||||
break;
|
||||
case 1:
|
||||
push_argument(arg, T_UNSIGNED_LONG);
|
||||
break;
|
||||
case 0:
|
||||
push_argument(arg, T_UNSIGNED_INT);
|
||||
break;
|
||||
case -1:
|
||||
push_argument(arg, T_UNSIGNED_SHORT);
|
||||
break;
|
||||
case -2:
|
||||
push_argument(arg, T_UNSIGNED_SHORT_SHORT);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
finished = true;
|
||||
break;
|
||||
|
||||
case 'e':
|
||||
case 'E':
|
||||
case 'f':
|
||||
case 'F':
|
||||
case 'g':
|
||||
case 'G':
|
||||
case 'a':
|
||||
case 'A':
|
||||
arg += *ptr;
|
||||
push_argument(arg, T_FLOAT);
|
||||
finished = true;
|
||||
break;
|
||||
|
||||
case 'c':
|
||||
arg += *ptr;
|
||||
push_argument(arg, T_CHAR);
|
||||
finished = true;
|
||||
break;
|
||||
|
||||
case 's':
|
||||
arg += *ptr;
|
||||
push_argument(arg, T_STRING);
|
||||
finished = true;
|
||||
break;
|
||||
|
||||
case 'p':
|
||||
arg += *ptr;
|
||||
push_argument(arg, T_POINTER);
|
||||
finished = true;
|
||||
break;
|
||||
|
||||
case 'C':
|
||||
case 'S':
|
||||
case 'm':
|
||||
case 'n': // unsupported for now.
|
||||
arg += *ptr;
|
||||
push_argument(arg, T_ANYTHING);
|
||||
finished = true;
|
||||
break;
|
||||
|
||||
default:
|
||||
arg += *ptr;
|
||||
break;
|
||||
}
|
||||
|
||||
++ptr;
|
||||
}
|
||||
|
||||
if (!arg.empty())
|
||||
push_argument(arg, T_LITERAL);
|
||||
}
|
||||
|
||||
if (!txt.empty())
|
||||
push_argument(txt, T_LITERAL);
|
||||
}
|
||||
|
||||
void Format::mark_invalid(std::string & msg)
|
||||
{
|
||||
if (_valid)
|
||||
{
|
||||
_valid = false;
|
||||
|
||||
std::string finalmsg;
|
||||
|
||||
finalmsg += "** INVALID FORMAT: ";
|
||||
finalmsg += msg;
|
||||
finalmsg += " **";
|
||||
|
||||
_result = finalmsg;
|
||||
}
|
||||
}
|
||||
|
||||
void Format::raise_check(void)
|
||||
{
|
||||
if (!_valid && _raise)
|
||||
throw InvalidFormat(_result);
|
||||
}
|
||||
|
||||
bool Format::validity_check(void)
|
||||
{
|
||||
raise_check();
|
||||
|
||||
return _valid;
|
||||
}
|
||||
|
||||
const Format::Argument * Format::next_argument(void)
|
||||
{
|
||||
// std::cerr << "size: " << _args.size() << std::endl;
|
||||
|
||||
while (true)
|
||||
{
|
||||
// std::cerr << "loop size: " << _args.size() << std::endl;
|
||||
|
||||
if (_args.empty())
|
||||
return NULL; // throw NoArgumentLeft();
|
||||
|
||||
const Argument & top = _args.front();
|
||||
|
||||
if (top.type() == T_LITERAL)
|
||||
{
|
||||
// std::cerr << "top type == LITERAL, looping..." << std::endl;
|
||||
_result += top.fmts();
|
||||
pop_argument();
|
||||
}
|
||||
else
|
||||
{
|
||||
// std::cerr << "top type: " << top.type() << std::endl;
|
||||
return ⊤
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Format::pop_argument(void)
|
||||
{
|
||||
_args.pop();
|
||||
}
|
||||
|
||||
void Format::push_argument(std::string & data, Format::Type type)
|
||||
{
|
||||
// std::cerr << "pushing type (" << type << ") with format (" << data << ")" << std::endl;
|
||||
|
||||
_args.push(Argument(data, type));
|
||||
data.clear();
|
||||
}
|
||||
|
||||
std::string Format::str()
|
||||
{
|
||||
if (!validity_check())
|
||||
return _result;
|
||||
|
||||
if (next_argument() == NULL)
|
||||
return _result;
|
||||
|
||||
std::string msg;
|
||||
|
||||
msg += "too few arguments passed for format '";
|
||||
msg += _format;
|
||||
msg += "' (";
|
||||
msg += _format;
|
||||
msg += ")";
|
||||
|
||||
mark_invalid(msg);
|
||||
|
||||
return _result;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,512 @@
|
||||
/*
|
||||
KHOMP generic endpoint/channel library.
|
||||
Copyright (C) 2007-2009 Khomp Ind. & Com.
|
||||
|
||||
The contents of this file are subject to the Mozilla Public License Version 1.1
|
||||
(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.mozilla.org/MPL/
|
||||
|
||||
Software distributed under the License is distributed on an "AS IS" basis,
|
||||
WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
|
||||
the specific language governing rights and limitations under the License.
|
||||
|
||||
Alternatively, the contents of this file may be used under the terms of the
|
||||
"GNU Lesser General Public License 2.1" license (the “LGPL" License), in which
|
||||
case the provisions of "LGPL License" are applicable instead of those above.
|
||||
|
||||
If you wish to allow use of your version of this file only under the terms of
|
||||
the LGPL License and not to allow others to use your version of this file under
|
||||
the MPL, indicate your decision by deleting the provisions above and replace them
|
||||
with the notice and other provisions required by the LGPL License. If you do not
|
||||
delete the provisions above, a recipient may use your version of this file under
|
||||
either the MPL or the LGPL License.
|
||||
|
||||
The LGPL header follows below:
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this library; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
*/
|
||||
|
||||
#ifndef _FORMAT_H_
|
||||
#define _FORMAT_H_
|
||||
|
||||
#include <cstring>
|
||||
#include <cstdlib>
|
||||
#include <typeinfo>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <queue>
|
||||
#include <iostream>
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef WIN32 // WINDOWS
|
||||
#include <KHostSystem.h>
|
||||
#endif
|
||||
|
||||
|
||||
/* macros used for shortening lines and making the code clearer */
|
||||
#define STG(x) (x).str()
|
||||
#define FMT(x) Format(x)
|
||||
|
||||
struct Format
|
||||
{
|
||||
static const unsigned int strings_base_length = 64;
|
||||
static const unsigned int generic_base_length = 64;
|
||||
|
||||
struct InvalidFormat
|
||||
{
|
||||
InvalidFormat(std::string msg) : _msg(msg) {}
|
||||
|
||||
std::string _msg;
|
||||
};
|
||||
|
||||
explicit Format(const char * format_string, bool raise_exception = false);
|
||||
explicit Format(std::string format_string, bool raise_exception = false);
|
||||
|
||||
void initialize(const char *);
|
||||
|
||||
std::string str(void);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
protected:
|
||||
|
||||
enum Type
|
||||
{
|
||||
T_ANYTHING = 1,
|
||||
|
||||
T_SIGNED_SHORT,
|
||||
T_SIGNED_SHORT_SHORT,
|
||||
T_SIGNED_INT,
|
||||
T_SIGNED_LONG,
|
||||
T_SIGNED_LONG_LONG,
|
||||
|
||||
T_UNSIGNED_SHORT,
|
||||
T_UNSIGNED_SHORT_SHORT,
|
||||
T_UNSIGNED_INT,
|
||||
T_UNSIGNED_LONG,
|
||||
T_UNSIGNED_LONG_LONG,
|
||||
|
||||
T_FLOAT,
|
||||
T_CHAR,
|
||||
|
||||
T_POINTER,
|
||||
T_STRING,
|
||||
|
||||
T_LITERAL
|
||||
};
|
||||
|
||||
struct Argument
|
||||
{
|
||||
Argument(std::string fmts, Type type)
|
||||
: _fmts(fmts), _type(type) {};
|
||||
|
||||
Type type(void) const { return _type; }
|
||||
const std::string & fmts(void) const { return _fmts; }
|
||||
|
||||
protected:
|
||||
std::string _fmts;
|
||||
Type _type;
|
||||
};
|
||||
|
||||
typedef std::queue < Argument > ArgumentQueue;
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
public:
|
||||
|
||||
template < typename V >
|
||||
Format & operator%( V value )
|
||||
{
|
||||
if (!validity_check())
|
||||
return *this;
|
||||
|
||||
const Argument * top = next_argument();
|
||||
|
||||
if (top == NULL)
|
||||
{
|
||||
std::string msg;
|
||||
|
||||
msg += "too many arguments passed for format '";
|
||||
msg += _format;
|
||||
msg += "'";
|
||||
|
||||
mark_invalid(msg);
|
||||
}
|
||||
else
|
||||
{
|
||||
char temp[generic_base_length];
|
||||
|
||||
if (!generic_verify(value, top->type()))
|
||||
{
|
||||
std::string msg;
|
||||
|
||||
msg += "type mismatch: got type '";
|
||||
msg += typeid(value).name();
|
||||
msg += "' in format '";
|
||||
msg += top->fmts();
|
||||
msg += "' (";
|
||||
msg += _format;
|
||||
msg += ")";
|
||||
|
||||
mark_invalid(msg);
|
||||
return *this;
|
||||
}
|
||||
|
||||
snprintf(temp, sizeof(temp), top->fmts().c_str(), value);
|
||||
_result += temp;
|
||||
|
||||
pop_argument();
|
||||
}
|
||||
|
||||
raise_check();
|
||||
return *this;
|
||||
}
|
||||
|
||||
template < typename V >
|
||||
Format & operator%( V * value )
|
||||
{
|
||||
if (!validity_check())
|
||||
return *this;
|
||||
|
||||
const Argument * top = next_argument();
|
||||
|
||||
if (top == NULL)
|
||||
{
|
||||
std::string msg;
|
||||
|
||||
msg += "too many arguments passed for format '";
|
||||
msg += _format;
|
||||
msg += "'";
|
||||
|
||||
mark_invalid(msg);
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (top->type())
|
||||
{
|
||||
case T_POINTER:
|
||||
{
|
||||
char temp[generic_base_length];
|
||||
snprintf(temp, sizeof(temp), top->fmts().c_str(), value);
|
||||
_result += temp;
|
||||
break;
|
||||
}
|
||||
|
||||
case T_STRING:
|
||||
{
|
||||
if ((typeid(const char) == typeid(V)) ||
|
||||
(typeid(char) == typeid(V)) ||
|
||||
(typeid(const unsigned char) == typeid(V)) ||
|
||||
(typeid(unsigned char) == typeid(V)) ||
|
||||
(typeid(const void) == typeid(V)) ||
|
||||
(typeid(void) == typeid(V)))
|
||||
{
|
||||
int len = strlen((const char*)value)+strings_base_length+1;
|
||||
|
||||
char * temp = new char[len];
|
||||
|
||||
snprintf(temp, len, top->fmts().c_str(), value);
|
||||
_result += temp;
|
||||
|
||||
delete[] temp;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string msg;
|
||||
|
||||
msg += "type mismatch: got type '";
|
||||
msg += typeid(value).name();
|
||||
msg += "' in string format (";
|
||||
msg += _format;
|
||||
msg += ")";
|
||||
|
||||
mark_invalid(msg);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
std::string msg;
|
||||
|
||||
msg += "type mismatch: got pointer/string type in format '";
|
||||
msg += top->fmts();
|
||||
msg += "' (";
|
||||
msg += _format;
|
||||
msg += ")";
|
||||
|
||||
mark_invalid(msg);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
pop_argument();
|
||||
}
|
||||
|
||||
raise_check();
|
||||
return *this;
|
||||
}
|
||||
|
||||
/*
|
||||
Format & operator%( std::string value )
|
||||
{
|
||||
return operator%(value);
|
||||
}
|
||||
*/
|
||||
|
||||
Format & operator%( const std::string value )
|
||||
{
|
||||
if (!validity_check())
|
||||
return *this;
|
||||
|
||||
const Argument * top = next_argument();
|
||||
|
||||
if (top == NULL)
|
||||
{
|
||||
std::string msg;
|
||||
|
||||
msg += "too many arguments passed for format '";
|
||||
msg += _format;
|
||||
msg += "'";
|
||||
|
||||
mark_invalid(msg);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (top->type() == T_STRING)
|
||||
{
|
||||
int len = value.length()+strings_base_length+1;
|
||||
|
||||
char * temp = new char[len];
|
||||
|
||||
snprintf(temp, len, top->fmts().c_str(), value.c_str());
|
||||
_result += temp;
|
||||
|
||||
delete[] temp;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string msg;
|
||||
|
||||
msg += "type mismatch: got string type in format '";
|
||||
msg += top->fmts();
|
||||
msg += "' (";
|
||||
msg += _format;
|
||||
msg += ")";
|
||||
|
||||
mark_invalid(msg);
|
||||
}
|
||||
|
||||
pop_argument();
|
||||
}
|
||||
|
||||
raise_check();
|
||||
return *this;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
template < typename V >
|
||||
bool number_verify_signed_short( V value )
|
||||
{
|
||||
return
|
||||
((typeid(V) == typeid(short int) ||
|
||||
typeid(V) == typeid(short) ||
|
||||
typeid(V) == typeid(const short int) ||
|
||||
typeid(V) == typeid(const short) ||
|
||||
typeid(V) == typeid(volatile short int) ||
|
||||
typeid(V) == typeid(volatile short)) &&
|
||||
sizeof(V) == sizeof(short));
|
||||
}
|
||||
|
||||
template < typename V >
|
||||
bool number_verify_unsigned_short( V value )
|
||||
{
|
||||
return
|
||||
((typeid(V) == typeid(unsigned short int) ||
|
||||
typeid(V) == typeid(unsigned short) ||
|
||||
typeid(V) == typeid(const unsigned short int) ||
|
||||
typeid(V) == typeid(const unsigned short) ||
|
||||
typeid(V) == typeid(volatile unsigned short int) ||
|
||||
typeid(V) == typeid(volatile unsigned short)) &&
|
||||
sizeof(V) == sizeof(unsigned short));
|
||||
}
|
||||
|
||||
template < typename V >
|
||||
bool number_verify_signed_long( V value )
|
||||
{
|
||||
return
|
||||
((typeid(V) == typeid(long int) ||
|
||||
typeid(V) == typeid(long) ||
|
||||
typeid(V) == typeid(const long int) ||
|
||||
typeid(V) == typeid(const long) ||
|
||||
typeid(V) == typeid(volatile long int) ||
|
||||
typeid(V) == typeid(volatile long)) &&
|
||||
sizeof(V) == sizeof(long));
|
||||
}
|
||||
|
||||
template < typename V >
|
||||
bool number_verify_unsigned_long( V value )
|
||||
{
|
||||
return
|
||||
((typeid(V) == typeid(unsigned long int) ||
|
||||
typeid(V) == typeid(unsigned long) ||
|
||||
typeid(V) == typeid(const unsigned long int) ||
|
||||
typeid(V) == typeid(const unsigned long) ||
|
||||
typeid(V) == typeid(volatile unsigned long int) ||
|
||||
typeid(V) == typeid(volatile unsigned long)) &&
|
||||
sizeof(V) == sizeof(long long));
|
||||
}
|
||||
|
||||
template < typename V >
|
||||
bool number_verify_signed_long_long( V value )
|
||||
{
|
||||
return
|
||||
((typeid(V) == typeid(long long int) ||
|
||||
typeid(V) == typeid(long long) ||
|
||||
typeid(V) == typeid(const long long int) ||
|
||||
typeid(V) == typeid(const long long) ||
|
||||
typeid(V) == typeid(volatile long long) ||
|
||||
typeid(V) == typeid(volatile long long int)) &&
|
||||
sizeof(V) == sizeof(long long));
|
||||
}
|
||||
|
||||
template < typename V >
|
||||
bool number_verify_unsigned_long_long( V value )
|
||||
{
|
||||
return
|
||||
((typeid(V) == typeid(unsigned long long int) ||
|
||||
typeid(V) == typeid(unsigned long long) ||
|
||||
typeid(V) == typeid(const unsigned long long int) ||
|
||||
typeid(V) == typeid(const unsigned long long) ||
|
||||
typeid(V) == typeid(volatile unsigned long long) ||
|
||||
typeid(V) == typeid(volatile unsigned long long int)) &&
|
||||
sizeof(V) == sizeof(unsigned long long));
|
||||
}
|
||||
|
||||
template < typename V >
|
||||
bool number_verify_signed_int( V value )
|
||||
{
|
||||
return
|
||||
(sizeof(V) <= sizeof(int) ||
|
||||
typeid(V) == typeid(int) ||
|
||||
typeid(V) == typeid(const int) ||
|
||||
typeid(V) == typeid(volatile int));
|
||||
}
|
||||
|
||||
template < typename V >
|
||||
bool number_verify_unsigned_int( V value )
|
||||
{
|
||||
return
|
||||
(sizeof(V) <= sizeof(unsigned int) ||
|
||||
typeid(V) == typeid(unsigned int) ||
|
||||
typeid(V) == typeid(const unsigned int) ||
|
||||
typeid(V) == typeid(volatile unsigned int));
|
||||
}
|
||||
|
||||
template < typename V >
|
||||
bool generic_verify( V value, Type type )
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
/* EXCEPTION: consider any number an valid input. */
|
||||
case T_SIGNED_INT:
|
||||
case T_UNSIGNED_INT:
|
||||
return
|
||||
(number_verify_signed_int(value) ||
|
||||
number_verify_unsigned_int(value) ||
|
||||
number_verify_signed_long(value) ||
|
||||
number_verify_unsigned_long(value) ||
|
||||
number_verify_signed_short(value) ||
|
||||
number_verify_unsigned_short(value));
|
||||
|
||||
case T_SIGNED_SHORT_SHORT:
|
||||
return (typeid(V) == typeid(char) || typeid(V) == typeid(const char));
|
||||
|
||||
case T_SIGNED_SHORT:
|
||||
return number_verify_signed_short(value);
|
||||
|
||||
case T_SIGNED_LONG:
|
||||
return number_verify_signed_long(value);
|
||||
|
||||
case T_SIGNED_LONG_LONG:
|
||||
return number_verify_signed_long_long(value);
|
||||
|
||||
case T_UNSIGNED_SHORT_SHORT:
|
||||
return (typeid(V) == typeid(unsigned char) || typeid(V) == typeid(unsigned char));
|
||||
|
||||
case T_UNSIGNED_SHORT:
|
||||
return number_verify_unsigned_short(value);
|
||||
|
||||
case T_UNSIGNED_LONG:
|
||||
return number_verify_unsigned_long(value);
|
||||
|
||||
case T_UNSIGNED_LONG_LONG:
|
||||
return number_verify_unsigned_long_long(value);
|
||||
|
||||
case T_FLOAT:
|
||||
return (typeid(V) == typeid(float)) || (typeid(V) == typeid(double) ||
|
||||
typeid(V) == typeid(const float)) || (typeid(V) == typeid(const double));
|
||||
|
||||
case T_CHAR:
|
||||
return (typeid(V) == typeid(char)) || (typeid(V) == typeid(unsigned char) ||
|
||||
typeid(V) == typeid(const char)) || (typeid(V) == typeid(const unsigned char));
|
||||
|
||||
case T_POINTER:
|
||||
case T_STRING:
|
||||
return false;
|
||||
|
||||
case T_ANYTHING:
|
||||
return true;
|
||||
|
||||
case T_LITERAL:
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
void mark_invalid(std::string &);
|
||||
|
||||
bool validity_check(void);
|
||||
void raise_check(void);
|
||||
|
||||
/*
|
||||
struct NoArgumentLeft
|
||||
{
|
||||
NoArgumentLeft(): empty(0) {};
|
||||
|
||||
unsigned int empty;
|
||||
};
|
||||
*/
|
||||
|
||||
const Argument * next_argument(void);
|
||||
|
||||
void pop_argument(void);
|
||||
void push_argument(std::string & data, Type type);
|
||||
|
||||
private:
|
||||
std::string _format;
|
||||
|
||||
bool _valid;
|
||||
bool _raise;
|
||||
|
||||
std::string _result;
|
||||
ArgumentQueue _args;
|
||||
};
|
||||
|
||||
#endif /* _FORMAT_H_ */
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
KHOMP generic endpoint/channel library.
|
||||
Copyright (C) 2007-2009 Khomp Ind. & Com.
|
||||
|
||||
The contents of this file are subject to the Mozilla Public License Version 1.1
|
||||
(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.mozilla.org/MPL/
|
||||
|
||||
Software distributed under the License is distributed on an "AS IS" basis,
|
||||
WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
|
||||
the specific language governing rights and limitations under the License.
|
||||
|
||||
Alternatively, the contents of this file may be used under the terms of the
|
||||
"GNU Lesser General Public License 2.1" license (the “LGPL" License), in which
|
||||
case the provisions of "LGPL License" are applicable instead of those above.
|
||||
|
||||
If you wish to allow use of your version of this file only under the terms of
|
||||
the LGPL License and not to allow others to use your version of this file under
|
||||
the MPL, indicate your decision by deleting the provisions above and replace them
|
||||
with the notice and other provisions required by the LGPL License. If you do not
|
||||
delete the provisions above, a recipient may use your version of this file under
|
||||
either the MPL or the LGPL License.
|
||||
|
||||
The LGPL header follows below:
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this library; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
*/
|
||||
|
||||
#include "saved_condition.hpp"
|
||||
|
||||
bool SavedCondition::wait(unsigned int msec)
|
||||
{
|
||||
bool ret = true;
|
||||
|
||||
switch_mutex_lock(_mutex);
|
||||
|
||||
if (!_signaled)
|
||||
{
|
||||
/* msec * 1000 = The amount of time in microseconds to wait. */
|
||||
if (switch_thread_cond_timedwait(_condition, _mutex, (switch_interval_time_t)msec * 1000) != 0)
|
||||
ret = false;
|
||||
}
|
||||
|
||||
_signaled = false;
|
||||
|
||||
switch_mutex_unlock(_mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -0,0 +1,136 @@
|
||||
/*
|
||||
KHOMP generic endpoint/channel library.
|
||||
Copyright (C) 2007-2009 Khomp Ind. & Com.
|
||||
|
||||
The contents of this file are subject to the Mozilla Public License Version 1.1
|
||||
(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.mozilla.org/MPL/
|
||||
|
||||
Software distributed under the License is distributed on an "AS IS" basis,
|
||||
WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
|
||||
the specific language governing rights and limitations under the License.
|
||||
|
||||
Alternatively, the contents of this file may be used under the terms of the
|
||||
"GNU Lesser General Public License 2.1" license (the “LGPL" License), in which
|
||||
case the provisions of "LGPL License" are applicable instead of those above.
|
||||
|
||||
If you wish to allow use of your version of this file only under the terms of
|
||||
the LGPL License and not to allow others to use your version of this file under
|
||||
the MPL, indicate your decision by deleting the provisions above and replace them
|
||||
with the notice and other provisions required by the LGPL License. If you do not
|
||||
delete the provisions above, a recipient may use your version of this file under
|
||||
either the MPL or the LGPL License.
|
||||
|
||||
The LGPL header follows below:
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this library; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
*/
|
||||
|
||||
#ifndef _SAVED_CONDITION_
|
||||
#define _SAVED_CONDITION_
|
||||
|
||||
#include <saved_condition.hpp>
|
||||
|
||||
extern "C"
|
||||
{
|
||||
#include <switch.h>
|
||||
}
|
||||
|
||||
struct SavedCondition : public SavedConditionCommon// : public RefCounter < SavedCondition >
|
||||
{
|
||||
typedef switch_thread_cond_t BaseConditionType;
|
||||
typedef switch_mutex_t BaseMutexType;
|
||||
|
||||
SavedCondition(switch_memory_pool_t *pool=NULL):
|
||||
_pool(pool),
|
||||
_can_delete_pool(false)
|
||||
{
|
||||
if(!_pool)
|
||||
{
|
||||
switch_core_new_memory_pool(&_pool);
|
||||
_can_delete_pool = true;
|
||||
}
|
||||
|
||||
switch_thread_cond_create(&_condition, _pool);
|
||||
switch_mutex_init(&_mutex, SWITCH_MUTEX_DEFAULT, _pool);
|
||||
}
|
||||
|
||||
//SavedCondition(const SavedCondition &);
|
||||
~SavedCondition()
|
||||
{
|
||||
switch_thread_cond_destroy(_condition);
|
||||
switch_mutex_destroy(_mutex);
|
||||
|
||||
if(_can_delete_pool)
|
||||
switch_core_destroy_memory_pool(&_pool);
|
||||
}
|
||||
|
||||
void signal(void)
|
||||
{
|
||||
switch_mutex_lock(_mutex);
|
||||
|
||||
_signaled = true;
|
||||
switch_thread_cond_signal(_condition);
|
||||
|
||||
switch_mutex_unlock(_mutex);
|
||||
}
|
||||
|
||||
void broadcast(void)
|
||||
{
|
||||
switch_mutex_lock(_mutex);
|
||||
|
||||
_signaled = true;
|
||||
switch_thread_cond_broadcast(_condition);
|
||||
|
||||
switch_mutex_unlock(_mutex);
|
||||
}
|
||||
|
||||
void wait(void)
|
||||
{
|
||||
switch_mutex_lock(_mutex);
|
||||
|
||||
if (!_signaled)
|
||||
switch_thread_cond_wait(_condition, _mutex);
|
||||
|
||||
_signaled = false;
|
||||
|
||||
switch_mutex_unlock(_mutex);
|
||||
}
|
||||
|
||||
bool wait(unsigned int);
|
||||
|
||||
void reset(void)
|
||||
{
|
||||
switch_mutex_lock(_mutex);
|
||||
|
||||
_signaled = false;
|
||||
|
||||
switch_mutex_unlock(_mutex);
|
||||
}
|
||||
|
||||
BaseMutexType * mutex() { return _mutex; };
|
||||
BaseConditionType * condition() { return _condition; };
|
||||
|
||||
protected:
|
||||
|
||||
BaseConditionType *_condition;
|
||||
BaseMutexType *_mutex;
|
||||
switch_memory_pool_t *_pool;
|
||||
bool _can_delete_pool;
|
||||
};
|
||||
|
||||
#endif /* _SAVED_CONDITION_ */
|
||||
|
||||
@@ -0,0 +1,177 @@
|
||||
/*
|
||||
KHOMP generic endpoint/channel library.
|
||||
Copyright (C) 2007-2009 Khomp Ind. & Com.
|
||||
|
||||
The contents of this file are subject to the Mozilla Public License Version 1.1
|
||||
(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.mozilla.org/MPL/
|
||||
|
||||
Software distributed under the License is distributed on an "AS IS" basis,
|
||||
WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
|
||||
the specific language governing rights and limitations under the License.
|
||||
|
||||
Alternatively, the contents of this file may be used under the terms of the
|
||||
"GNU Lesser General Public License 2.1" license (the “LGPL" License), in which
|
||||
case the provisions of "LGPL License" are applicable instead of those above.
|
||||
|
||||
If you wish to allow use of your version of this file only under the terms of
|
||||
the LGPL License and not to allow others to use your version of this file under
|
||||
the MPL, indicate your decision by deleting the provisions above and replace them
|
||||
with the notice and other provisions required by the LGPL License. If you do not
|
||||
delete the provisions above, a recipient may use your version of this file under
|
||||
either the MPL or the LGPL License.
|
||||
|
||||
The LGPL header follows below:
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this library; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
*/
|
||||
|
||||
#ifndef _SIMPLE_LOCK_HPP_
|
||||
#define _SIMPLE_LOCK_HPP_
|
||||
|
||||
#include <simple_lock.hpp>
|
||||
|
||||
extern "C"
|
||||
{
|
||||
#include <switch.h>
|
||||
}
|
||||
|
||||
template < typename Implementor >
|
||||
struct SimpleLockBasic: public SimpleLockCommon < Implementor >
|
||||
{
|
||||
typedef SimpleLockCommon < Implementor > Super;
|
||||
typedef typename Super::Result Result;
|
||||
|
||||
typedef switch_mutex_t BaseMutexType;
|
||||
|
||||
SimpleLockBasic(switch_memory_pool_t *pool = NULL)
|
||||
: _pool(pool), _can_delete_pool( (_pool == NULL) )
|
||||
|
||||
{
|
||||
if(!_pool)
|
||||
switch_core_new_memory_pool(&_pool);
|
||||
|
||||
//switch_mutex_init(&_mutex, SWITCH_MUTEX_DEFAULT, _pool);
|
||||
switch_mutex_init(&_mutex, SWITCH_MUTEX_NESTED, _pool);
|
||||
}
|
||||
|
||||
virtual ~SimpleLockBasic()
|
||||
{
|
||||
/* do nothing */
|
||||
};
|
||||
|
||||
void unreference()
|
||||
{
|
||||
switch_mutex_destroy(_mutex);
|
||||
|
||||
if (_can_delete_pool)
|
||||
switch_core_destroy_memory_pool(&_pool);
|
||||
}
|
||||
|
||||
Result trylock()
|
||||
{
|
||||
switch (switch_mutex_trylock(_mutex))
|
||||
{
|
||||
case SWITCH_STATUS_SUCCESS:
|
||||
return Super::SUCCESS;
|
||||
case SWITCH_STATUS_FALSE:
|
||||
case SWITCH_STATUS_TERM:
|
||||
case SWITCH_STATUS_NOTIMPL:
|
||||
case SWITCH_STATUS_MEMERR:
|
||||
case SWITCH_STATUS_GENERR:
|
||||
case SWITCH_STATUS_SOCKERR:
|
||||
case SWITCH_STATUS_NOTFOUND:
|
||||
case SWITCH_STATUS_UNLOAD:
|
||||
case SWITCH_STATUS_NOUNLOAD:
|
||||
case SWITCH_STATUS_NOT_INITALIZED:
|
||||
return Super::FAILURE;
|
||||
//case SWITCH_STATUS_INUSE:
|
||||
default:
|
||||
return Super::ISINUSE;
|
||||
}
|
||||
}
|
||||
|
||||
void unlock()
|
||||
{
|
||||
switch_mutex_unlock(_mutex);
|
||||
}
|
||||
|
||||
BaseMutexType * mutex() { return _mutex; };
|
||||
|
||||
protected:
|
||||
BaseMutexType *_mutex;
|
||||
switch_memory_pool_t *_pool;
|
||||
bool _can_delete_pool;
|
||||
};
|
||||
|
||||
struct SimpleLock: public SimpleLockBasic < SimpleLock >
|
||||
{
|
||||
typedef SimpleLockBasic < SimpleLock > Super;
|
||||
typedef Super::Result Result;
|
||||
|
||||
SimpleLock(switch_memory_pool_t *pool = NULL)
|
||||
: Super(pool) {};
|
||||
|
||||
Result lock()
|
||||
{
|
||||
switch (switch_mutex_lock(_mutex))
|
||||
{
|
||||
case SWITCH_STATUS_SUCCESS:
|
||||
return Super::SUCCESS;
|
||||
case SWITCH_STATUS_FALSE:
|
||||
case SWITCH_STATUS_TERM:
|
||||
case SWITCH_STATUS_NOTIMPL:
|
||||
case SWITCH_STATUS_MEMERR:
|
||||
case SWITCH_STATUS_GENERR:
|
||||
case SWITCH_STATUS_SOCKERR:
|
||||
case SWITCH_STATUS_NOTFOUND:
|
||||
case SWITCH_STATUS_UNLOAD:
|
||||
case SWITCH_STATUS_NOUNLOAD:
|
||||
case SWITCH_STATUS_NOT_INITALIZED:
|
||||
return Super::FAILURE;
|
||||
//case SWITCH_STATUS_INUSE:
|
||||
default:
|
||||
return Super::ISINUSE;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template < unsigned int Retries = 10, unsigned int Interval = 50 >
|
||||
struct SimpleNonBlockLock: public SimpleLockBasic < SimpleNonBlockLock < Retries, Interval > >
|
||||
{
|
||||
typedef SimpleLockBasic < SimpleNonBlockLock < Retries, Interval > > Super;
|
||||
typedef typename Super::Result Result;
|
||||
|
||||
SimpleNonBlockLock(switch_memory_pool_t *pool = NULL)
|
||||
: Super(pool) {};
|
||||
|
||||
inline Result lock()
|
||||
{
|
||||
for (unsigned int i = 0; i < Retries; i++)
|
||||
{
|
||||
Result ret = Super::trylock();
|
||||
|
||||
if (ret != Super::ISINUSE)
|
||||
return ret;
|
||||
|
||||
usleep(Interval * 1000);
|
||||
}
|
||||
|
||||
return Super::ISINUSE;
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* _SIMPLE_LOCK_HPP_ */
|
||||
@@ -0,0 +1,327 @@
|
||||
/*
|
||||
KHOMP generic endpoint/channel library.
|
||||
Copyright (C) 2007-2009 Khomp Ind. & Com.
|
||||
|
||||
The contents of this file are subject to the Mozilla Public License Version 1.1
|
||||
(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.mozilla.org/MPL/
|
||||
|
||||
Software distributed under the License is distributed on an "AS IS" basis,
|
||||
WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
|
||||
the specific language governing rights and limitations under the License.
|
||||
|
||||
Alternatively, the contents of this file may be used under the terms of the
|
||||
"GNU Lesser General Public License 2.1" license (the “LGPL" License), in which
|
||||
case the provisions of "LGPL License" are applicable instead of those above.
|
||||
|
||||
If you wish to allow use of your version of this file only under the terms of
|
||||
the LGPL License and not to allow others to use your version of this file under
|
||||
the MPL, indicate your decision by deleting the provisions above and replace them
|
||||
with the notice and other provisions required by the LGPL License. If you do not
|
||||
delete the provisions above, a recipient may use your version of this file under
|
||||
either the MPL or the LGPL License.
|
||||
|
||||
The LGPL header follows below:
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this library; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
*/
|
||||
|
||||
#ifndef _THREAD_HPP_
|
||||
#define _THREAD_HPP_
|
||||
|
||||
#include <thread.hpp>
|
||||
|
||||
extern "C"
|
||||
{
|
||||
#include <switch.h>
|
||||
}
|
||||
|
||||
struct Thread : ThreadCommon
|
||||
{
|
||||
typedef switch_thread_t BaseThreadType;
|
||||
|
||||
template<typename T, typename R, typename A>
|
||||
struct ThreadData : ThreadDataCommon
|
||||
{
|
||||
ThreadData(T data, A arg) : _data(data), _arg(arg) {}
|
||||
|
||||
int run()
|
||||
{
|
||||
return _data(_arg);
|
||||
}
|
||||
|
||||
T _data;
|
||||
A _arg;
|
||||
};
|
||||
|
||||
template<typename T, typename R>
|
||||
struct ThreadData < T, R, void > : ThreadDataCommon
|
||||
{
|
||||
ThreadData(T data) : _data(data) {}
|
||||
|
||||
int run()
|
||||
{
|
||||
return _data();
|
||||
}
|
||||
|
||||
T _data;
|
||||
};
|
||||
|
||||
template<typename T, typename A>
|
||||
struct ThreadData < T, void, A > : ThreadDataCommon
|
||||
{
|
||||
ThreadData(T data, A arg) : _data(data), _arg(arg) {}
|
||||
|
||||
int run()
|
||||
{
|
||||
_data(_arg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
T _data;
|
||||
A _arg;
|
||||
};
|
||||
|
||||
|
||||
template<typename T>
|
||||
struct ThreadData < T, void, void > : ThreadDataCommon
|
||||
{
|
||||
ThreadData(T data) : _data(data) {}
|
||||
|
||||
int run()
|
||||
{
|
||||
_data();
|
||||
return 0;
|
||||
}
|
||||
|
||||
T _data;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
Thread(T obj, switch_memory_pool_t *pool=NULL) :
|
||||
_thread_info(new ThreadData<T, typename DecomposeFunction<T>::Return, void>(obj)),
|
||||
_pool(pool),
|
||||
_can_delete_pool(false)
|
||||
{
|
||||
if(!_pool)
|
||||
{
|
||||
switch_core_new_memory_pool(&_pool);
|
||||
_can_delete_pool = true;
|
||||
}
|
||||
|
||||
_thread_info->_thread = this;
|
||||
_thread_info->_self = NULL;
|
||||
_thread_info->_attribute = NULL;
|
||||
|
||||
if(switch_threadattr_create(
|
||||
(switch_threadattr_t **)&_thread_info->_attribute, _pool) != 0)
|
||||
{
|
||||
_thread_info->_attribute = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
switch_threadattr_stacksize_set(
|
||||
(switch_threadattr_t *)_thread_info->_attribute,
|
||||
SWITCH_THREAD_STACKSIZE);
|
||||
|
||||
if(!priority())
|
||||
{
|
||||
_thread_info->_attribute = NULL;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
template<typename T, typename A>
|
||||
Thread(T obj, A arg, switch_memory_pool_t *pool=NULL) :
|
||||
_thread_info(new ThreadData<T, typename DecomposeFunction<T>::Return, A>(obj, arg)),
|
||||
_pool(pool),
|
||||
_can_delete_pool(false)
|
||||
{
|
||||
if(!_pool)
|
||||
{
|
||||
switch_core_new_memory_pool(&_pool);
|
||||
_can_delete_pool = true;
|
||||
}
|
||||
|
||||
_thread_info->_thread = this;
|
||||
_thread_info->_self = NULL;
|
||||
_thread_info->_attribute = NULL;
|
||||
|
||||
if(switch_threadattr_create(
|
||||
(switch_threadattr_t **)&_thread_info->_attribute, _pool) != 0)
|
||||
{
|
||||
_thread_info->_attribute = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
switch_threadattr_stacksize_set(
|
||||
(switch_threadattr_t *)_thread_info->_attribute,
|
||||
SWITCH_THREAD_STACKSIZE);
|
||||
|
||||
if(!priority())
|
||||
{
|
||||
_thread_info->_attribute = NULL;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
~Thread()
|
||||
{
|
||||
if(_thread_info)
|
||||
delete _thread_info;
|
||||
|
||||
if (_can_delete_pool)
|
||||
switch_core_destroy_memory_pool(&_pool);
|
||||
}
|
||||
|
||||
void detach(bool d = true)
|
||||
{
|
||||
if(!_thread_info->_attribute)
|
||||
return;
|
||||
|
||||
/* Non-zero if detached threads should be created. */
|
||||
switch_threadattr_detach_set(
|
||||
(switch_threadattr_t *)_thread_info->_attribute, d ? 1 : 0);
|
||||
}
|
||||
|
||||
bool start()
|
||||
{
|
||||
if(!_pool || !_thread_info->_attribute)
|
||||
return false;
|
||||
|
||||
switch_thread_create((switch_thread_t**)&_thread_info->_self,
|
||||
(switch_threadattr_t *)_thread_info->_attribute,
|
||||
run,
|
||||
_thread_info,
|
||||
_pool);
|
||||
|
||||
if(!_thread_info->_self)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int join()
|
||||
{
|
||||
/*
|
||||
* block until the desired thread stops executing.
|
||||
* @param retval The return value from the dead thread.
|
||||
* @param thd The thread to join
|
||||
*
|
||||
* SWITCH_DECLARE(switch_status_t) switch_thread_join(switch_status_t *retval, switch_thread_t *thd);
|
||||
*/
|
||||
|
||||
if(!_thread_info->_self)
|
||||
return -2;
|
||||
|
||||
int retval = 0;
|
||||
|
||||
if(switch_thread_join((switch_status_t*)&retval,
|
||||
(switch_thread_t *)_thread_info->_self) != 0)
|
||||
return -1;
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
BaseThreadType * self()
|
||||
{
|
||||
//switch_thread_self();
|
||||
//apr_os_thread_current();
|
||||
return (BaseThreadType *)_thread_info->_self;
|
||||
}
|
||||
|
||||
private:
|
||||
void exit(int status)
|
||||
{
|
||||
/**
|
||||
* stop the current thread
|
||||
* @param thd The thread to stop
|
||||
* @param retval The return value to pass back to any thread that cares
|
||||
*/
|
||||
//SWITCH_DECLARE(switch_status_t) switch_thread_exit(switch_thread_t *thd, switch_status_t retval);
|
||||
switch_thread_exit((switch_thread_t *)_thread_info->_self, (switch_status_t)status);
|
||||
|
||||
}
|
||||
|
||||
#ifndef WIN32
|
||||
struct apr_threadattr_t {
|
||||
apr_pool_t *pool;
|
||||
pthread_attr_t attr;
|
||||
};
|
||||
#endif
|
||||
|
||||
bool priority()
|
||||
{
|
||||
#ifndef WIN32
|
||||
struct sched_param param;
|
||||
|
||||
struct apr_threadattr_t *myattr = (struct apr_threadattr_t *)_thread_info->_attribute;
|
||||
|
||||
if (pthread_attr_setschedpolicy(
|
||||
(pthread_attr_t *)&myattr->attr, SCHED_RR) < 0)
|
||||
return false;
|
||||
|
||||
if (pthread_attr_getschedparam(
|
||||
(pthread_attr_t *)&myattr->attr, ¶m) < 0)
|
||||
return false;
|
||||
|
||||
param.sched_priority = sched_get_priority_max(SCHED_RR);
|
||||
|
||||
if (pthread_attr_setschedparam(
|
||||
(pthread_attr_t *)&myattr->attr, ¶m) < 0)
|
||||
return false;
|
||||
|
||||
#endif
|
||||
return true;
|
||||
|
||||
/*
|
||||
//BUG in Freeswitch
|
||||
if(switch_threadattr_priority_increase(
|
||||
(switch_threadattr_t *)_thread_info->_attribute) != 0)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
protected:
|
||||
ThreadDataCommon * _thread_info;
|
||||
switch_memory_pool_t *_pool;
|
||||
bool _can_delete_pool;
|
||||
|
||||
protected:
|
||||
|
||||
static void *SWITCH_THREAD_FUNC run(BaseThreadType *thread, void * obj)
|
||||
{
|
||||
//switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG,
|
||||
// "Starting new Thread\n");
|
||||
|
||||
ThreadDataCommon * data = (ThreadDataCommon *)obj;
|
||||
int retval = data->run();
|
||||
|
||||
//switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG,
|
||||
// "Stopping new Thread = %d\n", retval);
|
||||
|
||||
((Thread *)(data->_thread))->exit(retval);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif /* _THREAD_HPP_ */
|
||||
@@ -0,0 +1,337 @@
|
||||
/*
|
||||
KHOMP generic endpoint/channel library.
|
||||
Copyright (C) 2007-2009 Khomp Ind. & Com.
|
||||
|
||||
The contents of this file are subject to the Mozilla Public License Version 1.1
|
||||
(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.mozilla.org/MPL/
|
||||
|
||||
Software distributed under the License is distributed on an "AS IS" basis,
|
||||
WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
|
||||
the specific language governing rights and limitations under the License.
|
||||
|
||||
Alternatively, the contents of this file may be used under the terms of the
|
||||
"GNU Lesser General Public License 2.1" license (the "LGPL" License), in which
|
||||
case the provisions of "LGPL License" are applicable instead of those above.
|
||||
|
||||
If you wish to allow use of your version of this file only under the terms of
|
||||
the LGPL License and not to allow others to use your version of this file under
|
||||
the MPL, indicate your decision by deleting the provisions above and replace them
|
||||
with the notice and other provisions required by the LGPL License. If you do not
|
||||
delete the provisions above, a recipient may use your version of this file under
|
||||
either the MPL or the LGPL License.
|
||||
|
||||
The LGPL header follows below:
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this library; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
*/
|
||||
|
||||
#include <refcounter.hpp>
|
||||
|
||||
#ifndef _FUNCTION_HPP_
|
||||
#define _FUNCTION_HPP_
|
||||
|
||||
namespace Function
|
||||
{
|
||||
struct EmptyFunction {};
|
||||
|
||||
/**/
|
||||
|
||||
template < typename FunctionTraits >
|
||||
struct StorageBase: NEW_REFCOUNTER(StorageBase < FunctionTraits >)
|
||||
{
|
||||
typedef typename FunctionTraits::BaseType BaseType;
|
||||
|
||||
typedef typename FunctionTraits::FunType FunType;
|
||||
typedef typename FunctionTraits::ObjType ObjType;
|
||||
|
||||
template < typename Functor >
|
||||
StorageBase(Functor f)
|
||||
: _object(reinterpret_cast<ObjType>(new Functor(f))),
|
||||
_function(reinterpret_cast<FunType>(&(Functor::operator()))),
|
||||
_malloced(true)
|
||||
{};
|
||||
|
||||
template < typename Functor >
|
||||
StorageBase(Functor & f, bool malloced)
|
||||
: _object(reinterpret_cast<ObjType>((malloced ? new Functor(f) : &f))),
|
||||
_function(reinterpret_cast<FunType>(&(Functor::operator()))),
|
||||
_malloced(malloced)
|
||||
{};
|
||||
|
||||
StorageBase()
|
||||
: _object(reinterpret_cast<ObjType>(0)),
|
||||
_function(reinterpret_cast<FunType>(0)),
|
||||
_malloced(false)
|
||||
{};
|
||||
|
||||
StorageBase(const StorageBase & o)
|
||||
: INC_REFCOUNTER(o, StorageBase < FunctionTraits >),
|
||||
_object(o._object), _function(o._function), _malloced(o._malloced)
|
||||
{};
|
||||
|
||||
virtual ~StorageBase() {};
|
||||
|
||||
void unreference()
|
||||
{
|
||||
// TODO: will this work if we delete a different type? //
|
||||
if (_malloced)
|
||||
delete _object;
|
||||
};
|
||||
|
||||
template < typename Functor >
|
||||
void operator=(Functor f)
|
||||
{
|
||||
_object = reinterpret_cast<ObjType>(new Functor(f)),
|
||||
_function = reinterpret_cast<FunType>(&(Functor::operator()));
|
||||
_malloced = false;
|
||||
}
|
||||
|
||||
protected:
|
||||
ObjType _object;
|
||||
FunType _function;
|
||||
bool _malloced;
|
||||
};
|
||||
|
||||
/**/
|
||||
|
||||
template < typename R >
|
||||
struct VTable0
|
||||
{
|
||||
R operator()(void) { return R(); };
|
||||
};
|
||||
|
||||
template < >
|
||||
struct VTable0< void >
|
||||
{
|
||||
void operator()(void) { return; };
|
||||
};
|
||||
|
||||
template < typename R >
|
||||
struct Function0Traits
|
||||
{
|
||||
typedef VTable0<R> BaseType;
|
||||
|
||||
typedef R (BaseType::* FunType)(void);
|
||||
typedef BaseType * ObjType;
|
||||
};
|
||||
|
||||
/**/
|
||||
|
||||
template < typename R, typename A0 >
|
||||
struct VTable1
|
||||
{
|
||||
R operator()(A0 a0) { return R(); };
|
||||
};
|
||||
|
||||
template < typename A0 >
|
||||
struct VTable1< void, A0 >
|
||||
{
|
||||
void operator()(A0 a0) { return; };
|
||||
};
|
||||
|
||||
template < typename R, typename A0 >
|
||||
struct Function1Traits
|
||||
{
|
||||
typedef VTable1<R, A0> BaseType;
|
||||
|
||||
typedef R (BaseType::* FunType)(A0);
|
||||
typedef BaseType * ObjType;
|
||||
};
|
||||
|
||||
/**/
|
||||
|
||||
template < typename R, typename A0, typename A1 >
|
||||
struct VTable2
|
||||
{
|
||||
R operator()(A0 a0, A1) { return R(); };
|
||||
};
|
||||
|
||||
template < typename A0, typename A1 >
|
||||
struct VTable2< void, A0, A1 >
|
||||
{
|
||||
void operator()(A0 a0, A1 a1) { return; };
|
||||
};
|
||||
|
||||
template < typename R, typename A0, typename A1 >
|
||||
struct Function2Traits
|
||||
{
|
||||
typedef VTable2<R, A0, A1> BaseType;
|
||||
|
||||
typedef R (BaseType::* FunType)(A0, A1);
|
||||
typedef BaseType * ObjType;
|
||||
};
|
||||
|
||||
/**/
|
||||
|
||||
template < typename R, typename A0, typename A1, typename A2 >
|
||||
struct VTable3
|
||||
{
|
||||
R operator()(A0 a0, A1 a1, A2 a2) { return R(); };
|
||||
};
|
||||
|
||||
template < typename A0, typename A1, typename A2 >
|
||||
struct VTable3< void, A0, A1, A2 >
|
||||
{
|
||||
void operator()(A0 a0, A1 a1, A2 a2) { return; };
|
||||
};
|
||||
|
||||
template < typename R, typename A0, typename A1, typename A2 >
|
||||
struct Function3Traits
|
||||
{
|
||||
typedef VTable3<R, A0, A1, A2> BaseType;
|
||||
|
||||
typedef R (BaseType::* FunType)(A0, A1, A2);
|
||||
typedef BaseType * ObjType;
|
||||
};
|
||||
|
||||
/**/
|
||||
|
||||
template < typename R, typename A0, typename A1, typename A2, typename A3 >
|
||||
struct VTable4
|
||||
{
|
||||
R operator()(A0 a0, A1 a1, A2 a2, A3 a3) { return R(); };
|
||||
};
|
||||
|
||||
template < typename A0, typename A1, typename A2, typename A3 >
|
||||
struct VTable4< void, A0, A1, A2, A3 >
|
||||
{
|
||||
void operator()(A0 a0, A1 a1, A2 a2, A3 a3) { return; };
|
||||
};
|
||||
|
||||
template < typename R, typename A0, typename A1, typename A2, typename A3 >
|
||||
struct Function4Traits
|
||||
{
|
||||
typedef VTable4<R, A0, A1, A2, A3> BaseType;
|
||||
|
||||
typedef R (BaseType::* FunType)(A0, A1, A2, A3);
|
||||
typedef BaseType * ObjType;
|
||||
};
|
||||
|
||||
/**/
|
||||
|
||||
template < typename R, typename A0 >
|
||||
struct Function0 : public StorageBase < Function0Traits < R > >
|
||||
{
|
||||
typedef StorageBase < Function0Traits < R > > Storage;
|
||||
|
||||
template < typename Functor >
|
||||
Function0(Functor f): Storage(f) {};
|
||||
|
||||
template < typename Functor >
|
||||
Function0(Functor & f, bool m): Storage(f, m) {};
|
||||
|
||||
Function0() {};
|
||||
|
||||
R operator()(void)
|
||||
{
|
||||
if (reinterpret_cast<void *>(Storage::_object) == 0)
|
||||
throw EmptyFunction();
|
||||
|
||||
return ((Storage::_object)->*(Storage::_function))();
|
||||
}
|
||||
};
|
||||
|
||||
template < typename R, typename A0 >
|
||||
struct Function1 : public StorageBase < Function1Traits < R, A0 > >
|
||||
{
|
||||
typedef StorageBase < Function1Traits < R, A0 > > Storage;
|
||||
|
||||
template < typename Functor >
|
||||
Function1(Functor f): Storage(f) {};
|
||||
|
||||
template < typename Functor >
|
||||
Function1(Functor & f, bool m): Storage(f, m) {};
|
||||
|
||||
Function1() {};
|
||||
|
||||
R operator()(A0 a0)
|
||||
{
|
||||
if (reinterpret_cast<void *>(Storage::_object) == 0)
|
||||
throw EmptyFunction();
|
||||
|
||||
return ((Storage::_object)->*(Storage::_function))(a0);
|
||||
}
|
||||
};
|
||||
|
||||
template < typename R, typename A0, typename A1 >
|
||||
struct Function2 : public StorageBase < Function2Traits < R, A0, A1 > >
|
||||
{
|
||||
typedef StorageBase < Function2Traits < R, A0, A1 > > Storage;
|
||||
|
||||
template < typename Functor >
|
||||
Function2(Functor f): Storage(f) {};
|
||||
|
||||
template < typename Functor >
|
||||
Function2(Functor & f, bool m): Storage(f, m) {};
|
||||
|
||||
Function2() {};
|
||||
|
||||
R operator()(A0 a0, A1 a1)
|
||||
{
|
||||
if (reinterpret_cast<void *>(Storage::_object) == 0)
|
||||
throw EmptyFunction();
|
||||
|
||||
return ((Storage::_object)->*(Storage::_function))(a0, a1);
|
||||
}
|
||||
};
|
||||
|
||||
template < typename R, typename A0, typename A1, typename A2 >
|
||||
struct Function3 : public StorageBase < Function3Traits < R, A0, A1, A2 > >
|
||||
{
|
||||
typedef StorageBase < Function3Traits < R, A0, A1, A2 > > Storage;
|
||||
|
||||
template < typename Functor >
|
||||
Function3(Functor f): Storage(f) {};
|
||||
|
||||
template < typename Functor >
|
||||
Function3(Functor & f, bool m): Storage(f, m) {};
|
||||
|
||||
Function3() {};
|
||||
|
||||
R operator()(A0 a0, A1 a1, A2 a2)
|
||||
{
|
||||
if (reinterpret_cast<void *>(Storage::_object) == 0)
|
||||
throw EmptyFunction();
|
||||
|
||||
return ((Storage::_object)->*(Storage::_function))(a0, a1, a2);
|
||||
}
|
||||
};
|
||||
|
||||
template < typename R, typename A0, typename A1, typename A2, typename A3 >
|
||||
struct Function4 : public StorageBase < Function4Traits < R, A0, A1, A2, A3 > >
|
||||
{
|
||||
typedef StorageBase < Function4Traits < R, A0, A1, A2, A3 > > Storage;
|
||||
|
||||
template < typename Functor >
|
||||
Function4(Functor f): Storage(f) {};
|
||||
|
||||
template < typename Functor >
|
||||
Function4(Functor & f, bool m): Storage(f, m) {};
|
||||
|
||||
Function4() {};
|
||||
|
||||
R operator()(A0 a0, A1 a1, A2 a2, A3 a3)
|
||||
{
|
||||
if (reinterpret_cast<void *>(Storage::_object) == 0)
|
||||
throw EmptyFunction();
|
||||
|
||||
return ((Storage::_object)->*(Storage::_function))(a0, a1, a2, a3);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
#endif /* _FUNCTION_HPP_ */
|
||||
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
KHOMP generic endpoint/channel library.
|
||||
Copyright (C) 2007-2009 Khomp Ind. & Com.
|
||||
|
||||
The contents of this file are subject to the Mozilla Public License Version 1.1
|
||||
(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.mozilla.org/MPL/
|
||||
|
||||
Software distributed under the License is distributed on an "AS IS" basis,
|
||||
WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
|
||||
the specific language governing rights and limitations under the License.
|
||||
|
||||
Alternatively, the contents of this file may be used under the terms of the
|
||||
"GNU Lesser General Public License 2.1" license (the “LGPL" License), in which
|
||||
case the provisions of "LGPL License" are applicable instead of those above.
|
||||
|
||||
If you wish to allow use of your version of this file only under the terms of
|
||||
the LGPL License and not to allow others to use your version of this file under
|
||||
the MPL, indicate your decision by deleting the provisions above and replace them
|
||||
with the notice and other provisions required by the LGPL License. If you do not
|
||||
delete the provisions above, a recipient may use your version of this file under
|
||||
either the MPL or the LGPL License.
|
||||
|
||||
The LGPL header follows below:
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this library; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
*/
|
||||
|
||||
#include <vector>
|
||||
|
||||
#ifndef _INITIALIZER_HPP_
|
||||
#define _INITIALIZER_HPP_
|
||||
|
||||
template < typename Type >
|
||||
struct Initializer: public std::vector< Type >
|
||||
{
|
||||
typedef std::vector< Type > super;
|
||||
|
||||
Initializer(Type e) { push_back(e); };
|
||||
Initializer(Type & e) { push_back(e); };
|
||||
|
||||
Initializer & operator&(Initializer v)
|
||||
{
|
||||
insert(super::end(), v.begin(), v.end());
|
||||
return *this;
|
||||
};
|
||||
|
||||
Initializer & operator&(Initializer & v)
|
||||
{
|
||||
insert(super::end(), v.begin(), v.end());
|
||||
return *this;
|
||||
};
|
||||
|
||||
Initializer & operator&(Type v)
|
||||
{
|
||||
insert(super::end(), v);
|
||||
return *this;
|
||||
};
|
||||
|
||||
Initializer & operator&(Type & v)
|
||||
{
|
||||
insert(super::end(), v);
|
||||
return *this;
|
||||
};
|
||||
};
|
||||
|
||||
#endif /* _INITIALIZER_HPP_ */
|
||||
@@ -0,0 +1,313 @@
|
||||
/*
|
||||
KHOMP generic endpoint/channel library.
|
||||
Copyright (C) 2007-2009 Khomp Ind. & Com.
|
||||
|
||||
The contents of this file are subject to the Mozilla Public License Version 1.1
|
||||
(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.mozilla.org/MPL/
|
||||
|
||||
Software distributed under the License is distributed on an "AS IS" basis,
|
||||
WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
|
||||
the specific language governing rights and limitations under the License.
|
||||
|
||||
Alternatively, the contents of this file may be used under the terms of the
|
||||
"GNU Lesser General Public License 2.1" license (the “LGPL" License), in which
|
||||
case the provisions of "LGPL License" are applicable instead of those above.
|
||||
|
||||
If you wish to allow use of your version of this file only under the terms of
|
||||
the LGPL License and not to allow others to use your version of this file under
|
||||
the MPL, indicate your decision by deleting the provisions above and replace them
|
||||
with the notice and other provisions required by the LGPL License. If you do not
|
||||
delete the provisions above, a recipient may use your version of this file under
|
||||
either the MPL or the LGPL License.
|
||||
|
||||
The LGPL header follows below:
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this library; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
*/
|
||||
|
||||
#include <k3lapi.hpp>
|
||||
|
||||
#include <format.hpp>
|
||||
#include <verbose.hpp>
|
||||
|
||||
K3LAPI::K3LAPI(bool has_exceptions)
|
||||
: _has_exceptions(has_exceptions),
|
||||
_device_count(0), _channel_count(0), _link_count(0),
|
||||
_device_config(0), _channel_config(0), _link_config(0)
|
||||
{};
|
||||
|
||||
/* initialize the whole thing! */
|
||||
|
||||
void K3LAPI::start(void)
|
||||
{
|
||||
/* tie the used k3l to the compiled k3l version */
|
||||
char *ret = k3lStart(k3lApiMajorVersion, k3lApiMinorVersion, 0); //k3lApiBuildVersion);
|
||||
|
||||
if (ret && *ret)
|
||||
throw start_failed(ret);
|
||||
|
||||
/* call init automagically */
|
||||
init();
|
||||
}
|
||||
|
||||
void K3LAPI::stop(void)
|
||||
{
|
||||
k3lStop();
|
||||
fini();
|
||||
}
|
||||
|
||||
/* envio de comandos para placa */
|
||||
|
||||
void K3LAPI::mixer(int32 dev, int32 obj, byte track, KMixerSource src, int32 index)
|
||||
{
|
||||
KMixerCommand mix;
|
||||
|
||||
mix.Track = track;
|
||||
mix.Source = src;
|
||||
mix.SourceIndex = index;
|
||||
|
||||
command(dev, obj, CM_MIXER, (const char *) &mix);
|
||||
}
|
||||
|
||||
void K3LAPI::mixerRecord(int32 dev, int32 obj, byte track, KMixerSource src, int32 index)
|
||||
{
|
||||
/* estes buffers *NAO PODEM SER ESTATICOS*! */
|
||||
char cmd[] = { 0x3f, 0x03, (char)obj, (char)track, 0xff, 0xff };
|
||||
|
||||
switch (src)
|
||||
{
|
||||
case kmsChannel:
|
||||
cmd[4] = 0x05;
|
||||
cmd[5] = (char)index;
|
||||
break;
|
||||
|
||||
case kmsNoDelayChannel:
|
||||
cmd[4] = 0x0a;
|
||||
cmd[5] = (char)index;
|
||||
break;
|
||||
|
||||
case kmsGenerator:
|
||||
cmd[4] = 0x09;
|
||||
|
||||
switch ((KMixerTone)index)
|
||||
{
|
||||
case kmtSilence:
|
||||
cmd[5] = 0x0F;
|
||||
break;
|
||||
case kmtDial:
|
||||
cmd[5] = 0x08;
|
||||
break;
|
||||
case kmtBusy:
|
||||
cmd[5] = 0x0D;
|
||||
break;
|
||||
|
||||
case kmtFax:
|
||||
case kmtVoice:
|
||||
case kmtEndOf425:
|
||||
case kmtCollect:
|
||||
case kmtEndOfDtmf:
|
||||
/* TODO: exception, unable to generate */
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case kmsCTbus:
|
||||
case kmsPlay:
|
||||
/* TODO: exception, not implemented! */
|
||||
break;
|
||||
}
|
||||
|
||||
int32 dsp = get_dsp(dev, DSP_AUDIO);
|
||||
|
||||
raw_command(dev, dsp, cmd, sizeof(cmd));
|
||||
}
|
||||
|
||||
void K3LAPI::mixerCTbus(int32 dev, int32 obj, byte track, KMixerSource src, int32 index)
|
||||
{
|
||||
KMixerCommand mix;
|
||||
|
||||
mix.Track = track;
|
||||
mix.Source = src;
|
||||
mix.SourceIndex = index;
|
||||
|
||||
command(dev, obj, CM_MIXER_CTBUS, (const char *) &mix);
|
||||
}
|
||||
|
||||
void K3LAPI::command(int32 dev, int32 obj, int32 code, std::string & str)
|
||||
{
|
||||
command(dev, obj, code, str.c_str());
|
||||
}
|
||||
|
||||
void K3LAPI::command (int32 dev, int32 obj, int32 code, const char * parms)
|
||||
{
|
||||
K3L_COMMAND cmd;
|
||||
|
||||
cmd.Cmd = code;
|
||||
cmd.Object = obj;
|
||||
cmd.Params = (byte *)parms;
|
||||
|
||||
int32 rc = k3lSendCommand(dev, &cmd);
|
||||
|
||||
if (rc != ksSuccess)
|
||||
throw failed_command(code, dev, obj, rc);
|
||||
}
|
||||
|
||||
void K3LAPI::raw_command(int32 dev, int32 dsp, std::string & str)
|
||||
{
|
||||
raw_command(dev, dsp, str.data(), str.size());
|
||||
}
|
||||
|
||||
void K3LAPI::raw_command(int32 dev, int32 dsp, const char * cmds, int32 size)
|
||||
{
|
||||
std::string str(cmds, size);
|
||||
|
||||
int32 rc = k3lSendRawCommand(dev, dsp, (void *)cmds, size);
|
||||
|
||||
if (rc != ksSuccess)
|
||||
throw failed_raw_command(dev, dsp, rc);
|
||||
}
|
||||
|
||||
KLibraryStatus K3LAPI::get_param(K3L_EVENT *ev, const char *name, std::string &res)
|
||||
{
|
||||
char tmp_param[256];
|
||||
memset((void*)tmp_param, 0, sizeof(tmp_param));
|
||||
|
||||
int32 rc = k3lGetEventParam (ev, (sbyte *)name, (sbyte *)tmp_param, sizeof(tmp_param)-1);
|
||||
|
||||
if (rc != ksSuccess)
|
||||
return (KLibraryStatus)rc;
|
||||
|
||||
res.append(tmp_param, strlen(tmp_param));
|
||||
return ksSuccess;
|
||||
}
|
||||
|
||||
std::string K3LAPI::get_param(K3L_EVENT *ev, const char *name)
|
||||
{
|
||||
std::string res;
|
||||
|
||||
KLibraryStatus rc = get_param(ev, name, res);
|
||||
|
||||
if (rc != ksSuccess)
|
||||
throw get_param_failed(name, rc);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
void K3LAPI::init(void)
|
||||
{
|
||||
if (_device_count != 0) return;
|
||||
|
||||
_device_count = k3lGetDeviceCount();
|
||||
|
||||
_device_type = new KDeviceType[_device_count];
|
||||
_device_config = new device_conf_type[_device_count];
|
||||
_channel_config = new channel_ptr_conf_type[_device_count];
|
||||
_link_config = new link_ptr_conf_type[_device_count];
|
||||
_channel_count = new unsigned int[_device_count];
|
||||
_link_count = new unsigned int[_device_count];
|
||||
|
||||
for (unsigned int dev = 0; dev < _device_count; dev++)
|
||||
{
|
||||
KLibraryStatus ret = ksSuccess;
|
||||
|
||||
_device_type[dev] = (KDeviceType) k3lGetDeviceType(dev);
|
||||
|
||||
/* caches each device config */
|
||||
ret = (KLibraryStatus)k3lGetDeviceConfig(dev, ksoDevice + dev, &(_device_config[dev]), sizeof(_device_config[dev]));
|
||||
|
||||
if (ret != ksSuccess)
|
||||
throw start_failed(STG(FMT("k3lGetDeviceConfig(dev=%d): %s") % dev % Verbose::status(ret)));
|
||||
|
||||
/* adjust channel/link count for device */
|
||||
_channel_count[dev] = _device_config[dev].ChannelCount;
|
||||
_link_count[dev] = _device_config[dev].LinkCount;
|
||||
|
||||
/* caches each channel config */
|
||||
_channel_config[dev] = new channel_conf_type[_channel_count[dev]];
|
||||
|
||||
for (unsigned int obj = 0; obj < _channel_count[dev]; obj++)
|
||||
{
|
||||
ret = (KLibraryStatus)k3lGetDeviceConfig(dev, ksoChannel + obj, &(_channel_config[dev][obj]), sizeof(_channel_config[dev][obj]));
|
||||
|
||||
if (ret != ksSuccess)
|
||||
throw start_failed(STG(FMT("k3lGetDeviceConfig(dev=%d,chan=%d): %s") % dev % obj % Verbose::status(ret)));
|
||||
}
|
||||
|
||||
/* adjust link count for device */
|
||||
_link_count[dev] = _device_config[dev].LinkCount;
|
||||
|
||||
/* caches each link config */
|
||||
_link_config[dev] = new link_conf_type[_link_count[dev]];
|
||||
|
||||
for (unsigned int obj = 0; obj < _link_count[dev]; obj++)
|
||||
{
|
||||
ret = (KLibraryStatus)k3lGetDeviceConfig(dev, ksoLink + obj, &(_link_config[dev][obj]), sizeof(_link_config[dev][obj]));
|
||||
|
||||
if (ret != ksSuccess)
|
||||
throw start_failed(STG(FMT("k3lGetDeviceConfig(dev=%d,link=%d): %s") % dev % obj % Verbose::status(ret)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void K3LAPI::fini(void)
|
||||
{
|
||||
for (unsigned int dev = 0; dev < _device_count; dev++)
|
||||
{
|
||||
if (_channel_config[dev])
|
||||
{
|
||||
delete[] _channel_config[dev];
|
||||
_channel_config[dev] = NULL;
|
||||
}
|
||||
|
||||
if (_link_config[dev])
|
||||
{
|
||||
delete[] _link_config[dev];
|
||||
_link_config[dev] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
_device_count = 0;
|
||||
|
||||
if (_device_type) { delete[] _device_type; _device_type = NULL; }
|
||||
if (_device_config) { delete[] _device_config; _device_config = NULL; }
|
||||
if (_channel_config) { delete[] _channel_config; _channel_config = NULL; }
|
||||
if (_link_config) { delete[] _link_config; _link_config = NULL; }
|
||||
if (_channel_count) { delete[] _channel_count; _channel_count = NULL; }
|
||||
if (_link_count) { delete[] _link_count; _link_count = NULL; }
|
||||
}
|
||||
|
||||
int32 K3LAPI::get_dsp(int32 dev, K3LAPI::DspType type)
|
||||
{
|
||||
switch (device_type(dev))
|
||||
{
|
||||
case kdtFXO:
|
||||
case kdtFXOVoIP:
|
||||
#if K3L_AT_LEAST(1,6,0)
|
||||
case kdtGSM:
|
||||
case kdtGSMSpx:
|
||||
#endif
|
||||
#if K3L_AT_LEAST(2,1,0)
|
||||
case kdtGSMUSB:
|
||||
case kdtGSMUSBSpx:
|
||||
#endif
|
||||
return 0;
|
||||
|
||||
default:
|
||||
return (type == DSP_AUDIO ? 1 : 0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,408 @@
|
||||
/*
|
||||
KHOMP generic endpoint/channel library.
|
||||
Copyright (C) 2007-2009 Khomp Ind. & Com.
|
||||
|
||||
The contents of this file are subject to the Mozilla Public License Version 1.1
|
||||
(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.mozilla.org/MPL/
|
||||
|
||||
Software distributed under the License is distributed on an "AS IS" basis,
|
||||
WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
|
||||
the specific language governing rights and limitations under the License.
|
||||
|
||||
Alternatively, the contents of this file may be used under the terms of the
|
||||
"GNU Lesser General Public License 2.1" license (the “LGPL" License), in which
|
||||
case the provisions of "LGPL License" are applicable instead of those above.
|
||||
|
||||
If you wish to allow use of your version of this file only under the terms of
|
||||
the LGPL License and not to allow others to use your version of this file under
|
||||
the MPL, indicate your decision by deleting the provisions above and replace them
|
||||
with the notice and other provisions required by the LGPL License. If you do not
|
||||
delete the provisions above, a recipient may use your version of this file under
|
||||
either the MPL or the LGPL License.
|
||||
|
||||
The LGPL header follows below:
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this library; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
*/
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <k3l.h>
|
||||
|
||||
/* if using full k3l.h (for softpbx), version already defined. */
|
||||
#ifndef k3lApiMajorVersion
|
||||
# include <k3lVersion.h>
|
||||
#endif
|
||||
|
||||
#ifdef __GNUC_PREREQ
|
||||
#if __GNUC_PREREQ(4,3)
|
||||
#include <cstring>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include <types.hpp>
|
||||
|
||||
#ifndef _K3LAPI_HPP_
|
||||
#define _K3LAPI_HPP_
|
||||
|
||||
struct K3LAPI
|
||||
{
|
||||
/* exceptions */
|
||||
|
||||
struct start_failed
|
||||
{
|
||||
start_failed(const char * _msg) : msg(_msg) {};
|
||||
start_failed(std::string _msg) : msg(_msg) {};
|
||||
std::string msg;
|
||||
};
|
||||
|
||||
struct failed_command
|
||||
{
|
||||
failed_command(int32 _code, unsigned short _dev, unsigned short _obj, int32 _rc)
|
||||
: code(_code), dev(_dev), obj(_obj), rc(_rc) {};
|
||||
|
||||
int32 code;
|
||||
unsigned short dev;
|
||||
unsigned short obj;
|
||||
int32 rc;
|
||||
};
|
||||
|
||||
struct failed_raw_command
|
||||
{
|
||||
failed_raw_command(unsigned short _dev, unsigned short _dsp, int32 _rc)
|
||||
: dev(_dev), dsp(_dsp), rc(_rc) {};
|
||||
|
||||
unsigned short dev;
|
||||
unsigned short dsp;
|
||||
int32 rc;
|
||||
};
|
||||
|
||||
struct invalid_device
|
||||
{
|
||||
invalid_device(int32 _device)
|
||||
: device(_device) {};
|
||||
|
||||
int32 device;
|
||||
};
|
||||
|
||||
struct invalid_channel
|
||||
{
|
||||
invalid_channel(int32 _device, int32 _channel)
|
||||
: device(_device), channel(_channel) {};
|
||||
|
||||
int32 device, channel;
|
||||
};
|
||||
|
||||
struct invalid_link
|
||||
{
|
||||
invalid_link(unsigned int _device, unsigned int _link)
|
||||
: device(_device), link(_link) {};
|
||||
|
||||
int32 device, link;
|
||||
};
|
||||
|
||||
struct get_param_failed
|
||||
{
|
||||
get_param_failed(std::string _name, int32 _rc)
|
||||
: name(_name), rc((KLibraryStatus)_rc) {};
|
||||
|
||||
std::string name;
|
||||
KLibraryStatus rc;
|
||||
};
|
||||
|
||||
typedef K3L_DEVICE_CONFIG device_conf_type;
|
||||
typedef K3L_CHANNEL_CONFIG channel_conf_type;
|
||||
typedef K3L_CHANNEL_CONFIG * channel_ptr_conf_type;
|
||||
typedef K3L_LINK_CONFIG link_conf_type;
|
||||
typedef K3L_LINK_CONFIG * link_ptr_conf_type;
|
||||
|
||||
/* constructors/destructors */
|
||||
|
||||
K3LAPI(bool has_exceptions = false);
|
||||
virtual ~K3LAPI() {};
|
||||
|
||||
/* (init|final)ialize the whole thing! */
|
||||
|
||||
void start(void);
|
||||
void stop(void);
|
||||
|
||||
/* verificacao de intervalos */
|
||||
|
||||
inline bool valid_device(int32 dev)
|
||||
{
|
||||
return (dev >= 0 && dev < ((int32)_device_count));
|
||||
}
|
||||
|
||||
inline bool valid_channel(int32 dev, int32 obj)
|
||||
{
|
||||
return (valid_device(dev) && obj >= 0 && obj < ((int32)_channel_count[dev]));
|
||||
}
|
||||
|
||||
inline bool valid_link(int32 dev, int32 obj)
|
||||
{
|
||||
return (valid_device(dev) && obj >= 0 && obj < ((int32)_link_count[dev]));
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief High level object identifier
|
||||
Since Khomp works with an object concept, this is used to map the
|
||||
object id with its proper type.
|
||||
*/
|
||||
struct target
|
||||
{
|
||||
/*! The types a target can have */
|
||||
typedef enum { DEVICE, CHANNEL, MIXER, LINK } target_type;
|
||||
|
||||
target(K3LAPI & k3lapi, target_type type_init, int32 device_value, int32 object_value)
|
||||
: type(type_init),
|
||||
device((unsigned short)device_value),
|
||||
object((unsigned short)object_value)
|
||||
{
|
||||
switch (type_init)
|
||||
{
|
||||
case DEVICE:
|
||||
if (!k3lapi.valid_device(device_value))
|
||||
throw invalid_device(device_value);
|
||||
break;
|
||||
|
||||
case CHANNEL:
|
||||
case MIXER:
|
||||
if (!k3lapi.valid_channel(device_value, object_value))
|
||||
throw invalid_channel(device_value, object_value);
|
||||
break;
|
||||
|
||||
case LINK:
|
||||
if (!k3lapi.valid_link(device_value, object_value))
|
||||
throw invalid_link(device_value, object_value);
|
||||
break;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
const target_type type;
|
||||
|
||||
const unsigned short device;
|
||||
const unsigned short object;
|
||||
};
|
||||
|
||||
/* envio de comandos para placa (geral) */
|
||||
|
||||
void raw_command(int32 dev, int32 dsp, std::string & str);
|
||||
void raw_command(int32 dev, int32 dsp, const char * cmds, int32 size);
|
||||
|
||||
/* obter dados 'cacheados' (geral) */
|
||||
|
||||
inline unsigned int device_count(void)
|
||||
{
|
||||
return _device_count;
|
||||
}
|
||||
|
||||
/* envio de comandos para placa (sem identificadores) */
|
||||
|
||||
void mixer(int32 dev, int32 obj, byte track, KMixerSource src, int32 index);
|
||||
void mixerRecord(int32 dev, int32 obj, byte track, KMixerSource src, int32 index);
|
||||
void mixerCTbus(int32 dev, int32 obj, byte track, KMixerSource src, int32 index);
|
||||
|
||||
void command (int32 dev, int32 obj, int32 code, std::string & str);
|
||||
void command (int32 dev, int32 obj, int32 code, const char * parms = NULL);
|
||||
|
||||
/* obter dados 'cacheados' (sem identificadores) */
|
||||
|
||||
inline unsigned int channel_count(int32 dev)
|
||||
{
|
||||
if (!valid_device(dev))
|
||||
{
|
||||
if (_has_exceptions)
|
||||
throw invalid_device(dev);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
return _channel_count[dev];
|
||||
}
|
||||
|
||||
inline unsigned int link_count(int32 dev)
|
||||
{
|
||||
if (!valid_device(dev))
|
||||
{
|
||||
if (_has_exceptions)
|
||||
throw invalid_device(dev);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
return _link_count[dev];
|
||||
}
|
||||
|
||||
inline uint32 channel_stats(int32 dev, int32 obj, uint32 index)
|
||||
{
|
||||
if (!valid_channel(dev, obj))
|
||||
{
|
||||
if (_has_exceptions)
|
||||
throw invalid_channel(dev, obj);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32 res_value = (uint32)-1;
|
||||
stt_code stt_res = ksFail;
|
||||
|
||||
#if K3L_AT_LEAST(2,1,0)
|
||||
stt_res = k3lGetChannelStats(dev, obj, index, &res_value);
|
||||
#endif
|
||||
|
||||
if(stt_res != ksSuccess)
|
||||
{
|
||||
return (uint32)-1;
|
||||
}
|
||||
|
||||
return res_value;
|
||||
}
|
||||
|
||||
KDeviceType device_type(int32 dev)
|
||||
{
|
||||
if (!valid_device(dev))
|
||||
{
|
||||
if (_has_exceptions)
|
||||
throw invalid_device(dev);
|
||||
else
|
||||
return kdtDevTypeCount;
|
||||
}
|
||||
|
||||
return _device_type[dev];
|
||||
}
|
||||
|
||||
|
||||
K3L_DEVICE_CONFIG & device_config(int32 dev)
|
||||
{
|
||||
if (!valid_device(dev))
|
||||
throw invalid_device(dev);
|
||||
|
||||
return _device_config[dev];
|
||||
}
|
||||
|
||||
K3L_CHANNEL_CONFIG & channel_config(int32 dev, int32 obj)
|
||||
{
|
||||
if (!valid_channel(dev, obj))
|
||||
throw invalid_channel(dev, obj);
|
||||
|
||||
return _channel_config[dev][obj];
|
||||
}
|
||||
|
||||
K3L_LINK_CONFIG & link_config(int32 dev, int32 obj)
|
||||
{
|
||||
if (!valid_link(dev, obj))
|
||||
throw invalid_channel(dev, obj);
|
||||
|
||||
return _link_config[dev][obj];
|
||||
}
|
||||
|
||||
/* envio de comandos para placa (com identificadores) */
|
||||
|
||||
void mixer(target & tgt, byte track, KMixerSource src, int32 index)
|
||||
{
|
||||
mixer((int32)tgt.device, (int32)tgt.object, track, src, index);
|
||||
}
|
||||
|
||||
void mixerRecord(target & tgt, byte track, KMixerSource src, int32 index)
|
||||
{
|
||||
mixerRecord((int32)tgt.device, (int32)tgt.object, track, src, index);
|
||||
}
|
||||
|
||||
void mixerCTbus(target & tgt, byte track, KMixerSource src, int32 index)
|
||||
{
|
||||
mixerCTbus((int32)tgt.device, (int32)tgt.object, track, src, index);
|
||||
}
|
||||
|
||||
void command (target & tgt, int32 code, std::string & str)
|
||||
{
|
||||
command((int32)tgt.device, (int32)tgt.object, code, str);
|
||||
};
|
||||
|
||||
void command (target & tgt, int32 code, const char * parms = NULL)
|
||||
{
|
||||
command((int32)tgt.device, (int32)tgt.object, code, parms);
|
||||
};
|
||||
|
||||
/* obter dados 'cacheados' (com indentificadores) */
|
||||
|
||||
inline unsigned int channel_count(target & tgt)
|
||||
{
|
||||
return _channel_count[tgt.device];
|
||||
}
|
||||
|
||||
inline unsigned int link_count(target & tgt)
|
||||
{
|
||||
return _link_count[tgt.device];
|
||||
}
|
||||
|
||||
KDeviceType device_type(target & tgt)
|
||||
{
|
||||
return _device_type[tgt.device];
|
||||
}
|
||||
|
||||
|
||||
K3L_DEVICE_CONFIG & device_config(target & tgt)
|
||||
{
|
||||
return _device_config[tgt.device];
|
||||
}
|
||||
|
||||
K3L_CHANNEL_CONFIG & channel_config(target & tgt)
|
||||
{
|
||||
return _channel_config[tgt.device][tgt.object];
|
||||
}
|
||||
|
||||
K3L_LINK_CONFIG & link_config(target & tgt)
|
||||
{
|
||||
return _link_config[tgt.device][tgt.object];
|
||||
}
|
||||
|
||||
/* pega valores em strings de eventos */
|
||||
|
||||
KLibraryStatus get_param(K3L_EVENT *ev, const char *name, std::string &res);
|
||||
std::string get_param(K3L_EVENT *ev, const char *name);
|
||||
|
||||
/* inicializa valores em cache */
|
||||
|
||||
void init(void);
|
||||
void fini(void);
|
||||
|
||||
/* utilidades diversas e informacoes */
|
||||
|
||||
enum DspType
|
||||
{
|
||||
DSP_AUDIO,
|
||||
DSP_SIGNALING,
|
||||
};
|
||||
|
||||
int32 get_dsp(int32, DspType);
|
||||
|
||||
protected:
|
||||
|
||||
const bool _has_exceptions;
|
||||
|
||||
unsigned int _device_count;
|
||||
unsigned int * _channel_count;
|
||||
unsigned int * _link_count;
|
||||
|
||||
device_conf_type * _device_config;
|
||||
channel_ptr_conf_type * _channel_config;
|
||||
link_ptr_conf_type * _link_config;
|
||||
KDeviceType * _device_type;
|
||||
};
|
||||
|
||||
#endif /* _K3LAPI_HPP_ */
|
||||
@@ -0,0 +1,234 @@
|
||||
/*
|
||||
KHOMP generic endpoint/channel library.
|
||||
Copyright (C) 2007-2009 Khomp Ind. & Com.
|
||||
|
||||
The contents of this file are subject to the Mozilla Public License Version 1.1
|
||||
(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.mozilla.org/MPL/
|
||||
|
||||
Software distributed under the License is distributed on an "AS IS" basis,
|
||||
WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
|
||||
the specific language governing rights and limitations under the License.
|
||||
|
||||
Alternatively, the contents of this file may be used under the terms of the
|
||||
"GNU Lesser General Public License 2.1" license (the “LGPL" License), in which
|
||||
case the provisions of "LGPL License" are applicable instead of those above.
|
||||
|
||||
If you wish to allow use of your version of this file only under the terms of
|
||||
the LGPL License and not to allow others to use your version of this file under
|
||||
the MPL, indicate your decision by deleting the provisions above and replace them
|
||||
with the notice and other provisions required by the LGPL License. If you do not
|
||||
delete the provisions above, a recipient may use your version of this file under
|
||||
either the MPL or the LGPL License.
|
||||
|
||||
The LGPL header follows below:
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this library; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
*/
|
||||
|
||||
#include <k3lutil.hpp>
|
||||
|
||||
std::string K3LUtil::channelStatus(int32 dev, int32 channel,
|
||||
Verbose::Presentation fmt)
|
||||
{
|
||||
try
|
||||
{
|
||||
K3L_CHANNEL_CONFIG & config = _k3lapi.channel_config(dev, channel);
|
||||
K3L_CHANNEL_STATUS status;
|
||||
|
||||
KLibraryStatus ret = (KLibraryStatus) k3lGetDeviceStatus (dev,
|
||||
channel + ksoChannel, &status, sizeof(status));
|
||||
|
||||
switch (ret)
|
||||
{
|
||||
case ksSuccess: return Verbose::channelStatus(config.Signaling,
|
||||
status.AddInfo, fmt);
|
||||
default: return (fmt == Verbose::EXACT ? "<unknown[fail]>"
|
||||
: "Unknown (fail)");
|
||||
}
|
||||
}
|
||||
catch(K3LAPI::invalid_channel & e)
|
||||
{
|
||||
return (fmt == Verbose::EXACT ? "<unknown[fail]>" : "Unknown (fail)");
|
||||
}
|
||||
}
|
||||
|
||||
std::string K3LUtil::callStatus(int32 dev, int32 channel,
|
||||
Verbose::Presentation fmt)
|
||||
{
|
||||
K3L_CHANNEL_STATUS status;
|
||||
|
||||
KLibraryStatus ret = (KLibraryStatus) k3lGetDeviceStatus(dev,
|
||||
channel + ksoChannel, &status, sizeof(status));
|
||||
|
||||
switch (ret)
|
||||
{
|
||||
case ksSuccess: return Verbose::callStatus(status.CallStatus, fmt);
|
||||
default: return (fmt == Verbose::EXACT ? "<unknown[fail]>"
|
||||
: "Unknown (fail)");
|
||||
}
|
||||
}
|
||||
|
||||
std::string K3LUtil::linkStatus(int32 dev, int32 link,
|
||||
Verbose::Presentation fmt, KSignaling sig)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (sig == ksigInactive)
|
||||
{
|
||||
K3L_LINK_CONFIG & config = _k3lapi.link_config(dev, link);
|
||||
sig = config.Signaling;
|
||||
}
|
||||
|
||||
K3L_LINK_STATUS status;
|
||||
|
||||
KLibraryStatus ret = (KLibraryStatus) k3lGetDeviceStatus (dev,
|
||||
link + ksoLink, &status, sizeof(status));
|
||||
|
||||
switch (ret)
|
||||
{
|
||||
case ksSuccess: return Verbose::linkStatus(sig, status.E1, fmt);
|
||||
default: return (fmt == Verbose::EXACT ?
|
||||
"<unknown[failure]>" : "Unknown (failure)");
|
||||
}
|
||||
}
|
||||
catch(K3LAPI::invalid_channel & e)
|
||||
{
|
||||
return (fmt == Verbose::EXACT ? "<unknown[failure]>"
|
||||
: "Unknown (failure)");
|
||||
}
|
||||
}
|
||||
|
||||
std::string K3LUtil::getLinkStatus(int32 dev, int32 link,
|
||||
Verbose::Presentation fmt)
|
||||
{
|
||||
switch (_k3lapi.device_type(dev))
|
||||
{
|
||||
#if K3L_AT_LEAST(1,6,0)
|
||||
case kdtFXS:
|
||||
case kdtFXSSpx:
|
||||
return linkStatus(dev, link, fmt, ksigAnalogTerminal);
|
||||
|
||||
#if K3L_AT_LEAST(2,1,0)
|
||||
case kdtE1FXSSpx:
|
||||
if (link == 1)
|
||||
return linkStatus(dev, link, fmt, ksigAnalogTerminal);
|
||||
#endif
|
||||
#endif
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
K3L_LINK_CONFIG & conf = _k3lapi.link_config(dev, link);
|
||||
|
||||
std::string res = linkStatus(dev, link, fmt);
|
||||
|
||||
if (conf.ReceivingClock & 0x01)
|
||||
res += (fmt == Verbose::EXACT ? ",sync" : " (sync)");
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
unsigned int K3LUtil::physicalLinkCount(int32 dev, bool count_virtual)
|
||||
{
|
||||
unsigned int number = 0;
|
||||
|
||||
try
|
||||
{
|
||||
switch (_k3lapi.device_type(dev))
|
||||
{
|
||||
#if K3L_AT_LEAST(1,6,0)
|
||||
case kdtFXS:
|
||||
number = (count_virtual ? (_k3lapi.channel_count(dev) < 50 ? 1 : 2) : 0);
|
||||
break;
|
||||
|
||||
case kdtFXSSpx:
|
||||
number = (count_virtual ? (_k3lapi.channel_count(dev) < 30 ? 1 : 2) : 0);
|
||||
break;
|
||||
#endif
|
||||
|
||||
#if K3L_AT_LEAST(2,1,0)
|
||||
case kdtE1FXSSpx:
|
||||
number = (count_virtual ? 2 : 1);
|
||||
break;
|
||||
#endif
|
||||
|
||||
/* E1 boards */
|
||||
case kdtE1:
|
||||
case kdtE1Spx:
|
||||
case kdtE1IP:
|
||||
number = _k3lapi.link_count(dev);
|
||||
break;
|
||||
|
||||
case kdtPR:
|
||||
case kdtE1GW:
|
||||
number = 1;
|
||||
break;
|
||||
|
||||
#if K3L_AT_LEAST(1,6,0)
|
||||
case kdtFXO:
|
||||
case kdtFXOVoIP:
|
||||
case kdtGSM:
|
||||
case kdtGSMSpx:
|
||||
#else
|
||||
case kdtFX:
|
||||
case kdtFXVoIP:
|
||||
#endif
|
||||
case kdtConf:
|
||||
case kdtGWIP:
|
||||
#if K3L_AT_LEAST(2,1,0)
|
||||
case kdtGSMUSB:
|
||||
case kdtGSMUSBSpx:
|
||||
case kdtReserved1: // just to avoid warnings.
|
||||
case kdtDevTypeCount: // just to avoid warnings.
|
||||
#endif
|
||||
number = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch(K3LAPI::invalid_device & e)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return number;
|
||||
}
|
||||
|
||||
|
||||
K3LUtil::ErrorCountType K3LUtil::linkErrorCount(int32 dev, int32 link,
|
||||
Verbose::Presentation fmt)
|
||||
{
|
||||
ErrorCountType result;
|
||||
K3L_LINK_ERROR_COUNTER status;
|
||||
|
||||
KLibraryStatus ret = (KLibraryStatus) k3lGetDeviceStatus (dev,
|
||||
link + ksoLinkMon, &status, sizeof(status));
|
||||
|
||||
switch (ret)
|
||||
{
|
||||
case ksSuccess:
|
||||
for (unsigned int i = klecChangesToLock; i < klecCount; i++)
|
||||
{
|
||||
result.push_back(ErrorCountPairType(Verbose::linkErrorCounter
|
||||
((KLinkErrorCounter)i, fmt), status.ErrorCounters[i]));
|
||||
}
|
||||
/* fall */
|
||||
|
||||
default:
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
KHOMP generic endpoint/channel library.
|
||||
Copyright (C) 2007-2009 Khomp Ind. & Com.
|
||||
|
||||
The contents of this file are subject to the Mozilla Public License Version 1.1
|
||||
(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.mozilla.org/MPL/
|
||||
|
||||
Software distributed under the License is distributed on an "AS IS" basis,
|
||||
WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
|
||||
the specific language governing rights and limitations under the License.
|
||||
|
||||
Alternatively, the contents of this file may be used under the terms of the
|
||||
"GNU Lesser General Public License 2.1" license (the “LGPL" License), in which
|
||||
case the provisions of "LGPL License" are applicable instead of those above.
|
||||
|
||||
If you wish to allow use of your version of this file only under the terms of
|
||||
the LGPL License and not to allow others to use your version of this file under
|
||||
the MPL, indicate your decision by deleting the provisions above and replace them
|
||||
with the notice and other provisions required by the LGPL License. If you do not
|
||||
delete the provisions above, a recipient may use your version of this file under
|
||||
either the MPL or the LGPL License.
|
||||
|
||||
The LGPL header follows below:
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this library; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
*/
|
||||
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <list>
|
||||
|
||||
#include <k3lapi.hpp>
|
||||
#include <verbose.hpp>
|
||||
|
||||
#ifndef _K3LUTIL_HPP_
|
||||
#define _K3LUTIL_HPP_
|
||||
|
||||
struct K3LUtil
|
||||
{
|
||||
typedef std::pair < std::string, unsigned int > ErrorCountPairType;
|
||||
typedef std::list < ErrorCountPairType > ErrorCountType;
|
||||
|
||||
K3LUtil(K3LAPI & k3lapi): _k3lapi(k3lapi) {};
|
||||
|
||||
std::string callStatus(int32 dev, int32 channel,
|
||||
Verbose::Presentation fmt = Verbose::HUMAN);
|
||||
|
||||
std::string channelStatus(int32, int32,
|
||||
Verbose::Presentation fmt = Verbose::HUMAN);
|
||||
|
||||
std::string linkStatus(int32, int32,
|
||||
Verbose::Presentation fmt = Verbose::HUMAN,
|
||||
KSignaling sig = ksigInactive);
|
||||
|
||||
std::string getLinkStatus(int32, int32,
|
||||
Verbose::Presentation fmt = Verbose::HUMAN);
|
||||
|
||||
unsigned int physicalLinkCount(int32 dev, bool count_virtual = false);
|
||||
|
||||
ErrorCountType linkErrorCount(int32, int32,
|
||||
Verbose::Presentation fmt = Verbose::HUMAN);
|
||||
|
||||
protected:
|
||||
K3LAPI & _k3lapi;
|
||||
};
|
||||
|
||||
#endif /* _K3LUTIL_HPP_ */
|
||||
|
||||
@@ -0,0 +1,644 @@
|
||||
/*
|
||||
KHOMP generic endpoint/channel library.
|
||||
Copyright (C) 2007-2009 Khomp Ind. & Com.
|
||||
|
||||
The contents of this file are subject to the Mozilla Public License Version 1.1
|
||||
(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.mozilla.org/MPL/
|
||||
|
||||
Software distributed under the License is distributed on an "AS IS" basis,
|
||||
WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
|
||||
the specific language governing rights and limitations under the License.
|
||||
|
||||
Alternatively, the contents of this file may be used under the terms of the
|
||||
"GNU Lesser General Public License 2.1" license (the “LGPL" License), in which
|
||||
case the provisions of "LGPL License" are applicable instead of those above.
|
||||
|
||||
If you wish to allow use of your version of this file only under the terms of
|
||||
the LGPL License and not to allow others to use your version of this file under
|
||||
the MPL, indicate your decision by deleting the provisions above and replace them
|
||||
with the notice and other provisions required by the LGPL License. If you do not
|
||||
delete the provisions above, a recipient may use your version of this file under
|
||||
either the MPL or the LGPL License.
|
||||
|
||||
The LGPL header follows below:
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this library; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sys/time.h>
|
||||
#include <time.h>
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
|
||||
#include <tagged_union.hpp>
|
||||
#include <format.hpp>
|
||||
#include <refcounter.hpp>
|
||||
#include <flagger.hpp>
|
||||
|
||||
#if defined(COMMONS_LIBRARY_USING_ASTERISK)
|
||||
extern "C"
|
||||
{
|
||||
#include <asterisk/localtime.h>
|
||||
}
|
||||
#elif defined(COMMONS_LIBRARY_USING_CALLWEAVER)
|
||||
extern "C"
|
||||
{
|
||||
#include <callweaver/localtime.h>
|
||||
}
|
||||
#elif defined(COMMONS_LIBRARY_USING_FREESWITCH)
|
||||
extern "C"
|
||||
{
|
||||
#include <time.h>
|
||||
}
|
||||
#endif
|
||||
/*
|
||||
|
||||
********************************************************************************
|
||||
***************************** 'Logger' user manual *****************************
|
||||
********************************************************************************
|
||||
|
||||
* Description:
|
||||
|
||||
This class does the management of log messages for applications. It works with
|
||||
the following axioms:
|
||||
|
||||
<*> There are several class of messages.
|
||||
<*> There are some outputs, which may be files, sockets, or a console device.
|
||||
<*> There are options for classes, for outputs and for the association of both.
|
||||
|
||||
The last rule also shows the order in which options are processed: first the
|
||||
'classes' options are processed, then 'output' options are processed, and then
|
||||
the options for the tuple '(class, output)' are processed.
|
||||
|
||||
The options are mapped like this:
|
||||
|
||||
<class-of-message> -> options [prefix, flags]
|
||||
<output-sink> -> options [prefix]
|
||||
( <class-of-message>, <output-sink> ) -> options [prefix, flags]
|
||||
|
||||
- "prefix" means a fixed string prefix before the real message.
|
||||
- "flags" means auxiliary flags (DATETIME, THREADID) which are
|
||||
used to add information based on OS or process context info.
|
||||
|
||||
* Example of use:
|
||||
|
||||
typedef enum
|
||||
{
|
||||
C_DBG_FUNC,
|
||||
C_DBG_LOCK,
|
||||
C_WARNING,
|
||||
C_ERROR,
|
||||
C_CLI,
|
||||
}
|
||||
AstClassId;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
F_CONSOLE,
|
||||
F_GENERIC,
|
||||
F_TRACE,
|
||||
}
|
||||
AstOutputId;
|
||||
|
||||
// used to indicate the console log //
|
||||
struct AstConsoleLog {};
|
||||
|
||||
struct AstPrinter: public Logger::DefaultPrinter
|
||||
{
|
||||
typedef Logger::DefaultPrinter Super;
|
||||
|
||||
using namespace Tagged;
|
||||
|
||||
using Super::operator()(int);
|
||||
|
||||
// just 2 type of descriptors //
|
||||
typedef Union < int, Union < AstConsoleLog > > Container;
|
||||
|
||||
ast_printer(std::string & msg): Super(msg) {};
|
||||
|
||||
bool operator()(const AstConsoleLog & log)
|
||||
{
|
||||
ast_console_puts(_msg.c_str());
|
||||
return true;
|
||||
};
|
||||
|
||||
#if 0
|
||||
bool operator()(int log)
|
||||
{
|
||||
return Super::operator()(log);
|
||||
};
|
||||
#endif
|
||||
};
|
||||
|
||||
bool start_log()
|
||||
{
|
||||
typedef Logger::Manager<AstClassId, AstOutputId, AstPrinter, SimpleLock> LogManager;
|
||||
|
||||
LogManager logger;
|
||||
|
||||
// shortcut definition //
|
||||
typedef LogManager::Option LogOption;
|
||||
|
||||
FILE * log_file = fopen( "output.log", "a");
|
||||
|
||||
if (!log_file)
|
||||
return false;
|
||||
|
||||
logger.add( F_CONSOLE, AstConsoleLog(), "chan_khomp: ");
|
||||
logger.add( F_GENERIC, log_file);
|
||||
|
||||
logger.classe( C_WARNING )
|
||||
& LogOption(F_CONSOLE, "WARNING: ", LogOption::Flags(LogOption::Flag(LogOption::DATETIME)))
|
||||
& LogOption(F_GENERIC, "W: ", LogOption::Flags(LogOption::Flag(LogOption::DATETIME)))
|
||||
|
||||
logger.classe( C_DBG_LOCK ).enabled(false);
|
||||
|
||||
logger.classe( C_DBG_LOCK )
|
||||
& LogOption(F_GENERIC, "L: ", LogOption::Flags
|
||||
(LogOption::flag_type(LogOption::ENABLED) &
|
||||
LogOption::flag_type(LogOption::DATETIME))
|
||||
|
||||
logger(C_WARNING, "eu sou uma mensagem de warning");
|
||||
|
||||
logger.classe(C_WARNING).set(F_GENERIC, LogOption::ENABLED, true);
|
||||
logger.classe(C_WARNING).set(F_CONSOLE, LogOption::ENABLED, false);
|
||||
|
||||
logger.classe(C_CLI).prefix("<K>");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void message_the_user(int fd)
|
||||
{
|
||||
logger(C_CLI, fd, "eu sou uma mensagem de cli!");
|
||||
logger(C_WARNING, "eu sou um warning");
|
||||
}
|
||||
|
||||
********************************************************************************
|
||||
********************************************************************************
|
||||
|
||||
Now, the code..!
|
||||
|
||||
*/
|
||||
|
||||
#ifndef _LOGGER_HPP_
|
||||
#define _LOGGER_HPP_
|
||||
|
||||
#include <tagged_union.hpp>
|
||||
|
||||
struct Logger
|
||||
{
|
||||
/*** a base struct for printing messages in many ways ***/
|
||||
|
||||
struct DefaultPrinter
|
||||
{
|
||||
typedef Tagged::Union < int, Tagged::Union < FILE *, Tagged::Union < std::ostream * > > > BaseType;
|
||||
|
||||
typedef bool ReturnType;
|
||||
|
||||
DefaultPrinter(std::string & msg): _msg(msg) {};
|
||||
|
||||
bool operator()(std::ostream * out)
|
||||
{
|
||||
(*out) << _msg;
|
||||
out->flush();
|
||||
|
||||
return out->good();
|
||||
}
|
||||
|
||||
bool operator()(FILE * out)
|
||||
{
|
||||
if (fputs(_msg.c_str(), out) < 0)
|
||||
return false;
|
||||
|
||||
if (fflush(out) < 0)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool operator()(int out)
|
||||
{
|
||||
#ifndef KWIN32
|
||||
return (write(out, _msg.c_str(), _msg.size()) == (int)_msg.size());
|
||||
#else
|
||||
// no need for file descriptors on windows
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
std::string & msg() { return _msg; }
|
||||
|
||||
protected:
|
||||
std::string & _msg;
|
||||
};
|
||||
|
||||
/*** manage the printing of messages ***/
|
||||
|
||||
template <class ClassId, class OutputId, class Printer, class LockType>
|
||||
struct Manager
|
||||
{
|
||||
typedef typename Printer::BaseType BaseType;
|
||||
|
||||
protected:
|
||||
/* holds a stream, and an optimal message prefix */
|
||||
struct OutputOptions
|
||||
{
|
||||
OutputOptions(BaseType & stream, std::string & prefix)
|
||||
: _stream(stream), _prefix(prefix) {};
|
||||
|
||||
BaseType _stream;
|
||||
std::string _prefix;
|
||||
LockType _lock;
|
||||
};
|
||||
|
||||
typedef std::map < OutputId, OutputOptions > OutputMap;
|
||||
|
||||
public:
|
||||
|
||||
/* print in a specific 'message class' */
|
||||
struct ClassType
|
||||
{
|
||||
ClassType(void)
|
||||
: _enabled(true)
|
||||
{};
|
||||
|
||||
// ClassType(ClassType & o)
|
||||
// : _stream_map(o._stream_map), _prefix(o.prefix),
|
||||
// _lock(o._lock),_enabled(o._enabled)
|
||||
// {};
|
||||
|
||||
/* initializes the options of the (class, stream) pair */
|
||||
struct Option
|
||||
{
|
||||
typedef enum { ENABLED, DATETIME, THREADID, DATETIMEMS } EnumType;
|
||||
|
||||
typedef Flagger< EnumType > Flags;
|
||||
typedef typename Flags::InitFlags InitFlags;
|
||||
|
||||
Option(OutputId output, const char * prefix,
|
||||
Flags flags = InitFlags(ENABLED))
|
||||
: _output(output), _prefix(prefix), _flags(flags) {};
|
||||
|
||||
Option(OutputId output, std::string prefix,
|
||||
Flags flags = InitFlags(ENABLED))
|
||||
: _output(output), _prefix(prefix), _flags(flags) {};
|
||||
|
||||
Option(OutputId output,
|
||||
Flags flags = InitFlags(ENABLED))
|
||||
: _output(output), _flags(flags) {};
|
||||
|
||||
OutputId _output;
|
||||
std::string _prefix;
|
||||
Flags _flags;
|
||||
};
|
||||
|
||||
protected:
|
||||
|
||||
/* holds a prefix and a activation status */
|
||||
struct OptionContainer
|
||||
{
|
||||
OptionContainer(std::string prefix, typename Option::Flags flags)
|
||||
: _prefix(prefix), _flags(flags) {};
|
||||
|
||||
std::string _prefix;
|
||||
typename Option::Flags _flags;
|
||||
};
|
||||
|
||||
typedef std::multimap < OutputId, OptionContainer > OptionMap;
|
||||
|
||||
/* utility function for printing */
|
||||
bool print(std::string & msg, BaseType & stream, LockType & lock)
|
||||
{
|
||||
lock.lock();
|
||||
|
||||
Printer p(msg);
|
||||
bool ret = stream.visit(p);
|
||||
|
||||
lock.unlock();
|
||||
|
||||
return ret;
|
||||
};
|
||||
|
||||
/*
|
||||
bool print(std::string & msg, BaseType & stream, LockType & lock)
|
||||
{
|
||||
lock.lock();
|
||||
|
||||
Printer p(msg);
|
||||
bool ret = stream.visit(p);
|
||||
|
||||
lock.unlock();
|
||||
|
||||
return ret;
|
||||
};
|
||||
*/
|
||||
|
||||
public:
|
||||
ClassType & operator&(const Option & value)
|
||||
{
|
||||
add(value._output, value._prefix, value._flags);
|
||||
return *this;
|
||||
}
|
||||
|
||||
void add(OutputId output_id, std::string prefix,
|
||||
typename Option::Flags flags)
|
||||
{
|
||||
typedef std::pair < OutputId, OptionContainer > pair_type;
|
||||
_stream_map.insert(pair_type(output_id, OptionContainer(prefix, flags)));
|
||||
}
|
||||
|
||||
/* get and set methods for active mode */
|
||||
void set(OutputId id, typename Option::EnumType flag, bool value = true)
|
||||
{
|
||||
typename OptionMap::iterator iter = _stream_map.find(id);
|
||||
|
||||
if (iter == _stream_map.end())
|
||||
return;
|
||||
|
||||
(*iter).second._flags.set(flag, value);
|
||||
}
|
||||
|
||||
bool get(OutputId idx, typename Option::EnumType flag)
|
||||
{
|
||||
typename OptionMap::iterator iter = _stream_map.find(idx);
|
||||
|
||||
if (iter == _stream_map.end())
|
||||
return false;
|
||||
|
||||
return (*iter).second._flags.is_set(flag);
|
||||
}
|
||||
|
||||
/* get/adjust the enable/disable value for the class */
|
||||
void enabled(bool enabled) { _enabled = enabled; };
|
||||
bool enabled() { return _enabled; };
|
||||
|
||||
/* get/adjust the classe prefix */
|
||||
void prefix(const char * prefix) { _prefix = prefix; }
|
||||
void prefix(std::string & prefix) { _prefix = prefix; }
|
||||
std::string & prefix() { return _prefix; }
|
||||
|
||||
/* printing function (operator, actually) */
|
||||
bool operator()(OutputMap & out_map, std::string & msg)
|
||||
{
|
||||
if (!_enabled)
|
||||
return true;
|
||||
|
||||
typedef typename OptionMap::iterator Iter;
|
||||
|
||||
bool ret = true;
|
||||
|
||||
for (Iter iter = _stream_map.begin(); iter != _stream_map.end(); iter++)
|
||||
{
|
||||
OptionContainer & opt = (*iter).second;
|
||||
|
||||
if (!opt._flags[Option::ENABLED])
|
||||
continue;
|
||||
|
||||
typename OutputMap::iterator out_iter = out_map.find((*iter).first);
|
||||
|
||||
/* this stream have been added already? if not, skip! */
|
||||
if (out_iter == out_map.end())
|
||||
continue;
|
||||
|
||||
/* final message */
|
||||
std::string out_msg;
|
||||
|
||||
if (opt._flags[Option::DATETIME])
|
||||
{
|
||||
#if defined(COMMONS_LIBRARY_USING_ASTERISK)
|
||||
#if ASTERISK_AT_LEAST(1,6,0)
|
||||
struct timeval tv;
|
||||
struct ast_tm lt;
|
||||
|
||||
gettimeofday(&tv, NULL);
|
||||
|
||||
#else
|
||||
time_t tv;
|
||||
struct tm lt;
|
||||
|
||||
time (&tv);
|
||||
#endif
|
||||
|
||||
#if ASTERISK_AT_LEAST(1,4,5)
|
||||
ast_localtime (&tv, <, NULL);
|
||||
#else
|
||||
localtime_r (&tv, <);
|
||||
#endif
|
||||
|
||||
out_msg += STG(FMT("[%04d-%02d-%02d %02d:%02d:%02d] ")
|
||||
% (lt.tm_year + 1900) % (lt.tm_mon + 1) % lt.tm_mday % lt.tm_hour
|
||||
% lt.tm_min % lt.tm_sec);
|
||||
|
||||
#elif defined(COMMONS_LIBRARY_USING_CALLWEAVER)
|
||||
time_t tv;
|
||||
struct tm lt;
|
||||
|
||||
time (&tv);
|
||||
|
||||
localtime_r (&tv, <);
|
||||
|
||||
out_msg += STG(FMT("[%04d-%02d-%02d %02d:%02d:%02d] ")
|
||||
% (lt.tm_year + 1900) % (lt.tm_mon + 1) % lt.tm_mday % lt.tm_hour
|
||||
% lt.tm_min % lt.tm_sec);
|
||||
|
||||
#elif defined(COMMONS_LIBRARY_USING_FREESWITCH)
|
||||
time_t tv;
|
||||
struct tm lt;
|
||||
|
||||
time (&tv);
|
||||
|
||||
localtime_r (&tv, <);
|
||||
|
||||
out_msg += STG(FMT("[%04d-%02d-%02d %02d:%02d:%02d] ")
|
||||
% (lt.tm_year + 1900) % (lt.tm_mon + 1) % lt.tm_mday % lt.tm_hour
|
||||
% lt.tm_min % lt.tm_sec);
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
if (opt._flags[Option::DATETIMEMS])
|
||||
{
|
||||
#if defined(COMMONS_LIBRARY_USING_ASTERISK)
|
||||
#if ASTERISK_AT_LEAST(1,6,0)
|
||||
struct timeval tv;
|
||||
struct ast_tm lt;
|
||||
|
||||
gettimeofday(&tv, NULL);
|
||||
|
||||
#else
|
||||
time_t tv;
|
||||
struct tm lt;
|
||||
|
||||
time (&tv);
|
||||
#endif
|
||||
|
||||
#if ASTERISK_AT_LEAST(1,4,5)
|
||||
ast_localtime (&tv, <, NULL);
|
||||
#else
|
||||
localtime_r (&tv, <);
|
||||
#endif
|
||||
|
||||
#if ASTERISK_AT_LEAST(1,6,0)
|
||||
out_msg += STG(FMT("[%04d-%02d-%02d %02d:%02d:%02d:%04d] ")
|
||||
% (lt.tm_year + 1900) % (lt.tm_mon + 1) % lt.tm_mday % lt.tm_hour % lt.tm_min
|
||||
% lt.tm_sec % (tv.tv_usec / 1000));
|
||||
#else
|
||||
out_msg += STG(FMT("[%04d-%02d-%02d %02d:%02d:%02d:%04d] ")
|
||||
% (lt.tm_year + 1900) % (lt.tm_mon + 1) % lt.tm_mday % lt.tm_hour % lt.tm_min
|
||||
% lt.tm_sec % (tv * 1000));
|
||||
#endif
|
||||
|
||||
#elif defined(COMMONS_LIBRARY_USING_CALLWEAVER)
|
||||
time_t tv;
|
||||
struct tm lt;
|
||||
|
||||
time (&tv);
|
||||
|
||||
localtime_r (&tv, <);
|
||||
|
||||
out_msg += STG(FMT("[%04d-%02d-%02d %02d:%02d:%02d:%04d] ")
|
||||
% (lt.tm_year + 1900) % (lt.tm_mon + 1) % lt.tm_mday % lt.tm_hour % lt.tm_min
|
||||
% lt.tm_sec % (tv * 1000));
|
||||
|
||||
#elif defined(COMMONS_LIBRARY_USING_FREESWITCH)
|
||||
time_t tv;
|
||||
struct tm lt;
|
||||
|
||||
time (&tv);
|
||||
|
||||
localtime_r (&tv, <);
|
||||
|
||||
out_msg += STG(FMT("[%04d-%02d-%02d %02d:%02d:%02d:%04d] ")
|
||||
% (lt.tm_year + 1900) % (lt.tm_mon + 1) % lt.tm_mday % lt.tm_hour % lt.tm_min
|
||||
% lt.tm_sec % (tv * 1000));
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
OutputOptions & out_opt = (*out_iter).second;
|
||||
|
||||
if (opt._flags[Option::THREADID])
|
||||
{
|
||||
#if defined (COMMONS_LIBRARY_USING_ASTERISK) || defined(COMMONS_LIBRARY_USING_CALLWEAVER) || defined(COMMONS_LIBRARY_USING_FREESWITCH)
|
||||
out_msg += STG(FMT("t=%08p ") % ((void*)pthread_self()));
|
||||
#endif
|
||||
}
|
||||
|
||||
out_msg += _prefix;
|
||||
out_msg += out_opt._prefix;
|
||||
out_msg += opt._prefix;
|
||||
out_msg += msg;
|
||||
out_msg += "\n";
|
||||
|
||||
ret |= print(out_msg, out_opt._stream, out_opt._lock);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool operator()(BaseType & stream, std::string & msg)
|
||||
{
|
||||
std::string final_msg;
|
||||
|
||||
final_msg += _prefix;
|
||||
final_msg += msg;
|
||||
final_msg += "\n";
|
||||
|
||||
return print(final_msg, stream, _lock);
|
||||
}
|
||||
|
||||
protected:
|
||||
OptionMap _stream_map;
|
||||
std::string _prefix;
|
||||
LockType _lock;
|
||||
bool _enabled;
|
||||
};
|
||||
|
||||
/* util declaration */
|
||||
typedef typename ClassType::Option Option;
|
||||
|
||||
/* class_id_type -> ClassType mapper */
|
||||
typedef std::map < ClassId, ClassType > ClassMap;
|
||||
|
||||
/* local option pair */
|
||||
typedef std::pair < OutputId, OutputOptions > OutputOptionPair;
|
||||
|
||||
void add(OutputId output, BaseType stream, const char * prefix = "")
|
||||
{
|
||||
std::string str_prefix(prefix);
|
||||
|
||||
_output_map.insert(OutputOptionPair(output, OutputOptions(stream, str_prefix)));
|
||||
}
|
||||
|
||||
void add(OutputId output, BaseType stream, std::string prefix)
|
||||
{
|
||||
_output_map.insert(OutputOptionPair(output, OutputOptions(stream, prefix)));
|
||||
}
|
||||
|
||||
ClassType & classe(ClassId classeid)
|
||||
{
|
||||
return _classe_map[classeid];
|
||||
}
|
||||
|
||||
bool operator()(ClassId classeid, const char * msg)
|
||||
{
|
||||
std::string str_msg(msg);
|
||||
return _classe_map[classeid](_output_map, str_msg);
|
||||
}
|
||||
|
||||
bool operator()(ClassId classeid, std::string & msg)
|
||||
{
|
||||
return _classe_map[classeid](_output_map, msg);
|
||||
}
|
||||
|
||||
bool operator()(ClassId classeid, Format fmt)
|
||||
{
|
||||
std::string str_fmt = STG(fmt);
|
||||
return _classe_map[classeid](_output_map, str_fmt);
|
||||
}
|
||||
|
||||
bool operator()(ClassId classeid, BaseType stream, const char * msg)
|
||||
{
|
||||
std::string str_msg(msg);
|
||||
return _classe_map[classeid](stream, str_msg);
|
||||
}
|
||||
|
||||
bool operator()(ClassId classeid, BaseType stream, std::string & msg)
|
||||
{
|
||||
return _classe_map[classeid](stream, msg);
|
||||
}
|
||||
|
||||
bool operator()(ClassId classeid, BaseType stream, Format fmt)
|
||||
{
|
||||
std::string str_fmt = STG(fmt);
|
||||
return _classe_map[classeid](stream, str_fmt);
|
||||
}
|
||||
|
||||
protected:
|
||||
ClassMap _classe_map;
|
||||
OutputMap _output_map;
|
||||
};
|
||||
|
||||
private:
|
||||
Logger();
|
||||
};
|
||||
|
||||
#endif /* _LOGGER_HPP_ */
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
KHOMP generic endpoint/channel library.
|
||||
Copyright (C) 2007-2009 Khomp Ind. & Com.
|
||||
|
||||
The contents of this file are subject to the Mozilla Public License Version 1.1
|
||||
(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.mozilla.org/MPL/
|
||||
|
||||
Software distributed under the License is distributed on an "AS IS" basis,
|
||||
WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
|
||||
the specific language governing rights and limitations under the License.
|
||||
|
||||
Alternatively, the contents of this file may be used under the terms of the
|
||||
"GNU Lesser General Public License 2.1" license (the “LGPL" License), in which
|
||||
case the provisions of "LGPL License" are applicable instead of those above.
|
||||
|
||||
If you wish to allow use of your version of this file only under the terms of
|
||||
the LGPL License and not to allow others to use your version of this file under
|
||||
the MPL, indicate your decision by deleting the provisions above and replace them
|
||||
with the notice and other provisions required by the LGPL License. If you do not
|
||||
delete the provisions above, a recipient may use your version of this file under
|
||||
either the MPL or the LGPL License.
|
||||
|
||||
The LGPL header follows below:
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this library; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
*/
|
||||
|
||||
#ifndef _NONCOPYABLE_HPP_
|
||||
#define _NONCOPYABLE_HPP_
|
||||
|
||||
struct NonCopyable
|
||||
{
|
||||
NonCopyable() {};
|
||||
private:
|
||||
NonCopyable(NonCopyable const &) { };
|
||||
NonCopyable & operator=(NonCopyable const &) { return *this; };
|
||||
};
|
||||
|
||||
#endif /* _NONCOPYABLE_HPP_ */
|
||||
|
||||
@@ -0,0 +1,263 @@
|
||||
/*
|
||||
KHOMP generic endpoint/channel library.
|
||||
Copyright (C) 2007-2009 Khomp Ind. & Com.
|
||||
|
||||
The contents of this file are subject to the Mozilla Public License Version 1.1
|
||||
(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.mozilla.org/MPL/
|
||||
|
||||
Software distributed under the License is distributed on an "AS IS" basis,
|
||||
WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
|
||||
the specific language governing rights and limitations under the License.
|
||||
|
||||
Alternatively, the contents of this file may be used under the terms of the
|
||||
"GNU Lesser General Public License 2.1" license (the "LGPL" License), in which
|
||||
case the provisions of "LGPL License" are applicable instead of those above.
|
||||
|
||||
If you wish to allow use of your version of this file only under the terms of
|
||||
the LGPL License and not to allow others to use your version of this file under
|
||||
the MPL, indicate your decision by deleting the provisions above and replace them
|
||||
with the notice and other provisions required by the LGPL License. If you do not
|
||||
delete the provisions above, a recipient may use your version of this file under
|
||||
either the MPL or the LGPL License.
|
||||
|
||||
The LGPL header follows below:
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this library; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
*/
|
||||
|
||||
/* This struct uses static polymorphism, and derived classes should implement *
|
||||
* the "unreference()" method, which should release all resources when called */
|
||||
|
||||
#ifndef _REFCOUNTER_HPP_
|
||||
#define _REFCOUNTER_HPP_
|
||||
|
||||
#define NEW_REFCOUNTER(...) public ReferenceCounter< __VA_ARGS__ >
|
||||
#define INC_REFCOUNTER(o, ...) ReferenceCounter< __VA_ARGS__ >(static_cast< const ReferenceCounter < __VA_ARGS__ > & >(o))
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <noncopyable.hpp>
|
||||
#include <atomic.hpp>
|
||||
|
||||
#ifdef DEBUG
|
||||
# include <iostream>
|
||||
#endif
|
||||
|
||||
struct ReferenceData: public NonCopyable
|
||||
{
|
||||
ReferenceData()
|
||||
: _data_count(1)
|
||||
{};
|
||||
|
||||
inline unsigned int increment(void)
|
||||
{
|
||||
if (!_data_count)
|
||||
abort();
|
||||
|
||||
Atomic::doAdd(&_data_count);
|
||||
|
||||
return _data_count;
|
||||
}
|
||||
|
||||
inline unsigned int decrement(void)
|
||||
{
|
||||
if (!_data_count)
|
||||
abort();
|
||||
|
||||
Atomic::doSub(&_data_count);
|
||||
return _data_count;
|
||||
}
|
||||
|
||||
volatile unsigned int _data_count;
|
||||
};
|
||||
|
||||
template < typename T >
|
||||
struct ReferenceCounter
|
||||
{
|
||||
typedef T Type;
|
||||
|
||||
ReferenceCounter(bool create_counter = true)
|
||||
: _reference_count(0)
|
||||
{
|
||||
reference_restart(create_counter);
|
||||
|
||||
#ifdef DEBUG
|
||||
std::cerr << ((void*)this) << ": ReferenceCounter() [ref_count="
|
||||
<< (_reference_count ? (*_reference_count) : -1) << "]" << std::endl;
|
||||
#endif
|
||||
};
|
||||
|
||||
ReferenceCounter(const ReferenceCounter & o)
|
||||
: _reference_count(0)
|
||||
{
|
||||
reference_reflect(o);
|
||||
|
||||
#ifdef DEBUG
|
||||
std::cerr << ((void*)this) << ": ReferenceCounter(" << ((void*)(&o)) << ") [ref_count="
|
||||
<< (_reference_count ? (*_reference_count) : -1) << "]" << std::endl;
|
||||
#endif
|
||||
};
|
||||
|
||||
virtual ~ReferenceCounter()
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::cerr << ((void*)this) << ": ~ReferenceCounter() [ref_count="
|
||||
<< (_reference_count ? (*_reference_count) : -1) << "]" << std::endl;
|
||||
#endif
|
||||
reference_disconnect(_reference_count);
|
||||
}
|
||||
|
||||
ReferenceCounter & operator=(const ReferenceCounter & o)
|
||||
{
|
||||
reference_reflect(o);
|
||||
|
||||
#ifdef DEBUG
|
||||
std::cerr << ((void*)this) << ": ReferenceCounter::operator=(" << ((void*)(&o)) << ") [ref_count="
|
||||
<< (_reference_count ? (*_reference_count) : -1) << "]" << std::endl;
|
||||
#endif
|
||||
|
||||
return *this;
|
||||
};
|
||||
|
||||
protected:
|
||||
inline void reference_restart(bool create_counter = false)
|
||||
{
|
||||
ReferenceData * oldref = _reference_count;
|
||||
|
||||
_reference_count = (create_counter ? new ReferenceData() : 0);
|
||||
|
||||
if (oldref) reference_disconnect(oldref);
|
||||
}
|
||||
|
||||
inline void reference_reflect(const ReferenceCounter & other)
|
||||
{
|
||||
ReferenceData * newref = other._reference_count;
|
||||
ReferenceData * oldref = _reference_count;
|
||||
|
||||
/* NOTE: increment before, avoid our reference being zero, even *
|
||||
* for a short period of time. */
|
||||
|
||||
if (newref) newref->increment();
|
||||
|
||||
_reference_count = newref;
|
||||
|
||||
if (oldref) reference_disconnect(oldref);
|
||||
};
|
||||
|
||||
inline void reference_disconnect(ReferenceData *& counter)
|
||||
{
|
||||
if (counter)
|
||||
{
|
||||
unsigned int result = counter->decrement();
|
||||
|
||||
if (!result)
|
||||
{
|
||||
static_cast< Type * >(this)->unreference();
|
||||
delete counter;
|
||||
}
|
||||
|
||||
counter = 0;
|
||||
}
|
||||
};
|
||||
|
||||
private:
|
||||
ReferenceData * _reference_count;
|
||||
};
|
||||
|
||||
template < typename T >
|
||||
struct ReferenceContainer: NEW_REFCOUNTER(ReferenceContainer< T >)
|
||||
{
|
||||
/* type */
|
||||
typedef T Type;
|
||||
|
||||
/* shorthand */
|
||||
typedef ReferenceCounter < ReferenceContainer< Type > > Counter;
|
||||
|
||||
// TODO: make this a generic exception someday
|
||||
struct NotFound {};
|
||||
|
||||
ReferenceContainer()
|
||||
: Counter(false),
|
||||
_reference_value(0)
|
||||
{};
|
||||
|
||||
ReferenceContainer(Type * value)
|
||||
: _reference_value(value)
|
||||
{};
|
||||
|
||||
ReferenceContainer(const ReferenceContainer & value)
|
||||
: Counter(false),
|
||||
_reference_value(0)
|
||||
{
|
||||
operator()(value);
|
||||
};
|
||||
|
||||
virtual ~ReferenceContainer()
|
||||
{};
|
||||
|
||||
ReferenceContainer operator=(const ReferenceContainer & value)
|
||||
{
|
||||
operator()(value);
|
||||
return *this;
|
||||
};
|
||||
|
||||
/**/
|
||||
|
||||
void unreference()
|
||||
{
|
||||
if (_reference_value)
|
||||
{
|
||||
delete _reference_value;
|
||||
_reference_value = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// simulates a copy constructor
|
||||
void operator()(const ReferenceContainer & value)
|
||||
{
|
||||
Counter::reference_reflect(value);
|
||||
|
||||
_reference_value = const_cast<Type *>(value._reference_value);
|
||||
};
|
||||
|
||||
// shortcut for operator below
|
||||
void operator=(const Type * value)
|
||||
{
|
||||
operator()(value);
|
||||
};
|
||||
|
||||
// accept value (pointer)!
|
||||
void operator()(const Type * value)
|
||||
{
|
||||
Counter::reference_restart((value != 0));
|
||||
|
||||
_reference_value = const_cast<Type *>(value);
|
||||
};
|
||||
|
||||
// return value (pointer)!
|
||||
Type * operator()(void)
|
||||
{
|
||||
return _reference_value;
|
||||
};
|
||||
|
||||
protected:
|
||||
Type * _reference_value;
|
||||
|
||||
protected:
|
||||
};
|
||||
|
||||
#endif /* _REFCOUNTER_HPP_ */
|
||||
@@ -0,0 +1,148 @@
|
||||
/*
|
||||
KHOMP generic endpoint/channel library.
|
||||
Copyright (C) 2007-2009 Khomp Ind. & Com.
|
||||
|
||||
The contents of this file are subject to the Mozilla Public License Version 1.1
|
||||
(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.mozilla.org/MPL/
|
||||
|
||||
Software distributed under the License is distributed on an "AS IS" basis,
|
||||
WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
|
||||
the specific language governing rights and limitations under the License.
|
||||
|
||||
Alternatively, the contents of this file may be used under the terms of the
|
||||
"GNU Lesser General Public License 2.1" license (the “LGPL" License), in which
|
||||
case the provisions of "LGPL License" are applicable instead of those above.
|
||||
|
||||
If you wish to allow use of your version of this file only under the terms of
|
||||
the LGPL License and not to allow others to use your version of this file under
|
||||
the MPL, indicate your decision by deleting the provisions above and replace them
|
||||
with the notice and other provisions required by the LGPL License. If you do not
|
||||
delete the provisions above, a recipient may use your version of this file under
|
||||
either the MPL or the LGPL License.
|
||||
|
||||
The LGPL header follows below:
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this library; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
*/
|
||||
|
||||
#include <regex.hpp>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
void Regex::Expression::initialize(void)
|
||||
{
|
||||
unsigned int tmplen = strlen(_expression);
|
||||
|
||||
bool extflag = (_flags & E_EXTENDED);
|
||||
|
||||
for (unsigned int i = 0; i < tmplen; ++i)
|
||||
{
|
||||
switch (_expression[i])
|
||||
{
|
||||
case '\\':
|
||||
++i;
|
||||
|
||||
if (!extflag && i < tmplen)
|
||||
if (_expression[i] == '(')
|
||||
++_subcounter;
|
||||
|
||||
break;
|
||||
|
||||
case '(':
|
||||
if (extflag)
|
||||
++_subcounter;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
_errorstate = regcomp(&_comp_regex, _expression, _flags);
|
||||
}
|
||||
|
||||
std::string Regex::Expression::regerror_as_string(void)
|
||||
{
|
||||
unsigned int count = regerror(_errorstate, &_comp_regex, 0, 0) + 1;
|
||||
|
||||
char * msg = new char[count];
|
||||
|
||||
regerror(_errorstate, &_comp_regex, msg, count);
|
||||
|
||||
std::string tmp(msg, count);
|
||||
|
||||
delete[] msg;
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
void Regex::Match::initialize(void)
|
||||
{
|
||||
if (_expression.valid())
|
||||
{
|
||||
_subcounter = (_expression.subcount() + 2); // 0 + N.. + invalid
|
||||
_submatches = new regmatch_t[_subcounter];
|
||||
_have_match = (regexec(_expression.repr(), _basestring.c_str(),
|
||||
_subcounter, _submatches, _flags) == 0);
|
||||
}
|
||||
}
|
||||
|
||||
std::string Regex::Match::replace(std::string rep, unsigned int index)
|
||||
{
|
||||
ReplaceMap tmp;
|
||||
tmp.insert(ReplacePair(index,rep));
|
||||
return replace(tmp);
|
||||
}
|
||||
|
||||
std::string Regex::Match::replace(Regex::ReplaceMap & map)
|
||||
{
|
||||
if (!_have_match)
|
||||
return _basestring;
|
||||
|
||||
std::string buffer = _basestring;
|
||||
|
||||
try
|
||||
{
|
||||
if (_submatches[0].rm_so != 0 && (map.find(0) != map.end()))
|
||||
return _basestring.replace(_submatches[0].rm_so, _submatches[0].rm_eo - _submatches[0].rm_so, map.find(0)->second);
|
||||
|
||||
for (unsigned int n = 1; (_submatches[n].rm_so != -1) && (n < _subcounter); n++)
|
||||
{
|
||||
//// s f RRR s f RRR s f RRRR s f
|
||||
//// XXXYYY(ZZZ)AAA(BBB)CCCEEE(FFFF)GGGG
|
||||
|
||||
bool globalsubs = false;
|
||||
|
||||
if (map.find(n) == map.end())
|
||||
{
|
||||
if (map.find(UINT_MAX) == map.end())
|
||||
continue;
|
||||
|
||||
globalsubs = true;
|
||||
}
|
||||
|
||||
buffer = buffer.replace(_submatches[n].rm_so,
|
||||
_submatches[n].rm_eo - _submatches[n].rm_so,
|
||||
map.find((globalsubs ? UINT_MAX : n))->second);
|
||||
}
|
||||
}
|
||||
catch (std::out_of_range e)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
return buffer;
|
||||
}
|
||||
@@ -0,0 +1,252 @@
|
||||
/*
|
||||
KHOMP generic endpoint/channel library.
|
||||
Copyright (C) 2007-2009 Khomp Ind. & Com.
|
||||
|
||||
The contents of this file are subject to the Mozilla Public License Version 1.1
|
||||
(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.mozilla.org/MPL/
|
||||
|
||||
Software distributed under the License is distributed on an "AS IS" basis,
|
||||
WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
|
||||
the specific language governing rights and limitations under the License.
|
||||
|
||||
Alternatively, the contents of this file may be used under the terms of the
|
||||
"GNU Lesser General Public License 2.1" license (the “LGPL" License), in which
|
||||
case the provisions of "LGPL License" are applicable instead of those above.
|
||||
|
||||
If you wish to allow use of your version of this file only under the terms of
|
||||
the LGPL License and not to allow others to use your version of this file under
|
||||
the MPL, indicate your decision by deleting the provisions above and replace them
|
||||
with the notice and other provisions required by the LGPL License. If you do not
|
||||
delete the provisions above, a recipient may use your version of this file under
|
||||
either the MPL or the LGPL License.
|
||||
|
||||
The LGPL header follows below:
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this library; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <limits.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <regex.h>
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <stdexcept>
|
||||
#include <map>
|
||||
|
||||
#include <refcounter.hpp>
|
||||
#include <noncopyable.hpp>
|
||||
|
||||
#ifndef _REGEX_HPP_
|
||||
#define _REGEX_HPP_
|
||||
|
||||
struct Regex
|
||||
{
|
||||
enum
|
||||
{
|
||||
E_EXTENDED = REG_EXTENDED,
|
||||
E_IGNORE_CASE = REG_ICASE,
|
||||
E_NO_SUB_MATCH = REG_NOSUB,
|
||||
E_EXPLICIT_NEWLINE = REG_NEWLINE,
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
M_NO_BEGIN_OF_LINE = REG_NOTBOL,
|
||||
M_NO_END_OF_LINE = REG_NOTEOL,
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
/* mark replace for full match (submatch "0"). */
|
||||
REP_BASE = 0u,
|
||||
/* mark global string for replace. */
|
||||
REP_ALL = UINT_MAX,
|
||||
};
|
||||
|
||||
typedef std::pair < unsigned int, std::string > ReplacePair;
|
||||
typedef std::map < unsigned int, std::string > ReplaceMap;
|
||||
|
||||
struct Expression : public NonCopyable
|
||||
{
|
||||
Expression(const char * expression, unsigned int flags = 0)
|
||||
: _expression(expression), _alloced(false),
|
||||
_subcounter(0), _errorstate(INT_MAX), _flags(flags)
|
||||
{
|
||||
initialize();
|
||||
}
|
||||
|
||||
Expression(std::string & expression, unsigned int flags = 0)
|
||||
: _expression(strdup(expression.c_str())), _alloced(true),
|
||||
_subcounter(0), _errorstate(INT_MAX), _flags(flags)
|
||||
{
|
||||
initialize();
|
||||
}
|
||||
|
||||
~Expression()
|
||||
{
|
||||
if (_errorstate != INT_MAX)
|
||||
regfree(&_comp_regex);
|
||||
|
||||
if (_alloced)
|
||||
{
|
||||
delete _expression;
|
||||
_expression = 0;
|
||||
}
|
||||
}
|
||||
|
||||
bool valid(void) { return (_errorstate == 0); }
|
||||
|
||||
unsigned int subcount(void) { return _subcounter; }
|
||||
const regex_t * repr(void) { return &_comp_regex; }
|
||||
|
||||
std::string error(void)
|
||||
{
|
||||
switch (_errorstate)
|
||||
{
|
||||
case 0: return "";
|
||||
case INT_MAX: return "uninitialized";
|
||||
default: return regerror_as_string();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
void initialize(void);
|
||||
std::string regerror_as_string(void);
|
||||
|
||||
protected:
|
||||
const char * _expression;
|
||||
bool _alloced;
|
||||
|
||||
unsigned int _subcounter;
|
||||
|
||||
int _errorstate;
|
||||
regex_t _comp_regex;
|
||||
|
||||
unsigned int _flags;
|
||||
};
|
||||
|
||||
struct Match: NEW_REFCOUNTER(Match)
|
||||
{
|
||||
Match(const char * basestring, Expression & expression, unsigned int flags = 0)
|
||||
: _basestring(basestring), _expression(expression), _subcounter(0), _submatches(0),
|
||||
_have_match(false), _flags(flags)
|
||||
{
|
||||
initialize();
|
||||
}
|
||||
|
||||
Match(std::string & basestring, Expression & expression, unsigned int flags = 0)
|
||||
: _basestring(basestring), _expression(expression), _subcounter(0), _submatches(0),
|
||||
_have_match(false), _flags(flags)
|
||||
{
|
||||
initialize();
|
||||
}
|
||||
|
||||
Match(const Match & o)
|
||||
: INC_REFCOUNTER(o, Match),
|
||||
_basestring(o._basestring), _expression(o._expression),
|
||||
_subcounter(o._subcounter), _submatches(o._submatches),
|
||||
_have_match(o._have_match), _flags(o._flags)
|
||||
{
|
||||
}
|
||||
|
||||
void unreference()
|
||||
{
|
||||
delete[] _submatches;
|
||||
}
|
||||
|
||||
bool matched(void)
|
||||
{
|
||||
return _have_match;
|
||||
}
|
||||
|
||||
bool matched(unsigned int number)
|
||||
{
|
||||
if (_have_match && number < _subcounter)
|
||||
return (_submatches[number].rm_so != -1);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string submatch(int number)
|
||||
{
|
||||
if (!matched(number))
|
||||
return "";
|
||||
|
||||
return _basestring.substr(_submatches[number].rm_so,
|
||||
_submatches[number].rm_eo - _submatches[number].rm_so);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief gets a map with all matches
|
||||
* \return std::map<int,std::string> with all matches
|
||||
* \note index 0 in map, is the complete string
|
||||
* \author Eduardo Nunes Pereira
|
||||
*
|
||||
* If fails the empty map is returned
|
||||
*/
|
||||
std::map<int, std::string> obtain_match_map()
|
||||
{
|
||||
int match_counter = 0;
|
||||
std::map<int,std::string> tmp_map;
|
||||
while(matched(match_counter))
|
||||
{
|
||||
tmp_map.insert(std::make_pair(match_counter,submatch(match_counter)));
|
||||
match_counter++;
|
||||
}
|
||||
|
||||
return tmp_map;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief replaces strings matched by parentesis
|
||||
* \param each item of the vector is a parentesis replaced
|
||||
* \return string replaced
|
||||
* \note The overload method match only one string in parentesis.
|
||||
* \author Eduardo Nunes Pereira
|
||||
*
|
||||
* If fails the empty string is returned.
|
||||
*/
|
||||
std::string replace(ReplaceMap &);
|
||||
std::string replace(std::string, unsigned int index = REP_BASE);
|
||||
|
||||
std::string operator[](int number)
|
||||
{
|
||||
return submatch(number);
|
||||
}
|
||||
|
||||
// NOTE: there is already a way to get subcount defined on EXPRESSION class!
|
||||
|
||||
private:
|
||||
void initialize(void);
|
||||
|
||||
protected:
|
||||
std::string _basestring;
|
||||
Expression & _expression;
|
||||
|
||||
unsigned int _subcounter;
|
||||
regmatch_t * _submatches;
|
||||
|
||||
bool _have_match;
|
||||
unsigned int _flags;
|
||||
};
|
||||
};
|
||||
|
||||
#endif /* _REGEX_HPP_ */
|
||||
|
||||
@@ -0,0 +1,575 @@
|
||||
/*
|
||||
KHOMP generic endpoint/channel library.
|
||||
Copyright (C) 2007-2009 Khomp Ind. & Com.
|
||||
|
||||
The contents of this file are subject to the Mozilla Public License Version 1.1
|
||||
(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.mozilla.org/MPL/
|
||||
|
||||
Software distributed under the License is distributed on an "AS IS" basis,
|
||||
WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
|
||||
the specific language governing rights and limitations under the License.
|
||||
|
||||
Alternatively, the contents of this file may be used under the terms of the
|
||||
"GNU Lesser General Public License 2.1" license (the “LGPL" License), in which
|
||||
case the provisions of "LGPL License" are applicable instead of those above.
|
||||
|
||||
If you wish to allow use of your version of this file only under the terms of
|
||||
the LGPL License and not to allow others to use your version of this file under
|
||||
the MPL, indicate your decision by deleting the provisions above and replace them
|
||||
with the notice and other provisions required by the LGPL License. If you do not
|
||||
delete the provisions above, a recipient may use your version of this file under
|
||||
either the MPL or the LGPL License.
|
||||
|
||||
The LGPL header follows below:
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this library; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
*/
|
||||
|
||||
#include <ringbuffer.hpp>
|
||||
|
||||
/********** BUFFER FUNCTIONS **********/
|
||||
|
||||
/* writes everything or nothing */
|
||||
bool Ringbuffer_traits::traits_provide(char * buffer, const char * value, unsigned int amount, bool skip_overwrite)
|
||||
{
|
||||
/* avoid using different values */
|
||||
Buffer_table cache = _pointers;
|
||||
|
||||
const unsigned int reader = cache.reader.complete;
|
||||
const unsigned int writer = cache.writer.complete;
|
||||
|
||||
const unsigned int dest = cache.writer.complete - 1;
|
||||
|
||||
const bool reader_less = cache.reader.complete < cache.writer.complete;
|
||||
|
||||
if (amount >= _size)
|
||||
return false;
|
||||
|
||||
bool ret = true;
|
||||
|
||||
/* should we go around the buffer for writing? */
|
||||
if (((writer + amount) > _size) && (reader_less || !skip_overwrite))
|
||||
{
|
||||
/* Documentation of the formula used in the 'if' below.
|
||||
*
|
||||
* [0|1|2|3|4|5|6|7] => size=8
|
||||
* | |
|
||||
* reader |
|
||||
* writer
|
||||
*
|
||||
* => writer has places [5,6,7,0,1] to write (5 places).
|
||||
*
|
||||
* => 8 - (4-2+1) = 8 - (2+1) = 8 - 3 = 5
|
||||
*
|
||||
* > writer goes 1 up, amount goes 1 down.
|
||||
* > reader goes 1 up, amount goes 1 up.
|
||||
* > size goes 1 down, amount goes 1 down.
|
||||
*
|
||||
*/
|
||||
|
||||
if ((_size - (writer - reader + 1)) <= amount)
|
||||
{
|
||||
if (skip_overwrite)
|
||||
return false;
|
||||
|
||||
do
|
||||
{
|
||||
Buffer_pointer extra(cache.reader);
|
||||
extra.complete = (extra.complete + amount) % _size;
|
||||
|
||||
if (update(cache.reader, extra))
|
||||
break;
|
||||
}
|
||||
while (true);
|
||||
|
||||
ret = false;
|
||||
}
|
||||
|
||||
unsigned int wr1 = _size - writer + 1; /* writer is already 1 position after */
|
||||
unsigned int wr2 = amount - wr1;
|
||||
|
||||
// fprintf(stderr, "%p> partial write: (%d/%d) %d/%d [%d/%d]\n", this, wr1, wr2, amount, _size, reader, writer);
|
||||
|
||||
/* two partial writes (one at the end, another at the beginning) */
|
||||
memcpy((void *) &(buffer[dest]), (const void *) (value), _block * wr1);
|
||||
memcpy((void *) (buffer), (const void *) &(value[wr1]), _block * wr2);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!reader_less && ((reader - writer) <= amount))
|
||||
{
|
||||
if (skip_overwrite)
|
||||
return false;
|
||||
|
||||
do
|
||||
{
|
||||
Buffer_pointer extra(cache.reader);
|
||||
extra.complete = (extra.complete + amount) % _size;
|
||||
|
||||
if (update(cache.reader, extra))
|
||||
break;
|
||||
}
|
||||
while (true);
|
||||
|
||||
ret = false;
|
||||
}
|
||||
|
||||
// fprintf(stderr, "%p> full write: a=%d/s=%d [r=%d/w=%d]\n", this, amount, _size, reader, writer);
|
||||
|
||||
/* we are talking about buffers here, man! */
|
||||
memcpy((void *) &(buffer[dest]), (const void *) value, _block * amount);
|
||||
}
|
||||
|
||||
_pointers.writer.complete = ((dest + amount) % _size) + 1;
|
||||
_pointers.writer.partial = 1;
|
||||
|
||||
// fprintf(stderr, "%p> write end: %d [block=%d]\n", this, writer, _block);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* returns the number of itens that have been read */
|
||||
unsigned int Ringbuffer_traits::traits_consume(const char * buffer, char * value, unsigned int amount, bool atomic_mode)
|
||||
{
|
||||
/* avoid using different values */
|
||||
Buffer_table cache = _pointers;
|
||||
|
||||
const unsigned int writer = _pointers.writer.complete;
|
||||
const unsigned int reader = _pointers.reader.complete;
|
||||
|
||||
const bool writer_less = writer < reader;
|
||||
|
||||
unsigned int total = 0;
|
||||
|
||||
/* should we go around the buffer for reading? */
|
||||
if (writer_less && (reader + amount >= _size))
|
||||
{
|
||||
total = std::min(_size - (reader - writer + 1), amount);
|
||||
|
||||
if ((total == 0) || (atomic_mode && (total < amount)))
|
||||
return 0;
|
||||
|
||||
unsigned int rd1 = _size - reader;
|
||||
unsigned int rd2 = total - rd1;
|
||||
|
||||
// fprintf(stderr, "%p> partial read: (%d/%d) %d/%d [%d/%d]\n", this, rd1, rd2, total, _size, reader, writer);
|
||||
|
||||
/* two partial consumes (one at the end, another at the beginning) */
|
||||
memcpy((void *) (value), (const void *) &(buffer[reader]), _block * rd1);
|
||||
memcpy((void *) &(value[rd1]), (const void *) (buffer), _block * rd2);
|
||||
}
|
||||
else
|
||||
{
|
||||
total = std::min((!writer_less ? writer - (reader + 1) : amount), amount);
|
||||
|
||||
if ((total == 0) || (atomic_mode && (total < amount)))
|
||||
return 0;
|
||||
|
||||
// fprintf(stderr, "%p> full read: %d/%d [%d/%d]\n", this, total, _size, reader, writer);
|
||||
|
||||
/* we are talking about buffers here, man! */
|
||||
memcpy((void *) value, (const void *) &(buffer[reader]), _block * total);
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
/* jump the reader forward */
|
||||
Buffer_pointer index((cache.reader.complete + total) % _size);
|
||||
|
||||
if (update(cache.reader, index))
|
||||
break;
|
||||
}
|
||||
while (true);
|
||||
|
||||
// fprintf(stderr, "%p> read end: %d [block=%d]\n", this, reader, _block);
|
||||
|
||||
return total;
|
||||
}
|
||||
|
||||
/********** TWO-PHASE BUFFER FUNCTIONS ***********/
|
||||
|
||||
/* returns the number of itens that have been read */
|
||||
unsigned int Ringbuffer_traits::traits_consume_begins(const char * buffer, char * value, unsigned int amount, bool atomic_mode)
|
||||
{
|
||||
Buffer_table cache = _pointers;
|
||||
|
||||
/* avoid using different values */
|
||||
const unsigned int reader = cache.reader.complete;
|
||||
const unsigned int writer = cache.writer.complete;
|
||||
|
||||
const bool writer_less = writer < reader;
|
||||
|
||||
unsigned int total = 0;
|
||||
|
||||
/* should we go around the buffer for reading? */
|
||||
if (writer_less && (reader + amount >= _size))
|
||||
{
|
||||
total = std::min(_size - (reader - writer + 1), amount);
|
||||
|
||||
if ((total == 0) || (atomic_mode && (total < amount)))
|
||||
return 0;
|
||||
|
||||
unsigned int rd1 = _size - reader;
|
||||
unsigned int rd2 = total - rd1;
|
||||
|
||||
// fprintf(stderr, "%p> partial read: (%d/%d) %d/%d [%d/%d]\n", this, rd1, rd2, total, _size, reader, writer);
|
||||
|
||||
/* two partial consumes (one at the end, another at the beginning) */
|
||||
memcpy((void *) (value), (const void *) &(buffer[reader]), _block * rd1);
|
||||
memcpy((void *) &(value[rd1]), (const void *) (buffer), _block * rd2);
|
||||
}
|
||||
else
|
||||
{
|
||||
total = std::min((!writer_less ? writer - (reader + 1) : amount), amount);
|
||||
|
||||
if ((total == 0) || (atomic_mode && (total < amount)))
|
||||
return 0;
|
||||
|
||||
// fprintf(stderr, "%p> full read: %d/%d [%d/%d]\n", this, total, _size, reader, writer);
|
||||
|
||||
/* we are talking about buffers here, man! */
|
||||
memcpy((void *) value, (const void *) &(buffer[reader]), _block * total);
|
||||
}
|
||||
|
||||
// fprintf(stderr, "%p> read end: %d [%d]\n", this, _reader, _reader_partial);
|
||||
|
||||
return total;
|
||||
}
|
||||
|
||||
bool Ringbuffer_traits::traits_consume_commit(unsigned int amount)
|
||||
{
|
||||
/* avoid using different values */
|
||||
Buffer_table cache = _pointers;
|
||||
|
||||
const unsigned int writer = cache.writer.complete;
|
||||
const unsigned int reader = cache.reader.complete;
|
||||
|
||||
const bool writer_less = writer < reader;
|
||||
|
||||
unsigned int total = 0;
|
||||
|
||||
/* should we go around the buffer for reading? */
|
||||
if (writer_less && (reader + amount >= _size))
|
||||
{
|
||||
total = std::min(_size - (reader - writer + 1), amount);
|
||||
|
||||
if (total < amount)
|
||||
return false;
|
||||
|
||||
// fprintf(stderr, "%p> partial read: (%d/%d) %d/%d [%d/%d]\n", this, rd1, rd2, total, _size, reader, writer);
|
||||
}
|
||||
else
|
||||
{
|
||||
total = std::min((!writer_less ? writer - (reader + 1) : amount), amount);
|
||||
|
||||
if (total < amount)
|
||||
return false;
|
||||
|
||||
// fprintf(stderr, "%p> full read: %d/%d [%d/%d]\n", this, total, _size, reader, writer);
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
/* jump the reader forward */
|
||||
Buffer_pointer index(cache.reader);
|
||||
index.complete = (index.complete + total) % _size;
|
||||
|
||||
if (update(cache.reader, index))
|
||||
break;
|
||||
}
|
||||
while (true);
|
||||
|
||||
// fprintf(stderr, "%p> read end: %d [%d]\n", this, _reader, _reader_partial);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/********** PARTIAL BUFFER FUNCTIONS (bytes) ***********/
|
||||
|
||||
/* writes everything or nothing */
|
||||
bool Ringbuffer_traits::traits_provide_partial(char * buffer, const char * value, unsigned int amount)
|
||||
{
|
||||
/* avoid using different values */
|
||||
Buffer_table cache = _pointers;
|
||||
|
||||
const unsigned int reader = (cache.reader.complete * _block) + cache.reader.partial;
|
||||
const unsigned int writer = ((cache.writer.complete - 1) * _block) + cache.writer.partial;
|
||||
|
||||
const unsigned int size = _size * _block;
|
||||
const unsigned int dest = writer - 1;
|
||||
|
||||
// fprintf(stderr, "%p> provide partial: %d/%d [%d/%d]\n", this, reader, writer, amount, size);
|
||||
|
||||
const bool reader_less = reader < writer;
|
||||
|
||||
/* should we go around the buffer for writing? */
|
||||
if (reader_less && ((writer + amount) > size))
|
||||
{
|
||||
/* Documentation of the formula used in the 'if' below.
|
||||
*
|
||||
* [0|1|2|3|4|5|6|7] => size=8
|
||||
* | |
|
||||
* reader |
|
||||
* writer
|
||||
*
|
||||
* => writer has places [5,6,7,0,1] to write (5 places).
|
||||
*
|
||||
* => 8 - (4-2+1) = 8 - (2+1) = 8 - 3 = 5
|
||||
*
|
||||
* > writer goes 1 up, amount goes 1 down.
|
||||
* > reader goes 1 up, amount goes 1 up.
|
||||
* > size goes 1 down, amount goes 1 down.
|
||||
*
|
||||
*/
|
||||
|
||||
if ((size - (writer - reader + 1)) <= amount)
|
||||
return false;
|
||||
|
||||
unsigned int wr1 = size - writer + 1; /* writer is already 1 position after */
|
||||
unsigned int wr2 = amount - wr1;
|
||||
|
||||
// fprintf(stderr, "%p> p partial write: (%d/%d) %d/%d [%d/%d]\n", this, wr1, wr2, amount, size, reader, writer);
|
||||
|
||||
/* two partial writes (one at the end, another at the beginning) */
|
||||
memcpy((void *) &(buffer[dest]), (const void *) (value), wr1);
|
||||
memcpy((void *) (buffer), (const void *) &(value[wr1]), wr2);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!reader_less && ((reader - writer) <= amount))
|
||||
return false;
|
||||
|
||||
// fprintf(stderr, "%p> p full write: %d/%d [r=%d/w=%d]\n", this, amount, size, reader, writer);
|
||||
|
||||
/* we are talking about buffers here, man! */
|
||||
memcpy((void *) &(buffer[dest]), (const void *) value, amount);
|
||||
}
|
||||
|
||||
unsigned int new_writer = ((dest + amount) % size) + 1;
|
||||
|
||||
/* update "full length position" */
|
||||
_pointers.writer.complete = (unsigned int)floor((double) new_writer / (double)_block)+1;
|
||||
_pointers.writer.partial = (unsigned short)(new_writer % _block);
|
||||
|
||||
// fprintf(stderr, "%p> p write end: %d [block=%d]\n", this, new_writer, _block);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* returns the number of bytes that have been read */
|
||||
unsigned int Ringbuffer_traits::traits_consume_partial(const char * buffer, char * value, unsigned int amount)
|
||||
{
|
||||
/* avoid using different values */
|
||||
Buffer_table cache = _pointers;
|
||||
|
||||
const unsigned int writer = ((cache.writer.complete - 1) * _block) + cache.writer.partial;
|
||||
const unsigned int reader = (cache.reader.complete * _block) + cache.reader.partial;
|
||||
|
||||
const unsigned int size = _size * _block;
|
||||
|
||||
// fprintf(stderr, "%p> consume partial: %d/%d [%d/%d]\n", this, reader, writer, amount, size);
|
||||
|
||||
const bool writer_less = writer < reader;
|
||||
|
||||
unsigned int total = 0;
|
||||
|
||||
/* should we go around the buffer for reading? */
|
||||
if (writer_less && (reader + amount >= size))
|
||||
{
|
||||
total = std::min(size - (reader - writer + 1), amount);
|
||||
|
||||
if (total == 0)
|
||||
return 0;
|
||||
|
||||
unsigned int rd1 = size - reader;
|
||||
unsigned int rd2 = total - rd1;
|
||||
|
||||
// fprintf(stderr, "%p> p partial read: (%d/%d) %d/%d [%d/%d]\n", this, rd1, rd2, total, size, reader, writer);
|
||||
|
||||
/* two partial consumes (one at the end, another at the beginning) */
|
||||
memcpy((void *) (value), (const void *) &(buffer[reader]), rd1);
|
||||
memcpy((void *) &(value[rd1]), (const void *) (buffer), rd2);
|
||||
}
|
||||
else
|
||||
{
|
||||
total = std::min((writer_less ? amount : writer - (reader + 1)), amount);
|
||||
|
||||
if (total == 0)
|
||||
return 0;
|
||||
|
||||
// fprintf(stderr, "%p> p full read: %d/%d [r=%d/w=%d]\n", this, total, size, reader, writer);
|
||||
|
||||
/* we are talking about buffers here, man! */
|
||||
memcpy((void *) value, (const void *) &(buffer[reader]), total);
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
unsigned int new_reader = (((cache.reader.complete * _block) + cache.reader.partial) + total) % size;
|
||||
|
||||
/* jump the reader forward */
|
||||
Buffer_pointer index((unsigned int)floor((double)new_reader / (double)_block),
|
||||
(unsigned short)(new_reader % _block));
|
||||
|
||||
if (update(cache.reader, index))
|
||||
{
|
||||
// fprintf(stderr, "%p> p read end: %d [block=%d]\n", this, new_reader, _block);
|
||||
break;
|
||||
}
|
||||
}
|
||||
while (true);
|
||||
|
||||
return total;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/********** IO FUNCTIONS **********/
|
||||
|
||||
/* returns the number of items written to from buffer to stream */
|
||||
unsigned int Ringbuffer_traits::traits_put(const char * buffer, std::ostream &fd, unsigned int amount)
|
||||
{
|
||||
/* avoid using different values */
|
||||
Buffer_table cache = _pointers;
|
||||
|
||||
const unsigned int reader = cache.reader.complete;
|
||||
const unsigned int writer = cache.writer.complete;
|
||||
|
||||
const bool writer_less = writer < reader;
|
||||
|
||||
unsigned int total = 0;
|
||||
|
||||
/* should we go around the buffer for reading? */
|
||||
if (writer_less && (reader + amount >= _size))
|
||||
{
|
||||
total = std::min(_size - (reader - writer + 1), amount);
|
||||
|
||||
if (total == 0)
|
||||
return 0;
|
||||
|
||||
unsigned int rd1 = _size - reader;
|
||||
unsigned int rd2 = total - rd1;
|
||||
|
||||
// fprintf(stderr, "%p> partial read: (%d/%d) %d/%d [%d/%d]\n", this, rd1, rd2, total, _size, reader, writer);
|
||||
|
||||
/* two partial consumes (one at the end, another at the beginning) */
|
||||
fd.write((const char *) &(buffer[reader]), _block * rd1);
|
||||
fd.write((const char *) (buffer), _block * rd2);
|
||||
}
|
||||
else
|
||||
{
|
||||
total = std::min((!writer_less ? writer - (reader + 1) : amount), amount);
|
||||
|
||||
if (total == 0)
|
||||
return 0;
|
||||
|
||||
// fprintf(stderr, "%p> full read: %d/%d [%d/%d]\n", this, total, _size, reader, writer);
|
||||
|
||||
/* we are talking about buffers here, man! */
|
||||
fd.write((const char *) &(buffer[reader]), _block * total);
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
/* jump the reader forward */
|
||||
Buffer_pointer index(cache.reader);
|
||||
index.complete = (index.complete + total) % _size;
|
||||
|
||||
if (update(cache.reader, index))
|
||||
break;
|
||||
}
|
||||
while (true);
|
||||
|
||||
return total;
|
||||
}
|
||||
|
||||
/* returns number of items read from stream to buffer */
|
||||
unsigned int Ringbuffer_traits::traits_get(char * buffer, std::istream &fd, unsigned int amount)
|
||||
{
|
||||
/* avoid using different values */
|
||||
Buffer_table cache = _pointers;
|
||||
|
||||
const unsigned int reader = cache.reader.complete;
|
||||
const unsigned int writer = cache.writer.complete;
|
||||
|
||||
const unsigned int dest = writer - 1;
|
||||
|
||||
const bool reader_less = reader < writer;
|
||||
|
||||
unsigned int real_amount = 0;
|
||||
|
||||
/* should we go around the buffer for writing? */
|
||||
if (reader_less && ((writer + amount) > _size))
|
||||
{
|
||||
/* Documentation of the formula used in the 'if' below.
|
||||
*
|
||||
* [0|1|2|3|4|5|6|7] => size=8
|
||||
* | |
|
||||
* reader |
|
||||
* writer
|
||||
*
|
||||
* => writer has places [5,6,7,0,1] to write (5 places).
|
||||
*
|
||||
* => 8 - (4-2+1) = 8 - (2+1) = 8 - 3 = 5
|
||||
*
|
||||
* > writer goes 1 up, amount goes 1 down.
|
||||
* > reader goes 1 up, amount goes 1 up.
|
||||
* > size goes 1 down, amount goes 1 down.
|
||||
*
|
||||
*/
|
||||
|
||||
if ((_size - (writer - reader + 1)) <= amount)
|
||||
return false;
|
||||
|
||||
unsigned int wr1 = _size - writer + 1; /* writer is already 1 position after */
|
||||
unsigned int wr2 = amount - wr1;
|
||||
|
||||
// fprintf(stderr, "%p> partial write: (%d/%d) %d/%d [%d/%d]\n", this, wr1, wr2, amount, _size, reader, writer);
|
||||
|
||||
unsigned int char_amount = 0;
|
||||
|
||||
/* one partial write on the buffer (at the end) */
|
||||
fd.read((char *) &(buffer[dest]), _block * wr1);
|
||||
char_amount += fd.gcount();
|
||||
|
||||
if (fd.gcount() == (int)(_block * wr1))
|
||||
{
|
||||
/* another partial write on the buffer (at the beginning) */
|
||||
fd.read((char *) (buffer), _block * wr2);
|
||||
char_amount += fd.gcount();
|
||||
}
|
||||
|
||||
real_amount = char_amount / _block;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!reader_less && ((reader - writer) <= amount))
|
||||
return false;
|
||||
|
||||
// fprintf(stderr, "%p> full write: %d/%d [%d/%d]\n", this, amount, _size, reader, writer);
|
||||
|
||||
/* we are talking about buffers here, man! */
|
||||
fd.read((char *) &(buffer[dest]), _block * amount);
|
||||
|
||||
real_amount = fd.gcount() / _block;
|
||||
}
|
||||
|
||||
_pointers.writer.complete = ((dest + real_amount) % _size) + 1;
|
||||
_pointers.writer.partial = 1;
|
||||
|
||||
return real_amount;
|
||||
}
|
||||
@@ -0,0 +1,416 @@
|
||||
/*
|
||||
KHOMP generic endpoint/channel library.
|
||||
Copyright (C) 2007-2009 Khomp Ind. & Com.
|
||||
|
||||
The contents of this file are subject to the Mozilla Public License Version 1.1
|
||||
(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.mozilla.org/MPL/
|
||||
|
||||
Software distributed under the License is distributed on an "AS IS" basis,
|
||||
WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
|
||||
the specific language governing rights and limitations under the License.
|
||||
|
||||
Alternatively, the contents of this file may be used under the terms of the
|
||||
"GNU Lesser General Public License 2.1" license (the “LGPL" License), in which
|
||||
case the provisions of "LGPL License" are applicable instead of those above.
|
||||
|
||||
If you wish to allow use of your version of this file only under the terms of
|
||||
the LGPL License and not to allow others to use your version of this file under
|
||||
the MPL, indicate your decision by deleting the provisions above and replace them
|
||||
with the notice and other provisions required by the LGPL License. If you do not
|
||||
delete the provisions above, a recipient may use your version of this file under
|
||||
either the MPL or the LGPL License.
|
||||
|
||||
The LGPL header follows below:
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this library; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
*/
|
||||
|
||||
/* WARNING: This is a generic ringbuffer abstraction, which works for single-sized elements,
|
||||
partial elements, single/multi-elements read/writes. It is not wise to mix some
|
||||
functions (partial element write / full element write), since it was not designed
|
||||
with this use in mind.
|
||||
|
||||
Also, it works only for single-reader + single-writer, since it does not depends
|
||||
on external mutex functions.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <cmath>
|
||||
#include <iostream>
|
||||
|
||||
#include <noncopyable.hpp>
|
||||
#include <atomic.hpp>
|
||||
|
||||
#ifndef _RINGBUFFER_HPP_
|
||||
#define _RINGBUFFER_HPP_
|
||||
|
||||
struct Buffer_pointer
|
||||
{
|
||||
Buffer_pointer(unsigned int _complete = 0u, unsigned short _partial = 0u)
|
||||
: complete(_complete), partial(_partial)
|
||||
{};
|
||||
|
||||
Buffer_pointer(const Buffer_pointer & o)
|
||||
: complete(o.complete), partial(o.partial)
|
||||
{};
|
||||
|
||||
Buffer_pointer(const volatile Buffer_pointer & o)
|
||||
: complete(o.complete), partial(o.partial)
|
||||
{};
|
||||
|
||||
void operator=(const volatile Buffer_pointer o)
|
||||
{
|
||||
complete = o.complete;
|
||||
partial = o.partial;
|
||||
}
|
||||
|
||||
void operator=(const Buffer_pointer o) volatile
|
||||
{
|
||||
complete = o.complete;
|
||||
partial = o.partial;
|
||||
}
|
||||
|
||||
bool operator==(const Buffer_pointer & o)
|
||||
{
|
||||
return (complete == o.complete && partial == o.partial);
|
||||
}
|
||||
|
||||
unsigned int complete:20;
|
||||
unsigned short partial:12;
|
||||
}
|
||||
__attribute__((packed));
|
||||
|
||||
struct Buffer_table
|
||||
{
|
||||
Buffer_table()
|
||||
: reader(0,0),
|
||||
writer(1,1)
|
||||
{};
|
||||
|
||||
Buffer_table(const Buffer_table & o)
|
||||
: reader(o.reader), writer(o.writer)
|
||||
{};
|
||||
|
||||
Buffer_table(const volatile Buffer_table & o)
|
||||
: reader(o.reader), writer(o.writer)
|
||||
{};
|
||||
|
||||
void operator=(const volatile Buffer_table o)
|
||||
{
|
||||
reader = o.reader;
|
||||
writer = o.writer;
|
||||
}
|
||||
|
||||
void operator=(const Buffer_table o) volatile
|
||||
{
|
||||
reader = o.reader;
|
||||
writer = o.writer;
|
||||
}
|
||||
|
||||
bool operator==(const Buffer_table & o)
|
||||
{
|
||||
return (reader == o.reader && writer == o.writer);
|
||||
}
|
||||
|
||||
Buffer_pointer reader;
|
||||
Buffer_pointer writer;
|
||||
}
|
||||
__attribute__((packed));
|
||||
|
||||
struct Ringbuffer_traits
|
||||
{
|
||||
Ringbuffer_traits(unsigned int block, unsigned int size)
|
||||
: _block(block), _size(size)
|
||||
{};
|
||||
|
||||
bool traits_provide( char *, const char *, unsigned int, bool);
|
||||
unsigned int traits_consume(const char *, char *, unsigned int, bool);
|
||||
|
||||
unsigned int traits_consume_begins(const char *, char *, unsigned int, bool);
|
||||
bool traits_consume_commit(unsigned int);
|
||||
|
||||
bool traits_provide_partial( char *, const char *, unsigned int);
|
||||
unsigned int traits_consume_partial(const char *, char *, unsigned int);
|
||||
|
||||
unsigned int traits_get( char *, std::istream &, unsigned int);
|
||||
unsigned int traits_put(const char *, std::ostream &, unsigned int);
|
||||
|
||||
bool update(Buffer_pointer & cache, Buffer_pointer & update)
|
||||
{
|
||||
return Atomic::doCAS(&(_pointers.reader), &cache, update);
|
||||
}
|
||||
|
||||
protected:
|
||||
const unsigned int _block;
|
||||
const unsigned int _size;
|
||||
|
||||
volatile Buffer_table _pointers;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct Ringbuffer: protected Ringbuffer_traits, public NonCopyable
|
||||
{
|
||||
struct BufferFull {};
|
||||
struct BufferEmpty {};
|
||||
|
||||
Ringbuffer(unsigned int size)
|
||||
: Ringbuffer_traits(sizeof(T), size)
|
||||
{
|
||||
_buffer = new T[_size];
|
||||
_malloc = true;
|
||||
};
|
||||
|
||||
Ringbuffer(unsigned int size, T * buffer)
|
||||
: Ringbuffer_traits(sizeof(T), size)
|
||||
{
|
||||
_buffer = buffer;
|
||||
_malloc = false;
|
||||
};
|
||||
|
||||
~Ringbuffer()
|
||||
{
|
||||
if (_malloc)
|
||||
delete[] _buffer;
|
||||
}
|
||||
|
||||
/***** GENERIC RANGE/INDEX CALCULATION FUNCTIONS *****/
|
||||
bool may_write(Buffer_table & cache)
|
||||
{
|
||||
const unsigned int r = cache.reader.complete;
|
||||
const unsigned int w = cache.writer.complete;
|
||||
|
||||
return (((r - w) != 1) && (!(r == 0 && w == _size)));
|
||||
}
|
||||
|
||||
bool may_read(Buffer_table & cache)
|
||||
{
|
||||
if ((cache.writer.complete - cache.reader.complete) == 1)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
unsigned int writer_next(Buffer_pointer & cache, Buffer_pointer & index)
|
||||
{
|
||||
unsigned int dest = cache.complete - 1,
|
||||
temp = cache.complete + 1;
|
||||
|
||||
if (temp > _size) index.complete = 1;
|
||||
else index.complete = temp;
|
||||
|
||||
index.partial = 1;
|
||||
|
||||
return dest;
|
||||
};
|
||||
|
||||
void reader_next(Buffer_pointer & cache, Buffer_pointer & index)
|
||||
{
|
||||
unsigned int temp = cache.complete + 1;
|
||||
|
||||
if (temp == _size) index.complete = 0;
|
||||
else index.complete = temp;
|
||||
|
||||
index.partial = 0;
|
||||
}
|
||||
|
||||
/***** BUFFER FUNCTIONS *****/
|
||||
|
||||
bool provide(const T & value)
|
||||
{
|
||||
Buffer_table cache = _pointers;
|
||||
Buffer_pointer index = _pointers.writer;
|
||||
|
||||
if (!may_write(cache))
|
||||
return false;
|
||||
|
||||
// fprintf(stderr, "%p> provide %d/%d!\n", this, reader, writer);
|
||||
|
||||
unsigned int dest = writer_next(cache.writer, index);
|
||||
|
||||
_buffer[dest] = value;
|
||||
|
||||
_pointers.writer = index;
|
||||
|
||||
// fprintf(stderr, "%p> write: %d/%d [%d/%d]\n", this, _pointers.reader, _pointers.writer, _pointers.reader_partial, _pointers.writer_partial);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool consume(T & value)
|
||||
{
|
||||
Buffer_table cache = _pointers;
|
||||
Buffer_pointer index = _pointers.reader;
|
||||
|
||||
if (!may_read(cache))
|
||||
return false;
|
||||
|
||||
// fprintf(stderr, "%p> consume %d/%d!\n", this, reader, writer);
|
||||
|
||||
value = _buffer[index.complete];
|
||||
|
||||
do
|
||||
{
|
||||
reader_next(cache.reader, index);
|
||||
|
||||
if (update(cache.reader, index))
|
||||
break;
|
||||
|
||||
cache.reader = index;
|
||||
}
|
||||
while (true);
|
||||
|
||||
// fprintf(stderr, "%p> read: %d/%d [%d/%d]\n", this, _pointers.reader, _pointers.writer, _pointers.reader_partial, _pointers.writer_partial);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* writes everything or nothing */
|
||||
inline bool provide(const T * value, unsigned int amount, bool skip_overwrite = true)
|
||||
{
|
||||
return traits_provide((char *)_buffer, (const char *) value, amount, skip_overwrite);
|
||||
}
|
||||
|
||||
/* returns the number of items that have been read (atomic_mode == true means 'all or nothing') */
|
||||
inline unsigned int consume(T * value, unsigned int amount, bool atomic_mode = false)
|
||||
{
|
||||
return traits_consume((const char *)_buffer, (char *) value, amount, atomic_mode);
|
||||
}
|
||||
|
||||
/***** TWO-PHASE BUFFER FUNCTIONS *****/
|
||||
|
||||
/* returns the number of items that have been read (atomic_mode == true means 'all or nothing') */
|
||||
inline unsigned int consume_begins(T * value, unsigned int amount, bool atomic_mode = false)
|
||||
{
|
||||
return traits_consume_begins((const char *)_buffer, (char *) value, amount, atomic_mode);
|
||||
}
|
||||
|
||||
/* returns true if we could commit that much of buffer (use only after consume_begins). *
|
||||
* note: you may commit less bytes that have been read to keep some data inside the buffer */
|
||||
inline bool consume_commit(unsigned int amount)
|
||||
{
|
||||
return traits_consume_commit(amount);
|
||||
}
|
||||
|
||||
/***** TWO-PHASE SINGLE-ELEMENT BUFFER FUNCTIONS *****/
|
||||
|
||||
T & provider_start(void)
|
||||
{
|
||||
Buffer_table cache = _pointers;
|
||||
|
||||
if (!may_write(cache))
|
||||
throw BufferFull();
|
||||
|
||||
unsigned writer = _pointers.writer.complete - 1;
|
||||
|
||||
// fprintf(stderr, "%p> provider start %d/%d!\n", this, reader, writer);
|
||||
|
||||
return _buffer[writer];
|
||||
}
|
||||
|
||||
void provider_commit(void)
|
||||
{
|
||||
unsigned int temp = _pointers.writer.complete + 1;
|
||||
|
||||
// fprintf(stderr, "%p> provider commit %d!\n", this, temp);
|
||||
|
||||
if (temp > _size)
|
||||
temp = 1;
|
||||
|
||||
_pointers.writer.complete = temp;
|
||||
_pointers.writer.partial = 1;
|
||||
|
||||
// fprintf(stderr, "%p> write: %d/%d [%d/%d]\n", this, _pointers.reader, _pointers.writer, _pointers.reader_partial, _pointers.writer_partial);
|
||||
}
|
||||
|
||||
T & consumer_start(void)
|
||||
{
|
||||
Buffer_table cache = _pointers;
|
||||
|
||||
if (!may_read(cache))
|
||||
throw BufferEmpty();
|
||||
|
||||
unsigned int reader = _pointers.reader.complete;
|
||||
|
||||
// fprintf(stderr, "%p> consumer start %d/%d!\n", this, reader, writer);
|
||||
|
||||
return _buffer[reader];
|
||||
}
|
||||
|
||||
void consumer_commit(void)
|
||||
{
|
||||
Buffer_pointer cache = _pointers.reader;
|
||||
Buffer_pointer index(cache);
|
||||
|
||||
do
|
||||
{
|
||||
reader_next(cache, index);
|
||||
|
||||
if (update(cache, index))
|
||||
break;
|
||||
|
||||
cache = index;
|
||||
}
|
||||
while (true);
|
||||
|
||||
// fprintf(stderr, "%p> consumer commit %d!\n", this, temp);
|
||||
|
||||
// fprintf(stderr, "%p> read: %d/%d [%d/%d]\n", this, _pointers.reader, _pointers.writer, _pointers.reader_partial, _pointers.writer_partial);
|
||||
}
|
||||
|
||||
/* writes everything or nothing, but works on bytes (may write incomplete elements) */
|
||||
/* WARNING: do not mix this with full element provider */
|
||||
inline bool provider_partial(const char *buffer, unsigned int amount)
|
||||
{
|
||||
return traits_provide_partial((char *)_buffer, buffer, amount);
|
||||
}
|
||||
|
||||
/* returns the number of bytes that have been read (may read incomplete elements) */
|
||||
/* WARNING: do not mix this with full element consumer */
|
||||
inline unsigned int consumer_partial(char *buffer, unsigned int amount)
|
||||
{
|
||||
return traits_consume_partial((const char *)_buffer, buffer, amount);
|
||||
}
|
||||
|
||||
/***** IO FUNCTIONS *****/
|
||||
|
||||
/* returns the number of items written to from buffer to stream */
|
||||
inline unsigned int put(std::ostream &fd, unsigned int amount)
|
||||
{
|
||||
return traits_put((char *)_buffer, fd, amount);
|
||||
}
|
||||
|
||||
/* returns number of items read from stream to buffer */
|
||||
inline unsigned int get(std::istream &fd, unsigned int amount)
|
||||
{
|
||||
return traits_get((const char *)_buffer, fd, amount);
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
_pointers.reader.complete = 0;
|
||||
_pointers.reader.partial = 0;
|
||||
_pointers.writer.complete = 1;
|
||||
_pointers.writer.partial = 1;
|
||||
}
|
||||
|
||||
protected:
|
||||
T * _buffer;
|
||||
bool _malloc;
|
||||
};
|
||||
|
||||
#endif /* _RINGBUFFER_HPP_ */
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
KHOMP generic endpoint/channel library.
|
||||
Copyright (C) 2007-2009 Khomp Ind. & Com.
|
||||
|
||||
The contents of this file are subject to the Mozilla Public License Version 1.1
|
||||
(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.mozilla.org/MPL/
|
||||
|
||||
Software distributed under the License is distributed on an "AS IS" basis,
|
||||
WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
|
||||
the specific language governing rights and limitations under the License.
|
||||
|
||||
Alternatively, the contents of this file may be used under the terms of the
|
||||
"GNU Lesser General Public License 2.1" license (the “LGPL" License), in which
|
||||
case the provisions of "LGPL License" are applicable instead of those above.
|
||||
|
||||
If you wish to allow use of your version of this file only under the terms of
|
||||
the LGPL License and not to allow others to use your version of this file under
|
||||
the MPL, indicate your decision by deleting the provisions above and replace them
|
||||
with the notice and other provisions required by the LGPL License. If you do not
|
||||
delete the provisions above, a recipient may use your version of this file under
|
||||
either the MPL or the LGPL License.
|
||||
|
||||
The LGPL header follows below:
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this library; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#include <config_commons.hpp>
|
||||
|
||||
#include COMMONS_INCLUDE(saved_condition.cpp)
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
KHOMP generic endpoint/channel library.
|
||||
Copyright (C) 2007-2009 Khomp Ind. & Com.
|
||||
|
||||
The contents of this file are subject to the Mozilla Public License Version 1.1
|
||||
(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.mozilla.org/MPL/
|
||||
|
||||
Software distributed under the License is distributed on an "AS IS" basis,
|
||||
WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
|
||||
the specific language governing rights and limitations under the License.
|
||||
|
||||
Alternatively, the contents of this file may be used under the terms of the
|
||||
"GNU Lesser General Public License 2.1" license (the “LGPL" License), in which
|
||||
case the provisions of "LGPL License" are applicable instead of those above.
|
||||
|
||||
If you wish to allow use of your version of this file only under the terms of
|
||||
the LGPL License and not to allow others to use your version of this file under
|
||||
the MPL, indicate your decision by deleting the provisions above and replace them
|
||||
with the notice and other provisions required by the LGPL License. If you do not
|
||||
delete the provisions above, a recipient may use your version of this file under
|
||||
either the MPL or the LGPL License.
|
||||
|
||||
The LGPL header follows below:
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this library; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
*/
|
||||
|
||||
#ifndef _SAVED_CONDITION_COMMON_HPP_
|
||||
#define _SAVED_CONDITION_COMMON_HPP_
|
||||
|
||||
#include <config_commons.hpp>
|
||||
|
||||
//#include <refcounter.hpp>
|
||||
|
||||
struct SavedConditionCommon
|
||||
{
|
||||
SavedConditionCommon() : _signaled(false) {}
|
||||
|
||||
protected:
|
||||
bool _signaled;
|
||||
};
|
||||
|
||||
|
||||
#include COMMONS_INCLUDE(saved_condition.hpp)
|
||||
|
||||
#endif /* _SAVED_CONDITION_COMMON_HPP_ */
|
||||
|
||||
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
KHOMP generic endpoint/channel library.
|
||||
Copyright (C) 2007-2009 Khomp Ind. & Com.
|
||||
|
||||
The contents of this file are subject to the Mozilla Public License Version 1.1
|
||||
(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.mozilla.org/MPL/
|
||||
|
||||
Software distributed under the License is distributed on an "AS IS" basis,
|
||||
WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
|
||||
the specific language governing rights and limitations under the License.
|
||||
|
||||
Alternatively, the contents of this file may be used under the terms of the
|
||||
"GNU Lesser General Public License 2.1" license (the “LGPL" License), in which
|
||||
case the provisions of "LGPL License" are applicable instead of those above.
|
||||
|
||||
If you wish to allow use of your version of this file only under the terms of
|
||||
the LGPL License and not to allow others to use your version of this file under
|
||||
the MPL, indicate your decision by deleting the provisions above and replace them
|
||||
with the notice and other provisions required by the LGPL License. If you do not
|
||||
delete the provisions above, a recipient may use your version of this file under
|
||||
either the MPL or the LGPL License.
|
||||
|
||||
The LGPL header follows below:
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this library; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
*/
|
||||
|
||||
#include <simple_lock.hpp>
|
||||
|
||||
struct ScopedLockBasic
|
||||
{
|
||||
ScopedLockBasic(void)
|
||||
: _locked(true) {};
|
||||
|
||||
ScopedLockBasic(bool locked)
|
||||
: _locked(locked) {};
|
||||
|
||||
virtual ~ScopedLockBasic() {};
|
||||
|
||||
protected:
|
||||
bool _locked;
|
||||
};
|
||||
|
||||
|
||||
struct ScopedLock : public ScopedLockBasic
|
||||
{
|
||||
struct LockFailed {};
|
||||
|
||||
ScopedLock(SimpleLock & mutex)
|
||||
: ScopedLockBasic(false), _mutex(mutex)
|
||||
{
|
||||
switch (_mutex.lock())
|
||||
{
|
||||
case SimpleLock::ISINUSE:
|
||||
case SimpleLock::FAILURE:
|
||||
throw LockFailed();
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
_locked = true;
|
||||
}
|
||||
|
||||
~ScopedLock()
|
||||
{
|
||||
unlock();
|
||||
}
|
||||
|
||||
void unlock()
|
||||
{
|
||||
if (_locked)
|
||||
{
|
||||
_locked = false;
|
||||
_mutex.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
SimpleLock & _mutex;
|
||||
};
|
||||
|
||||
@@ -0,0 +1,104 @@
|
||||
/*
|
||||
KHOMP generic endpoint/channel library.
|
||||
Copyright (C) 2007-2009 Khomp Ind. & Com.
|
||||
|
||||
The contents of this file are subject to the Mozilla Public License Version 1.1
|
||||
(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.mozilla.org/MPL/
|
||||
|
||||
Software distributed under the License is distributed on an "AS IS" basis,
|
||||
WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
|
||||
the specific language governing rights and limitations under the License.
|
||||
|
||||
Alternatively, the contents of this file may be used under the terms of the
|
||||
"GNU Lesser General Public License 2.1" license (the “LGPL" License), in which
|
||||
case the provisions of "LGPL License" are applicable instead of those above.
|
||||
|
||||
If you wish to allow use of your version of this file only under the terms of
|
||||
the LGPL License and not to allow others to use your version of this file under
|
||||
the MPL, indicate your decision by deleting the provisions above and replace them
|
||||
with the notice and other provisions required by the LGPL License. If you do not
|
||||
delete the provisions above, a recipient may use your version of this file under
|
||||
either the MPL or the LGPL License.
|
||||
|
||||
The LGPL header follows below:
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this library; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
*/
|
||||
|
||||
#ifndef _SIMPLE_LOCK_COMMON_HPP_
|
||||
#define _SIMPLE_LOCK_COMMON_HPP_
|
||||
|
||||
#include <config_commons.hpp>
|
||||
|
||||
#include <unistd.h>
|
||||
#include <noncopyable.hpp>
|
||||
|
||||
#include <refcounter.hpp>
|
||||
|
||||
/* This struct uses static polymorphism, and derived classes should implement *
|
||||
* the "lock/trylock/unlock()" methods for correct code compilation. *
|
||||
* The base class also features reference counting, so derived classes should *
|
||||
* implement the "unreference()" method for releasing resources. */
|
||||
|
||||
template < typename Implementor >
|
||||
struct SimpleLockCommon: NEW_REFCOUNTER( SimpleLockCommon < Implementor > )
|
||||
{
|
||||
friend class ReferenceCounter < SimpleLockCommon < Implementor > >;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
ISINUSE = 0, // operation not succeded (no error)
|
||||
SUCCESS = 1, // operation succeded (no error)
|
||||
FAILURE = 2, // mutex or state is somehow invalid (error! run for your life!)
|
||||
}
|
||||
Result;
|
||||
|
||||
SimpleLockCommon()
|
||||
{};
|
||||
|
||||
SimpleLockCommon(const SimpleLockCommon & o)
|
||||
: INC_REFCOUNTER(o, SimpleLockCommon)
|
||||
{};
|
||||
|
||||
virtual ~SimpleLockCommon()
|
||||
{};
|
||||
|
||||
inline Result lock()
|
||||
{
|
||||
return static_cast<Implementor*>(this)->lock();
|
||||
}
|
||||
|
||||
inline Result trylock()
|
||||
{
|
||||
return static_cast<Implementor*>(this)->trylock();
|
||||
}
|
||||
|
||||
inline void unlock()
|
||||
{
|
||||
static_cast<Implementor*>(this)->unlock();
|
||||
}
|
||||
|
||||
protected:
|
||||
void unreference(void)
|
||||
{
|
||||
static_cast<Implementor*>(this)->unreference();
|
||||
}
|
||||
};
|
||||
|
||||
#include COMMONS_INCLUDE(simple_lock.hpp)
|
||||
|
||||
#endif /* _SIMPLE_LOCK_COMMON_HPP_ */
|
||||
@@ -0,0 +1,247 @@
|
||||
/*
|
||||
KHOMP generic endpoint/channel library.
|
||||
Copyright (C) 2007-2009 Khomp Ind. & Com.
|
||||
|
||||
The contents of this file are subject to the Mozilla Public License Version 1.1
|
||||
(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.mozilla.org/MPL/
|
||||
|
||||
Software distributed under the License is distributed on an "AS IS" basis,
|
||||
WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
|
||||
the specific language governing rights and limitations under the License.
|
||||
|
||||
Alternatively, the contents of this file may be used under the terms of the
|
||||
"GNU Lesser General Public License 2.1" license (the “LGPL" License), in which
|
||||
case the provisions of "LGPL License" are applicable instead of those above.
|
||||
|
||||
If you wish to allow use of your version of this file only under the terms of
|
||||
the LGPL License and not to allow others to use your version of this file under
|
||||
the MPL, indicate your decision by deleting the provisions above and replace them
|
||||
with the notice and other provisions required by the LGPL License. If you do not
|
||||
delete the provisions above, a recipient may use your version of this file under
|
||||
either the MPL or the LGPL License.
|
||||
|
||||
The LGPL header follows below:
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this library; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
*/
|
||||
|
||||
#include <strings.hpp>
|
||||
|
||||
void Strings::Merger::add(std::string s)
|
||||
{
|
||||
_list.push_back(s);
|
||||
};
|
||||
|
||||
std::string Strings::Merger::merge(const std::string & sep)
|
||||
{
|
||||
list_type::iterator i = _list.begin();
|
||||
|
||||
std::string res;
|
||||
|
||||
if (i != _list.end())
|
||||
{
|
||||
res += (*i);
|
||||
++i;
|
||||
};
|
||||
|
||||
while (i != _list.end())
|
||||
{
|
||||
res += sep;
|
||||
res += (*i);
|
||||
++i;
|
||||
}
|
||||
|
||||
return res;
|
||||
};
|
||||
|
||||
std::string Strings::Merger::merge(const char *sep)
|
||||
{
|
||||
std::string ssep(sep);
|
||||
return merge(ssep);
|
||||
}
|
||||
|
||||
unsigned int Strings::tokenize(const std::string & str, Strings::vector_type & tokens,
|
||||
const std::string & delims, long int max_tokens, bool keep_empty)
|
||||
{
|
||||
std::string::size_type base = 0;
|
||||
|
||||
std::string::size_type init = str.find_first_not_of(delims, 0);
|
||||
std::string::size_type fini = str.find_first_of(delims, init);
|
||||
|
||||
long int cur_token = 1;
|
||||
|
||||
while (std::string::npos != init)
|
||||
{
|
||||
if (keep_empty && base < init)
|
||||
{
|
||||
std::string::size_type cur_empty = init - base;
|
||||
|
||||
while (cur_empty && cur_token < max_tokens)
|
||||
{
|
||||
tokens.push_back("");
|
||||
|
||||
++cur_token;
|
||||
--cur_empty;
|
||||
}
|
||||
}
|
||||
|
||||
if (std::string::npos != fini && cur_token < max_tokens)
|
||||
{
|
||||
base = fini + 1;
|
||||
|
||||
tokens.push_back(str.substr(init, fini - init));
|
||||
++cur_token;
|
||||
}
|
||||
else
|
||||
{
|
||||
base = str.size(); // find_first_of(delims, init);
|
||||
|
||||
tokens.push_back(str.substr(init, str.size() - init));
|
||||
break;
|
||||
}
|
||||
|
||||
init = str.find_first_not_of(delims, fini);
|
||||
fini = str.find_first_of(delims, init);
|
||||
}
|
||||
|
||||
if (keep_empty && base != str.size())
|
||||
{
|
||||
std::string::size_type cur_empty = str.size() - base + 1;
|
||||
|
||||
while (cur_empty && cur_token < max_tokens)
|
||||
{
|
||||
tokens.push_back("");
|
||||
|
||||
++cur_token;
|
||||
--cur_empty;
|
||||
}
|
||||
|
||||
if (cur_empty)
|
||||
{
|
||||
std::string::size_type pos = base + cur_empty - 1;
|
||||
tokens.push_back(str.substr(pos, str.size() - pos));
|
||||
++cur_token;
|
||||
}
|
||||
}
|
||||
|
||||
return (cur_token - 1);
|
||||
}
|
||||
|
||||
bool Strings::toboolean(std::string str)
|
||||
{
|
||||
std::string tmp(str);
|
||||
|
||||
Strings::lower(tmp);
|
||||
|
||||
if ((tmp == "true") || (tmp == "yes")) return true;
|
||||
if ((tmp == "false") || (tmp == "no")) return false;
|
||||
|
||||
throw invalid_value(str);
|
||||
}
|
||||
|
||||
long Strings::tolong(std::string str, int base)
|
||||
{
|
||||
char *str_end = 0;
|
||||
|
||||
unsigned long value = strtol(str.c_str(), &str_end, base);
|
||||
|
||||
if (str_end && *str_end == 0)
|
||||
return value;
|
||||
|
||||
throw invalid_value(str);
|
||||
}
|
||||
|
||||
unsigned long Strings::toulong(std::string str, int base)
|
||||
{
|
||||
char *str_end = 0;
|
||||
|
||||
unsigned long value = strtoul(str.c_str(), &str_end, base);
|
||||
|
||||
if (str_end && *str_end == 0)
|
||||
return value;
|
||||
|
||||
throw invalid_value(str);
|
||||
}
|
||||
|
||||
unsigned long long Strings::toulonglong(std::string str, int base)
|
||||
{
|
||||
#if defined(_WINDOWS) || defined(_Windows) || defined(_WIN32) || defined(WIN32)
|
||||
throw not_implemented();
|
||||
#else
|
||||
char *str_end = 0;
|
||||
|
||||
unsigned long long value = strtoull(str.c_str(), &str_end, base);
|
||||
|
||||
if (str_end && *str_end == 0)
|
||||
return value;
|
||||
|
||||
throw invalid_value(str);
|
||||
#endif
|
||||
}
|
||||
|
||||
double Strings::todouble(std::string str)
|
||||
{
|
||||
char *str_end = 0;
|
||||
|
||||
double value = strtod(str.c_str(), &str_end);
|
||||
|
||||
if (str_end && *str_end == 0)
|
||||
return value;
|
||||
|
||||
throw invalid_value(str);
|
||||
}
|
||||
|
||||
std::string Strings::fromboolean(bool value)
|
||||
{
|
||||
if (value) return "true";
|
||||
else return "false";
|
||||
}
|
||||
|
||||
std::string Strings::lower(std::string str)
|
||||
{
|
||||
std::string res;
|
||||
|
||||
for (std::string::iterator i = str.begin(); i != str.end(); i++)
|
||||
res += tolower((*i));
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
std::string Strings::hexadecimal(std::string value)
|
||||
{
|
||||
std::string result;
|
||||
|
||||
for (std::string::iterator i = value.begin(); i != value.end(); i++)
|
||||
{
|
||||
if (i != value.begin())
|
||||
result += " ";
|
||||
|
||||
result += STG(FMT("%2x") % (unsigned int)(*i));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string Strings::trim(const std::string& str, const std::string& trim_chars)
|
||||
{
|
||||
std::string result(str);
|
||||
|
||||
result.erase( result.find_last_not_of( trim_chars ) + 1 );
|
||||
result.erase( 0, result.find_first_not_of( trim_chars ) );
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
/*
|
||||
KHOMP generic endpoint/channel library.
|
||||
Copyright (C) 2007-2009 Khomp Ind. & Com.
|
||||
|
||||
The contents of this file are subject to the Mozilla Public License Version 1.1
|
||||
(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.mozilla.org/MPL/
|
||||
|
||||
Software distributed under the License is distributed on an "AS IS" basis,
|
||||
WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
|
||||
the specific language governing rights and limitations under the License.
|
||||
|
||||
Alternatively, the contents of this file may be used under the terms of the
|
||||
"GNU Lesser General Public License 2.1" license (the “LGPL" License), in which
|
||||
case the provisions of "LGPL License" are applicable instead of those above.
|
||||
|
||||
If you wish to allow use of your version of this file only under the terms of
|
||||
the LGPL License and not to allow others to use your version of this file under
|
||||
the MPL, indicate your decision by deleting the provisions above and replace them
|
||||
with the notice and other provisions required by the LGPL License. If you do not
|
||||
delete the provisions above, a recipient may use your version of this file under
|
||||
either the MPL or the LGPL License.
|
||||
|
||||
The LGPL header follows below:
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this library; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
*/
|
||||
|
||||
#include <limits.h>
|
||||
|
||||
#include <list>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
#include <types.hpp>
|
||||
|
||||
#include <format.hpp>
|
||||
|
||||
/* Generic string funcions */
|
||||
|
||||
#ifndef _STRINGS_HPP_
|
||||
#define _STRINGS_HPP_
|
||||
|
||||
struct Strings
|
||||
{
|
||||
typedef std::list<std::string> list_type;
|
||||
typedef std::vector<std::string> vector_type;
|
||||
|
||||
struct Merger
|
||||
{
|
||||
void add(std::string);
|
||||
|
||||
std::string merge(const std::string &);
|
||||
std::string merge(const char *);
|
||||
|
||||
bool empty() { return _list.empty(); };
|
||||
|
||||
protected:
|
||||
list_type _list;
|
||||
};
|
||||
|
||||
public:
|
||||
struct invalid_value
|
||||
{
|
||||
invalid_value(const char * value): _value(value) {};
|
||||
invalid_value(std::string value): _value(value) {};
|
||||
|
||||
std::string & value() { return _value; }
|
||||
|
||||
protected:
|
||||
std::string _value;
|
||||
};
|
||||
|
||||
struct not_implemented {};
|
||||
|
||||
static unsigned int tokenize(const std::string &, vector_type &, const std::string & delims = ",;:",
|
||||
long int max_toxens = LONG_MAX, bool keep_empty = true);
|
||||
|
||||
static bool toboolean(std::string);
|
||||
static std::string fromboolean(bool);
|
||||
|
||||
static long tolong(std::string, int base = 10);
|
||||
static unsigned long toulong(std::string, int base = 10);
|
||||
static unsigned long long toulonglong(std::string, int base = 10);
|
||||
static double todouble(std::string);
|
||||
|
||||
static std::string lower(std::string);
|
||||
static std::string hexadecimal(std::string);
|
||||
|
||||
static std::string trim(const std::string&, const std::string& trim_chars = " \f\n\r\t\v");
|
||||
};
|
||||
|
||||
#endif // _STRINGS_HPP_ //
|
||||
@@ -0,0 +1,307 @@
|
||||
/*
|
||||
KHOMP generic endpoint/channel library.
|
||||
Copyright (C) 2007-2009 Khomp Ind. & Com.
|
||||
|
||||
The contents of this file are subject to the Mozilla Public License Version 1.1
|
||||
(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.mozilla.org/MPL/
|
||||
|
||||
Software distributed under the License is distributed on an "AS IS" basis,
|
||||
WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
|
||||
the specific language governing rights and limitations under the License.
|
||||
|
||||
Alternatively, the contents of this file may be used under the terms of the
|
||||
"GNU Lesser General Public License 2.1" license (the “LGPL" License), in which
|
||||
case the provisions of "LGPL License" are applicable instead of those above.
|
||||
|
||||
If you wish to allow use of your version of this file only under the terms of
|
||||
the LGPL License and not to allow others to use your version of this file under
|
||||
the MPL, indicate your decision by deleting the provisions above and replace them
|
||||
with the notice and other provisions required by the LGPL License. If you do not
|
||||
delete the provisions above, a recipient may use your version of this file under
|
||||
either the MPL or the LGPL License.
|
||||
|
||||
The LGPL header follows below:
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this library; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
*/
|
||||
|
||||
#ifndef _TAGGED_UNION_HPP_
|
||||
#define _TAGGED_UNION_HPP_
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
#include <iostream>
|
||||
#include <unistd.h>
|
||||
|
||||
namespace Tagged
|
||||
{
|
||||
struct EmptyUnion
|
||||
{
|
||||
friend class Value;
|
||||
|
||||
EmptyUnion()
|
||||
: _adjusted(false) {};
|
||||
|
||||
// copy constructor
|
||||
EmptyUnion(const EmptyUnion & o)
|
||||
: _adjusted(o._adjusted) {};
|
||||
|
||||
// copy assignment operator
|
||||
EmptyUnion & operator=(const EmptyUnion & o)
|
||||
{
|
||||
_adjusted = o._adjusted;
|
||||
return *this;
|
||||
};
|
||||
|
||||
~EmptyUnion() { _adjusted = false; };
|
||||
|
||||
bool operator==(const EmptyUnion & o)
|
||||
{
|
||||
return true;
|
||||
};
|
||||
|
||||
public:
|
||||
void clear(void) { _adjusted = false; };
|
||||
protected:
|
||||
void setup(void) { _adjusted = true; };
|
||||
|
||||
protected:
|
||||
bool value_set(void) { return false; };
|
||||
bool value_get(void) { return false; };
|
||||
|
||||
bool value_check(void) { return false; };
|
||||
|
||||
template < typename S >
|
||||
bool value_visit(S & visitor, typename S::ReturnType & ret)
|
||||
{
|
||||
return false;
|
||||
};
|
||||
|
||||
template < typename S >
|
||||
bool value_visit_void(S & visitor)
|
||||
{
|
||||
return false;
|
||||
};
|
||||
|
||||
bool adjusted() { return _adjusted; };
|
||||
|
||||
private:
|
||||
bool _adjusted;
|
||||
};
|
||||
|
||||
template < typename V, typename E = EmptyUnion >
|
||||
struct Union: public E
|
||||
{
|
||||
friend class Value;
|
||||
|
||||
// default constructor
|
||||
Union()
|
||||
: _value(0) {};
|
||||
|
||||
// constructor with initializer
|
||||
template < typename U >
|
||||
Union( U value )
|
||||
: _value(0)
|
||||
{
|
||||
set(value);
|
||||
};
|
||||
|
||||
// copy constructor
|
||||
Union(const Union & o)
|
||||
: E(static_cast<const E&>(o)),
|
||||
_value( (o._value ? new const V(*(o._value)) : 0) )
|
||||
{};
|
||||
|
||||
// copy assignment operator
|
||||
Union & operator=(const Union & o)
|
||||
{
|
||||
if (_value)
|
||||
{
|
||||
delete _value;
|
||||
_value = 0;
|
||||
}
|
||||
|
||||
if (o._value)
|
||||
{
|
||||
_value = new const V(*(o._value));
|
||||
}
|
||||
|
||||
E::operator=(static_cast<const E&>(o));
|
||||
|
||||
return *this;
|
||||
};
|
||||
|
||||
// destructor
|
||||
~Union()
|
||||
{
|
||||
if (_value)
|
||||
{
|
||||
delete _value;
|
||||
_value = 0;
|
||||
}
|
||||
};
|
||||
|
||||
// equal sign operator
|
||||
template < typename U >
|
||||
void operator=(U value)
|
||||
{
|
||||
set(value);
|
||||
}
|
||||
|
||||
template < typename U >
|
||||
bool check(void)
|
||||
{
|
||||
return value_check(static_cast<const U * const>(0));
|
||||
};
|
||||
|
||||
template < typename U >
|
||||
const U & get(void)
|
||||
{
|
||||
const U * res = 0;
|
||||
|
||||
if (!value_get(&res) || !res)
|
||||
throw std::runtime_error("type mismatch");
|
||||
|
||||
return *res;
|
||||
};
|
||||
|
||||
template < typename U >
|
||||
void set(U val)
|
||||
{
|
||||
if (E::adjusted())
|
||||
clear();
|
||||
|
||||
if (!value_set(val))
|
||||
throw std::runtime_error("unable to set value of invalid type");
|
||||
};
|
||||
|
||||
template < typename S >
|
||||
typename S::ReturnType visit(S visitor)
|
||||
{
|
||||
typename S::ReturnType ret;
|
||||
|
||||
if (!value_visit(visitor, ret))
|
||||
throw std::runtime_error("unable to visit empty value");
|
||||
|
||||
return ret;
|
||||
};
|
||||
|
||||
template < typename S >
|
||||
void visit_void(S visitor)
|
||||
{
|
||||
if (!value_visit_void(visitor))
|
||||
throw std::runtime_error("unable to visit empty value");
|
||||
};
|
||||
|
||||
void clear()
|
||||
{
|
||||
if (_value)
|
||||
{
|
||||
delete _value;
|
||||
_value = 0;
|
||||
}
|
||||
|
||||
E::clear();
|
||||
};
|
||||
|
||||
// compare (equal) operator
|
||||
bool operator==(const Union & o)
|
||||
{
|
||||
bool are_equal = false;
|
||||
|
||||
if (!_value && !(o._value))
|
||||
are_equal = true;
|
||||
|
||||
if (_value && o._value)
|
||||
are_equal = (*_value == *(o._value));
|
||||
|
||||
if (are_equal)
|
||||
return E::operator==(static_cast<const E&>(o));
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
// compare types
|
||||
bool sameType(const Union & o)
|
||||
{
|
||||
if ((!(_value) && !(o._value)) || (_value && o._value))
|
||||
return E::operator==(static_cast<const E&>(o));
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
protected:
|
||||
using E::value_set;
|
||||
using E::value_get;
|
||||
|
||||
using E::value_check;
|
||||
using E::value_visit;
|
||||
using E::value_visit_void;
|
||||
|
||||
bool value_set(V val)
|
||||
{
|
||||
_value = new const V(val);
|
||||
E::setup();
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
bool value_get(const V ** val)
|
||||
{
|
||||
if (!_value)
|
||||
return false;
|
||||
|
||||
*val = _value;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool value_check(const V * const junk)
|
||||
{
|
||||
(void)junk;
|
||||
return (_value != 0);
|
||||
};
|
||||
|
||||
template < typename S >
|
||||
bool value_visit(S & visitor, typename S::ReturnType & ret)
|
||||
{
|
||||
if (_value)
|
||||
{
|
||||
ret = visitor(*const_cast<V*>(_value));
|
||||
return true;
|
||||
};
|
||||
|
||||
return E::value_visit(visitor, ret);
|
||||
};
|
||||
|
||||
template < typename S >
|
||||
bool value_visit_void(S & visitor)
|
||||
{
|
||||
if (_value)
|
||||
{
|
||||
visitor(*const_cast<V*>(_value));
|
||||
return true;
|
||||
};
|
||||
|
||||
return E::value_visit_void(visitor);
|
||||
};
|
||||
|
||||
private:
|
||||
const V * _value;
|
||||
};
|
||||
};
|
||||
|
||||
#endif /* _TAGGED_UNION_HPP_ */
|
||||
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
KHOMP generic endpoint/channel library.
|
||||
Copyright (C) 2007-2009 Khomp Ind. & Com.
|
||||
|
||||
The contents of this file are subject to the Mozilla Public License Version 1.1
|
||||
(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.mozilla.org/MPL/
|
||||
|
||||
Software distributed under the License is distributed on an "AS IS" basis,
|
||||
WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
|
||||
the specific language governing rights and limitations under the License.
|
||||
|
||||
Alternatively, the contents of this file may be used under the terms of the
|
||||
"GNU Lesser General Public License 2.1" license (the “LGPL" License), in which
|
||||
case the provisions of "LGPL License" are applicable instead of those above.
|
||||
|
||||
If you wish to allow use of your version of this file only under the terms of
|
||||
the LGPL License and not to allow others to use your version of this file under
|
||||
the MPL, indicate your decision by deleting the provisions above and replace them
|
||||
with the notice and other provisions required by the LGPL License. If you do not
|
||||
delete the provisions above, a recipient may use your version of this file under
|
||||
either the MPL or the LGPL License.
|
||||
|
||||
The LGPL header follows below:
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this library; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
*/
|
||||
|
||||
#ifndef _THREAD_COMMON_HPP_
|
||||
#define _THREAD_COMMON_HPP_
|
||||
|
||||
#include <config_commons.hpp>
|
||||
|
||||
#include <types.hpp>
|
||||
//#include <function.hpp>
|
||||
|
||||
struct ThreadCommon
|
||||
{
|
||||
protected:
|
||||
template<typename FuncPtrType>
|
||||
struct DecomposeFuncPtr;
|
||||
|
||||
template<typename ReturnType, typename ArgType>
|
||||
struct DecomposeFuncPtr<ReturnType(*)(ArgType)>
|
||||
{
|
||||
typedef ReturnType Return;
|
||||
};
|
||||
|
||||
template<typename SomeClass>
|
||||
struct DecomposeFuncPtr
|
||||
{
|
||||
typedef void Return;
|
||||
};
|
||||
|
||||
template<typename ReturnType>
|
||||
struct DecomposeFuncPtr<ReturnType(*)()>
|
||||
{
|
||||
typedef ReturnType Return;
|
||||
};
|
||||
|
||||
template< typename FunctionType >
|
||||
struct DecomposeFunction
|
||||
{
|
||||
typedef typename Select < IsClass< FunctionType >::Result, int,
|
||||
typename DecomposeFuncPtr< FunctionType >::Return >::Result
|
||||
Return;
|
||||
};
|
||||
|
||||
public:
|
||||
struct ThreadDataCommon
|
||||
{
|
||||
ThreadDataCommon() {}
|
||||
|
||||
virtual ~ThreadDataCommon() {}
|
||||
|
||||
virtual int run() = 0;
|
||||
|
||||
ThreadCommon * _thread;
|
||||
|
||||
void * _self;
|
||||
void * _attribute;
|
||||
};
|
||||
|
||||
ThreadCommon() {}
|
||||
};
|
||||
|
||||
|
||||
#include COMMONS_INCLUDE(thread.hpp)
|
||||
|
||||
#endif /* _THREAD_COMMON_HPP_ */
|
||||
@@ -0,0 +1,352 @@
|
||||
/*
|
||||
KHOMP generic endpoint/channel library.
|
||||
Copyright (C) 2007-2009 Khomp Ind. & Com.
|
||||
|
||||
The contents of this file are subject to the Mozilla Public License Version 1.1
|
||||
(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.mozilla.org/MPL/
|
||||
|
||||
Software distributed under the License is distributed on an "AS IS" basis,
|
||||
WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
|
||||
the specific language governing rights and limitations under the License.
|
||||
|
||||
Alternatively, the contents of this file may be used under the terms of the
|
||||
"GNU Lesser General Public License 2.1" license (the “LGPL" License), in which
|
||||
case the provisions of "LGPL License" are applicable instead of those above.
|
||||
|
||||
If you wish to allow use of your version of this file only under the terms of
|
||||
the LGPL License and not to allow others to use your version of this file under
|
||||
the MPL, indicate your decision by deleting the provisions above and replace them
|
||||
with the notice and other provisions required by the LGPL License. If you do not
|
||||
delete the provisions above, a recipient may use your version of this file under
|
||||
either the MPL or the LGPL License.
|
||||
|
||||
The LGPL header follows below:
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this library; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
*/
|
||||
|
||||
#include <timer.hpp>
|
||||
|
||||
TimerTraits::TimerTraits()
|
||||
: _thread((Thread*)0), _purify(false), _last_tick(0), _age_count(0), _shutdown(false)
|
||||
{};
|
||||
|
||||
bool TimerTraits::start (void)
|
||||
{
|
||||
_shutdown = false;
|
||||
|
||||
_condition.reset();
|
||||
_finalized.reset();
|
||||
|
||||
if (!_thread)
|
||||
{
|
||||
_thread = new Thread(TimerTraits::loop_thread(this));
|
||||
_purify = true;
|
||||
}
|
||||
|
||||
#if defined(_WINDOWS) || defined(_Windows) || defined(_WIN32) || defined(WIN32)
|
||||
// set priority ...
|
||||
#else
|
||||
pthread_attr_t attrs;
|
||||
sched_param param;
|
||||
|
||||
if (pthread_attr_init(&attrs) < 0)
|
||||
return false;
|
||||
|
||||
if (pthread_attr_setschedpolicy(&attrs, SCHED_RR) < 0)
|
||||
return false;
|
||||
|
||||
if (pthread_attr_getschedparam(&attrs, ¶m) < 0)
|
||||
return false;
|
||||
|
||||
param.sched_priority = sched_get_priority_max(SCHED_RR);
|
||||
|
||||
if (pthread_attr_setschedparam(&attrs, ¶m) < 0)
|
||||
return false;
|
||||
|
||||
// set priority...
|
||||
|
||||
// if (pthread_create(&_thread, &attrs, TimerTraits::loop_thread, NULL) < 0)
|
||||
// return false;
|
||||
|
||||
_thread->start();
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TimerTraits::stop (void)
|
||||
{
|
||||
_shutdown = true;
|
||||
|
||||
_condition.signal();
|
||||
|
||||
_finalized.wait(10000); /* 10 seconds max wait */
|
||||
|
||||
if (_thread && _purify)
|
||||
{
|
||||
delete _thread;
|
||||
|
||||
_thread = (Thread *)0;
|
||||
_purify = false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//-----------------------------------------
|
||||
|
||||
int TimerTraits::loop_thread::operator()(void)
|
||||
{
|
||||
try
|
||||
{
|
||||
_timer->loop();
|
||||
}
|
||||
catch( ... )
|
||||
{
|
||||
/* something wrong happened! */
|
||||
}
|
||||
|
||||
_timer->_finalized.signal();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void TimerTraits::execute(ControlSet::iterator init, const TimerTraits::Control & ctrl)
|
||||
{
|
||||
volatile CallbackFuncType func = (volatile CallbackFuncType) ctrl._func;
|
||||
volatile CallbackDataType data = (volatile CallbackDataType) ctrl._data;
|
||||
|
||||
_timer_set.erase(init);
|
||||
|
||||
_mutex.unlock();
|
||||
|
||||
func(data);
|
||||
}
|
||||
|
||||
void TimerTraits::loop (void)
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
if (_shutdown) break;
|
||||
|
||||
_mutex.lock();
|
||||
|
||||
ControlSet::iterator init = _timer_set.begin();
|
||||
|
||||
if (init == _timer_set.end())
|
||||
{
|
||||
_mutex.unlock();
|
||||
_condition.wait();
|
||||
}
|
||||
else
|
||||
{
|
||||
const Control & ctrl = *init;
|
||||
|
||||
unsigned int ts_now = TimerTraits::tick();
|
||||
|
||||
if (_age_count == ctrl._age)
|
||||
{
|
||||
if (ts_now < ctrl._msecs)
|
||||
{
|
||||
/* age is right, but it is not time to expire yet... */
|
||||
volatile unsigned int wait_time = ctrl._msecs - ts_now;
|
||||
_mutex.unlock();
|
||||
_condition.wait(wait_time); /* expire - now */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* age is right, and we should expire! */
|
||||
execute(init, ctrl); /* called locked, return unlocked */
|
||||
}
|
||||
}
|
||||
else if (_age_count < ctrl._age)
|
||||
{
|
||||
/* age is not there yet (need some time to overlap)... */
|
||||
volatile unsigned int wait_time = (UINT_MAX - ts_now) + ctrl._msecs;
|
||||
_mutex.unlock();
|
||||
_condition.wait(wait_time); /* MAX - now + expire */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* age has passed, we should have expired before! */
|
||||
execute(init, ctrl); /* called locked, return unlocked */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_finalized.signal();
|
||||
}
|
||||
|
||||
unsigned int TimerTraits::tick()
|
||||
{
|
||||
#if defined(_WINDOWS) || defined(_Windows) || defined(_WIN32) || defined(WIN32)
|
||||
unsigned int tick = GetTickCount();
|
||||
#else
|
||||
struct timespec ticks;
|
||||
|
||||
// error condition, make the user notice this..
|
||||
if (clock_gettime(CLOCK_MONOTONIC, &ticks) < 0)
|
||||
return 0;
|
||||
|
||||
unsigned int tick = ( ticks.tv_sec * 1000 ) + ( ticks.tv_nsec / 1000000 );
|
||||
#endif
|
||||
|
||||
if (_last_tick > tick)
|
||||
++_age_count;
|
||||
|
||||
_last_tick = tick;
|
||||
|
||||
return tick;
|
||||
}
|
||||
|
||||
//-----------------------------------------
|
||||
|
||||
TimerTraits::Index TimerTraits::traits_add_unlocked (unsigned int msecs, const void * func, const void * data, unsigned int value)
|
||||
{
|
||||
unsigned int ms_tick = TimerTraits::tick();
|
||||
|
||||
unsigned int ms_left = UINT_MAX - ms_tick;
|
||||
unsigned int ms_real = msecs;
|
||||
|
||||
unsigned int age_num = _age_count;
|
||||
|
||||
if (ms_left < msecs)
|
||||
{
|
||||
ms_real -= ms_left;
|
||||
++age_num;
|
||||
}
|
||||
else
|
||||
{
|
||||
ms_real += ms_tick;
|
||||
}
|
||||
|
||||
ControlSet::iterator it = _timer_set.insert(Control(age_num,ms_real,func,data,value));
|
||||
|
||||
if (_timer_set.size() == 1 || _timer_set.begin() == it)
|
||||
{
|
||||
_condition.signal();
|
||||
};
|
||||
|
||||
return Index(age_num, ms_real, msecs, func, data, value);
|
||||
}
|
||||
|
||||
TimerTraits::Index TimerTraits::traits_add (unsigned int msecs, const void * func, const void * data, unsigned int value)
|
||||
{
|
||||
_mutex.lock();
|
||||
|
||||
Index idx = traits_add_unlocked(msecs, func, data, value);
|
||||
|
||||
_mutex.unlock();
|
||||
|
||||
return idx;
|
||||
}
|
||||
|
||||
bool TimerTraits::traits_restart (TimerTraits::Index & idx, bool force)
|
||||
{
|
||||
bool ret = false;
|
||||
|
||||
_mutex.lock();
|
||||
|
||||
if (idx.valid)
|
||||
{
|
||||
if (traits_del_unlocked(idx) || force)
|
||||
{
|
||||
idx = traits_add_unlocked(idx.delta, idx.func, idx.data, idx.value);
|
||||
ret = true;
|
||||
}
|
||||
}
|
||||
|
||||
_mutex.unlock();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool TimerTraits::traits_del_unlocked (TimerTraits::Index & idx)
|
||||
{
|
||||
bool ret = false;
|
||||
|
||||
if (idx.valid)
|
||||
{
|
||||
ControlSet::iterator i = _timer_set.lower_bound(Control(idx.era, idx.msec));
|
||||
ControlSet::iterator j = _timer_set.upper_bound(Control(idx.era, idx.msec));
|
||||
|
||||
for (; i != j; i++)
|
||||
{
|
||||
const Control & ctrl = (*i);
|
||||
|
||||
if ((idx.value && !(ctrl._value & idx.value)))
|
||||
continue;
|
||||
|
||||
if (((idx.func && ctrl._func == idx.func) || !idx.func) && ((idx.data && ctrl._data == idx.data) || !idx.data))
|
||||
{
|
||||
if (_timer_set.begin() == i)
|
||||
_condition.signal();
|
||||
|
||||
_timer_set.erase(i);
|
||||
|
||||
ret = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
idx.valid = false;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool TimerTraits::traits_del (TimerTraits::Index & idx)
|
||||
{
|
||||
_mutex.lock();
|
||||
|
||||
bool ret = traits_del_unlocked(idx);
|
||||
|
||||
_mutex.unlock();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool TimerTraits::traits_del (const void * func, const void * data, unsigned int value)
|
||||
{
|
||||
bool ret = false;
|
||||
|
||||
_mutex.lock();
|
||||
|
||||
for (ControlSet::iterator i = _timer_set.begin(); i != _timer_set.end(); i++)
|
||||
{
|
||||
const Control & ctrl = (*i);
|
||||
|
||||
if ((value && !(ctrl._value & value)))
|
||||
continue;
|
||||
|
||||
if (((func && ctrl._func == func) || !func) && ((data && ctrl._data == data) || !data))
|
||||
{
|
||||
if (_timer_set.begin() == i)
|
||||
_condition.signal();
|
||||
|
||||
_timer_set.erase(i);
|
||||
|
||||
ret = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
_mutex.unlock();
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -0,0 +1,224 @@
|
||||
/*
|
||||
KHOMP generic endpoint/channel library.
|
||||
Copyright (C) 2007-2009 Khomp Ind. & Com.
|
||||
|
||||
The contents of this file are subject to the Mozilla Public License Version 1.1
|
||||
(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.mozilla.org/MPL/
|
||||
|
||||
Software distributed under the License is distributed on an "AS IS" basis,
|
||||
WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
|
||||
the specific language governing rights and limitations under the License.
|
||||
|
||||
Alternatively, the contents of this file may be used under the terms of the
|
||||
"GNU Lesser General Public License 2.1" license (the “LGPL" License), in which
|
||||
case the provisions of "LGPL License" are applicable instead of those above.
|
||||
|
||||
If you wish to allow use of your version of this file only under the terms of
|
||||
the LGPL License and not to allow others to use your version of this file under
|
||||
the MPL, indicate your decision by deleting the provisions above and replace them
|
||||
with the notice and other provisions required by the LGPL License. If you do not
|
||||
delete the provisions above, a recipient may use your version of this file under
|
||||
either the MPL or the LGPL License.
|
||||
|
||||
The LGPL header follows below:
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this library; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
*/
|
||||
|
||||
#if defined(_WINDOWS) || defined(_Windows) || defined(_WIN32) || defined(WIN32)
|
||||
#include <windows.h>
|
||||
#else
|
||||
#include <sched.h>
|
||||
#endif
|
||||
|
||||
#include <set>
|
||||
|
||||
#include <simple_lock.hpp>
|
||||
#include <saved_condition.hpp>
|
||||
#include <thread.hpp>
|
||||
#include <refcounter.hpp>
|
||||
|
||||
#ifndef _TIMER_HPP_
|
||||
#define _TIMER_HPP_
|
||||
|
||||
struct TimerTraits
|
||||
{
|
||||
typedef bool (* CallbackFuncType)(const void * volatile);
|
||||
typedef const void * CallbackDataType;
|
||||
|
||||
TimerTraits();
|
||||
|
||||
virtual ~TimerTraits() {};
|
||||
|
||||
protected:
|
||||
|
||||
/* pre-declaration, used below */
|
||||
struct ControlCompare;
|
||||
|
||||
struct Control
|
||||
{
|
||||
Control(unsigned int age, unsigned int msecs, const void * func = 0, const void * data = 0, unsigned int value = 0)
|
||||
: _age(age), _msecs(msecs), _func(func), _data(data), _value(value) {}
|
||||
|
||||
unsigned int _age;
|
||||
|
||||
unsigned int _msecs;
|
||||
|
||||
const void * _func;
|
||||
const void * _data;
|
||||
|
||||
unsigned int _value;
|
||||
};
|
||||
|
||||
struct ControlCompare
|
||||
{
|
||||
bool operator()(const Control & c1, const Control & c2) const
|
||||
{
|
||||
return (c1._age < c2._age ? true : c1._msecs < c2._msecs);
|
||||
}
|
||||
};
|
||||
|
||||
typedef std::multiset < Control, ControlCompare > ControlSet;
|
||||
|
||||
public:
|
||||
struct Index
|
||||
{
|
||||
Index(): era(0), msec(0), valid(false) {};
|
||||
|
||||
Index(unsigned int _era, unsigned int _msec, unsigned int _delta, const void * _func, const void * _data, unsigned int _value)
|
||||
: era(_era), msec(_msec), delta(_delta), func(_func), data(_data), value(_value), valid(true) {};
|
||||
|
||||
unsigned int era;
|
||||
unsigned int msec;
|
||||
|
||||
unsigned int delta;
|
||||
|
||||
const void * func;
|
||||
const void * data;
|
||||
|
||||
unsigned int value;
|
||||
|
||||
bool valid;
|
||||
|
||||
void reset(void) { era = 0; msec = 0; valid = false; };
|
||||
};
|
||||
|
||||
/* timer add/remove functions */
|
||||
Index traits_add (unsigned int msecs, const void * func, const void * data = 0, unsigned int value = 0);
|
||||
|
||||
bool traits_restart (Index & idx, bool force);
|
||||
|
||||
bool traits_del (Index & idx);
|
||||
bool traits_del (const void * func, const void * data = 0, unsigned int value = 0);
|
||||
|
||||
/* timer start/stop functions */
|
||||
bool start(void);
|
||||
bool stop(void);
|
||||
|
||||
protected:
|
||||
Index traits_add_unlocked (unsigned int msecs, const void * func, const void * data, unsigned int value);
|
||||
|
||||
bool traits_del_unlocked (Index & idx);
|
||||
|
||||
protected:
|
||||
void execute(ControlSet::iterator, const Control &);
|
||||
|
||||
void loop(void);
|
||||
|
||||
struct loop_thread
|
||||
{
|
||||
loop_thread(TimerTraits *timer) : _timer(timer) {};
|
||||
|
||||
int operator()(void);
|
||||
|
||||
protected:
|
||||
TimerTraits * _timer;
|
||||
};
|
||||
|
||||
unsigned int tick();
|
||||
|
||||
/* variables */
|
||||
|
||||
SavedCondition _condition;
|
||||
|
||||
SimpleLock _mutex;
|
||||
Thread * _thread;
|
||||
bool _purify;
|
||||
|
||||
ControlSet _timer_set;
|
||||
|
||||
unsigned int _last_tick;
|
||||
unsigned int _age_count;
|
||||
|
||||
SavedCondition _finalized;
|
||||
bool _shutdown;
|
||||
};
|
||||
|
||||
template < typename F, typename D >
|
||||
struct TimerTemplate: NEW_REFCOUNTER(TimerTemplate< F, D >)
|
||||
{
|
||||
typedef TimerTraits::Index Index;
|
||||
typedef TimerTraits::Control Control;
|
||||
|
||||
TimerTemplate()
|
||||
: _timer(new TimerTraits())
|
||||
{};
|
||||
|
||||
TimerTemplate(const TimerTemplate< F, D > & o)
|
||||
: INC_REFCOUNTER(o, TimerTemplate< F, D >),
|
||||
_timer(o._timer)
|
||||
{};
|
||||
|
||||
void unreference(void)
|
||||
{
|
||||
if (_timer)
|
||||
delete _timer;
|
||||
};
|
||||
|
||||
bool start() { return _timer->start(); }
|
||||
bool stop() { return _timer->stop(); }
|
||||
|
||||
inline Index add(unsigned int msecs, F * func, D data = 0, unsigned int value = 0)
|
||||
{
|
||||
return _timer->traits_add(msecs, (const void *)func, (void *)(data), value);
|
||||
}
|
||||
|
||||
inline bool restart(Index & idx, bool force = false)
|
||||
{
|
||||
return _timer->traits_restart(idx, force);
|
||||
}
|
||||
|
||||
inline bool del(Index & idx)
|
||||
{
|
||||
return _timer->traits_del(idx);
|
||||
}
|
||||
|
||||
inline bool del(F * func, D data, unsigned int value = 0)
|
||||
{
|
||||
return _timer->traits_del((const void *)func, (void *)(data), value);
|
||||
}
|
||||
|
||||
inline bool del(unsigned int value)
|
||||
{
|
||||
return _timer->traits_del((const void *)0, (void *)0, value);
|
||||
}
|
||||
|
||||
protected:
|
||||
TimerTraits * _timer;
|
||||
};
|
||||
|
||||
#endif /* _TIMER_HPP_ */
|
||||
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
KHOMP generic endpoint/channel library.
|
||||
Copyright (C) 2007-2009 Khomp Ind. & Com.
|
||||
|
||||
The contents of this file are subject to the Mozilla Public License Version 1.1
|
||||
(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.mozilla.org/MPL/
|
||||
|
||||
Software distributed under the License is distributed on an "AS IS" basis,
|
||||
WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
|
||||
the specific language governing rights and limitations under the License.
|
||||
|
||||
Alternatively, the contents of this file may be used under the terms of the
|
||||
"GNU Lesser General Public License 2.1" license (the “LGPL" License), in which
|
||||
case the provisions of "LGPL License" are applicable instead of those above.
|
||||
|
||||
If you wish to allow use of your version of this file only under the terms of
|
||||
the LGPL License and not to allow others to use your version of this file under
|
||||
the MPL, indicate your decision by deleting the provisions above and replace them
|
||||
with the notice and other provisions required by the LGPL License. If you do not
|
||||
delete the provisions above, a recipient may use your version of this file under
|
||||
either the MPL or the LGPL License.
|
||||
|
||||
The LGPL header follows below:
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this library; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
*/
|
||||
|
||||
#ifndef _TYPES_HPP_
|
||||
#define _TYPES_HPP_
|
||||
|
||||
/*** Used for conditional compilation based on K3L version ***/
|
||||
|
||||
#define K3L_AT_LEAST(major,minor,build) \
|
||||
(((k3lApiMajorVersion == major) && ((k3lApiMinorVersion == minor) && (k3lApiBuildVersion >= build)) || \
|
||||
((k3lApiMajorVersion == major) && (k3lApiMinorVersion > minor))) || \
|
||||
(k3lApiMajorVersion > major))
|
||||
|
||||
#define K3L_EXACT(major,minor,build) \
|
||||
((k3lApiMajorVersion == major) && (k3lApiMinorVersion == minor) && (k3lApiBuildVersion >= build))
|
||||
|
||||
/*** Used for checking information on classes and stuff.. ***/
|
||||
|
||||
template< typename T >
|
||||
class IsClass
|
||||
{
|
||||
protected:
|
||||
template< typename X > static char ( &A( void(X::*)() ) )[1];
|
||||
template< typename X > static char ( &A( X ) )[2];
|
||||
public:
|
||||
static bool const Result = sizeof( A< T >(0) ) == 1;
|
||||
};
|
||||
|
||||
/*** Used for template metaprogramming ***/
|
||||
|
||||
template < bool Value, typename Then, typename Else >
|
||||
struct Select
|
||||
{
|
||||
typedef Then Result;
|
||||
};
|
||||
|
||||
template < typename Then, typename Else >
|
||||
struct Select < false, Then, Else >
|
||||
{
|
||||
typedef Else Result;
|
||||
};
|
||||
|
||||
#endif /* _TYPES_HPP_ */
|
||||
@@ -0,0 +1,127 @@
|
||||
/*
|
||||
KHOMP generic endpoint/channel library.
|
||||
Copyright (C) 2007-2009 Khomp Ind. & Com.
|
||||
|
||||
The contents of this file are subject to the Mozilla Public License Version 1.1
|
||||
(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.mozilla.org/MPL/
|
||||
|
||||
Software distributed under the License is distributed on an "AS IS" basis,
|
||||
WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
|
||||
the specific language governing rights and limitations under the License.
|
||||
|
||||
Alternatively, the contents of this file may be used under the terms of the
|
||||
"GNU Lesser General Public License 2.1" license (the “LGPL" License), in which
|
||||
case the provisions of "LGPL License" are applicable instead of those above.
|
||||
|
||||
If you wish to allow use of your version of this file only under the terms of
|
||||
the LGPL License and not to allow others to use your version of this file under
|
||||
the MPL, indicate your decision by deleting the provisions above and replace them
|
||||
with the notice and other provisions required by the LGPL License. If you do not
|
||||
delete the provisions above, a recipient may use your version of this file under
|
||||
either the MPL or the LGPL License.
|
||||
|
||||
The LGPL header follows below:
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this library; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
*/
|
||||
|
||||
#include <refcounter.hpp>
|
||||
|
||||
#include <typeinfo>
|
||||
|
||||
#ifndef _VARIANT_H_
|
||||
#define _VARIANT_H_
|
||||
|
||||
/* this is internal, should not be used by the user */
|
||||
struct NoArgumentDefined {};
|
||||
|
||||
template < typename UserReturnType, typename UserArgumentType = NoArgumentDefined >
|
||||
struct VariantBaseType
|
||||
{
|
||||
typedef UserReturnType ReturnType;
|
||||
typedef UserArgumentType ArgumentType;
|
||||
|
||||
virtual ~VariantBaseType() {};
|
||||
|
||||
virtual int which() = 0;
|
||||
|
||||
virtual ReturnType visit(void) { return ReturnType(); };
|
||||
virtual ReturnType visit(ArgumentType) { return ReturnType(); };
|
||||
};
|
||||
|
||||
template < typename BaseType = VariantBaseType < void > >
|
||||
struct Variant: NEW_REFCOUNTER(Variant < BaseType >)
|
||||
{
|
||||
typedef typename BaseType::ReturnType ReturnType;
|
||||
typedef typename BaseType::ArgumentType ArgumentType;
|
||||
|
||||
struct InvalidType {};
|
||||
|
||||
Variant(BaseType * value, bool is_owner = false)
|
||||
: _value(value), _is_owner(is_owner) {};
|
||||
|
||||
Variant(const Variant & v)
|
||||
: INC_REFCOUNTER(v, Variant < BaseType >),
|
||||
_value(v._value), _is_owner(v._is_owner) {};
|
||||
|
||||
virtual ~Variant() {};
|
||||
|
||||
void unreference()
|
||||
{
|
||||
if (_is_owner && _value)
|
||||
{
|
||||
delete _value;
|
||||
_value = 0;
|
||||
}
|
||||
};
|
||||
|
||||
template < typename ValueType >
|
||||
ValueType & get(void)
|
||||
{
|
||||
try
|
||||
{
|
||||
ValueType & ret = dynamic_cast < ValueType & > (*_value);
|
||||
return ret;
|
||||
}
|
||||
catch (std::bad_cast & e)
|
||||
{
|
||||
throw InvalidType();
|
||||
}
|
||||
};
|
||||
|
||||
int which()
|
||||
{
|
||||
return _value->which();
|
||||
}
|
||||
|
||||
ReturnType visit(void)
|
||||
{
|
||||
return _value->visit();
|
||||
}
|
||||
|
||||
ReturnType visit(ArgumentType arg)
|
||||
{
|
||||
return _value->visit(arg);
|
||||
}
|
||||
|
||||
protected:
|
||||
BaseType * _value;
|
||||
bool _is_owner;
|
||||
};
|
||||
|
||||
#endif /* _VARIANT_H_ */
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,505 @@
|
||||
/*
|
||||
KHOMP generic endpoint/channel library.
|
||||
Copyright (C) 2007-2009 Khomp Ind. & Com.
|
||||
|
||||
The contents of this file are subject to the Mozilla Public License Version 1.1
|
||||
(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.mozilla.org/MPL/
|
||||
|
||||
Software distributed under the License is distributed on an "AS IS" basis,
|
||||
WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
|
||||
the specific language governing rights and limitations under the License.
|
||||
|
||||
Alternatively, the contents of this file may be used under the terms of the
|
||||
"GNU Lesser General Public License 2.1" license (the “LGPL" License), in which
|
||||
case the provisions of "LGPL License" are applicable instead of those above.
|
||||
|
||||
If you wish to allow use of your version of this file only under the terms of
|
||||
the LGPL License and not to allow others to use your version of this file under
|
||||
the MPL, indicate your decision by deleting the provisions above and replace them
|
||||
with the notice and other provisions required by the LGPL License. If you do not
|
||||
delete the provisions above, a recipient may use your version of this file under
|
||||
either the MPL or the LGPL License.
|
||||
|
||||
The LGPL header follows below:
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this library; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
*/
|
||||
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <map>
|
||||
|
||||
#include <k3l.h>
|
||||
|
||||
// k3lApiMajorVersion
|
||||
#ifndef CM_PING
|
||||
# include <k3lVersion.h>
|
||||
# include <KTools.h>
|
||||
#endif
|
||||
|
||||
#include <types.hpp>
|
||||
#include <k3lapi.hpp>
|
||||
#include <format.hpp>
|
||||
|
||||
#ifndef _VERBOSE_HPP_
|
||||
#define _VERBOSE_HPP_
|
||||
|
||||
struct Verbose
|
||||
{
|
||||
typedef enum
|
||||
{
|
||||
K_CM_SEIZE = CM_SEIZE,
|
||||
K_CM_SYNC_SEIZE = CM_SYNC_SEIZE,
|
||||
#if K3L_AT_LEAST(1,6,0)
|
||||
K_CM_SIP_REGISTER = CM_SIP_REGISTER,
|
||||
#endif
|
||||
K_CM_DIAL_DTMF = CM_DIAL_DTMF,
|
||||
K_CM_DISCONNECT = CM_DISCONNECT,
|
||||
K_CM_CONNECT = CM_CONNECT,
|
||||
K_CM_PRE_CONNECT = CM_PRE_CONNECT,
|
||||
K_CM_CAS_CHANGE_LINE_STT = CM_CAS_CHANGE_LINE_STT,
|
||||
K_CM_CAS_SEND_MFC = CM_CAS_SEND_MFC,
|
||||
K_CM_SET_FORWARD_CHANNEL = CM_SET_FORWARD_CHANNEL,
|
||||
K_CM_CAS_SET_MFC_DETECT_MODE = CM_CAS_SET_MFC_DETECT_MODE,
|
||||
K_CM_DROP_COLLECT_CALL = CM_DROP_COLLECT_CALL,
|
||||
K_CM_MAKE_CALL = CM_MAKE_CALL,
|
||||
K_CM_RINGBACK = CM_RINGBACK,
|
||||
K_CM_USER_INFORMATION = CM_USER_INFORMATION,
|
||||
#if !K3L_AT_LEAST(2,2,0)
|
||||
K_CM_VOIP_SEIZE = CM_VOIP_SEIZE, //deprecated
|
||||
#endif
|
||||
K_CM_LOCK_INCOMING = CM_LOCK_INCOMING,
|
||||
K_CM_UNLOCK_INCOMING = CM_UNLOCK_INCOMING,
|
||||
K_CM_LOCK_OUTGOING = CM_LOCK_OUTGOING,
|
||||
K_CM_UNLOCK_OUTGOING = CM_UNLOCK_OUTGOING,
|
||||
K_CM_START_SEND_FAIL = CM_START_SEND_FAIL,
|
||||
K_CM_STOP_SEND_FAIL = CM_STOP_SEND_FAIL,
|
||||
K_CM_END_OF_NUMBER = CM_END_OF_NUMBER,
|
||||
#if K3L_AT_LEAST(1,6,0)
|
||||
K_CM_SS_TRANSFER = CM_SS_TRANSFER,
|
||||
K_CM_GET_SMS = CM_GET_SMS,
|
||||
K_CM_PREPARE_SMS = CM_PREPARE_SMS,
|
||||
K_CM_SEND_SMS = CM_SEND_SMS,
|
||||
#endif
|
||||
#if K3L_HAS_MPTY_SUPPORT
|
||||
K_CM_HOLD_SWITCH = CM_HOLD_SWITCH,
|
||||
K_CM_MPTY_CONF = CM_MPTY_CONF,
|
||||
K_CM_MPTY_SPLIT = CM_MPTY_SPLIT,
|
||||
#endif
|
||||
K_CM_ENABLE_DTMF_SUPPRESSION = CM_ENABLE_DTMF_SUPPRESSION,
|
||||
K_CM_DISABLE_DTMF_SUPPRESSION = CM_DISABLE_DTMF_SUPPRESSION,
|
||||
K_CM_ENABLE_AUDIO_EVENTS = CM_ENABLE_AUDIO_EVENTS,
|
||||
K_CM_DISABLE_AUDIO_EVENTS = CM_DISABLE_AUDIO_EVENTS,
|
||||
K_CM_ENABLE_CALL_PROGRESS = CM_ENABLE_CALL_PROGRESS,
|
||||
K_CM_DISABLE_CALL_PROGRESS = CM_DISABLE_CALL_PROGRESS,
|
||||
K_CM_FLASH = CM_FLASH,
|
||||
K_CM_ENABLE_PULSE_DETECTION = CM_ENABLE_PULSE_DETECTION,
|
||||
K_CM_DISABLE_PULSE_DETECTION = CM_DISABLE_PULSE_DETECTION,
|
||||
K_CM_ENABLE_ECHO_CANCELLER = CM_ENABLE_ECHO_CANCELLER,
|
||||
K_CM_DISABLE_ECHO_CANCELLER = CM_DISABLE_ECHO_CANCELLER,
|
||||
K_CM_ENABLE_AGC = CM_ENABLE_AGC,
|
||||
K_CM_DISABLE_AGC = CM_DISABLE_AGC,
|
||||
K_CM_ENABLE_HIGH_IMP_EVENTS = CM_ENABLE_HIGH_IMP_EVENTS,
|
||||
K_CM_DISABLE_HIGH_IMP_EVENTS = CM_DISABLE_HIGH_IMP_EVENTS,
|
||||
#if K3L_AT_LEAST(1,6,0)
|
||||
K_CM_ENABLE_CALL_ANSWER_INFO = CM_ENABLE_CALL_ANSWER_INFO,
|
||||
K_CM_DISABLE_CALL_ANSWER_INFO = CM_DISABLE_CALL_ANSWER_INFO,
|
||||
#endif
|
||||
K_CM_RESET_LINK = CM_RESET_LINK,
|
||||
#if K3L_AT_LEAST(1,6,0)
|
||||
K_CM_CLEAR_LINK_ERROR_COUNTER = CM_CLEAR_LINK_ERROR_COUNTER,
|
||||
#endif
|
||||
K_CM_SEND_DTMF = CM_SEND_DTMF,
|
||||
K_CM_STOP_AUDIO = CM_STOP_AUDIO,
|
||||
K_CM_HARD_RESET = CM_HARD_RESET,
|
||||
K_CM_SEND_TO_CTBUS = CM_SEND_TO_CTBUS,
|
||||
K_CM_RECV_FROM_CTBUS = CM_RECV_FROM_CTBUS,
|
||||
K_CM_SETUP_H100 = CM_SETUP_H100,
|
||||
K_CM_MIXER = CM_MIXER,
|
||||
K_CM_CLEAR_MIXER = CM_CLEAR_MIXER,
|
||||
K_CM_PLAY_FROM_FILE = CM_PLAY_FROM_FILE,
|
||||
K_CM_RECORD_TO_FILE = CM_RECORD_TO_FILE,
|
||||
K_CM_PLAY_FROM_STREAM = CM_PLAY_FROM_STREAM,
|
||||
K_CM_INTERNAL_PLAY = CM_INTERNAL_PLAY,
|
||||
K_CM_STOP_PLAY = CM_STOP_PLAY,
|
||||
K_CM_STOP_RECORD = CM_STOP_RECORD,
|
||||
K_CM_PAUSE_PLAY = CM_PAUSE_PLAY,
|
||||
K_CM_PAUSE_RECORD = CM_PAUSE_RECORD,
|
||||
K_CM_RESUME_PLAY = CM_RESUME_PLAY,
|
||||
K_CM_RESUME_RECORD = CM_RESUME_RECORD,
|
||||
K_CM_INCREASE_VOLUME = CM_INCREASE_VOLUME,
|
||||
K_CM_DECREASE_VOLUME = CM_DECREASE_VOLUME,
|
||||
K_CM_LISTEN = CM_LISTEN,
|
||||
K_CM_STOP_LISTEN = CM_STOP_LISTEN,
|
||||
K_CM_PREPARE_FOR_LISTEN = CM_PREPARE_FOR_LISTEN,
|
||||
K_CM_PLAY_SOUND_CARD = CM_PLAY_SOUND_CARD,
|
||||
K_CM_STOP_SOUND_CARD = CM_STOP_SOUND_CARD,
|
||||
K_CM_MIXER_CTBUS = CM_MIXER_CTBUS,
|
||||
K_CM_PLAY_FROM_STREAM_EX = CM_PLAY_FROM_STREAM_EX,
|
||||
K_CM_INTERNAL_PLAY_EX = CM_INTERNAL_PLAY_EX,
|
||||
K_CM_ENABLE_PLAYER_AGC = CM_ENABLE_PLAYER_AGC,
|
||||
K_CM_DISABLE_PLAYER_AGC = CM_DISABLE_PLAYER_AGC,
|
||||
K_CM_START_STREAM_BUFFER = CM_START_STREAM_BUFFER,
|
||||
K_CM_ADD_STREAM_BUFFER = CM_ADD_STREAM_BUFFER,
|
||||
K_CM_STOP_STREAM_BUFFER = CM_STOP_STREAM_BUFFER,
|
||||
K_CM_SEND_BEEP = CM_SEND_BEEP,
|
||||
K_CM_SEND_BEEP_CONF = CM_SEND_BEEP_CONF,
|
||||
K_CM_ADD_TO_CONF = CM_ADD_TO_CONF,
|
||||
K_CM_REMOVE_FROM_CONF = CM_REMOVE_FROM_CONF,
|
||||
K_CM_RECORD_TO_FILE_EX = CM_RECORD_TO_FILE_EX,
|
||||
K_CM_SET_VOLUME = CM_SET_VOLUME,
|
||||
K_CM_SET_LINE_CONDITION = CM_SET_LINE_CONDITION,
|
||||
K_CM_SEND_LINE_CONDITION = CM_SEND_LINE_CONDITION,
|
||||
K_CM_SET_CALLER_CATEGORY = CM_SET_CALLER_CATEGORY,
|
||||
K_CM_DIAL_MFC = CM_DIAL_MFC,
|
||||
#if !K3L_AT_LEAST(2,0,0)
|
||||
K_CM_VOIP_START_DEBUG = CM_VOIP_START_DEBUG,
|
||||
K_CM_VOIP_STOP_DEBUG = CM_VOIP_STOP_DEBUG,
|
||||
K_CM_VOIP_DUMP_STAT = CM_VOIP_DUMP_STAT,
|
||||
K_CM_ISDN_DEBUG = CM_ISDN_DEBUG,
|
||||
K_CM_PING = CM_PING,
|
||||
K_CM_LOG_REQUEST = CM_LOG_REQUEST,
|
||||
K_CM_LOG_CREATE_DISPATCHER = CM_LOG_CREATE_DISPATCHER,
|
||||
K_CM_LOG_DESTROY_DISPATCHER = CM_LOG_DESTROY_DISPATCHER,
|
||||
#endif
|
||||
#if K3L_AT_LEAST(1,6,0)
|
||||
K_CM_START_CADENCE = CM_START_CADENCE,
|
||||
K_CM_STOP_CADENCE = CM_STOP_CADENCE,
|
||||
K_CM_CHECK_NEW_SMS = CM_CHECK_NEW_SMS,
|
||||
K_CM_SEND_TO_MODEM = CM_SEND_TO_MODEM,
|
||||
#endif
|
||||
#if K3L_AT_LEAST(2,1,0)
|
||||
K_CM_START_FAX_TX = CM_START_FAX_TX,
|
||||
K_CM_STOP_FAX_TX = CM_STOP_FAX_TX,
|
||||
K_CM_ADD_FAX_FILE = CM_ADD_FAX_FILE,
|
||||
K_CM_ADD_FAX_PAGE_BREAK = CM_ADD_FAX_PAGE_BREAK,
|
||||
K_CM_START_FAX_RX = CM_START_FAX_RX,
|
||||
K_CM_STOP_FAX_RX = CM_STOP_FAX_RX,
|
||||
K_CM_SIM_CARD_SELECT = CM_SIM_CARD_SELECT,
|
||||
#endif
|
||||
|
||||
#if K3L_AT_LEAST(2,1,0)
|
||||
K_CM_NOTIFY_WATCHDOG = CM_NOTIFY_WATCHDOG,
|
||||
K_CM_STOP_WATCHDOG = CM_STOP_WATCHDOG,
|
||||
K_CM_WATCHDOG_COUNT = CM_WATCHDOG_COUNT,
|
||||
K_CM_START_WATCHDOG = CM_START_WATCHDOG,
|
||||
#endif
|
||||
|
||||
}
|
||||
kcommand;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
K_EV_CHANNEL_FREE = EV_CHANNEL_FREE,
|
||||
K_EV_CONNECT = EV_CONNECT,
|
||||
K_EV_DISCONNECT = EV_DISCONNECT,
|
||||
K_EV_CALL_SUCCESS = EV_CALL_SUCCESS,
|
||||
K_EV_CALL_FAIL = EV_CALL_FAIL,
|
||||
K_EV_NO_ANSWER = EV_NO_ANSWER,
|
||||
K_EV_BILLING_PULSE = EV_BILLING_PULSE,
|
||||
K_EV_SEIZE_SUCCESS = EV_SEIZE_SUCCESS,
|
||||
K_EV_SEIZE_FAIL = EV_SEIZE_FAIL,
|
||||
K_EV_SEIZURE_START = EV_SEIZURE_START,
|
||||
K_EV_CAS_LINE_STT_CHANGED = EV_CAS_LINE_STT_CHANGED,
|
||||
K_EV_CAS_MFC_RECV = EV_CAS_MFC_RECV,
|
||||
K_EV_NEW_CALL = EV_NEW_CALL,
|
||||
K_EV_USER_INFORMATION = EV_USER_INFORMATION,
|
||||
K_EV_DIALED_DIGIT = EV_DIALED_DIGIT,
|
||||
#if K3L_AT_LEAST(1,6,0)
|
||||
K_EV_SIP_REGISTER_INFO = EV_SIP_REGISTER_INFO,
|
||||
K_EV_RING_DETECTED = EV_RING_DETECTED,
|
||||
#endif
|
||||
K_EV_CALL_HOLD_START = EV_CALL_HOLD_START,
|
||||
K_EV_CALL_HOLD_STOP = EV_CALL_HOLD_STOP,
|
||||
#if K3L_AT_LEAST(1,6,0)
|
||||
K_EV_SS_TRANSFER_FAIL = EV_SS_TRANSFER_FAIL,
|
||||
K_EV_FLASH = EV_FLASH,
|
||||
#endif
|
||||
K_EV_DTMF_DETECTED = EV_DTMF_DETECTED,
|
||||
K_EV_DTMF_SEND_FINISH = EV_DTMF_SEND_FINISH,
|
||||
K_EV_AUDIO_STATUS = EV_AUDIO_STATUS,
|
||||
K_EV_CADENCE_RECOGNIZED = EV_CADENCE_RECOGNIZED,
|
||||
K_EV_END_OF_STREAM = EV_END_OF_STREAM,
|
||||
K_EV_PULSE_DETECTED = EV_PULSE_DETECTED,
|
||||
K_EV_POLARITY_REVERSAL = EV_POLARITY_REVERSAL,
|
||||
#if K3L_AT_LEAST(1,6,0)
|
||||
K_EV_ISDN_PROGRESS_INDICATOR = EV_ISDN_PROGRESS_INDICATOR,
|
||||
K_EV_CALL_ANSWER_INFO = EV_CALL_ANSWER_INFO,
|
||||
K_EV_COLLECT_CALL = EV_COLLECT_CALL,
|
||||
K_EV_SIP_DTMF_DETECTED = EV_SIP_DTMF_DETECTED,
|
||||
K_EV_RECV_FROM_MODEM = EV_RECV_FROM_MODEM,
|
||||
K_EV_NEW_SMS = EV_NEW_SMS,
|
||||
K_EV_SMS_INFO = EV_SMS_INFO,
|
||||
K_EV_SMS_DATA = EV_SMS_DATA,
|
||||
K_EV_SMS_SEND_RESULT = EV_SMS_SEND_RESULT,
|
||||
#endif
|
||||
#if K3L_HAS_MPTY_SUPPORT
|
||||
K_EV_CALL_MPTY_START = EV_CALL_MPTY_START,
|
||||
K_EV_CALL_MPTY_STOP = EV_CALL_MPTY_STOP,
|
||||
K_EV_GSM_COMMAND_STATUS = EV_GSM_COMMAND_STATUS,
|
||||
#endif
|
||||
K_EV_CHANNEL_FAIL = EV_CHANNEL_FAIL,
|
||||
K_EV_REFERENCE_FAIL = EV_REFERENCE_FAIL,
|
||||
K_EV_INTERNAL_FAIL = EV_INTERNAL_FAIL,
|
||||
K_EV_HARDWARE_FAIL = EV_HARDWARE_FAIL,
|
||||
K_EV_LINK_STATUS = EV_LINK_STATUS,
|
||||
#if K3L_AT_LEAST(1,6,0)
|
||||
K_EV_PHYSICAL_LINK_UP = EV_PHYSICAL_LINK_UP,
|
||||
K_EV_PHYSICAL_LINK_DOWN = EV_PHYSICAL_LINK_DOWN,
|
||||
#endif
|
||||
K_EV_CLIENT_RECONNECT = EV_CLIENT_RECONNECT,
|
||||
K_EV_VOIP_SEIZURE = EV_VOIP_SEIZURE,
|
||||
K_EV_SEIZURE = EV_SEIZURE,
|
||||
|
||||
#if K3L_AT_LEAST(2,1,0)
|
||||
K_EV_FAX_CHANNEL_FREE = EV_FAX_CHANNEL_FREE,
|
||||
K_EV_FAX_FILE_SENT = EV_FAX_FILE_SENT,
|
||||
K_EV_FAX_FILE_FAIL = EV_FAX_FILE_FAIL,
|
||||
K_EV_FAX_MESSAGE_CONFIRMATION = EV_FAX_MESSAGE_CONFIRMATION,
|
||||
K_EV_FAX_TX_TIMEOUT = EV_FAX_TX_TIMEOUT,
|
||||
K_EV_FAX_PAGE_CONFIRMATION = EV_FAX_PAGE_CONFIRMATION,
|
||||
K_EV_FAX_REMOTE_INFO = EV_FAX_REMOTE_INFO,
|
||||
#endif
|
||||
|
||||
#if K3L_AT_LEAST(2,1,0)
|
||||
K_EV_WATCHDOG_COUNT = EV_WATCHDOG_COUNT,
|
||||
#endif
|
||||
|
||||
#if !K3L_AT_LEAST(2,0,0)
|
||||
K_EV_PONG = EV_PONG,
|
||||
#endif
|
||||
}
|
||||
kevent;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
R2_COUNTRY_ARG = 1,
|
||||
R2_COUNTRY_BRA = 2,
|
||||
R2_COUNTRY_CHI = 3,
|
||||
R2_COUNTRY_MEX = 4,
|
||||
R2_COUNTRY_URY = 5,
|
||||
R2_COUNTRY_VEN = 6
|
||||
}
|
||||
R2CountryType;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
HUMAN,
|
||||
EXACT
|
||||
}
|
||||
Presentation;
|
||||
|
||||
/* dynamic (object) stuff */
|
||||
|
||||
Verbose(K3LAPI & api): _api(api) {};
|
||||
|
||||
#if K3L_AT_LEAST(2,0,0)
|
||||
std::string event(int32, K3L_EVENT*, R2CountryType r2_country = R2_COUNTRY_BRA,
|
||||
Presentation fmt = HUMAN);
|
||||
#else
|
||||
std::string event(int32, K3L_EVENT*, Presentation fmt = HUMAN);
|
||||
#endif
|
||||
|
||||
std::string channelStatus(int32, int32, int32, Presentation fmt = HUMAN);
|
||||
|
||||
/* end of dynamic (object) stuff */
|
||||
|
||||
protected:
|
||||
K3LAPI & _api;
|
||||
|
||||
/* used internally */
|
||||
struct internal_not_found {};
|
||||
|
||||
public:
|
||||
|
||||
/* static (class) stuff */
|
||||
|
||||
static std::string echoLocation(KEchoLocation, Presentation fmt = HUMAN);
|
||||
static std::string echoCancellerConfig(KEchoCancellerConfig, Presentation fmt = HUMAN);
|
||||
|
||||
#if K3L_AT_LEAST(2,0,0)
|
||||
static std::string event(KSignaling, int32, K3L_EVENT*, R2CountryType = R2_COUNTRY_BRA,
|
||||
Presentation fmt = HUMAN);
|
||||
#else
|
||||
static std::string event(KSignaling, int32, K3L_EVENT*, Presentation fmt = HUMAN);
|
||||
#endif
|
||||
|
||||
#if K3L_AT_LEAST(2,0,0)
|
||||
static std::string command(int32, K3L_COMMAND*, R2CountryType = R2_COUNTRY_BRA,
|
||||
Presentation fmt = HUMAN);
|
||||
static std::string command(int32, int32, int32, const char *, R2CountryType = R2_COUNTRY_BRA,
|
||||
Presentation fmt = HUMAN);
|
||||
#else
|
||||
static std::string command(int32, K3L_COMMAND*, Presentation fmt = HUMAN);
|
||||
static std::string command(int32, int32, int32, const char *, Presentation fmt = HUMAN);
|
||||
#endif
|
||||
|
||||
|
||||
static std::string deviceName(KDeviceType, int32, Presentation fmt = HUMAN);
|
||||
|
||||
static std::string deviceType(KDeviceType, Presentation fmt = HUMAN);
|
||||
static std::string deviceModel(KDeviceType, int32, Presentation fmt = HUMAN);
|
||||
|
||||
static std::string channelFeatures(int32, Presentation fmt = HUMAN);
|
||||
static std::string signaling(KSignaling, Presentation fmt = HUMAN);
|
||||
static std::string systemObject(KSystemObject, Presentation fmt = HUMAN);
|
||||
static std::string mixerTone(KMixerTone, Presentation fmt = HUMAN);
|
||||
static std::string mixerSource(KMixerSource, Presentation fmt = HUMAN);
|
||||
|
||||
static std::string seizeFail(KSeizeFail, Presentation fmt = HUMAN);
|
||||
|
||||
#if K3L_AT_LEAST(2,0,0)
|
||||
static std::string callFail(KSignaling, R2CountryType, int32, Presentation fmt = HUMAN);
|
||||
#else
|
||||
static std::string callFail(KSignaling, int32, Presentation fmt = HUMAN);
|
||||
#endif
|
||||
|
||||
static std::string channelFail(KSignaling, int32, Presentation fmt = HUMAN);
|
||||
static std::string internalFail(KInternalFail, Presentation fmt = HUMAN);
|
||||
|
||||
static std::string linkErrorCounter(KLinkErrorCounter, Presentation fmt = HUMAN);
|
||||
|
||||
static std::string linkStatus(KSignaling, int32, Presentation fmt = HUMAN);
|
||||
static std::string channelStatus(KSignaling, int32, Presentation fmt = HUMAN);
|
||||
static std::string callStatus(KCallStatus, Presentation fmt = HUMAN);
|
||||
static std::string status(KLibraryStatus, Presentation fmt = HUMAN);
|
||||
|
||||
#if K3L_AT_LEAST(2,0,0)
|
||||
static std::string signGroupB(KSignGroupB, R2CountryType contry = R2_COUNTRY_BRA,
|
||||
Presentation fmt = HUMAN);
|
||||
#else
|
||||
static std::string signGroupB(KSignGroupB, Presentation fmt = HUMAN);
|
||||
#endif
|
||||
|
||||
#if K3L_AT_LEAST(2,0,0)
|
||||
static std::string signGroupII(KSignGroupII, R2CountryType contry = R2_COUNTRY_BRA,
|
||||
Presentation fmt = HUMAN);
|
||||
#else
|
||||
static std::string signGroupII(KSignGroupII, Presentation fmt = HUMAN);
|
||||
#endif
|
||||
|
||||
static std::string h100configIndex(KH100ConfigIndex, Presentation fmt = HUMAN);
|
||||
|
||||
static std::string eventName(int32);
|
||||
static std::string commandName(int32);
|
||||
|
||||
#if K3L_AT_LEAST(1,5,0)
|
||||
static std::string sipFailures(KSIP_Failures, Presentation fmt = HUMAN);
|
||||
#endif
|
||||
|
||||
#if K3L_AT_LEAST(1,5,1)
|
||||
static std::string isdnCause(KQ931Cause, Presentation fmt = HUMAN);
|
||||
#endif
|
||||
|
||||
#if K3L_AT_LEAST(1,5,2)
|
||||
static std::string isdnDebug(int32, Presentation fmt = HUMAN);
|
||||
#endif
|
||||
|
||||
#if K3L_AT_LEAST(1,6,0)
|
||||
static std::string callStartInfo(KCallStartInfo, Presentation fmt = HUMAN);
|
||||
|
||||
static std::string gsmCallCause(KGsmCallCause, Presentation fmt = HUMAN);
|
||||
static std::string gsmMobileCause(KGsmMobileCause, Presentation fmt = HUMAN);
|
||||
static std::string gsmSmsCause(KGsmSmsCause, Presentation fmt = HUMAN);
|
||||
|
||||
static std::string q931ProgressIndication(KQ931ProgressIndication,
|
||||
Presentation fmt = HUMAN);
|
||||
#endif
|
||||
|
||||
#if K3L_AT_LEAST(2,1,0)
|
||||
static std::string faxResult(KFaxResult code, Presentation fmt = HUMAN);
|
||||
static std::string faxFileErrorCause(KFaxFileErrorCause code, Presentation fmt = HUMAN);
|
||||
#endif
|
||||
|
||||
/* end of static (class) stuff */
|
||||
|
||||
private:
|
||||
static std::string internal_deviceType(KDeviceType);
|
||||
static std::string internal_deviceModel(KDeviceType, int32);
|
||||
|
||||
#if K3L_AT_LEAST(1,5,0)
|
||||
static std::string internal_sipFailures(KSIP_Failures, Presentation fmt = HUMAN);
|
||||
#endif
|
||||
#if K3L_AT_LEAST(1,5,1)
|
||||
static std::string internal_isdnCause(KQ931Cause, Presentation fmt = HUMAN);
|
||||
#endif
|
||||
|
||||
#if K3L_AT_LEAST(2,0,0)
|
||||
static std::string internal_signGroupB(KSignGroupB, R2CountryType contry, Presentation fmt = HUMAN);
|
||||
static std::string internal_signGroupII(KSignGroupII, R2CountryType contry, Presentation fmt = HUMAN);
|
||||
#else
|
||||
static std::string internal_signGroupB(KSignGroupB, Presentation fmt = HUMAN);
|
||||
static std::string internal_signGroupII(KSignGroupII, Presentation fmt = HUMAN);
|
||||
#endif
|
||||
|
||||
#if K3L_AT_LEAST(1,6,0)
|
||||
static std::string internal_gsmCallCause(KGsmCallCause, Presentation fmt = HUMAN);
|
||||
static std::string internal_gsmMobileCause(KGsmMobileCause, Presentation fmt = HUMAN);
|
||||
static std::string internal_gsmSmsCause(KGsmSmsCause, Presentation fmt = HUMAN);
|
||||
|
||||
static std::string internal_q931ProgressIndication(KQ931ProgressIndication, Presentation fmt = HUMAN);
|
||||
#endif
|
||||
|
||||
private:
|
||||
enum Type
|
||||
{
|
||||
DEVICE,
|
||||
CHANNEL,
|
||||
PLAYER,
|
||||
MIXER,
|
||||
LINK,
|
||||
NONE
|
||||
};
|
||||
|
||||
struct Target
|
||||
{
|
||||
Target(Type _type)
|
||||
: type(_type), device(-1), object(-1)
|
||||
{};
|
||||
|
||||
Target(Type _type, int32 _device)
|
||||
: type(_type), device(_device), object(-1)
|
||||
{};
|
||||
|
||||
Target(Type _type, int32 _device, int32 _object)
|
||||
: type(_type), device(_device), object(_object)
|
||||
{};
|
||||
|
||||
Type type;
|
||||
int32 device;
|
||||
int32 object;
|
||||
};
|
||||
|
||||
static void generate(std::string &, std::string &, Target, std::string &);
|
||||
|
||||
static std::string show(std::string &, std::string, Target, std::string &);
|
||||
static std::string show(std::string &, std::string, Target);
|
||||
|
||||
template < typename ReturnType >
|
||||
static ReturnType presentation(Presentation fmt, ReturnType str_exact, ReturnType str_human)
|
||||
{
|
||||
switch (fmt)
|
||||
{
|
||||
case HUMAN: return str_human;
|
||||
case EXACT: return str_exact;
|
||||
};
|
||||
|
||||
return str_exact;
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* _VERBOSE_HPP_ */
|
||||
Reference in new issue
Block a user