Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

If a regex evaluates to true call a member function (C++14)

37 views
Skip to first unread message

Chicken Mcnuggets

unread,
May 15, 2015, 8:44:48 AM5/15/15
to
I'm having a bit of difficulty in working out the best way to approach a
particular problem. I'll try and describe it as well as I can but if you
understand HTTP requests it will be much easier.

Basically I'm writing a C++ web framework that takes requests from an
SCGI client (confusingly this is an HTTP server such as Nginx or Apache)
and acts as an SCGI server. When an SCGI request comes from the HTTP
server I need to take the requested URL and match it to a class or a
specific member function which will then handle the request, get data
from a database and reply with the correct SCGI response to the HTTP server.

In order to do this I want to have a set of regex patterns match against
the resource that is being requested and if one of the regex patterns
match the resource requested it calls a member function of a given class.

I was thinking of doing this by having an std::unordered_map with a
regex pattern as the key and using a std::bind as the value which links
it to a member function. Does this sound like a reasonable way to do this?

Are there any better ways at all?

Öö Tiib

unread,
May 15, 2015, 10:18:38 AM5/15/15
to
There always are better ways because "better" is subjective.
There do not exist ultimate ways because there are no ultimate
goals. I can only ask some questions you may want to think
about.

Do I understand it correctly that your algorithm is to try whole
pile of regexes to match with request and then call according
function?

