Browse Source

Closing feature request #13 dispatcher().assign() and more then e4 parameters

master
Artyom Beilis 11 years ago
parent
commit
771eb7af56
3 changed files with 198 additions and 4 deletions
  1. +111
    -0
      cppcms/url_dispatcher.h
  2. +33
    -4
      src/url_dispatcher.cpp
  3. +54
    -0
      tests/url_mapper_test.cpp

+ 111
- 0
cppcms/url_dispatcher.h View File

@@ -14,6 +14,7 @@
#include <booster/hold_ptr.h>
#include <booster/traits/enable_if.h>
#include <booster/traits/is_base_of.h>
#include <booster/regex.h>
#include <cppcms/application.h>
#include <string>
#include <list>
@@ -46,13 +47,21 @@ namespace cppcms {
public:
// Handlers
typedef booster::function<void()> handler;
typedef booster::function<void(booster::cmatch const &)> rhandler;
typedef booster::function<void(std::string)> handler1;
typedef booster::function<void(std::string,std::string)> handler2;
typedef booster::function<void(std::string,std::string,std::string)> handler3;
typedef booster::function<void(std::string,std::string,std::string,std::string)> handler4;
typedef booster::function<void(std::string,std::string,std::string,std::string,std::string)> handler5;
typedef booster::function<void(std::string,std::string,std::string,std::string,std::string,std::string)> handler6;

///
/// Assign \a handler to pattern \a regex thus if URL that matches
/// this pattern requested, \a handler is called with matched results
///
void assign_generic(std::string const &regex,rhandler handler);
///
/// Assign \a handler to pattern \a regex thus if URL that matches
/// this pattern requested, \a handler is called
///
void assign(std::string const &regex,handler handler);
@@ -85,6 +94,18 @@ namespace cppcms {
/// the string that was matched at position \a exp1, \a exp2, \a exp3 and \a exp4
///
void assign(std::string const &regex,handler4 handler,int exp1,int exp2,int exp3,int exp4);
///
/// Assign \a handler to pattern \a regex thus if URL that matches
/// this pattern requested, \a handler is called with 1st, 2nd, 3rd, 4th and 5th parameters
/// the string that was matched at position \a exp1, \a exp2, \a exp3, \a exp4 and \a exp5
///
void assign(std::string const &regex,handler5 handler,int exp1,int exp2,int exp3,int exp4,int exp5);
///
/// Assign \a handler to pattern \a regex thus if URL that matches
/// this pattern requested, \a handler is called with 1st, 2nd, 3rd, 4th, 5th and 6th parameters
/// the string that was matched at position \a exp1, \a exp2, \a exp3, \a exp4, \a exp 5 and \a exp6
///
void assign(std::string const &regex,handler6 handler,int exp1,int exp2,int exp3,int exp4,int exp5,int exp6);

///
/// Try to find match between \a url and registered handlers and applications.
@@ -112,6 +133,18 @@ namespace cppcms {
assign(regex,binder0<C>(member,object));
}
///
/// This template function is a shortcut to assign_generic(regex,rhandler). It allows
/// assignment of \a member function of an \a object with signature void handler(booster::cmatch const &)
///
/// In addition to calling \a member function it calls object->init() before call
/// and object->clean() after the call of the C is derived from cppcms::application
///
template<typename C>
void assign_generic(std::string const &regex,void (C::*member)(booster::cmatch const &),C *object)
{
assign_generic(regex,rbinder<C>(member,object));
}
///
/// This template function is a shortcut to assign(regex,callback,int). It allows
/// assignment of \a member function of an \a object with signature void handler(string)
///
@@ -159,6 +192,30 @@ namespace cppcms {
{
assign(regex,binder4<C>(member,object),e1,e2,e3,e4);
}
///
/// This template function is a shortcut to assign(regex,callback,int,int,int,int,int). It allows
/// assignment of \a member function of an \a object with signature void handler(string,string,string,string,string)
///
/// In addition to calling \a member function it calls object->init() before call
/// and object->clean() after the call of the C is derived from cppcms::application
///
template<typename C>
void assign(std::string const &regex,void (C::*member)(std::string,std::string,std::string,std::string,std::string),C *object,int e1,int e2,int e3,int e4,int e5)
{
assign(regex,binder5<C>(member,object),e1,e2,e3,e4,e5);
}
///
/// This template function is a shortcut to assign(regex,callback,int,int,int,int,int,int). It allows
/// assignment of \a member function of an \a object with signature void handler(string,string,string,string,string,string)
///
/// In addition to calling \a member function it calls object->init() before call
/// and object->clean() after the call of the C is derived from cppcms::application
///
template<typename C>
void assign(std::string const &regex,void (C::*member)(std::string,std::string,std::string,std::string,std::string,std::string),C *object,int e1,int e2,int e3,int e4,int e5,int e6)
{
assign(regex,binder6<C>(member,object),e1,e2,e3,e4,e5,e6);
}

///
/// Mount a sub application \a app to the URL dispatcher, using regular expression match.
@@ -217,6 +274,24 @@ namespace cppcms {
};
template<typename C>
struct rbinder{
typedef void (C::*member_type)(booster::cmatch const &);
member_type member;
C *object;
rbinder(member_type m,C *o) :
member(m),
object(o)
{
}
void operator()(booster::cmatch const &p1) const
{
page_guard<C> guard(object);
(object->*member)(p1);
}
};

template<typename C>
struct binder1{
typedef void (C::*member_type)(std::string);
member_type member;
@@ -285,6 +360,42 @@ namespace cppcms {
(object->*member)(p1,p2,p3,p4);
}
};

template<typename C>
struct binder5{
typedef void (C::*member_type)(std::string,std::string,std::string,std::string,std::string);
member_type member;
C *object;
binder5(member_type m,C *o) :
member(m),
object(o)
{
}
void operator()(std::string p1,std::string p2,std::string p3,std::string p4,std::string p5) const
{
page_guard<C> guard(object);
(object->*member)(p1,p2,p3,p4,p5);
}
};

template<typename C>
struct binder6{
typedef void (C::*member_type)(std::string,std::string,std::string,std::string,std::string,std::string);
member_type member;
C *object;
binder6(member_type m,C *o) :
member(m),
object(o)
{
}
void operator()(std::string p1,std::string p2,std::string p3,std::string p4,std::string p5,std::string p6) const
{
page_guard<C> guard(object);
(object->*member)(p1,p2,p3,p4,p5,p6);
}
};

struct _data;


+ 33
- 4
src/url_dispatcher.cpp View File

@@ -58,13 +58,15 @@ namespace cppcms {

template<typename H>
struct base_handler : public option {
base_handler(std::string expr,H handle,int a=0,int b=0,int c=0,int d=0)
base_handler(std::string expr,H handle,int a=0,int b=0,int c=0,int d=0,int e=0,int f=0)
: option(expr),handle_(handle)
{
select_[0]=a;
select_[1]=b;
select_[2]=c;
select_[3]=d;
select_[4]=e;
select_[5]=f;
}
virtual bool dispatch(std::string url)
{
@@ -80,6 +82,11 @@ namespace cppcms {
h();
}

void execute_handler(url_dispatcher::rhandler const &h)
{
h(match_);
}

void execute_handler(url_dispatcher::handler1 const &h)
{
h(match_[select_[0]]);
@@ -97,16 +104,24 @@ namespace cppcms {
{
h(match_[select_[0]],match_[select_[1]],match_[select_[2]],match_[select_[3]]);
}
void execute_handler(url_dispatcher::handler5 const &h)
{
h(match_[select_[0]],match_[select_[1]],match_[select_[2]],match_[select_[3]],match_[select_[4]]);
}
void execute_handler(url_dispatcher::handler6 const &h)
{
h(match_[select_[0]],match_[select_[1]],match_[select_[2]],match_[select_[3]],match_[select_[4]],match_[select_[5]]);
}

int select_[4];
int select_[6];
H handle_;
};


template<typename H>
booster::shared_ptr<option> make_handler(std::string expr,H const &handler,int a=0,int b=0,int c=0,int d=0)
booster::shared_ptr<option> make_handler(std::string expr,H const &handler,int a=0,int b=0,int c=0,int d=0,int e=0,int f=0)
{
return booster::shared_ptr<option>(new base_handler<H>(expr,handler,a,b,c,d));
return booster::shared_ptr<option>(new base_handler<H>(expr,handler,a,b,c,d,e,f));
}

} // anonynoys
@@ -147,6 +162,10 @@ namespace cppcms {
{
d->options.push_back(make_handler(expr,h));
}
void url_dispatcher::assign_generic(std::string const &expr,rhandler h)
{
d->options.push_back(make_handler(expr,h));
}

void url_dispatcher::assign(std::string const &expr,handler1 h,int p1)
{
@@ -168,4 +187,14 @@ namespace cppcms {
d->options.push_back(make_handler(expr,h,p1,p2,p3,p4));
}

void url_dispatcher::assign(std::string const &expr,handler5 h,int p1,int p2,int p3,int p4,int p5)
{
d->options.push_back(make_handler(expr,h,p1,p2,p3,p4,p5));
}

void url_dispatcher::assign(std::string const &expr,handler6 h,int p1,int p2,int p3,int p4,int p5,int p6)
{
d->options.push_back(make_handler(expr,h,p1,p2,p3,p4,p5,p6));
}

} // namespace cppcms

+ 54
- 0
tests/url_mapper_test.cpp View File

@@ -6,6 +6,7 @@
//
///////////////////////////////////////////////////////////////////////////////
#include <cppcms/url_mapper.h>
#include <cppcms/url_dispatcher.h>
#include <cppcms/application.h>
#include <cppcms/service.h>
#include <cppcms/json.h>
@@ -21,6 +22,55 @@ std::string value(std::ostringstream &s)
return res;
}

class disp : public cppcms::application {
public:
void hg(booster::cmatch const &m)
{ v_ = "m:" + std::string(m[0]) +':'+std::string(m[1]); }
void h0() { v_ = "-"; }
void h1(std::string s1)
{ v_ = ':'+s1; }
void h2(std::string s1,std::string s2)
{ v_ = ':'+s1+':'+s2; }
void h3(std::string s1,std::string s2,std::string s3)
{ v_ = ':'+s1+':'+s2+':'+s3; }
void h4(std::string s1,std::string s2,std::string s3,std::string s4)
{ v_ = ':'+s1+':'+s2+':'+s3+':'+s4; }
void h5(std::string s1,std::string s2,std::string s3,std::string s4,std::string s5)
{ v_ = ':'+s1+':'+s2+':'+s3+':'+s4+':'+s5; }
void h6(std::string s1,std::string s2,std::string s3,std::string s4,std::string s5,std::string s6)
{ v_ = ':'+s1+':'+s2+':'+s3+':'+s4+':'+s5+':'+s6; }
disp(cppcms::service &s) : cppcms::application(s)
{
dispatcher().assign_generic("hg/(.*)",&disp::hg,this);
dispatcher().assign("h0",&disp::h0,this);
dispatcher().assign("h1/(a(\\d+))",&disp::h1,this,2);
dispatcher().assign("h2/(a(\\d+))/(a(\\d+))",&disp::h2,this,2,4);
dispatcher().assign("h3/(a(\\d+))/(a(\\d+))/(a(\\d+))",&disp::h3,this,2,4,6);
dispatcher().assign("h4/(a(\\d+))/(a(\\d+))/(a(\\d+))/(a(\\d+))",&disp::h4,this,2,4,6,8);
dispatcher().assign("h5/(a(\\d+))/(a(\\d+))/(a(\\d+))/(a(\\d+))/(a(\\d+))",&disp::h5,this,2,4,6,8,10);
dispatcher().assign("h6/(a(\\d+))/(a(\\d+))/(a(\\d+))/(a(\\d+))/(a(\\d+))/(a(\\d+))",&disp::h6,this,2,4,6,8,10,12);
}
#define TESTD(x,y) do { main(x); TEST(v_==y); } while(0)
void test()
{
TESTD("hg/x","m:hg/x:x");
TESTD("h0","-");
TESTD("h1/a1",":1");
TESTD("h2/a1/a2",":1:2");
TESTD("h3/a1/a2/a3",":1:2:3");
TESTD("h4/a1/a2/a3/a4",":1:2:3:4");
TESTD("h5/a1/a2/a3/a4/a5",":1:2:3:4:5");
TESTD("h6/a1/a2/a3/a4/a5/a6",":1:2:3:4:5:6");
}
std::string v_;
};

void dispatcher_test(cppcms::service &srv)
{
disp d(srv);
d.test();
}

void basic_test(cppcms::service &srv,bool throws)
{
cppcms::application app(srv);
@@ -288,6 +338,7 @@ int main()
{
try {


std::cout << "- Basics no throw" << std::endl;

cppcms::json::value cfg;
@@ -316,6 +367,9 @@ int main()
std::cout << "- Keyword substitution" << std::endl;
app.test_keywords();

std::cout << "- Dispatcher Test" << std::endl;
dispatcher_test(srv);

}
catch(std::exception const &e) {
std::cerr << "Fail: " << e.what() << std::endl;


Loading…
Cancel
Save