Skip to content
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

Add iterator support to url_search_params #532

Merged
merged 1 commit into from
Oct 10, 2023

Conversation

jasnell
Copy link
Contributor

@jasnell jasnell commented Oct 9, 2023

Does two things:

  • Adds simple iterators to ada::url_search_params. These are implemented as distinct types with next() and is_done() methods as opposed to traditional c++ iterators.

  • Adds url search params apis to ada_c

@jasnell jasnell force-pushed the url_search_params_iterators branch from 60579dd to bab1ae7 Compare October 9, 2023 20:25
@jasnell

This comment was marked as resolved.

include/ada/url_search_params-inl.h Outdated Show resolved Hide resolved
include/ada/url_search_params.h Show resolved Hide resolved
include/ada_c.h Show resolved Hide resolved
include/ada/url_search_params.h Outdated Show resolved Hide resolved
src/ada_c.cpp Outdated Show resolved Hide resolved
include/ada/url_search_params-inl.h Outdated Show resolved Hide resolved
tests/ada_c.cpp Show resolved Hide resolved
tests/ada_c.cpp Outdated Show resolved Hide resolved
tests/url_search_params.cpp Show resolved Hide resolved
@anonrig anonrig requested a review from lemire October 9, 2023 21:05
@anonrig
Copy link
Member

anonrig commented Oct 9, 2023

@jasnell Can you add documentation to each function and a small example to README?

@jasnell jasnell force-pushed the url_search_params_iterators branch from 8e0f3ed to 1a56d71 Compare October 9, 2023 21:45
@jasnell jasnell requested a review from anonrig October 9, 2023 22:00
Copy link
Member

@anonrig anonrig left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me. I want to take a look at it after @lemire leaves a review. Thank you @jasnell

@lemire
Copy link
Member

lemire commented Oct 10, 2023

@jasnell Looks fine to me.

However, I am unsure why you don't want to use conventional C++ iterators, which allow you to automagically do this:

 for (auto key : search_params.get_keys()) {
   // do something with key
 }

The approach you document...

auto keys = search_params.get_keys();
 while (!keys.is_done()) {
   auto key = keys.next();  // "a", "c", "e", "g"
 }

will appear odd (I don't mean to be insulting) to many modern C++ users. It is also objectively 'busier' and easier to get wrong.

Furthermore, why 'is_done' instead of the conventional 'has_next... That is, the following is easier to understand...

auto keys = search_params.get_keys();
 while (keys.has_next()) {
   auto key = keys.next();  // "a", "c", "e", "g"
 }

Isn't it?

Can you elaborate on your design decisions ?

@lemire
Copy link
Member

lemire commented Oct 10, 2023

Effectively, I think you need very strong arguments if you are going to bypass the standard C++ iterators. They are easy to implement, and they lead to all sorts of goodies. They are expected in C++.

@jasnell
Copy link
Contributor Author

jasnell commented Oct 10, 2023

Yep, I'd considered implementing normal c++ iterators but opted for this model to keep it conceptually similar to JavaScripts iterator pattern (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols#the_iterator_protocol), which has next(), done, etc. The key expectation being that these are most likely to be wrapped in an implementation of the URLSearchParams class where next() is called to advance.

There the pattern for wrapping these is more likely something like (forgive the mild pseudocode)

class URLStringParamsKeysIterator {
 public:
  struct Result {
    bool done;
    JsValue value;
  };
  Result next() {
    if (iter.done) return { true, JsUndefined};
    return { false, iter.next() };
  }

private:
  ada::url_search_params_keys_iter iter;
}

I wanted also to leave room for someone to implement the conventional c++ iterator pattern if they wanted -- these should be able to co-exist. I just really have no immediate need for the c++ style iterators. I need this only to support the JS pattern.

And yes, I know that I could implement these using the C++ iterator pattern under the covers but this was just easier :-)

Also note that the JS iterator pattern for URLSearchParams is... quirky, when it comes to edits. The iterator itself needs to continue to work in the face of edits, even if the behavior is... odd. If I was implementing a conventional c++ iterator I would want the behavior to be a bit stricter here.

image

@jasnell
Copy link
Contributor Author

jasnell commented Oct 10, 2023

@lemire @anonrig ... ok, I've updated to add the conventional c++ iterator in addition to the JS-style. For the c++ iterator I'm really just deferring to the underlying std::vector for entries, whereas the js-style has distinct instances for keys, values, and entries.

I also renamed is_done to has_next and updated accordingly. Hopefully this will strike a nice balance for both JS and C++ use.

@lemire
Copy link
Member

lemire commented Oct 10, 2023

Approved.

src/ada_c.cpp Outdated Show resolved Hide resolved
src/ada_c.cpp Show resolved Hide resolved
src/ada_c.cpp Outdated Show resolved Hide resolved
src/ada_c.cpp Outdated Show resolved Hide resolved
src/ada_c.cpp Show resolved Hide resolved
src/ada_c.cpp Show resolved Hide resolved
@jasnell
Copy link
Contributor Author

jasnell commented Oct 10, 2023

I see that many of the operations in ada_c are intended to be safe when !r but the current approach means that these will crash after the various ada_free* calls. In a separate PR I'll go through and make these all safer (not just the search_params ones) so that double frees and the other ops are more resilient after free.

@jasnell jasnell merged commit 2f1130a into ada-url:main Oct 10, 2023
31 checks passed
@jasnell jasnell deleted the url_search_params_iterators branch October 10, 2023 16:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants