Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
A
Actor Framework
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Metrics
Environments
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
cpp-libs
Actor Framework
Commits
d12398ad
Commit
d12398ad
authored
Sep 07, 2022
by
Dominik Charousset
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Allow parsing JSON directly from file
parent
e8db2cb1
Changes
7
Show whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
218 additions
and
97 deletions
+218
-97
libcaf_core/caf/detail/json.hpp
libcaf_core/caf/detail/json.hpp
+13
-1
libcaf_core/caf/json_reader.hpp
libcaf_core/caf/json_reader.hpp
+11
-0
libcaf_core/caf/json_value.hpp
libcaf_core/caf/json_value.hpp
+7
-0
libcaf_core/caf/parser_state.hpp
libcaf_core/caf/parser_state.hpp
+0
-3
libcaf_core/src/detail/json.cpp
libcaf_core/src/detail/json.cpp
+127
-73
libcaf_core/src/json_reader.cpp
libcaf_core/src/json_reader.cpp
+31
-7
libcaf_core/src/json_value.cpp
libcaf_core/src/json_value.cpp
+29
-13
No files found.
libcaf_core/caf/detail/json.hpp
View file @
d12398ad
...
...
@@ -682,7 +682,19 @@ const array* empty_array() noexcept;
// -- parsing ------------------------------------------------------------------
// Parses the input and makes a deep copy of all strings.
// Specialization for parsers operating on mutable character sequences.
using
mutable_string_parser_state
=
parser_state
<
char
*>
;
// Specialization for parsers operating on files.
using
file_parser_state
=
parser_state
<
std
::
istreambuf_iterator
<
char
>>
;
// Parses the input string and makes a deep copy of all strings.
value
*
parse
(
string_parser_state
&
ps
,
monotonic_buffer_resource
*
storage
);
// Parses the input string and makes a deep copy of all strings.
value
*
parse
(
file_parser_state
&
ps
,
monotonic_buffer_resource
*
storage
);
// Parses the input file and makes a deep copy of all strings.
value
*
parse
(
string_parser_state
&
ps
,
monotonic_buffer_resource
*
storage
);
// Parses the input and makes a shallow copy of strings whenever possible.
...
...
libcaf_core/caf/json_reader.hpp
View file @
d12398ad
...
...
@@ -133,6 +133,17 @@ public:
/// @note Implicitly calls `reset`.
bool
load
(
std
::
string_view
json_text
);
/// Parses the content of the file under the given @p path. After loading the
/// content of the JSON file, the reader is ready for attempting to
/// deserialize inspectable objects.
/// @note Implicitly calls `reset`.
bool
load_file
(
const
char
*
path
);
/// @copydoc load_file
bool
load_file
(
const
std
::
string
&
path
)
{
return
load_file
(
path
.
c_str
());
}
/// Reverts the state of the reader back to where it was after calling `load`.
/// @post The reader is ready for attempting to deserialize another
/// inspectable object.
...
...
libcaf_core/caf/json_value.hpp
View file @
d12398ad
...
...
@@ -134,6 +134,13 @@ public:
/// objects created from that value.
static
expected
<
json_value
>
parse_in_situ
(
std
::
string
&
str
);
/// Attempts to parse the content of the file at @p path as JSON input into a
/// self-contained value.
static
expected
<
json_value
>
parse_file
(
const
char
*
path
);
/// @copydoc parse_file
static
expected
<
json_value
>
parse_file
(
const
std
::
string
&
path
);
// -- printing ---------------------------------------------------------------
template
<
class
Buffer
>
...
...
libcaf_core/caf/parser_state.hpp
View file @
d12398ad
...
...
@@ -141,7 +141,4 @@ auto make_error(const parser_state<Iterator, Sentinel>& ps, Ts&&... xs)
/// Specialization for parsers operating on string views.
using
string_parser_state
=
parser_state
<
std
::
string_view
::
iterator
>
;
/// Specialization for parsers operating on mutable character sequences.
using
mutable_string_parser_state
=
parser_state
<
char
*>
;
}
// namespace caf
libcaf_core/src/detail/json.cpp
View file @
d12398ad
...
...
@@ -8,6 +8,7 @@
#include <iterator>
#include <memory>
#include <numeric>
#include <streambuf>
#include "caf/config.hpp"
#include "caf/detail/parser/chars.hpp"
...
...
@@ -78,64 +79,63 @@ size_t do_unescape(const char* i, const char* e, char* out) {
return
new_size
;
}
std
::
string_view
as_str_view
(
const
char
*
first
,
const
char
*
last
)
{
return
{
first
,
static_cast
<
size_t
>
(
last
-
first
)};
}
struct
regular_unescaper
{
std
::
string_view
unescape
(
caf
::
detail
::
monotonic_buffer_resource
*
storage
,
std
::
string_view
str
,
bool
is_escaped
)
const
{
std
::
string_view
operator
()(
caf
::
detail
::
monotonic_buffer_resource
*
storage
,
const
char
*
first
,
const
char
*
last
,
bool
is_escaped
)
const
{
auto
len
=
static_cast
<
size_t
>
(
last
-
first
);
caf
::
detail
::
monotonic_buffer_resource
::
allocator
<
char
>
alloc
{
storage
};
auto
*
str_buf
=
alloc
.
allocate
(
str
.
size
()
);
auto
*
str_buf
=
alloc
.
allocate
(
len
);
if
(
!
is_escaped
)
{
strncpy
(
str_buf
,
str
.
data
(),
str
.
size
()
);
return
std
::
string_view
{
str_buf
,
str
.
size
()
};
strncpy
(
str_buf
,
first
,
len
);
return
std
::
string_view
{
str_buf
,
len
};
}
auto
unescaped_size
=
do_unescape
(
str
.
data
(),
str
.
data
()
+
str
.
size
(),
str_buf
);
auto
unescaped_size
=
do_unescape
(
first
,
last
,
str_buf
);
return
std
::
string_view
{
str_buf
,
unescaped_size
};
}
template
<
class
Consumer
>
void
assign
(
Consumer
&
f
,
const
char
*
str
,
size_t
len
,
bool
is_escaped
)
const
{
auto
val
=
std
::
string_view
{
str
,
len
};
f
.
value
(
unescape
(
f
.
storage
,
val
,
is_escaped
));
}
};
struct
shallow_unescaper
{
std
::
string_view
unescape
(
caf
::
detail
::
monotonic_buffer_resource
*
storage
,
std
::
string_view
str
,
bool
is_escaped
)
const
{
if
(
!
is_escaped
)
{
return
str
;
}
std
::
string_view
operator
()
(
caf
::
detail
::
monotonic_buffer_resource
*
storage
,
const
char
*
first
,
const
char
*
last
,
bool
is_escaped
)
const
{
if
(
!
is_escaped
)
return
as_str_view
(
first
,
last
);
caf
::
detail
::
monotonic_buffer_resource
::
allocator
<
char
>
alloc
{
storage
};
auto
*
str_buf
=
alloc
.
allocate
(
str
.
size
());
auto
unescaped_size
=
do_unescape
(
str
.
data
(),
str
.
data
()
+
str
.
size
(),
str_buf
);
auto
*
str_buf
=
alloc
.
allocate
(
static_cast
<
size_t
>
(
last
-
first
));
auto
unescaped_size
=
do_unescape
(
first
,
last
,
str_buf
);
return
std
::
string_view
{
str_buf
,
unescaped_size
};
}
template
<
class
Consumer
>
void
assign
(
Consumer
&
f
,
const
char
*
str
,
size_t
len
,
bool
is_escaped
)
const
{
auto
val
=
std
::
string_view
{
str
,
len
};
f
.
value
(
unescape
(
f
.
storage
,
val
,
is_escaped
));
}
};
struct
in_situ_unescaper
{
std
::
string_view
unescape
(
caf
::
span
<
char
>
str
,
bool
is_escaped
)
const
{
if
(
!
is_escaped
)
{
return
std
::
string_view
{
str
.
data
(),
str
.
size
()};
}
auto
unescaped_size
=
do_unescape
(
str
.
data
(),
str
.
data
()
+
str
.
size
(),
str
.
data
());
return
std
::
string_view
{
str
.
data
(),
unescaped_size
};
}
template
<
class
Consumer
>
void
assign
(
Consumer
&
f
,
char
*
str
,
size_t
len
,
bool
is_escaped
)
const
{
auto
val
=
caf
::
span
<
char
>
{
str
,
len
};
f
.
value
(
unescape
(
val
,
is_escaped
));
std
::
string_view
operator
()(
caf
::
detail
::
monotonic_buffer_resource
*
,
char
*
first
,
char
*
last
,
bool
is_escaped
)
const
{
if
(
!
is_escaped
)
return
as_str_view
(
first
,
last
);
auto
unescaped_size
=
do_unescape
(
first
,
last
,
first
);
return
std
::
string_view
{
first
,
unescaped_size
};
}
};
template
<
class
Escaper
,
class
Consumer
,
class
Iterator
>
void
assign_value
(
Escaper
escaper
,
Consumer
&
consumer
,
Iterator
first
,
Iterator
last
,
bool
is_escaped
)
{
auto
iter2ptr
=
[](
Iterator
iter
)
{
if
constexpr
(
std
::
is_pointer_v
<
Iterator
>
)
return
iter
;
else
return
std
::
addressof
(
*
iter
);
};
auto
str
=
escaper
(
consumer
.
storage
,
iter2ptr
(
first
),
iter2ptr
(
last
),
is_escaped
);
consumer
.
value
(
str
);
}
}
// namespace
namespace
caf
::
detail
::
parser
{
...
...
@@ -211,9 +211,6 @@ obj_consumer val_consumer::begin_object() {
return
{
&
obj
};
}
void
read_value
(
string_parser_state
&
ps
,
size_t
nesting_level
,
val_consumer
consumer
);
template
<
class
ParserState
,
class
Consumer
>
void
read_json_null_or_nan
(
ParserState
&
ps
,
Consumer
consumer
)
{
enum
{
nil
,
is_null
,
is_nan
};
...
...
@@ -253,9 +250,16 @@ void read_json_null_or_nan(ParserState& ps, Consumer consumer) {
// clang-format on
}
// If we have an iterator into a contiguous memory block, we simply store the
// iterator position and use the escaper to decide whether we make regular,
// shallow or in-situ copies. Otherwise, we use the scratch-space and decode the
// string while parsing.
template
<
class
ParserState
,
class
Unescaper
,
class
Consumer
>
void
read_json_string
(
ParserState
&
ps
,
Unescaper
escaper
,
Consumer
consumer
)
{
typename
ParserState
::
iterator_type
first
;
void
read_json_string
(
ParserState
&
ps
,
unit_t
,
Unescaper
escaper
,
Consumer
consumer
)
{
using
iterator_t
=
typename
ParserState
::
iterator_type
;
iterator_t
first
;
// clang-format off
start
();
state
(
init
)
{
...
...
@@ -264,21 +268,17 @@ void read_json_string(ParserState& ps, Unescaper escaper, Consumer consumer) {
}
state
(
read_chars
)
{
transition
(
escape
,
'\\'
)
transition
(
done
,
'"'
,
escaper
.
assign
(
consumer
,
std
::
addressof
(
*
first
),
static_cast
<
size_t
>
(
ps
.
i
-
first
),
false
))
transition
(
done
,
'"'
,
assign_value
(
escaper
,
consumer
,
first
,
ps
.
i
,
false
))
transition
(
read_chars
,
any_char
)
}
state
(
read_chars_after_escape
)
{
transition
(
escape
,
'\\'
)
transition
(
done
,
'"'
,
escaper
.
assign
(
consumer
,
std
::
addressof
(
*
first
),
static_cast
<
size_t
>
(
ps
.
i
-
first
),
true
))
transition
(
done
,
'"'
,
assign_value
(
escaper
,
consumer
,
first
,
ps
.
i
,
true
))
transition
(
read_chars_after_escape
,
any_char
)
}
state
(
escape
)
{
// TODO: Add support for JSON's \uXXXX escaping.
transition
(
read_chars_after_escape
,
"
\"\\
/bfnrt"
)
transition
(
read_chars_after_escape
,
"
\"\\
/bfnrt
v
"
)
}
term_state
(
done
)
{
transition
(
done
,
"
\t\n
"
)
...
...
@@ -287,19 +287,56 @@ void read_json_string(ParserState& ps, Unescaper escaper, Consumer consumer) {
// clang-format on
}
template
<
class
ParserState
,
class
Unescaper
>
void
read_member
(
ParserState
&
ps
,
Unescaper
unescaper
,
size_t
nesting_level
,
template
<
class
ParserState
,
class
Unescaper
,
class
Consumer
>
void
read_json_string
(
ParserState
&
ps
,
std
::
vector
<
char
>&
scratch_space
,
Unescaper
escaper
,
Consumer
consumer
)
{
scratch_space
.
clear
();
// clang-format off
start
();
state
(
init
)
{
transition
(
init
,
"
\t\n
"
)
transition
(
read_chars
,
'"'
)
}
state
(
read_chars
)
{
transition
(
escape
,
'\\'
)
transition
(
done
,
'"'
,
assign_value
(
escaper
,
consumer
,
scratch_space
.
begin
(),
scratch_space
.
end
(),
false
))
transition
(
read_chars
,
any_char
,
scratch_space
.
push_back
(
ch
))
}
state
(
escape
)
{
// TODO: Add support for JSON's \uXXXX escaping.
transition
(
read_chars
,
'"'
,
scratch_space
.
push_back
(
'"'
))
transition
(
read_chars
,
'\\'
,
scratch_space
.
push_back
(
'\\'
))
transition
(
read_chars
,
'b'
,
scratch_space
.
push_back
(
'\b'
))
transition
(
read_chars
,
'f'
,
scratch_space
.
push_back
(
'\f'
))
transition
(
read_chars
,
'n'
,
scratch_space
.
push_back
(
'\n'
))
transition
(
read_chars
,
'r'
,
scratch_space
.
push_back
(
'\r'
))
transition
(
read_chars
,
't'
,
scratch_space
.
push_back
(
'\t'
))
transition
(
read_chars
,
'v'
,
scratch_space
.
push_back
(
'\v'
))
}
term_state
(
done
)
{
transition
(
done
,
"
\t\n
"
)
}
fin
();
// clang-format on
}
template
<
class
ParserState
,
class
ScratchSpace
,
class
Unescaper
>
void
read_member
(
ParserState
&
ps
,
ScratchSpace
&
scratch_space
,
Unescaper
unescaper
,
size_t
nesting_level
,
member_consumer
consumer
)
{
// clang-format off
start
();
state
(
init
)
{
transition
(
init
,
"
\t\n
"
)
fsm_epsilon
(
read_json_string
(
ps
,
unescaper
,
consumer
.
begin_key
()),
fsm_epsilon
(
read_json_string
(
ps
,
scratch_space
,
unescaper
,
consumer
.
begin_key
()),
after_key
,
'"'
)
}
state
(
after_key
)
{
transition
(
after_key
,
"
\t\n
"
)
fsm_transition
(
read_value
(
ps
,
unescaper
,
nesting_level
,
fsm_transition
(
read_value
(
ps
,
scratch_space
,
unescaper
,
nesting_level
,
consumer
.
begin_val
()),
done
,
':'
)
}
...
...
@@ -310,9 +347,10 @@ void read_member(ParserState& ps, Unescaper unescaper, size_t nesting_level,
// clang-format on
}
template
<
class
ParserState
,
class
Unescaper
>
void
read_json_object
(
ParserState
&
ps
,
Unescaper
unescaper
,
size_t
nesting_level
,
obj_consumer
consumer
)
{
template
<
class
ParserState
,
class
ScratchSpace
,
class
Unescaper
>
void
read_json_object
(
ParserState
&
ps
,
ScratchSpace
&
scratch_space
,
Unescaper
unescaper
,
size_t
nesting_level
,
obj_consumer
consumer
)
{
if
(
nesting_level
>=
max_nesting_level
)
{
ps
.
code
=
pec
::
nested_too_deeply
;
return
;
...
...
@@ -325,7 +363,7 @@ void read_json_object(ParserState& ps, Unescaper unescaper,
}
state
(
has_open_brace
)
{
transition
(
has_open_brace
,
"
\t\n
"
)
fsm_epsilon
(
read_member
(
ps
,
unescaper
,
nesting_level
+
1
,
fsm_epsilon
(
read_member
(
ps
,
scratch_space
,
unescaper
,
nesting_level
+
1
,
consumer
.
begin_member
()),
after_member
,
'"'
)
transition
(
done
,
'}'
)
...
...
@@ -337,7 +375,7 @@ void read_json_object(ParserState& ps, Unescaper unescaper,
}
state
(
after_comma
)
{
transition
(
after_comma
,
"
\t\n
"
)
fsm_epsilon
(
read_member
(
ps
,
unescaper
,
nesting_level
+
1
,
fsm_epsilon
(
read_member
(
ps
,
scratch_space
,
unescaper
,
nesting_level
+
1
,
consumer
.
begin_member
()),
after_member
,
'"'
)
}
...
...
@@ -348,8 +386,9 @@ void read_json_object(ParserState& ps, Unescaper unescaper,
// clang-format on
}
template
<
class
ParserState
,
class
Unescaper
>
void
read_json_array
(
ParserState
&
ps
,
Unescaper
unescaper
,
size_t
nesting_level
,
template
<
class
ParserState
,
class
ScratchSpace
,
class
Unescaper
>
void
read_json_array
(
ParserState
&
ps
,
ScratchSpace
&
scratch_space
,
Unescaper
unescaper
,
size_t
nesting_level
,
arr_consumer
consumer
)
{
if
(
nesting_level
>=
max_nesting_level
)
{
ps
.
code
=
pec
::
nested_too_deeply
;
...
...
@@ -364,7 +403,7 @@ void read_json_array(ParserState& ps, Unescaper unescaper, size_t nesting_level,
state
(
has_open_brace
)
{
transition
(
has_open_brace
,
"
\t\n
"
)
transition
(
done
,
']'
)
fsm_epsilon
(
read_value
(
ps
,
unescaper
,
nesting_level
+
1
,
fsm_epsilon
(
read_value
(
ps
,
scratch_space
,
unescaper
,
nesting_level
+
1
,
consumer
.
begin_value
()),
after_value
)
}
...
...
@@ -375,7 +414,7 @@ void read_json_array(ParserState& ps, Unescaper unescaper, size_t nesting_level,
}
state
(
after_comma
)
{
transition
(
after_comma
,
"
\t\n
"
)
fsm_epsilon
(
read_value
(
ps
,
unescaper
,
nesting_level
+
1
,
fsm_epsilon
(
read_value
(
ps
,
scratch_space
,
unescaper
,
nesting_level
+
1
,
consumer
.
begin_value
()),
after_value
)
}
...
...
@@ -386,21 +425,23 @@ void read_json_array(ParserState& ps, Unescaper unescaper, size_t nesting_level,
// clang-format on
}
template
<
class
ParserState
,
class
Unescaper
>
void
read_value
(
ParserState
&
ps
,
Unescaper
unescaper
,
size_t
nesting_level
,
template
<
class
ParserState
,
class
ScratchSpace
,
class
Unescaper
>
void
read_value
(
ParserState
&
ps
,
ScratchSpace
&
scratch_space
,
Unescaper
unescaper
,
size_t
nesting_level
,
val_consumer
consumer
)
{
// clang-format off
start
();
state
(
init
)
{
transition
(
init
,
"
\t\n
"
)
fsm_epsilon
(
read_json_string
(
ps
,
unescaper
,
consumer
),
done
,
'"'
)
fsm_epsilon
(
read_json_string
(
ps
,
scratch_space
,
unescaper
,
consumer
),
done
,
'"'
)
fsm_epsilon
(
read_bool
(
ps
,
consumer
),
done
,
"ft"
)
fsm_epsilon
(
read_json_null_or_nan
(
ps
,
consumer
),
done
,
"n"
)
fsm_epsilon
(
read_number
(
ps
,
consumer
),
done
,
"+-.0123456789"
)
fsm_epsilon
(
read_json_object
(
ps
,
unescaper
,
nesting_level
,
fsm_epsilon
(
read_json_object
(
ps
,
scratch_space
,
unescaper
,
nesting_level
,
consumer
.
begin_object
()),
done
,
'{'
)
fsm_epsilon
(
read_json_array
(
ps
,
unescaper
,
nesting_level
,
fsm_epsilon
(
read_json_array
(
ps
,
scratch_space
,
unescaper
,
nesting_level
,
consumer
.
begin_array
()),
done
,
'['
)
}
...
...
@@ -499,28 +540,41 @@ const array* empty_array() noexcept {
}
value
*
parse
(
string_parser_state
&
ps
,
monotonic_buffer_resource
*
storage
)
{
unit_t
scratch_space
;
regular_unescaper
unescaper
;
monotonic_buffer_resource
::
allocator
<
value
>
alloc
{
storage
};
auto
result
=
new
(
alloc
.
allocate
(
1
))
value
();
parser
::
read_value
(
ps
,
scratch_space
,
unescaper
,
0
,
{
storage
,
result
});
return
result
;
}
value
*
parse
(
file_parser_state
&
ps
,
monotonic_buffer_resource
*
storage
)
{
std
::
vector
<
char
>
scratch_space
;
scratch_space
.
reserve
(
64
);
regular_unescaper
unescaper
;
monotonic_buffer_resource
::
allocator
<
value
>
alloc
{
storage
};
auto
result
=
new
(
alloc
.
allocate
(
1
))
value
();
parser
::
read_value
(
ps
,
unescaper
,
0
,
{
storage
,
result
});
parser
::
read_value
(
ps
,
scratch_space
,
unescaper
,
0
,
{
storage
,
result
});
return
result
;
}
value
*
parse_shallow
(
string_parser_state
&
ps
,
monotonic_buffer_resource
*
storage
)
{
unit_t
scratch_space
;
shallow_unescaper
unescaper
;
monotonic_buffer_resource
::
allocator
<
value
>
alloc
{
storage
};
auto
result
=
new
(
alloc
.
allocate
(
1
))
value
();
parser
::
read_value
(
ps
,
unescaper
,
0
,
{
storage
,
result
});
parser
::
read_value
(
ps
,
scratch_space
,
unescaper
,
0
,
{
storage
,
result
});
return
result
;
}
value
*
parse_in_situ
(
mutable_string_parser_state
&
ps
,
monotonic_buffer_resource
*
storage
)
{
unit_t
scratch_space
;
in_situ_unescaper
unescaper
;
monotonic_buffer_resource
::
allocator
<
value
>
alloc
{
storage
};
auto
result
=
new
(
alloc
.
allocate
(
1
))
value
();
parser
::
read_value
(
ps
,
unescaper
,
0
,
{
storage
,
result
});
parser
::
read_value
(
ps
,
scratch_space
,
unescaper
,
0
,
{
storage
,
result
});
return
result
;
}
...
...
libcaf_core/src/json_reader.cpp
View file @
d12398ad
...
...
@@ -8,6 +8,8 @@
#include "caf/detail/print.hpp"
#include "caf/string_algorithms.hpp"
#include <fstream>
namespace
{
static
constexpr
const
char
class_name
[]
=
"caf::json_reader"
;
...
...
@@ -150,14 +152,36 @@ bool json_reader::load(std::string_view json_text) {
set_error
(
make_error
(
ps
));
st_
=
nullptr
;
return
false
;
}
else
{
}
err_
.
reset
();
detail
::
monotonic_buffer_resource
::
allocator
<
stack_type
>
alloc
{
&
buf_
};
st_
=
new
(
alloc
.
allocate
(
1
))
stack_type
(
stack_allocator
{
&
buf_
});
st_
->
reserve
(
16
);
st_
->
emplace_back
(
root_
);
return
true
;
}
bool
json_reader
::
load_file
(
const
char
*
path
)
{
using
iterator_t
=
std
::
istreambuf_iterator
<
char
>
;
reset
();
std
::
ifstream
input
{
path
};
if
(
!
input
.
is_open
())
{
emplace_error
(
sec
::
cannot_open_file
);
return
false
;
}
detail
::
json
::
file_parser_state
ps
{
iterator_t
{
input
},
iterator_t
{}};
root_
=
detail
::
json
::
parse
(
ps
,
&
buf_
);
if
(
ps
.
code
!=
pec
::
success
)
{
set_error
(
make_error
(
ps
));
st_
=
nullptr
;
return
false
;
}
err_
.
reset
();
detail
::
monotonic_buffer_resource
::
allocator
<
stack_type
>
alloc
{
&
buf_
};
st_
=
new
(
alloc
.
allocate
(
1
))
stack_type
(
stack_allocator
{
&
buf_
});
st_
->
reserve
(
16
);
st_
->
emplace_back
(
root_
);
return
true
;
}
void
json_reader
::
revert
()
{
...
...
libcaf_core/src/json_value.cpp
View file @
d12398ad
...
...
@@ -10,6 +10,8 @@
#include "caf/make_counted.hpp"
#include "caf/parser_state.hpp"
#include <fstream>
namespace
caf
{
// -- conversion ---------------------------------------------------------------
...
...
@@ -92,35 +94,49 @@ expected<json_value> json_value::parse(std::string_view str) {
auto
storage
=
make_counted
<
detail
::
json
::
storage
>
();
string_parser_state
ps
{
str
.
begin
(),
str
.
end
()};
auto
root
=
detail
::
json
::
parse
(
ps
,
&
storage
->
buf
);
if
(
ps
.
code
!=
pec
::
success
)
{
return
{
make_error
(
ps
)};
}
else
{
if
(
ps
.
code
==
pec
::
success
)
return
{
json_value
{
root
,
std
::
move
(
storage
)}};
}
return
{
make_error
(
ps
)};
}
expected
<
json_value
>
json_value
::
parse_shallow
(
std
::
string_view
str
)
{
auto
storage
=
make_counted
<
detail
::
json
::
storage
>
();
string_parser_state
ps
{
str
.
begin
(),
str
.
end
()};
auto
root
=
detail
::
json
::
parse_shallow
(
ps
,
&
storage
->
buf
);
if
(
ps
.
code
!=
pec
::
success
)
{
return
{
make_error
(
ps
)};
}
else
{
if
(
ps
.
code
==
pec
::
success
)
return
{
json_value
{
root
,
std
::
move
(
storage
)}};
}
return
{
make_error
(
ps
)};
}
expected
<
json_value
>
json_value
::
parse_in_situ
(
std
::
string
&
str
)
{
auto
storage
=
make_counted
<
detail
::
json
::
storage
>
();
mutable_string_parser_state
ps
{
str
.
data
(),
str
.
data
()
+
str
.
size
()};
detail
::
json
::
mutable_string_parser_state
ps
{
str
.
data
(),
str
.
data
()
+
str
.
size
()};
auto
root
=
detail
::
json
::
parse_in_situ
(
ps
,
&
storage
->
buf
);
if
(
ps
.
code
!=
pec
::
success
)
{
if
(
ps
.
code
==
pec
::
success
)
return
{
json_value
{
root
,
std
::
move
(
storage
)}};
return
{
make_error
(
ps
)};
}
else
{
}
expected
<
json_value
>
json_value
::
parse_file
(
const
char
*
path
)
{
using
iterator_t
=
std
::
istreambuf_iterator
<
char
>
;
std
::
ifstream
input
{
path
};
if
(
!
input
.
is_open
())
return
make_error
(
sec
::
cannot_open_file
);
auto
storage
=
make_counted
<
detail
::
json
::
storage
>
();
detail
::
json
::
file_parser_state
ps
{
iterator_t
{
input
},
iterator_t
{}};
auto
root
=
detail
::
json
::
parse
(
ps
,
&
storage
->
buf
);
if
(
ps
.
code
==
pec
::
success
)
return
{
json_value
{
root
,
std
::
move
(
storage
)}};
}
return
{
make_error
(
ps
)};
}
expected
<
json_value
>
json_value
::
parse_file
(
const
std
::
string
&
path
)
{
return
parse_file
(
path
.
c_str
());
}
// -- free functions -----------------------------------------------------------
std
::
string
to_string
(
const
json_value
&
val
)
{
std
::
string
result
;
val
.
print_to
(
result
);
...
...
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