Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
Adam Osuchowski
Kea
Commits
ff216738
Commit
ff216738
authored
Nov 27, 2012
by
Marcin Siodelski
Browse files
[2312] Implemented OptionCustom::toText() function.
parent
2dd98a11
Changes
5
Hide whitespace changes
Inline
Side-by-side
src/lib/dhcp/option_custom.cc
View file @
ff216738
...
...
@@ -242,20 +242,30 @@ OptionCustom::len() {
return
(
length
);
}
std
::
string
OptionCustom
::
toText
(
int
/* =0 */
)
{
std
::
string
OptionCustom
::
toText
(
int
indent
/* =
0 */
)
{
std
::
stringstream
tmp
;
/*
for (int i = 0; i < indent;
i
++)
for
(
int
i
=
0
;
i
<
indent
;
++
i
)
tmp
<<
" "
;
tmp << "type=" << type_ << ", len=" << len()-getHeaderLen() << ": ";
tmp
<<
"type="
<<
type_
<<
", len="
<<
len
()
-
getHeaderLen
()
<<
", data fields:"
<<
std
::
endl
;
for (unsigned int i = 0; i < data_.size(); i++) {
if (i) {
tmp << ":";
OptionDataType
data_type
=
definition_
.
getType
();
for
(
unsigned
int
i
=
0
;
i
<
getDataFieldsNum
();
++
i
)
{
if
(
data_type
==
OPT_RECORD_TYPE
)
{
const
OptionDefinition
::
RecordFieldsCollection
&
fields
=
definition_
.
getRecordFields
();
for
(
OptionDefinition
::
RecordFieldsConstIter
field
=
fields
.
begin
();
field
!=
fields
.
end
();
++
field
)
{
for
(
int
j
=
0
;
j
<
indent
+
2
;
++
j
)
{
tmp
<<
" "
;
}
tmp
<<
OptionDataTypeUtil
::
getDataTypeName
(
*
field
)
<<
", value = "
<<
"here is a value"
<<
std
::
endl
;
}
}
tmp << setfill('0') << setw(2) << hex
<< static_cast<unsigned short>(data_[i]);
}
// print suboptions
...
...
@@ -263,7 +273,7 @@ std::string OptionCustom::toText(int /* =0 */ ) {
opt
!=
options_
.
end
();
++
opt
)
{
tmp
<<
(
*
opt
).
second
->
toText
(
indent
+
2
);
}
*/
}
return
tmp
.
str
();
}
...
...
src/lib/dhcp/option_data_types.cc
View file @
ff216738
...
...
@@ -18,6 +18,54 @@
namespace
isc
{
namespace
dhcp
{
OptionDataTypeUtil
::
OptionDataTypeUtil
()
{
data_types_
[
"empty"
]
=
OPT_EMPTY_TYPE
;
data_types_
[
"binary"
]
=
OPT_BINARY_TYPE
;
data_types_
[
"boolean"
]
=
OPT_BOOLEAN_TYPE
;
data_types_
[
"int8"
]
=
OPT_INT8_TYPE
;
data_types_
[
"int16"
]
=
OPT_INT16_TYPE
;
data_types_
[
"int32"
]
=
OPT_INT32_TYPE
;
data_types_
[
"uint8"
]
=
OPT_UINT8_TYPE
;
data_types_
[
"uint16"
]
=
OPT_UINT16_TYPE
;
data_types_
[
"uint32"
]
=
OPT_UINT32_TYPE
;
data_types_
[
"ipv4-address"
]
=
OPT_IPV4_ADDRESS_TYPE
;
data_types_
[
"ipv6-address"
]
=
OPT_IPV6_ADDRESS_TYPE
;
data_types_
[
"string"
]
=
OPT_STRING_TYPE
;
data_types_
[
"fqdn"
]
=
OPT_FQDN_TYPE
;
data_types_
[
"record"
]
=
OPT_RECORD_TYPE
;
data_type_names_
[
OPT_EMPTY_TYPE
]
=
"empty"
;
data_type_names_
[
OPT_BINARY_TYPE
]
=
"binary"
;
data_type_names_
[
OPT_BOOLEAN_TYPE
]
=
"boolean"
;
data_type_names_
[
OPT_INT8_TYPE
]
=
"int8"
;
data_type_names_
[
OPT_INT16_TYPE
]
=
"int16"
;
data_type_names_
[
OPT_INT32_TYPE
]
=
"int32"
;
data_type_names_
[
OPT_UINT8_TYPE
]
=
"uint8"
;
data_type_names_
[
OPT_UINT16_TYPE
]
=
"uint16"
;
data_type_names_
[
OPT_UINT32_TYPE
]
=
"uint32"
;
data_type_names_
[
OPT_IPV4_ADDRESS_TYPE
]
=
"ipv4-address"
;
data_type_names_
[
OPT_IPV6_ADDRESS_TYPE
]
=
"ipv4-address"
;
data_type_names_
[
OPT_STRING_TYPE
]
=
"string"
;
data_type_names_
[
OPT_FQDN_TYPE
]
=
"fqdn"
;
data_type_names_
[
OPT_RECORD_TYPE
]
=
"record"
;
data_type_names_
[
OPT_UNKNOWN_TYPE
]
=
"unknown"
;
}
OptionDataType
OptionDataTypeUtil
::
getDataType
(
const
std
::
string
&
data_type
)
{
return
(
OptionDataTypeUtil
::
instance
().
getDataTypeImpl
(
data_type
));
}
OptionDataType
OptionDataTypeUtil
::
getDataTypeImpl
(
const
std
::
string
&
data_type
)
const
{
std
::
map
<
std
::
string
,
OptionDataType
>::
const_iterator
data_type_it
=
data_types_
.
find
(
data_type
);
if
(
data_type_it
!=
data_types_
.
end
())
{
return
(
data_type_it
->
second
);
}
return
(
OPT_UNKNOWN_TYPE
);
}
int
OptionDataTypeUtil
::
getDataTypeLen
(
const
OptionDataType
data_type
)
{
switch
(
data_type
)
{
...
...
@@ -41,6 +89,27 @@ OptionDataTypeUtil::getDataTypeLen(const OptionDataType data_type) {
return
(
0
);
}
const
std
::
string
&
OptionDataTypeUtil
::
getDataTypeName
(
const
OptionDataType
data_type
)
{
return
(
OptionDataTypeUtil
::
instance
().
getDataTypeNameImpl
(
data_type
));
}
const
std
::
string
&
OptionDataTypeUtil
::
getDataTypeNameImpl
(
const
OptionDataType
data_type
)
const
{
std
::
map
<
OptionDataType
,
std
::
string
>::
const_iterator
data_type_it
=
data_type_names_
.
find
(
data_type
);
if
(
data_type_it
!=
data_type_names_
.
end
())
{
return
(
data_type_it
->
second
);
}
return
(
data_type_names_
.
find
(
OPT_UNKNOWN_TYPE
)
->
second
);
}
OptionDataTypeUtil
&
OptionDataTypeUtil
::
instance
()
{
static
OptionDataTypeUtil
instance
;
return
(
instance
);
}
void
OptionDataTypeUtil
::
readAddress
(
const
std
::
vector
<
uint8_t
>&
buf
,
const
short
family
,
...
...
src/lib/dhcp/option_data_types.h
View file @
ff216738
...
...
@@ -174,10 +174,22 @@ struct OptionDataTypeTraits<std::string> {
static
const
OptionDataType
type
=
OPT_STRING_TYPE
;
};
/// @brief Utility class
to write/read data to/from a buffer
.
/// @brief Utility class
for option data types
.
class
OptionDataTypeUtil
{
public:
/// @brief Return option data type from its name.
///
/// @param data_type data type name.
/// @return option data type.
static
OptionDataType
getDataType
(
const
std
::
string
&
data_type
);
/// @brief Return option data type name from the data type enumerator.
///
/// @param data_type option data type.
/// @return option data type name.
static
const
std
::
string
&
getDataTypeName
(
const
OptionDataType
data_type
);
/// @brief Get data type buffer length.
///
/// This functionm returs the size of a particular data type.
...
...
@@ -312,7 +324,43 @@ public:
/// @param [out] buf output buffer.
static
void
writeString
(
const
std
::
string
&
value
,
std
::
vector
<
uint8_t
>&
buf
);
private:
/// The container holding mapping of data type names to
/// data types enumerator.
std
::
map
<
std
::
string
,
OptionDataType
>
data_types_
;
/// The container holding mapping of data types to data
/// type names.
std
::
map
<
OptionDataType
,
std
::
string
>
data_type_names_
;
/// @brief Private constructor.
///
/// This constructor is private because this class should
/// be used as singleton (through static public functions).
OptionDataTypeUtil
();
/// @brief Return instance of OptionDataTypeUtil
///
/// This function is used by some of the public static functions
/// to create an instance of OptionDataTypeUtil class.
/// When instance is called it calls the class'es constructor
/// and initializes some of the private data members.
///
/// @return instance of OptionDataTypeUtil singleton.
static
OptionDataTypeUtil
&
instance
();
/// @brief Return option data type from its name.
///
/// @param data_type data type name.
/// @return option data type.
OptionDataType
getDataTypeImpl
(
const
std
::
string
&
data_type
)
const
;
/// @brief Return option data type name from the data type enumerator.
///
/// @param data_type option data type.
/// @return option data type name.
const
std
::
string
&
getDataTypeNameImpl
(
const
OptionDataType
data_type
)
const
;
};
...
...
src/lib/dhcp/option_definition.cc
View file @
ff216738
...
...
@@ -28,150 +28,6 @@ using namespace isc::util;
namespace
isc
{
namespace
dhcp
{
OptionDefinition
::
DataTypeUtil
::
DataTypeUtil
()
{
data_types_
[
"empty"
]
=
OPT_EMPTY_TYPE
;
data_types_
[
"binary"
]
=
OPT_BINARY_TYPE
;
data_types_
[
"boolean"
]
=
OPT_BOOLEAN_TYPE
;
data_types_
[
"int8"
]
=
OPT_INT8_TYPE
;
data_types_
[
"int16"
]
=
OPT_INT16_TYPE
;
data_types_
[
"int32"
]
=
OPT_INT32_TYPE
;
data_types_
[
"uint8"
]
=
OPT_UINT8_TYPE
;
data_types_
[
"uint16"
]
=
OPT_UINT16_TYPE
;
data_types_
[
"uint32"
]
=
OPT_UINT32_TYPE
;
data_types_
[
"ipv4-address"
]
=
OPT_IPV4_ADDRESS_TYPE
;
data_types_
[
"ipv6-address"
]
=
OPT_IPV6_ADDRESS_TYPE
;
data_types_
[
"string"
]
=
OPT_STRING_TYPE
;
data_types_
[
"fqdn"
]
=
OPT_FQDN_TYPE
;
data_types_
[
"record"
]
=
OPT_RECORD_TYPE
;
}
OptionDataType
OptionDefinition
::
DataTypeUtil
::
getOptionDataType
(
const
std
::
string
&
data_type
)
{
std
::
map
<
std
::
string
,
OptionDataType
>::
const_iterator
data_type_it
=
data_types_
.
find
(
data_type
);
if
(
data_type_it
!=
data_types_
.
end
())
{
return
(
data_type_it
->
second
);
}
return
(
OPT_UNKNOWN_TYPE
);
}
template
<
typename
T
>
T
OptionDefinition
::
DataTypeUtil
::
lexicalCastWithRangeCheck
(
const
std
::
string
&
value_str
)
const
{
// Lexical cast in case of our data types make sense only
// for uintX_t, intX_t and bool type.
if
(
!
OptionDataTypeTraits
<
T
>::
integer_type
&&
OptionDataTypeTraits
<
T
>::
type
!=
OPT_BOOLEAN_TYPE
)
{
isc_throw
(
BadDataTypeCast
,
"unable to do lexical cast to non-integer and"
<<
" non-boolean data type"
);
}
// We use the 64-bit value here because it has wider range than
// any other type we use here and it allows to detect out of
// bounds conditions e.g. negative value specified for uintX_t
// data type. Obviously if the value exceeds the limits of int64
// this function will not handle that properly.
int64_t
result
=
0
;
try
{
result
=
boost
::
lexical_cast
<
int64_t
>
(
value_str
);
}
catch
(
const
boost
::
bad_lexical_cast
&
ex
)
{
// Prepare error message here.
std
::
string
data_type_str
=
"boolean"
;
if
(
OptionDataTypeTraits
<
T
>::
integer_type
)
{
data_type_str
=
"integer"
;
}
isc_throw
(
BadDataTypeCast
,
"unable to do lexical cast to "
<<
data_type_str
<<
" data type for value "
<<
value_str
<<
": "
<<
ex
.
what
());
}
// Perform range checks for integer values only (exclude bool values).
if
(
OptionDataTypeTraits
<
T
>::
integer_type
)
{
if
(
result
>
numeric_limits
<
T
>::
max
()
||
result
<
numeric_limits
<
T
>::
min
())
{
isc_throw
(
BadDataTypeCast
,
"unable to do lexical cast for value "
<<
value_str
<<
". This value is expected to be in the range of "
<<
numeric_limits
<
T
>::
min
()
<<
".."
<<
numeric_limits
<
T
>::
max
());
}
}
return
(
static_cast
<
T
>
(
result
));
}
void
OptionDefinition
::
DataTypeUtil
::
writeToBuffer
(
const
std
::
string
&
value
,
const
OptionDataType
type
,
OptionBuffer
&
buf
)
{
// We are going to write value given by value argument to the buffer.
// The actual type of the value is given by second argument. Check
// this argument to determine how to write this value to the buffer.
switch
(
type
)
{
case
OPT_BINARY_TYPE
:
OptionDataTypeUtil
::
writeBinary
(
value
,
buf
);
return
;
case
OPT_BOOLEAN_TYPE
:
// We encode the true value as 1 and false as 0 on 8 bits.
// That way we actually waste 7 bits but it seems to be the
// simpler way to encode boolean.
// @todo Consider if any other encode methods can be used.
OptionDataTypeUtil
::
writeBool
(
lexicalCastWithRangeCheck
<
bool
>
(
value
),
buf
);
return
;
case
OPT_INT8_TYPE
:
OptionDataTypeUtil
::
writeInt
<
uint8_t
>
(
lexicalCastWithRangeCheck
<
int8_t
>
(
value
),
buf
);
return
;
case
OPT_INT16_TYPE
:
OptionDataTypeUtil
::
writeInt
<
uint16_t
>
(
lexicalCastWithRangeCheck
<
int16_t
>
(
value
),
buf
);
return
;
case
OPT_INT32_TYPE
:
OptionDataTypeUtil
::
writeInt
<
uint32_t
>
(
lexicalCastWithRangeCheck
<
int32_t
>
(
value
),
buf
);
return
;
case
OPT_UINT8_TYPE
:
OptionDataTypeUtil
::
writeInt
<
uint8_t
>
(
lexicalCastWithRangeCheck
<
uint8_t
>
(
value
),
buf
);
return
;
case
OPT_UINT16_TYPE
:
OptionDataTypeUtil
::
writeInt
<
uint16_t
>
(
lexicalCastWithRangeCheck
<
uint16_t
>
(
value
),
buf
);
return
;
case
OPT_UINT32_TYPE
:
OptionDataTypeUtil
::
writeInt
<
uint32_t
>
(
lexicalCastWithRangeCheck
<
uint32_t
>
(
value
),
buf
);
return
;
case
OPT_IPV4_ADDRESS_TYPE
:
case
OPT_IPV6_ADDRESS_TYPE
:
{
asiolink
::
IOAddress
address
(
value
);
if
(
!
address
.
getAddress
().
is_v4
()
&&
!
address
.
getAddress
().
is_v6
())
{
isc_throw
(
BadDataTypeCast
,
"provided address "
<<
address
.
toText
()
<<
" is not a valid "
<<
(
address
.
getAddress
().
is_v4
()
?
"IPv4"
:
"IPv6"
)
<<
" address"
);
}
OptionDataTypeUtil
::
writeAddress
(
address
,
buf
);
return
;
}
case
OPT_STRING_TYPE
:
OptionDataTypeUtil
::
writeString
(
value
,
buf
);
return
;
case
OPT_FQDN_TYPE
:
{
// FQDN implementation is not terribly complicated but will require
// creation of some additional logic (maybe object) that will parse
// the fqdn into labels.
isc_throw
(
isc
::
NotImplemented
,
"write of FQDN record into option buffer"
" is not supported yet"
);
return
;
}
default:
// We hit this point because invalid option data type has been specified
// This may be the case because 'empty' or 'record' data type has been
// specified. We don't throw exception here because it will be thrown
// at the exit point from this function.
;
}
isc_throw
(
isc
::
BadValue
,
"attempt to write invalid option data field type"
" into the option buffer: "
<<
type
);
}
OptionDefinition
::
OptionDefinition
(
const
std
::
string
&
name
,
const
uint16_t
code
,
...
...
@@ -184,7 +40,7 @@ OptionDefinition::OptionDefinition(const std::string& name,
// Data type is held as enum value by this class.
// Use the provided option type string to get the
// corresponding enum value.
type_
=
DataTypeUtil
::
instance
().
getOption
DataType
(
type
);
type_
=
Option
DataTypeUtil
::
get
DataType
(
type
);
}
OptionDefinition
::
OptionDefinition
(
const
std
::
string
&
name
,
...
...
@@ -199,7 +55,7 @@ OptionDefinition::OptionDefinition(const std::string& name,
void
OptionDefinition
::
addRecordField
(
const
std
::
string
&
data_type_name
)
{
OptionDataType
data_type
=
DataTypeUtil
::
instance
().
getOption
DataType
(
data_type_name
);
OptionDataType
data_type
=
Option
DataTypeUtil
::
get
DataType
(
data_type_name
);
addRecordField
(
data_type
);
}
...
...
@@ -291,10 +147,10 @@ OptionDefinition::optionFactory(Option::Universe u, uint16_t type,
if
(
values
.
size
()
==
0
)
{
isc_throw
(
InvalidOptionValue
,
"no option value specified"
);
}
DataTypeUtil
::
instance
().
writeToBuffer
(
values
[
0
],
type_
,
buf
);
writeToBuffer
(
values
[
0
],
type_
,
buf
);
}
else
if
(
array_type_
&&
type_
!=
OPT_RECORD_TYPE
)
{
for
(
size_t
i
=
0
;
i
<
values
.
size
();
++
i
)
{
DataTypeUtil
::
instance
().
writeToBuffer
(
values
[
i
],
type_
,
buf
);
writeToBuffer
(
values
[
i
],
type_
,
buf
);
}
}
else
if
(
type_
==
OPT_RECORD_TYPE
)
{
const
RecordFieldsCollection
&
records
=
getRecordFields
();
...
...
@@ -304,7 +160,7 @@ OptionDefinition::optionFactory(Option::Universe u, uint16_t type,
<<
" provided."
);
}
for
(
size_t
i
=
0
;
i
<
records
.
size
();
++
i
)
{
DataTypeUtil
::
instance
().
writeToBuffer
(
values
[
i
],
records
[
i
],
buf
);
writeToBuffer
(
values
[
i
],
records
[
i
],
buf
);
}
}
return
(
optionFactory
(
u
,
type
,
buf
.
begin
(),
buf
.
end
()));
...
...
@@ -410,6 +266,124 @@ OptionDefinition::haveIAAddr6Format() const {
return
(
haveIAx6Format
(
OPT_IPV6_ADDRESS_TYPE
));
}
template
<
typename
T
>
T
OptionDefinition
::
lexicalCastWithRangeCheck
(
const
std
::
string
&
value_str
)
const
{
// Lexical cast in case of our data types make sense only
// for uintX_t, intX_t and bool type.
if
(
!
OptionDataTypeTraits
<
T
>::
integer_type
&&
OptionDataTypeTraits
<
T
>::
type
!=
OPT_BOOLEAN_TYPE
)
{
isc_throw
(
BadDataTypeCast
,
"unable to do lexical cast to non-integer and"
<<
" non-boolean data type"
);
}
// We use the 64-bit value here because it has wider range than
// any other type we use here and it allows to detect out of
// bounds conditions e.g. negative value specified for uintX_t
// data type. Obviously if the value exceeds the limits of int64
// this function will not handle that properly.
int64_t
result
=
0
;
try
{
result
=
boost
::
lexical_cast
<
int64_t
>
(
value_str
);
}
catch
(
const
boost
::
bad_lexical_cast
&
ex
)
{
// Prepare error message here.
std
::
string
data_type_str
=
"boolean"
;
if
(
OptionDataTypeTraits
<
T
>::
integer_type
)
{
data_type_str
=
"integer"
;
}
isc_throw
(
BadDataTypeCast
,
"unable to do lexical cast to "
<<
data_type_str
<<
" data type for value "
<<
value_str
<<
": "
<<
ex
.
what
());
}
// Perform range checks for integer values only (exclude bool values).
if
(
OptionDataTypeTraits
<
T
>::
integer_type
)
{
if
(
result
>
numeric_limits
<
T
>::
max
()
||
result
<
numeric_limits
<
T
>::
min
())
{
isc_throw
(
BadDataTypeCast
,
"unable to do lexical cast for value "
<<
value_str
<<
". This value is expected to be in the range of "
<<
numeric_limits
<
T
>::
min
()
<<
".."
<<
numeric_limits
<
T
>::
max
());
}
}
return
(
static_cast
<
T
>
(
result
));
}
void
OptionDefinition
::
writeToBuffer
(
const
std
::
string
&
value
,
const
OptionDataType
type
,
OptionBuffer
&
buf
)
const
{
// We are going to write value given by value argument to the buffer.
// The actual type of the value is given by second argument. Check
// this argument to determine how to write this value to the buffer.
switch
(
type
)
{
case
OPT_BINARY_TYPE
:
OptionDataTypeUtil
::
writeBinary
(
value
,
buf
);
return
;
case
OPT_BOOLEAN_TYPE
:
// We encode the true value as 1 and false as 0 on 8 bits.
// That way we actually waste 7 bits but it seems to be the
// simpler way to encode boolean.
// @todo Consider if any other encode methods can be used.
OptionDataTypeUtil
::
writeBool
(
lexicalCastWithRangeCheck
<
bool
>
(
value
),
buf
);
return
;
case
OPT_INT8_TYPE
:
OptionDataTypeUtil
::
writeInt
<
uint8_t
>
(
lexicalCastWithRangeCheck
<
int8_t
>
(
value
),
buf
);
return
;
case
OPT_INT16_TYPE
:
OptionDataTypeUtil
::
writeInt
<
uint16_t
>
(
lexicalCastWithRangeCheck
<
int16_t
>
(
value
),
buf
);
return
;
case
OPT_INT32_TYPE
:
OptionDataTypeUtil
::
writeInt
<
uint32_t
>
(
lexicalCastWithRangeCheck
<
int32_t
>
(
value
),
buf
);
return
;
case
OPT_UINT8_TYPE
:
OptionDataTypeUtil
::
writeInt
<
uint8_t
>
(
lexicalCastWithRangeCheck
<
uint8_t
>
(
value
),
buf
);
return
;
case
OPT_UINT16_TYPE
:
OptionDataTypeUtil
::
writeInt
<
uint16_t
>
(
lexicalCastWithRangeCheck
<
uint16_t
>
(
value
),
buf
);
return
;
case
OPT_UINT32_TYPE
:
OptionDataTypeUtil
::
writeInt
<
uint32_t
>
(
lexicalCastWithRangeCheck
<
uint32_t
>
(
value
),
buf
);
return
;
case
OPT_IPV4_ADDRESS_TYPE
:
case
OPT_IPV6_ADDRESS_TYPE
:
{
asiolink
::
IOAddress
address
(
value
);
if
(
!
address
.
getAddress
().
is_v4
()
&&
!
address
.
getAddress
().
is_v6
())
{
isc_throw
(
BadDataTypeCast
,
"provided address "
<<
address
.
toText
()
<<
" is not a valid "
<<
(
address
.
getAddress
().
is_v4
()
?
"IPv4"
:
"IPv6"
)
<<
" address"
);
}
OptionDataTypeUtil
::
writeAddress
(
address
,
buf
);
return
;
}
case
OPT_STRING_TYPE
:
OptionDataTypeUtil
::
writeString
(
value
,
buf
);
return
;
case
OPT_FQDN_TYPE
:
{
// FQDN implementation is not terribly complicated but will require
// creation of some additional logic (maybe object) that will parse
// the fqdn into labels.
isc_throw
(
isc
::
NotImplemented
,
"write of FQDN record into option buffer"
" is not supported yet"
);
return
;
}
default:
// We hit this point because invalid option data type has been specified
// This may be the case because 'empty' or 'record' data type has been
// specified. We don't throw exception here because it will be thrown
// at the exit point from this function.
;
}
isc_throw
(
isc
::
BadValue
,
"attempt to write invalid option data field type"
" into the option buffer: "
<<
type
);
}
OptionPtr
OptionDefinition
::
factoryAddrList4
(
uint16_t
type
,
OptionBufferConstIter
begin
,
...
...
src/lib/dhcp/option_definition.h
View file @
ff216738
...
...
@@ -131,83 +131,6 @@ public:
/// Const iterator for record data fields.
typedef
std
::
vector
<
OptionDataType
>::
const_iterator
RecordFieldsConstIter
;
private:
/// @brief Utility class for operations on OptionDataTypes.
///
/// This class is implemented as the singleton because the list of
/// supported data types need only be loaded only once into memory as it
/// can persist for all option definitions.
///
/// @todo This class can be extended to return the string value
/// representing the data type from the enum value.
class
DataTypeUtil
{
public:
/// @brief Return the sole instance of this class.
///
/// @return instance of this class.
static
DataTypeUtil
&
instance
()
{
static
DataTypeUtil
instance
;
return
(
instance
);
}
/// @brief Convert type given as string value to option data type.
///
/// @param data_type_name data type string.
///
/// @return option data type.
OptionDataType
getOptionDataType
(
const
std
::
string
&
data_type_name
);
/// @brief Perform lexical cast of the value and validate its range.
///
/// This function performs lexical cast of a string value to integer
/// or boolean value and checks if the resulting value is within a
/// range of a target type. Note that range checks are not performed
/// on boolean values. The target type should be one of the supported
/// integer types or bool.
///
/// @param value_str input value given as string.
/// @tparam T target type for lexical cast.
///
/// @return cast value.
/// @throw BadDataTypeCast if cast was not successful.
template
<
typename
T
>
T
lexicalCastWithRangeCheck
(
const
std
::
string
&
value_str
)
const
;
/// @brief Write the string value into the provided buffer.
///
/// This method writes the given value to the specified buffer.
/// The provided string value may represent data of different types.
/// The actual data type is specified with the second argument.
/// Based on a value of this argument, this function will first
/// try to cast the string value to the particular data type and
/// if it is successful it will store the data in the buffer
/// in a binary format.
///
/// @param value string representation of the value to be written.
/// @param type the actual data type to be stored.
/// @param [in, out] buf buffer where the value is to be stored.
///
/// @throw BadDataTypeCast if data write was unsuccessful.
void
writeToBuffer
(
const
std
::
string
&
value
,
const
OptionDataType
type
,
OptionBuffer
&
buf
);
private:
/// @brief Private constructor.
///
/// Constructor initializes the internal data structures, e.g.
/// mapping between data type name and the corresponding enum.
/// This constructor is private to ensure that exactly one
/// instance of this class can be created using \ref instance
/// function.
DataTypeUtil
();
/// Map of data types, maps name of the type to enum value.
std
::
map
<
std
::
string
,
OptionDataType
>
data_types_
;
};
public:
/// @brief Constructor.
///
/// @param name option name.
...
...
@@ -471,6 +394,40 @@ private:
return
(
type
==
type_
);
}
/// @brief Perform lexical cast of the value and validate its range.
///
/// This function performs lexical cast of a string value to integer
/// or boolean value and checks if the resulting value is within a
/// range of a target type. Note that range checks are not performed
/// on boolean values. The target type should be one of the supported
/// integer types or bool.
///
/// @param value_str input value given as string.
/// @tparam T target type for lexical cast.