Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Kea
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Service Desk
Milestones
Merge Requests
0
Merge Requests
0
Operations
Operations
Incidents
Packages & Registries
Packages & Registries
Container Registry
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Sebastian Schrader
Kea
Commits
cd0b51a6
Commit
cd0b51a6
authored
Apr 17, 2014
by
Marcin Siodelski
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[3408] Propagate line numbers and positions of elements in Element objects
parent
d1c178b9
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
221 additions
and
55 deletions
+221
-55
src/lib/cc/data.cc
src/lib/cc/data.cc
+43
-31
src/lib/cc/data.h
src/lib/cc/data.h
+94
-23
src/lib/cc/tests/data_unittests.cc
src/lib/cc/tests/data_unittests.cc
+84
-1
No files found.
src/lib/cc/data.cc
View file @
cd0b51a6
// Copyright (C) 2010 Internet Systems Consortium, Inc. ("ISC")
// Copyright (C) 2010
, 2014
Internet Systems Consortium, Inc. ("ISC")
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
...
...
@@ -209,38 +209,38 @@ bool operator!=(const Element& a, const Element& b) {
// factory functions
//
ElementPtr
Element
::
create
()
{
return
(
ElementPtr
(
new
NullElement
()));
Element
::
create
(
const
Position
&
pos
)
{
return
(
ElementPtr
(
new
NullElement
(
pos
)));
}
ElementPtr
Element
::
create
(
const
long
long
int
i
)
{
return
(
ElementPtr
(
new
IntElement
(
static_cast
<
int64_t
>
(
i
))));
Element
::
create
(
const
long
long
int
i
,
const
Position
&
pos
)
{
return
(
ElementPtr
(
new
IntElement
(
static_cast
<
int64_t
>
(
i
)
,
pos
)));
}
ElementPtr
Element
::
create
(
const
double
d
)
{
return
(
ElementPtr
(
new
DoubleElement
(
d
)));
Element
::
create
(
const
double
d
,
const
Position
&
pos
)
{
return
(
ElementPtr
(
new
DoubleElement
(
d
,
pos
)));
}
ElementPtr
Element
::
create
(
const
std
::
string
&
s
)
{
return
(
ElementPtr
(
new
StringElement
(
s
)));
Element
::
create
(
const
std
::
string
&
s
,
const
Position
&
pos
)
{
return
(
ElementPtr
(
new
StringElement
(
s
,
pos
)));
}
ElementPtr
Element
::
create
(
const
bool
b
)
{
return
(
ElementPtr
(
new
BoolElement
(
b
)));
Element
::
create
(
const
bool
b
,
const
Position
&
pos
)
{
return
(
ElementPtr
(
new
BoolElement
(
b
,
pos
)));
}
ElementPtr
Element
::
createList
()
{
return
(
ElementPtr
(
new
ListElement
()));
Element
::
createList
(
const
Position
&
pos
)
{
return
(
ElementPtr
(
new
ListElement
(
pos
)));
}
ElementPtr
Element
::
createMap
()
{
return
(
ElementPtr
(
new
MapElement
()));
Element
::
createMap
(
const
Position
&
pos
)
{
return
(
ElementPtr
(
new
MapElement
(
pos
)));
}
...
...
@@ -399,49 +399,59 @@ numberFromStringstream(std::istream& in, int& pos) {
// value is larger than an int can handle)
//
ElementPtr
fromStringstreamNumber
(
std
::
istream
&
in
,
int
&
pos
)
{
std
::
string
number
=
numberFromStringstream
(
in
,
pos
);
fromStringstreamNumber
(
std
::
istream
&
in
,
const
std
::
string
&
file
,
const
int
&
line
,
int
&
pos
)
{
const
uint32_t
start_pos
=
pos
;
const
std
::
string
number
=
numberFromStringstream
(
in
,
pos
);
if
(
number
.
find_first_of
(
".eE"
)
<
number
.
size
())
{
try
{
return
(
Element
::
create
(
boost
::
lexical_cast
<
double
>
(
number
)));
return
(
Element
::
create
(
boost
::
lexical_cast
<
double
>
(
number
),
Element
::
Position
(
line
,
start_pos
)));
}
catch
(
const
boost
::
bad_lexical_cast
&
)
{
isc_throw
(
JSONError
,
std
::
string
(
"Number overflow: "
)
+
number
);
}
}
else
{
try
{
return
(
Element
::
create
(
boost
::
lexical_cast
<
int64_t
>
(
number
)));
return
(
Element
::
create
(
boost
::
lexical_cast
<
int64_t
>
(
number
),
Element
::
Position
(
line
,
start_pos
)));
}
catch
(
const
boost
::
bad_lexical_cast
&
)
{
isc_throw
(
JSONError
,
std
::
string
(
"Number overflow: "
)
+
number
);
throwJSONError
(
std
::
string
(
"Number overflow: "
)
+
number
,
file
,
line
,
start_pos
);
}
}
return
(
ElementPtr
());
}
ElementPtr
fromStringstreamBool
(
std
::
istream
&
in
,
const
std
::
string
&
file
,
const
int
line
,
int
&
pos
)
{
const
uint32_t
start_pos
=
pos
;
const
std
::
string
word
=
wordFromStringstream
(
in
,
pos
);
if
(
boost
::
iequals
(
word
,
"True"
))
{
return
(
Element
::
create
(
true
));
return
(
Element
::
create
(
true
,
Element
::
Position
(
line
,
start_pos
)
));
}
else
if
(
boost
::
iequals
(
word
,
"False"
))
{
return
(
Element
::
create
(
false
));
return
(
Element
::
create
(
false
,
Element
::
Position
(
line
,
start_pos
)
));
}
else
{
throwJSONError
(
std
::
string
(
"Bad boolean value: "
)
+
word
,
file
,
line
,
pos
);
// above is a throw shortcurt, return empty is never reached
return
(
ElementPtr
());
throwJSONError
(
std
::
string
(
"Bad boolean value: "
)
+
word
,
file
,
line
,
start_pos
);
}
return
(
ElementPtr
());
}
ElementPtr
fromStringstreamNull
(
std
::
istream
&
in
,
const
std
::
string
&
file
,
const
int
line
,
int
&
pos
)
{
const
uint32_t
start_pos
=
pos
;
const
std
::
string
word
=
wordFromStringstream
(
in
,
pos
);
if
(
boost
::
iequals
(
word
,
"null"
))
{
return
(
Element
::
create
());
return
(
Element
::
create
(
Element
::
Position
(
line
,
start_pos
)
));
}
else
{
throwJSONError
(
std
::
string
(
"Bad null value: "
)
+
word
,
file
,
line
,
pos
);
throwJSONError
(
std
::
string
(
"Bad null value: "
)
+
word
,
file
,
line
,
start_pos
);
return
(
ElementPtr
());
}
}
...
...
@@ -450,7 +460,9 @@ ElementPtr
fromStringstreamString
(
std
::
istream
&
in
,
const
std
::
string
&
file
,
int
&
line
,
int
&
pos
)
{
return
(
Element
::
create
(
strFromStringstream
(
in
,
file
,
line
,
pos
)));
const
uint32_t
start_pos
=
pos
;
const
std
::
string
string_value
=
strFromStringstream
(
in
,
file
,
line
,
pos
);
return
(
Element
::
create
(
string_value
,
Element
::
Position
(
line
,
start_pos
)));
}
ElementPtr
...
...
@@ -458,7 +470,7 @@ fromStringstreamList(std::istream& in, const std::string& file, int& line,
int
&
pos
)
{
int
c
=
0
;
ElementPtr
list
=
Element
::
createList
();
ElementPtr
list
=
Element
::
createList
(
Element
::
Position
(
line
,
pos
)
);
ConstElementPtr
cur_list_element
;
skipChars
(
in
,
WHITESPACE
,
line
,
pos
);
...
...
@@ -479,7 +491,7 @@ ElementPtr
fromStringstreamMap
(
std
::
istream
&
in
,
const
std
::
string
&
file
,
int
&
line
,
int
&
pos
)
{
ElementPtr
map
=
Element
::
createMap
();
ElementPtr
map
=
Element
::
createMap
(
Element
::
Position
(
line
,
pos
)
);
skipChars
(
in
,
WHITESPACE
,
line
,
pos
);
int
c
=
in
.
peek
();
if
(
c
==
EOF
)
{
...
...
@@ -594,7 +606,7 @@ Element::fromJSON(std::istream& in, const std::string& file, int& line,
case
'.'
:
in
.
putback
(
c
);
--
pos
;
element
=
fromStringstreamNumber
(
in
,
pos
);
element
=
fromStringstreamNumber
(
in
,
file
,
line
,
pos
);
el_read
=
true
;
break
;
case
't'
:
...
...
src/lib/cc/data.h
View file @
cd0b51a6
// Copyright (C) 2010 Internet Systems Consortium, Inc. ("ISC")
// Copyright (C) 2010
, 2014
Internet Systems Consortium, Inc. ("ISC")
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
...
...
@@ -72,16 +72,56 @@ public:
///
class
Element
{
public:
/// \brief Represents the position of the data element within a
/// configuration string.
struct
Position
{
uint32_t
line_
;
///< Line number.
uint32_t
pos_
;
///< Position within the line.
/// \brief Constructor.
///
/// \param line Line number.
/// \param pos Position within the line.
Position
(
const
uint32_t
line
,
const
uint32_t
pos
)
:
line_
(
line
),
pos_
(
pos
)
{
}
};
/// \brief Returns @c Position object with line_ and pos_ set to 0.
///
/// The object containing two zeros is a default for most of the
/// methods creating @c Element objects.
static
const
Position
&
ZERO_POSITION
()
{
static
Position
position
(
0
,
0
);
return
(
position
);
}
private:
// technically the type could be omitted; is it useful?
// should we remove it or replace it with a pure virtual
// function getType?
int
type
;
int
type_
;
/// \brief Position of the element in the configuration string.
Position
position_
;
protected:
Element
(
int
t
)
{
type
=
t
;
}
/// \brief Constructor.
///
/// \param t Element type.
/// \param line Line number in the configuration string where this element
/// starts. It is used to communicate the broken parts of configuration
/// through logging mechanism.
/// \param line_pos Position within the line of the configuration string
/// where this element's value starts.
Element
(
int
t
,
const
Position
&
pos
=
ZERO_POSITION
())
:
type_
(
t
),
position_
(
pos
)
{
}
public:
// any is a special type used in list specifications, specifying
// that the elements can be of any type
enum
types
{
integer
,
real
,
boolean
,
null
,
string
,
list
,
map
,
any
};
...
...
@@ -89,7 +129,11 @@ public:
virtual
~
Element
()
{};
/// \return the type of this element
int
getType
()
const
{
return
(
type
);
}
int
getType
()
const
{
return
(
type_
);
}
/// \brief Returns line number where the data element's value starts in a
/// configuration string
const
Position
&
getPosition
()
const
{
return
(
position_
);
}
/// Returns a string representing the Element and all its
/// child elements; note that this is different from stringValue(),
...
...
@@ -282,22 +326,42 @@ public:
/// Notes: Read notes of IntElement definition about the use of
/// long long int, long int and int.
//@{
static
ElementPtr
create
();
static
ElementPtr
create
(
const
long
long
int
i
);
static
ElementPtr
create
(
const
int
i
)
{
return
(
create
(
static_cast
<
long
long
int
>
(
i
)));
};
static
ElementPtr
create
(
const
long
int
i
)
{
return
(
create
(
static_cast
<
long
long
int
>
(
i
)));
};
static
ElementPtr
create
(
const
double
d
);
static
ElementPtr
create
(
const
bool
b
);
static
ElementPtr
create
(
const
std
::
string
&
s
);
static
ElementPtr
create
(
const
Position
&
pos
=
ZERO_POSITION
());
static
ElementPtr
create
(
const
long
long
int
i
,
const
Position
&
pos
=
ZERO_POSITION
());
static
ElementPtr
create
(
const
int
i
,
const
Position
&
pos
=
ZERO_POSITION
())
{
return
(
create
(
static_cast
<
long
long
int
>
(
i
),
pos
));
};
static
ElementPtr
create
(
const
long
int
i
,
const
Position
&
pos
=
ZERO_POSITION
())
{
return
(
create
(
static_cast
<
long
long
int
>
(
i
),
pos
));
};
static
ElementPtr
create
(
const
double
d
,
const
Position
&
pos
=
ZERO_POSITION
());
static
ElementPtr
create
(
const
bool
b
,
const
Position
&
pos
=
ZERO_POSITION
());
static
ElementPtr
create
(
const
std
::
string
&
s
,
const
Position
&
pos
=
ZERO_POSITION
());
// need both std:string and char *, since c++ will match
// bool before std::string when you pass it a char *
static
ElementPtr
create
(
const
char
*
s
)
{
return
(
create
(
std
::
string
(
s
)));
}
static
ElementPtr
create
(
const
char
*
s
,
const
Position
&
pos
=
ZERO_POSITION
())
{
return
(
create
(
std
::
string
(
s
),
pos
));
}
/// \brief Creates an empty ListElement type ElementPtr.
static
ElementPtr
createList
();
///
/// \param line_num Line number in the configuration string where the
/// data element is located.
static
ElementPtr
createList
(
const
Position
&
pos
=
ZERO_POSITION
());
/// \brief Creates an empty MapElement type ElementPtr.
static
ElementPtr
createMap
();
///
/// \param line_num Line number in the configuration string where the
/// data element is located.
static
ElementPtr
createMap
(
const
Position
&
pos
=
ZERO_POSITION
());
//@}
...
...
@@ -386,7 +450,7 @@ public:
/// (C++ tries to convert integer type values and reference/pointer
/// if value types do not match exactly)
/// We decided the storage as int64_t,
/// three (long long, long, int) override function defintions
/// three (long long, long, int) override function defintions
/// and cast int/long/long long to int64_t via long long.
/// Therefore, call by value methods (create, setValue) have three
/// (int,long,long long) definitions. Others use int64_t.
...
...
@@ -396,7 +460,8 @@ class IntElement : public Element {
private:
public:
IntElement
(
int64_t
v
)
:
Element
(
integer
),
i
(
v
)
{
}
IntElement
(
int64_t
v
,
const
Position
&
pos
=
ZERO_POSITION
())
:
Element
(
integer
,
pos
),
i
(
v
)
{
}
int64_t
intValue
()
const
{
return
(
i
);
}
using
Element
::
getValue
;
bool
getValue
(
int64_t
&
t
)
const
{
t
=
i
;
return
(
true
);
}
...
...
@@ -410,7 +475,8 @@ class DoubleElement : public Element {
double
d
;
public:
DoubleElement
(
double
v
)
:
Element
(
real
),
d
(
v
)
{};
DoubleElement
(
double
v
,
const
Position
&
pos
=
ZERO_POSITION
())
:
Element
(
real
,
pos
),
d
(
v
)
{};
double
doubleValue
()
const
{
return
(
d
);
}
using
Element
::
getValue
;
bool
getValue
(
double
&
t
)
const
{
t
=
d
;
return
(
true
);
}
...
...
@@ -424,7 +490,8 @@ class BoolElement : public Element {
bool
b
;
public:
BoolElement
(
const
bool
v
)
:
Element
(
boolean
),
b
(
v
)
{};
BoolElement
(
const
bool
v
,
const
Position
&
pos
=
ZERO_POSITION
())
:
Element
(
boolean
,
pos
),
b
(
v
)
{};
bool
boolValue
()
const
{
return
(
b
);
}
using
Element
::
getValue
;
bool
getValue
(
bool
&
t
)
const
{
t
=
b
;
return
(
true
);
}
...
...
@@ -436,7 +503,8 @@ public:
class
NullElement
:
public
Element
{
public:
NullElement
()
:
Element
(
null
)
{};
NullElement
(
const
Position
&
pos
=
ZERO_POSITION
())
:
Element
(
null
,
pos
)
{};
void
toJSON
(
std
::
ostream
&
ss
)
const
;
bool
equals
(
const
Element
&
other
)
const
;
};
...
...
@@ -445,7 +513,8 @@ class StringElement : public Element {
std
::
string
s
;
public:
StringElement
(
std
::
string
v
)
:
Element
(
string
),
s
(
v
)
{};
StringElement
(
std
::
string
v
,
const
Position
&
pos
=
ZERO_POSITION
())
:
Element
(
string
,
pos
),
s
(
v
)
{};
std
::
string
stringValue
()
const
{
return
(
s
);
}
using
Element
::
getValue
;
bool
getValue
(
std
::
string
&
t
)
const
{
t
=
s
;
return
(
true
);
}
...
...
@@ -459,7 +528,8 @@ class ListElement : public Element {
std
::
vector
<
ConstElementPtr
>
l
;
public:
ListElement
()
:
Element
(
list
)
{}
ListElement
(
const
Position
&
pos
=
ZERO_POSITION
())
:
Element
(
list
,
pos
)
{}
const
std
::
vector
<
ConstElementPtr
>&
listValue
()
const
{
return
(
l
);
}
using
Element
::
getValue
;
bool
getValue
(
std
::
vector
<
ConstElementPtr
>&
t
)
const
{
...
...
@@ -490,8 +560,9 @@ class MapElement : public Element {
std
::
map
<
std
::
string
,
ConstElementPtr
>
m
;
public:
MapElement
()
:
Element
(
map
)
{}
// TODO: should we have direct iterators instead of exposing the std::map here?
MapElement
(
const
Position
&
pos
=
ZERO_POSITION
())
:
Element
(
map
,
pos
)
{}
// @todo should we have direct iterators instead of exposing the std::map
// here?
const
std
::
map
<
std
::
string
,
ConstElementPtr
>&
mapValue
()
const
{
return
(
m
);
}
...
...
src/lib/cc/tests/data_unittests.cc
View file @
cd0b51a6
// Copyright (C) 2009
Internet Systems Consortium, Inc. ("ISC")
// Copyright (C) 2009
, 2014
Internet Systems Consortium, Inc. ("ISC")
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
...
...
@@ -929,4 +929,87 @@ TEST(Element, merge) {
EXPECT_EQ
(
*
b
,
*
c
);
}
TEST
(
Element
,
getPosition
)
{
// Create a JSON string holding different type of values. Some of the
// values in the config string are not aligned, so as we can check that
// the position is set correctly for the elements.
ElementPtr
top
=
Element
::
fromJSON
(
"{
\n
"
"
\"
a
\"
: 2,
\n
"
"
\"
b
\"
:true,
\n
"
"
\"
cy
\"
:
\"
a string
\"
,
\n
"
"
\"
dyz
\"
: {
\n
"
"
\n
"
"
\"
e
\"
: 3,
\n
"
"
\"
f
\"
: null
\n
"
"
\n
"
" },
\n
"
"
\"
g
\"
: [ 5, 6,
\n
"
" 7 ]
\n
"
"}
\n
"
);
ASSERT_TRUE
(
top
);
// Element "a"
ConstElementPtr
level1_el
=
top
->
get
(
"a"
);
ASSERT_TRUE
(
level1_el
);
EXPECT_EQ
(
2
,
level1_el
->
getPosition
().
line_
);
EXPECT_EQ
(
11
,
level1_el
->
getPosition
().
pos_
);
// Element "b"
level1_el
=
top
->
get
(
"b"
);
ASSERT_TRUE
(
level1_el
);
EXPECT_EQ
(
3
,
level1_el
->
getPosition
().
line_
);
EXPECT_EQ
(
9
,
level1_el
->
getPosition
().
pos_
);
// Element "cy"
level1_el
=
top
->
get
(
"cy"
);
ASSERT_TRUE
(
level1_el
);
EXPECT_EQ
(
4
,
level1_el
->
getPosition
().
line_
);
EXPECT_EQ
(
11
,
level1_el
->
getPosition
().
pos_
);
// Element "dyz"
level1_el
=
top
->
get
(
"dyz"
);
ASSERT_TRUE
(
level1_el
);
EXPECT_EQ
(
5
,
level1_el
->
getPosition
().
line_
);
EXPECT_EQ
(
13
,
level1_el
->
getPosition
().
pos_
);
// Element "e" is a sub element of "dyz".
ConstElementPtr
level2_el
=
level1_el
->
get
(
"e"
);
ASSERT_TRUE
(
level2_el
);
EXPECT_EQ
(
7
,
level2_el
->
getPosition
().
line_
);
EXPECT_EQ
(
12
,
level2_el
->
getPosition
().
pos_
);
// Element "f" is also a sub element of "dyz"
level2_el
=
level1_el
->
get
(
"f"
);
ASSERT_TRUE
(
level2_el
);
EXPECT_EQ
(
8
,
level2_el
->
getPosition
().
line_
);
EXPECT_EQ
(
14
,
level2_el
->
getPosition
().
pos_
);
// Element "g" is a list.
level1_el
=
top
->
get
(
"g"
);
ASSERT_TRUE
(
level1_el
);
EXPECT_EQ
(
11
,
level1_el
->
getPosition
().
line_
);
// Position indicates where the values start (excluding the "[" character)"
EXPECT_EQ
(
11
,
level1_el
->
getPosition
().
pos_
);
// First element from the list.
level2_el
=
level1_el
->
get
(
0
);
ASSERT_TRUE
(
level2_el
);
EXPECT_EQ
(
11
,
level2_el
->
getPosition
().
line_
);
EXPECT_EQ
(
12
,
level2_el
->
getPosition
().
pos_
);
// Second element from the list.
level2_el
=
level1_el
->
get
(
1
);
ASSERT_TRUE
(
level2_el
);
EXPECT_EQ
(
11
,
level2_el
->
getPosition
().
line_
);
EXPECT_EQ
(
15
,
level2_el
->
getPosition
().
pos_
);
// Third element from the list.
level2_el
=
level1_el
->
get
(
2
);
ASSERT_TRUE
(
level2_el
);
EXPECT_EQ
(
12
,
level2_el
->
getPosition
().
line_
);
EXPECT_EQ
(
14
,
level2_el
->
getPosition
().
pos_
);
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment