-
Notifications
You must be signed in to change notification settings - Fork 4
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Function find_key #26
Comments
I am hesitating a bit, not because I dislike the suggestion, but because I am trying to understand if there is a larger framework lurking behind this. For example, we could create a "virtual container" that wraps |
Let's leave the issue for sleep for a few months. I'll think about it. |
I have added the feature/viewer branch to experiment with this. The branch contains a The only "documentation" is |
I think And rename I think this should only be merged to |
I agree about |
I would like to keep the There was an old C++ proposal for adding trees, where the recursive iterators were called cursors. |
BinToken has both begin-end arrays ( |
Btw, an iterator for
That's basically what I used in a recent project of mine. I didn't actually reified it into a real iterator, but I manipulated the same data structure that such iterator would use (a But that's FYI as they say. I'm not asking for an iterator implementation. I'm just reporting back from one recent experience I had. |
So I believe #16 ( Boost.Serialization generates non-introspectable archives. The output format will be meaningless without the C++ source code. The data schema resides not in the final archive itself, but in the C++ code. The final archive is just a bunch of S-exprs in new disguises. However Trial.Protocol offers the user the chance to control not serialization code for C++ structures, but to define protocols. You made this small observation yourself in one of our email exchanges. So if the user has a type template <typename CharT>
struct load_overloader<json::basic_iarchive<CharT>,
Foobar>
{
static void load(json::basic_iarchive<CharT>& ar,
Foobar& data,
const unsigned int /*protocol_version*/)
{
...
}
}; That's where we can help with a few algorithms. There's already {
"foo": 2,
"bar": 3
} into: struct Foobar
{
int foo;
int bar;
}; However the network protocol sometimes defines object hierarchies. And as Marcel Weiher has noted in his call for "less lethargic JSON support" [sic]:
We need to look ahead to check for some {
"x": 4,
"type": "pos",
"y": 5
} And the C++ classes:
So... to help the hand-written serialization code that encodes this network protocol (as opposed to serialization) we could offer an algorithm such as: template<class F>
bool copy_and_look_ahead(const json::reader& reader, F&& f); The function copies reader and modifies its own copy to traverse the substream. So it's handling one responsibility and one responsibility only: look ahead. It'll call enum { POS, IMAGE, UNKNOWN } current;
auto on_value = [&](json::reader& reader) {
// ... more code to check current type is string ...
if (reader.value<std::string>() == "pos")
current = POS;
else if (reader.value<std::string>() == "image")
current = IMAGE;
else
current = UNKNOWN;
};
std::error_code ec;
if (!json::copy_and_look_ahead(reader, "type", on_value, ec))
throw std::runtime_error("invalid protocol");
switch (current) {
// ...
} The use case is clear and the semantics are much easier to figure it out than the initial |
I like this approach. Serialization gives us support for protocols with a schema where data is determined by their position, and this look-ahead functionality gives us support for tag-based protocols. |
I've been playing with C++17's There's a “flat” iterator as well for iterating over the same “collection”: https://en.cppreference.com/w/cpp/filesystem/directory_iterator The tree/recursive iterator is more complex and has a few more methods than the usual ones found on “flat” iterators:
The last two methods fill the same gap as the I think there has been enough stories collected about tree iterators to make a decision already. I used Trial.Protocol on many projects of different needs. On the ones where I could have used a tree iterator, I've reported back the requirements I'd have. Independent teams designed a recursive iterator for |
I experimented with a recursive iterator a while back. The design consisted of two parts:
I did not proceed with this design because the std algorithms assume that iterators a as simple as pointers and therefore copies iterators rather than moving them. This caused all shorts of odd behavior because they manipulated the copies, not the original state. Now that I look at the Regarding
|
For
I wrote Lua bindings for for entry, depth in fs.recursive_directory_iterator(fs.path.new(".")) do
print(string.rep("\t", depth) .. tostring(entry.path:filename()))
end If one wanted to ignore for entry, depth in fs.recursive_directory_iterator(fs.path.new(".")) do
if entry.path:filename() ~= ".git" then
print(string.rep("\t", depth) .. tostring(entry.path:filename()))
end
end The use case for ignoring CVS subdirectories common enough that it should be possible to abstract it. For this, we can write the following: function cvs_exclude(iter, ctrl)
local function next()
local entry, depth = iter()
if entry == nil then
return
end
local p = tostring(entry.path:filename())
if p == ".git" or p == ".svn" or p == ".hg" then
ctrl:disable_recursion_pending()
end
return entry, depth
end
return next, ctrl
end
for entry, depth in cvs_exclude(fs.recursive_directory_iterator(fs.path.new("."))) do
print(string.rep("\t", depth) .. tostring(entry.path:filename()))
end The C++17 design helped my Lua abstraction. Now we can not only compose one level of abstraction, but we could further stack more behaviors on top. However C++ is not Lua. For C++, the same could be achieved with the traditional iterator design (we just need to give a different meaning for
Even if we go with such alternatives, I'd like to also keep the method |
On another note, there's another useful side of That's something Trial.Protocol's iterator could also mirror. |
I got two experiments mixed up. The recursive iterator I mentioned above was for the Adding Regarding
which becomes as follows with
You can also use The I am still skeptical about |
It almost works for me, but I also need a path object telling me where I am. I can't imagine a use case where the lack of path information would work.
I agree about your assessment. However, putting
I'm not sure what the answer is here. For algorithms, suppose: std::for_each(trial_protocol_iterator, end, [](auto&& x) {
if (x.path().back() == "foobar")
x.disable_recursion_pending();
}); The interface I think the uses cases diverge too much. The example above doesn't need to recurse on every subobject. The use case I had earlier required me to recurse on every subobject. An iterator might be used to reuse the iterators ecosystem, or maybe the user doesn't care about it (the latter is the use case where I fall into). |
That information is currently not stored anywhere. I have to think about how we can add that without introducing unnecessary overhead.
We would have to resort to a plain for loop, in which case we can do this:
Another approach we should consider is to make a sibling-iterator instead of a recursive-iterator and let the user recurse when needed. |
Given this JSON:
and a reader which is in the root JSON point:
find_key(reader, "def")
would advance the reader to hold the point/value42
.An initial non-tested implementation is:
I think this function should only try to find the key if it is given the token at the
begin_object
token because the semantics are clearer. If you're already iterating over the object keys, there is no point in provide an “easier” function to you, as all you'd need is theskip_element
function and stay in the loop (one call to theskip_element
in the else clause and nothing more... which is 2 extra lines for user code...).Also, if you think this function can belong to Trial.Protocol, another function could be
close_current_object
which would pair with thereader
advanced byfind_key
nicely.The text was updated successfully, but these errors were encountered: