Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
What's new
7
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Open sidebar
Pavel Zhukov
Kea
Commits
66a390fe
Commit
66a390fe
authored
Oct 02, 2018
by
Tomek Mrugalski
🛰
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[#10,!3] Docgen sources are now documented.
parent
84a5a8af
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
175 additions
and
108 deletions
+175
-108
doc/docgen/kea_docgen.cc
doc/docgen/kea_docgen.cc
+175
-108
No files found.
doc/docgen/kea_docgen.cc
View file @
66a390fe
// Copyright (C) 2018 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
#include <iostream>
#include <fstream>
#include <sstream>
...
...
@@ -13,14 +19,19 @@ using namespace isc;
using
namespace
isc
::
data
;
/// @brief API documentation generator
class
DocGen
{
public:
/// Output location of a file.
const
string
OUTPUT
=
"guide/api.xml"
;
/// Controls whether to print out extra information.
bool
verbose
=
false
;
/// @brief Load JSON files that each contain description of an API command
///
/// @param files a vector with names of files.
void
loadFiles
(
const
vector
<
string
>&
files
)
{
map
<
string
,
ElementPtr
>
commands
;
...
...
@@ -61,42 +72,57 @@ public:
<<
" file(s)"
<<
endl
;
}
/// @brief checks if mandatory string parameter is specified
///
/// @param x a map that is being checked
/// @param name name of the string element expected to be there
/// @param fname name of the file (used in error reporting)
/// @throw Unexpected if missing, different type or empty
void
requireString
(
const
ElementPtr
&
x
,
const
string
&
name
,
const
string
&
fname
)
{
if
(
!
x
->
contains
(
name
))
{
isc_throw
(
Unexpected
,
"Mandatory '"
+
name
+
" field missing while "
"processing file "
+
fname
);
}
if
(
x
->
get
(
name
)
->
getType
()
!=
Element
::
string
)
{
isc_throw
(
BadValue
,
"'"
+
name
+
" field is present, but is not a string"
isc_throw
(
Unexpected
,
"'"
+
name
+
" field is present, but is not a string"
" in file "
+
fname
);
}
if
(
x
->
get
(
name
)
->
stringValue
().
empty
())
{
isc_throw
(
BadValue
,
"'"
+
name
+
" field is present, is a string, but is "
isc_throw
(
Unexpected
,
"'"
+
name
+
" field is present, is a string, but is "
"empty in file "
+
fname
);
}
}
/// @brief checks if mandatory list parameter is specified
///
/// @param x a map that is being checked
/// @param name name of the list element expected to be there
/// @param fname name of the file (used in error reporting)
/// @throw Unexpected if missing, different type or empty
void
requireList
(
const
ElementPtr
&
x
,
const
string
&
name
,
const
string
&
fname
)
{
if
(
!
x
->
contains
(
name
))
{
isc_throw
(
Unexpected
,
"Mandatory '"
+
name
+
" field missing while "
"processing file "
+
fname
);
}
if
(
x
->
get
(
name
)
->
getType
()
!=
Element
::
list
)
{
isc_throw
(
BadValue
,
"'"
+
name
+
" field is present, but is not a list "
isc_throw
(
Unexpected
,
"'"
+
name
+
" field is present, but is not a list "
"in file "
+
fname
);
}
ConstElementPtr
l
=
x
->
get
(
name
);
if
(
l
->
size
()
==
0
)
{
isc_throw
(
BadValue
,
"'"
+
name
+
" field is a list, but is empty in file "
isc_throw
(
Unexpected
,
"'"
+
name
+
" field is a list, but is empty in file "
+
fname
);
}
// todo: check that every element is a string
}
/// @brief Checks that the essential parameters for each command are defined
///
/// @param fname name of the file the data was read from (printed if error is detected)
/// @param x a JSON map that contains content of the file
void
sanityCheck
(
const
string
&
fname
,
const
ElementPtr
&
x
)
{
requireString
(
x
,
"name"
,
fname
);
requireString
(
x
,
"brief"
,
fname
);
...
...
@@ -111,6 +137,9 @@ public:
//requireString(x, "resp-comment", fname);
}
/// @brief Writes ISC copyright note to the stream
///
/// @param f stream to write copyrights to
void
generateCopyright
(
stringstream
&
f
)
{
f
<<
"<!--"
<<
endl
;
f
<<
" - Copyright (C) 2018 Internet Systems Consortium, Inc. (
\"
ISC
\"
)"
<<
endl
;
...
...
@@ -123,10 +152,23 @@ public:
f
<<
"<!-- autogenerated using cmd_docgen. Do not edit by hand! -->"
<<
endl
;
}
/// @brief generates a link to command
///
/// @param f stream to write the generated link to
/// @param cmd name of the command
void
generateCmdLink
(
stringstream
&
f
,
const
string
&
cmd
)
{
f
<<
"<command><link linkend=
\"
ref-"
<<
cmd
<<
"
\"
>"
<<
cmd
<<
"</link></command>"
<<
endl
;
f
<<
"<command><link linkend=
\"
ref-"
<<
cmd
<<
"
\"
>"
<<
cmd
<<
"</link></command>"
<<
endl
;
}
/// @brief generates lists of all commands.
///
/// Currently there are several lists (or rather lists of lists). They all enumerate
/// commands, but each list serving a different purpose:
/// - list of commands supported by a daemon
/// - list of commands provided by a hook
///
/// @param f stream to write the generated lists to
void
generateLists
(
stringstream
&
f
)
{
// Generate a list of all commands
f
<<
" <para>Kea currently supports "
<<
cmds_
.
size
()
<<
" commands:"
<<
endl
;
...
...
@@ -163,8 +205,8 @@ public:
}
}
cout
<<
"### "
<<
all_daemons
.
size
()
<<
" daemon(s) detected."
<<
endl
;
cout
<<
"### "
<<
all_hooks
.
size
()
<<
" hook lib(s) detected."
<<
endl
;
cout
<<
all_daemons
.
size
()
<<
" daemon(s) detected."
<<
endl
;
cout
<<
all_hooks
.
size
()
<<
" hook lib(s) detected."
<<
endl
;
for
(
auto
daemon
:
all_daemons
)
{
f
<<
"<para xml:id=
\"
commands-"
<<
daemon
<<
"
\"
>"
...
...
@@ -214,6 +256,7 @@ public:
}
/// @brief generates the whole API documentation
void
generateOutput
()
{
stringstream
f
;
...
...
@@ -244,6 +287,9 @@ public:
cout
<<
"Output written to "
<<
OUTPUT
<<
endl
;
}
/// @brief generate sections for all commands
///
/// @param f stream to write the commands to
void
generateCommands
(
stringstream
&
f
){
for
(
auto
cmd
:
cmds_
)
{
...
...
@@ -257,118 +303,139 @@ public:
}
}
void
replaceAll
(
std
::
string
&
str
,
const
std
::
string
&
from
,
const
std
::
string
&
to
)
{
if
(
from
.
empty
())
return
;
size_t
start_pos
=
0
;
while
((
start_pos
=
str
.
find
(
from
,
start_pos
))
!=
std
::
string
::
npos
)
{
str
.
replace
(
start_pos
,
from
.
length
(),
to
);
start_pos
+=
to
.
length
();
/// @brief replace all strings
///
/// @param str [in,out] this string will have some replacements
/// @param from what to replace
/// @param to what to replace with
void
replaceAll
(
std
::
string
&
str
,
const
std
::
string
&
from
,
const
std
::
string
&
to
)
{
if
(
from
.
empty
())
return
;
size_t
start_pos
=
0
;
while
((
start_pos
=
str
.
find
(
from
,
start_pos
))
!=
std
::
string
::
npos
)
{
str
.
replace
(
start_pos
,
from
.
length
(),
to
);
start_pos
+=
to
.
length
();
}
}
}
string
escapeString
(
string
txt
)
{
replaceAll
(
txt
,
"<"
,
"<"
);
replaceAll
(
txt
,
">"
,
">"
);
return
(
txt
);
}
string
standardResponseSyntax
()
{
stringstream
t
;
/// @brief escapes string to be safe for XML (docbook)
///
/// @param txt string to be escaped
/// @return escaped string
string
escapeString
(
string
txt
)
{
t
<<
"{"
<<
endl
<<
"
\"
result
\"
: <integer>,"
<<
endl
<<
"
\"
text
\"
: <string>"
<<
endl
<<
"}"
<<
endl
;
return
(
t
.
str
());
}
replaceAll
(
txt
,
"<"
,
"<"
);
replaceAll
(
txt
,
">"
,
">"
);
return
(
txt
);
}
string
standardResponseComment
()
{
stringstream
t
;
t
<<
"Result is an integer representation of the status. Currently supported"
<<
" statuses are:"
<<
endl
<<
"<itemizedlist>"
<<
endl
<<
" <listitem><para>0 - success</para></listitem>"
<<
endl
<<
" <listitem><para>1 - error</para></listitem>"
<<
endl
<<
" <listitem><para>2 - unsupported</para></listitem>"
<<
endl
<<
" <listitem><para>3 - empty (command was completed successfully, but "
<<
"no data was affected or returned)</para>"
<<
"</listitem>"
<<
endl
<<
"</itemizedlist>"
<<
endl
;
return
(
t
.
str
());
}
/// @brief generates standard description of command's response
///
/// If a command doesn't have response syntax specified, we will
/// assume it follows the usual syntax and provide the default description.
string
standardResponseSyntax
()
{
stringstream
t
;
t
<<
"{"
<<
endl
<<
"
\"
result
\"
: <integer>,"
<<
endl
<<
"
\"
text
\"
: <string>"
<<
endl
<<
"}"
<<
endl
;
return
(
t
.
str
());
}
void
generateCommand
(
stringstream
&
f
,
const
ElementPtr
&
cmd
)
{
/// @brief generates standard description of command's comment
///
/// If a command doesn't have response syntax comment specified, we will
/// assume it follows the usual syntax and provide the default description.
string
standardResponseComment
()
{
stringstream
t
;
t
<<
"Result is an integer representation of the status. Currently supported"
<<
" statuses are:"
<<
endl
<<
"<itemizedlist>"
<<
endl
<<
" <listitem><para>0 - success</para></listitem>"
<<
endl
<<
" <listitem><para>1 - error</para></listitem>"
<<
endl
<<
" <listitem><para>2 - unsupported</para></listitem>"
<<
endl
<<
" <listitem><para>3 - empty (command was completed successfully, but "
<<
"no data was affected or returned)</para>"
<<
"</listitem>"
<<
endl
<<
"</itemizedlist>"
<<
endl
;
return
(
t
.
str
());
}
// command overview
f
<<
"<para xml:id=
\"
ref-"
<<
cmd
->
get
(
"name"
)
->
stringValue
()
<<
"
\"
><command>"
<<
cmd
->
get
(
"name"
)
->
stringValue
()
<<
"</command> - "
<<
cmd
->
get
(
"brief"
)
->
stringValue
()
<<
"</para>"
<<
endl
<<
endl
;
/// @brief generates command description
///
/// @param f stream to write the description to
/// @param cmd pointer to JSON structure that describes the command
void
generateCommand
(
stringstream
&
f
,
const
ElementPtr
&
cmd
)
{
// command overview
f
<<
"<para xml:id=
\"
ref-"
<<
cmd
->
get
(
"name"
)
->
stringValue
()
<<
"
\"
><command>"
<<
cmd
->
get
(
"name"
)
->
stringValue
()
<<
"</command> - "
<<
cmd
->
get
(
"brief"
)
->
stringValue
()
<<
"</para>"
<<
endl
<<
endl
;
// command can be issued to the following daemons
f
<<
"<para>Supported by: "
;
ConstElementPtr
daemons
=
cmd
->
get
(
"support"
);
for
(
int
i
=
0
;
i
<
daemons
->
size
();
i
++
)
{
if
(
i
)
{
f
<<
", "
;
}
// command can be issued to the following daemons
f
<<
"<para>Supported by: "
;
ConstElementPtr
daemons
=
cmd
->
get
(
"support"
);
for
(
int
i
=
0
;
i
<
daemons
->
size
();
i
++
)
{
if
(
i
)
{
f
<<
", "
;
f
<<
"<command><link linkend=
\"
commands-"
<<
daemons
->
get
(
i
)
->
stringValue
()
<<
"
\"
>"
<<
daemons
->
get
(
i
)
->
stringValue
()
<<
"</link></command>"
;
}
f
<<
"</para>"
<<
endl
<<
endl
;
// availability
f
<<
"<para>Availability: "
<<
cmd
->
get
(
"avail"
)
->
stringValue
();
auto
hook
=
cmd
->
get
(
"hook"
);
if
(
hook
)
{
f
<<
" (<link linkend=
\"
commands-"
<<
hook
->
stringValue
()
<<
"-lib
\"
>"
<<
hook
->
stringValue
()
<<
"</link>)"
;
}
else
{
f
<<
" (built-in)"
;
}
f
<<
"<command><link linkend=
\"
commands-"
<<
daemons
->
get
(
i
)
->
stringValue
()
<<
"
\"
>"
<<
daemons
->
get
(
i
)
->
stringValue
()
<<
"</link></command>"
;
}
f
<<
"</para>"
<<
endl
<<
endl
;
// availability
f
<<
"<para>Availability: "
<<
cmd
->
get
(
"avail"
)
->
stringValue
();
auto
hook
=
cmd
->
get
(
"hook"
);
if
(
hook
)
{
f
<<
" (<link linkend=
\"
commands-"
<<
hook
->
stringValue
()
<<
"-lib
\"
>"
<<
hook
->
stringValue
()
<<
"</link>)"
;
}
else
{
f
<<
" (built-in)"
;
}
f
<<
"</para>"
<<
endl
<<
endl
;
// description and examples
f
<<
"<para>Description and examples: See <xref linkend=
\"
command-"
<<
cmd
->
get
(
"name"
)
->
stringValue
()
<<
"
\"
/></para>"
<<
endl
<<
endl
;
// Command syntax:
f
<<
"<para>Command syntax:"
<<
endl
;
if
(
cmd
->
contains
(
"cmd-syntax"
))
{
f
<<
" <screen>"
<<
escapeString
(
cmd
->
get
(
"cmd-syntax"
)
->
stringValue
())
<<
"</screen>"
<<
endl
;
}
else
{
f
<<
" <screen>{"
<<
endl
<<
"
\"
command
\"
:
\"
"
<<
cmd
->
get
(
"name"
)
->
stringValue
()
<<
"
\"
"
<<
endl
<<
"}</screen>"
<<
endl
;
}
if
(
cmd
->
contains
(
"cmd-comment"
))
{
f
<<
cmd
->
get
(
"cmd-comment"
)
->
stringValue
();
}
f
<<
"</para>"
<<
endl
<<
endl
;
f
<<
"</para>"
<<
endl
<<
endl
;
// description and examples
f
<<
"<para>Description and examples: See <xref linkend=
\"
command-"
<<
cmd
->
get
(
"name"
)
->
stringValue
()
<<
"
\"
/></para>"
<<
endl
<<
endl
;
// Command syntax:
f
<<
"<para>Command syntax:"
<<
endl
;
if
(
cmd
->
contains
(
"cmd-syntax"
))
{
f
<<
" <screen>"
<<
escapeString
(
cmd
->
get
(
"cmd-syntax"
)
->
stringValue
())
<<
"</screen>"
<<
endl
;
}
else
{
f
<<
" <screen>{"
<<
endl
<<
"
\"
command
\"
:
\"
"
<<
cmd
->
get
(
"name"
)
->
stringValue
()
<<
"
\"
"
<<
endl
<<
"}</screen>"
<<
endl
;
}
if
(
cmd
->
contains
(
"cmd-comment"
))
{
f
<<
cmd
->
get
(
"cmd-comment"
)
->
stringValue
();
}
f
<<
"</para>"
<<
endl
<<
endl
;
// Response syntax
f
<<
"<para>Response syntax:"
<<
endl
<<
" <screen>"
;
// Response syntax
f
<<
"<para>Response syntax:"
<<
endl
<<
" <screen>"
;
if
(
cmd
->
contains
(
"resp-syntax"
))
{
f
<<
escapeString
(
cmd
->
get
(
"resp-syntax"
)
->
stringValue
());
}
else
{
f
<<
escapeString
(
standardResponseSyntax
());
}
f
<<
"</screen>"
<<
endl
;
if
(
cmd
->
contains
(
"resp-syntax"
))
{
f
<<
escapeString
(
cmd
->
get
(
"resp-syntax"
)
->
stringValue
());
}
else
{
f
<<
escapeString
(
standardResponseSyntax
());
}
f
<<
"</screen>"
<<
endl
;
if
(
cmd
->
contains
(
"resp-comment"
))
{
f
<<
cmd
->
get
(
"resp-comment"
)
->
stringValue
();
}
else
{
f
<<
standardResponseComment
();
if
(
cmd
->
contains
(
"resp-comment"
))
{
f
<<
cmd
->
get
(
"resp-comment"
)
->
stringValue
();
}
else
{
f
<<
standardResponseComment
();
}
f
<<
"</para>"
<<
endl
<<
endl
;
}
f
<<
"</para>"
<<
endl
<<
endl
;
}
map
<
string
,
ElementPtr
>
cmds_
;
};
...
...
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