diff --git a/uppsrc/Skylark/Compile.cpp b/uppsrc/Skylark/Compile.cpp index f34aa5c66..9530e18c6 100644 --- a/uppsrc/Skylark/Compile.cpp +++ b/uppsrc/Skylark/Compile.cpp @@ -89,6 +89,8 @@ One Compiler::Prim() if(p.Char('@')) id = "@"; id << p.ReadId(); + while(p.Char(':')) + id << ':' << p.ReadId(); int n = var.Find(id); if(p.Char('(')) { Value (*f)(const Vector&, const Renderer *) = functions().Get(id, NULL); diff --git a/uppsrc/Skylark/Dispatch.cpp b/uppsrc/Skylark/Dispatch.cpp index 16b763197..dcbddfb09 100644 --- a/uppsrc/Skylark/Dispatch.cpp +++ b/uppsrc/Skylark/Dispatch.cpp @@ -1,9 +1,17 @@ #include "Skylark.h" -#define LLOG(x) //DLOG(x) -#define LDUMP(x) //DDUMP(x) -#define LDUMPC(x) //DDUMPC(x) -#define LDUMPM(x) //DDUMPM(x) +#if 0 +#define LLOG(x) DLOG(x) +#define LDUMP(x) DDUMP(x) +#define LDUMPC(x) DDUMPC(x) +#define LDUMPM(x) DDUMPM(x) +#else +#define LLOG(x) +#define LDUMP(x) +#define LDUMPC(x) +#define LDUMPM(x) +#endif + #define LTIMING(x) //RTIMING(x) namespace Upp { @@ -49,10 +57,15 @@ void DumpDispatchMap() String sub; for(int j = 0; j < DispatchMap[i].subnode.GetCount(); j++) sub << DispatchMap[i].subnode.GetKey(j) << "->" << DispatchMap[i].subnode[j] << ", "; - LLOG(i << " " << (bool)DispatchMap[i].view << ": " << sub); + LLOG(i << " " << (bool)DispatchMap[i].handler << ": " << sub); } } +String SkylarkAppendPath__(const String& path_prefix, const String& path) +{ + return path_prefix.GetCount() ? path_prefix + '/' + path : path; +} + Vector *GetUrlViewLinkParts(const String& id) { int q = sLinkMap().Find(id); @@ -61,9 +74,8 @@ Vector *GetUrlViewLinkParts(const String& id) return &sLinkMap()[q]; } -String MakeLink(void (*view)(Http&), const Vector& arg) +String MakeLink0(int q, const Vector& arg) { - int q = sHandlerIndex().Find((uintptr_t)view); if(q < 0) throw Exc("Invalid view"); if(q < 0) @@ -73,13 +85,18 @@ String MakeLink(void (*view)(Http&), const Vector& arg) return out; } +String MakeLink(const HandlerId& id, const Vector& arg) +{ + return MakeLink0(id.handler ? sHandlerIndex().Find((uintptr_t)id.handler) : sLinkMap().Find(id.id), arg); +} + void RegisterView0(void (*fn)(Http&), Callback1 cb, const char *id, String path, bool primary) { - LLOG("RegisterView " << path); + LLOG("RegisterView " << id << " -> " << path); ASSERT_(sLinkMap().Find(id) < 0, "duplicate handler id " + String(id)); Vector& linkpart = sLinkMap().GetAdd(id); ASSERT_(!fn || sHandlerIndex().Find((uintptr_t)fn) < 0, "duplicate view function registration " + String(id)); - sHandlerIndex().FindAdd((uintptr_t)fn); + sHandlerIndex().Add((uintptr_t)fn); Vector& DispatchMap = sDispatchMap(); int method = DispatchNode::GET; bool post_raw = false; @@ -142,6 +159,8 @@ struct HandlerData { // temporary storage of handlers until FinalizeViews call Callback1 cb; String id; String path; + + HandlerData() { fn = NULL; } }; static Array& sHandlerData() @@ -342,7 +361,7 @@ void Http::Dispatch(TcpSocket& socket) var.GetAdd(".__lang__") = lang; var.GetAdd(".language") = ToLower(LNGAsText(lang)); handlerid = bd.id; - LDUMP(viewid); + LDUMP(handlerid); bd.handler(*this); if(session_dirty) SaveSession(); diff --git a/uppsrc/Skylark/Http.cpp b/uppsrc/Skylark/Http.cpp index bf0291800..f4dfb4871 100644 --- a/uppsrc/Skylark/Http.cpp +++ b/uppsrc/Skylark/Http.cpp @@ -309,33 +309,33 @@ Http& Http::RenderResult(const char *template_name) return *this; } -Http& Http::Redirect(void (*view)(Http&), const Vector& arg) +Http& Http::Redirect(const HandlerId& handler, const Vector& arg) { - Redirect(MakeLink(view, arg)); + Redirect(MakeLink(handler, arg)); return *this; } -Http& Http::Redirect(void (*view)(Http&)) +Http& Http::Redirect(const HandlerId& handler) { Vector arg; - Redirect(view, arg); + Redirect(handler, arg); return *this; } -Http& Http::Redirect(void (*view)(Http&), const Value& v1) +Http& Http::Redirect(const HandlerId& handler, const Value& v1) { Vector arg; arg.Add(v1); - Redirect(view, arg); + Redirect(handler, arg); return *this; } -Http& Http::Redirect(void (*view)(Http&), const Value& v1, const Value& v2) +Http& Http::Redirect(const HandlerId& handler, const Value& v1, const Value& v2) { Vector arg; arg.Add(v1); arg.Add(v2); - Redirect(view, arg); + Redirect(handler, arg); return *this; } diff --git a/uppsrc/Skylark/Http.h b/uppsrc/Skylark/Http.h index c7665d361..c10af802c 100644 --- a/uppsrc/Skylark/Http.h +++ b/uppsrc/Skylark/Http.h @@ -1,16 +1,29 @@ void MakeLink(StringBuffer& out, const Vector& part, const Vector& arg); +struct HandlerId { + void (*handler)(Http& http); + String id; + + HandlerId(const char *id) : id(id) { handler = NULL; } + HandlerId(void (*handler)(Http& http)) : handler(handler) {} + + HandlerId() { handler = NULL; } +}; + class Renderer { protected: VectorMap var; int lang; - Renderer& Link(const char *id, void (*view)(Http&), const Vector& arg); + Renderer& Link(const char *id, const HandlerId& handler, const Vector& arg); const One& GetTemplate(const char *template_name); public: Renderer& operator()(const char *id, const Value& v) { var.Add(id, v); return *this; } Renderer& operator()(const ValueMap& map); + Renderer& operator()(const char *id, const HandlerId& handler); + Renderer& operator()(const char *id, const HandlerId& handler, const Value& arg1); + Renderer& operator()(const char *id, const HandlerId& handler, const Value& arg1, const Value& arg2); Renderer& operator()(const char *id, void (*handler)(Http&)); Renderer& operator()(const char *id, void (*handler)(Http&), const Value& arg1); Renderer& operator()(const char *id, void (*handler)(Http&), const Value& arg1, const Value& arg2); @@ -69,6 +82,9 @@ class Http : public Renderer { public: Http& operator()(const char *id, const Value& v) { var.Add(id, v); return *this; } Http& operator()(const ValueMap& map) { Renderer::operator()(map); return *this; } + Http& operator()(const char *id, const HandlerId& handler) { Renderer::operator()(id, handler); return *this; } + Http& operator()(const char *id, const HandlerId& handler, const Value& arg1) { Renderer::operator()(id, handler, arg1); return *this; } + Http& operator()(const char *id, const HandlerId& handler, const Value& arg1, const Value& arg2) { Renderer::operator()(id, handler, arg1, arg2); return *this; } Http& operator()(const char *id, void (*handler)(Http&)) { Renderer::operator()(id, handler); return *this; } Http& operator()(const char *id, void (*handler)(Http&), const Value& arg1) { Renderer::operator()(id, handler, arg1); return *this; } Http& operator()(const char *id, void (*handler)(Http&), const Value& arg1, const Value& arg2) { Renderer::operator()(id, handler, arg1, arg2); return *this; } @@ -119,10 +135,10 @@ public: Http& RenderResult(const char *template_name); Http& Redirect(const char *url, int code_ = 302) { code = code_; redirect = url; return *this; } - Http& Redirect(void (*handler)(Http&), const Vector& arg); - Http& Redirect(void (*handler)(Http&)); - Http& Redirect(void (*handler)(Http&), const Value& v1); - Http& Redirect(void (*handler)(Http&), const Value& v1, const Value& v2); + Http& Redirect(const HandlerId& handler, const Vector& arg); + Http& Redirect(const HandlerId& handler); + Http& Redirect(const HandlerId& handler, const Value& v1); + Http& Redirect(const HandlerId& handler, const Value& v1, const Value& v2); Http& Ux(const char *id, const String& text); Http& UxRender(const char *id, const char *template_name); @@ -145,8 +161,31 @@ void RegisterHandler(Callback1 handler, const char *id, const char *path) Vector *GetUrlViewLinkParts(const String& id); -String MakeLink(void (*handler)(Http&), const Vector& arg); +String MakeLink(const HandlerId& id, const Vector& arg); enum { SESSION_FORMAT_BINARY, SESSION_FORMAT_JSON, SESSION_FORMAT_XML }; + +struct SkylarkPack { + String instance_id; + String instance_path; +}; + +String SkylarkAppendPath__(const String& path_prefix, const String& path); + +#define SKYLARK_USE(cls, id, path) \ +static void cls##_##id##_##init(cls& id); \ +INITBLOCK { \ + static cls id; \ + id.instance_id = #id; \ + id.instance_path = path; \ + cls##_##id##_##init(id); \ + id.Use(); \ +} \ +static void cls##_##id##_##init(cls& id) + +#define SKYLARK_METHOD(method, path) \ +RegisterHandler(THISBACK(method), instance_id + ':' + #method, SkylarkAppendPath__(instance_path, path)) + +#define THISLINK(x) HandlerId(instance_id + ':' + #x) diff --git a/uppsrc/Skylark/Renderer.cpp b/uppsrc/Skylark/Renderer.cpp index 43c38e0ea..bcd25d911 100644 --- a/uppsrc/Skylark/Renderer.cpp +++ b/uppsrc/Skylark/Renderer.cpp @@ -14,25 +14,40 @@ Renderer& Renderer::operator()(const ValueMap& map) return *this; } -Renderer& Renderer::Link(const char *id, void (*view)(Http&), const Vector& arg) +Renderer& Renderer::Link(const char *id, const HandlerId& handler, const Vector& arg) { - var.Add(id, Raw('\"' + MakeLink(view, arg) + '\"')); + var.Add(id, Raw('\"' + MakeLink(handler, arg) + '\"')); return *this; } -Renderer& Renderer::operator()(const char *id, void (*view)(Http&)) +Renderer& Renderer::operator()(const char *id, const HandlerId& handler) { - return Link(id, view, Vector()); + return Link(id, handler, Vector()); } -Renderer& Renderer::operator()(const char *id, void (*view)(Http&), const Value& arg1) +Renderer& Renderer::operator()(const char *id, const HandlerId& handler, const Value& arg1) { - return Link(id, view, Vector() << arg1); + return Link(id, handler, Vector() << arg1); } -Renderer& Renderer::operator()(const char *id, void (*view)(Http&), const Value& arg1, const Value& arg2) +Renderer& Renderer::operator()(const char *id, const HandlerId& handler, const Value& arg1, const Value& arg2) { - return Link(id, view, Vector() << arg1 << arg2); + return Link(id, handler, Vector() << arg1 << arg2); +} + +Renderer& Renderer::operator()(const char *id, void (*handler)(Http&)) +{ + return operator()(id, HandlerId(handler)); +} + +Renderer& Renderer::operator()(const char *id, void (*handler)(Http&), const Value& arg1) +{ + return operator()(id, HandlerId(handler), arg1); +} + +Renderer& Renderer::operator()(const char *id, void (*handler)(Http&), const Value& arg1, const Value& arg2) +{ + return operator()(id, HandlerId(handler), arg1, arg2); } Renderer& Renderer::SetLanguage(int lang_)