Why you write your own "web communication framework"? It is
complex subject and so using work of good people out there
(like http://cgi.sourceforge.net/) might save you some time.
Also you may learn something from their code.

Why there is unordered_map? It is more complex than vector of
pairs but search still stays O(N) if you (regardless of what it is)
try them all.

Why there are regular expressions? Typically it is simple to split
out some keystring that indicates what service is needed. Search
for matching string in sorted array is dirt cheap compared with
checking whole list of regexes.

Alain Ketterlin

unread,
May 15, 2015, 10:31:15 AM5/15/15
to
Chicken Mcnuggets <chi...@mcnuggets.com> writes:

[...]
> In order to do this I want to have a set of regex patterns match
> against the resource that is being requested and if one of the regex
> patterns match the resource requested it calls a member function of a
> given class.
>
> I was thinking of doing this by having an std::unordered_map with a
> regex pattern as the key and using a std::bind as the value which
> links it to a member function. Does this sound like a reasonable way
> to do this?

Don't keep several regexps. Build a single regexp like "(...)|(...)|..."
and use either group numbers (to index a vector) or group names (to
index an unordered_map). This will be much faster: you compile it once
and for all, and you match all cases at once. This assumes you have a
more or less fixed set of regexps. If regexps are added/removed very
frequently, then keep a list or vector of pair<regexp,binder>. You'll
have to traverse it anyway to find the matching one, there is no point
in having a map for this iiuc.

std::bind is fine, but if all handlers have identical signatures you can
simply use member function pointers. It depends on your calling
protocol.

-- Alain.
Message has been deleted

Jorgen Grahn

unread,
May 17, 2015, 8:05:29 AM5/17/15
to
On Fri, 2015-05-15, Stefan Ram wrote:
> Chicken Mcnuggets <chi...@mcnuggets.com> writes:
>>and acts as an SCGI server. When an SCGI request comes from the HTTP
>
> If I'd have to do this, I'd ask for the grammar of the SCGI
> request language.
>
> If there is no such grammar, then it is not specified what I
> am actually supposed to implement.
>
> If there is such a grammar, then I can write a parser.
>
> Regular expressions are not always suitable to parse
> expressions. Are you sure that there is always at most
> one pattern that matches?
>
> Think about implementing it in the most natural way for now:
>
> if the request matches regexp0 then ...
> else if the request matches regexp1 then ...
> ...
> else if the request matches regexp9 then ...
>
> (This approach might not be suitable when there are very
> many such if-branches or the request syntax changes very
> often at runtime.)

Yeah. The problem, as stated, really boils down to the
old "execute a command, specified in a certain input language".
Nothing special about it -- and unless that language changes a lot, I
find it best to just suck it up and do it the boring if ... else if
... way described above. Overengineering this problem doesn't pay
off.

/Jorgen

--
// Jorgen Grahn <grahn@ Oo o. . .
\X/ snipabacken.se> O o .

Richard

unread,
May 17, 2015, 1:38:49 PM5/17/15
to
[Please do not mail me a copy of your followup]

Jorgen Grahn <grahn...@snipabacken.se> spake the secret code
<slrnmlh0vu.2...@frailea.sa.invalid> thusly:
Parsing is one of those things that is so easy to unit test that there
really isn't any excuse for not unit testing it.

If you put tests around it, you can do the regex match style above until
it becomes burdensome and then switch to some kind of more formal parser
and your tests will ensure that everything is still working.
--
"The Direct3D Graphics Pipeline" free book <http://tinyurl.com/d3d-pipeline>
The Computer Graphics Museum <http://computergraphicsmuseum.org>
The Terminals Wiki <http://terminals.classiccmp.org>
Legalize Adulthood! (my blog) <http://legalizeadulthood.wordpress.com>

Chicken Mcnuggets

unread,
May 17, 2015, 7:11:18 PM5/17/15
to
Sorry folks. Been busy the last day or two so haven't been able to reply.

I think I explained the problem rather poorly in my original post. Let
me try and explain better.

If the request was coming directly into the framework and the framework
could provide the regex and the member function that should be called
this would be a non-issue and it would be easy to solve as described
above. But that is not the case.

The request actually comes into the framework via an SCGI protocol
handling class but the regex and the class containing the member
function which renders the HTML for the response is provided by the
user. I have no control over this (other than specifying conventions in
documentation of course).

So the problem is this:

HTTP Request -> HTTP Server -> SCGI Request - C++ Web Framework -> User
provided C++ code to match request to a regex and then call a member
function -> User provided C++ member function -> C++ Web Framework ->
SCGI Response -> HTTP Server -> HTTP Response

The only code I have control over is the C++ web framework. Somehow I
need to allow a user to extend the framework with a set of code that
will allow requests to be routed to a class which contains a member
function that renders HTML as a response (for those who know MVC this is
the view class).

I've been basing my design off the Django web framework which is written
in Python since I already know that but I'm having a hard time
converting things which make heavy use of Python's dynamism into the
more static C++ world.

For reference this is how Django deals with URLs:

https://docs.djangoproject.com/en/1.8/topics/http/urls/

and this is what I was roughly hoping to emulate. The URL regex and the
views are provided by the user and the framework provides the code to
link the two together.

So it is not as simple as a if / else if / else branch since the
framework doesn't know ahead of time what is being provided by the user.

Hopefully that has explained things a little bit better.

Richard

unread,
May 17, 2015, 10:30:42 PM5/17/15
to
[Please do not mail me a copy of your followup]

Chicken Mcnuggets <chi...@mcnuggets.com> spake the secret code
<ge96x.801815$396.7...@fx12.am4> thusly:

>For reference this is how Django deals with URLs:
>
>https://docs.djangoproject.com/en/1.8/topics/http/urls/
>
>and this is what I was roughly hoping to emulate. The URL regex and the
>views are provided by the user and the framework provides the code to
>link the two together.

I'm familiar with Django and how it maps URLs to views.

There are a number of ways to orchestrate the C++ equivalent.

For instance:

class IView {
public:
virtual ~IView() {}

// user implements this
virtual void render() = 0;
};

std::map<std::string, std::unique_ptr<IView>> viewMapping;

Really, you want to define an abstraction for your C++ customers to
implement so that you are employing Dependency Inversion Principle
and eliminating unnecessary coupling.

Their callback handler is a detail that depends on an abstraction (IView).

Your regex->handler dispatcher is a detail that depends on an abstraction
(IView).

You publish the IView interface for your clients to implement.
0 new messages