Upgrade to Pro — share decks privately, control downloads, hide ads and more …

node-ffi

othree
October 12, 2014

 node-ffi

othree

October 12, 2014
Tweet

More Decks by othree

Other Decks in Technology

Transcript

  1. Sample 1/2 n = r3_tree_create(10);! ! int route_data = 3;!

    ! r3_tree_insert_routel(n, METHOD_GET, "/blog/post", ! sizeof("/blog/post") - 1, &route_data );! ! int err = r3_tree_compile(n, &errstr);
  2. Sample 1/2 n = r3_tree_create(10);! ! int route_data = 3;!

    ! r3_tree_insert_routel(n, METHOD_GET, "/blog/post", ! sizeof("/blog/post") - 1, &route_data );! ! int err = r3_tree_compile(n, &errstr); Create Tree
  3. Sample 1/2 n = r3_tree_create(10);! ! int route_data = 3;!

    ! r3_tree_insert_routel(n, METHOD_GET, "/blog/post", ! sizeof("/blog/post") - 1, &route_data );! ! int err = r3_tree_compile(n, &errstr); Insert Route
  4. Sample 1/2 n = r3_tree_create(10);! ! int route_data = 3;!

    ! r3_tree_insert_routel(n, METHOD_GET, "/blog/post", ! sizeof("/blog/post") - 1, &route_data );! ! int err = r3_tree_compile(n, &errstr); Data
  5. Sample 1/2 n = r3_tree_create(10);! ! int route_data = 3;!

    ! r3_tree_insert_routel(n, METHOD_GET, "/blog/post", ! sizeof("/blog/post") - 1, &route_data );! ! int err = r3_tree_compile(n, &errstr); Compile
  6. Sample 2/2 match_entry * entry = match_entry_create("/blog/post");! entry->request_method = METHOD_GET;!

    ! route *matched_route = r3_tree_match_route(n, entry);! matched_route->data; // The Data! ! match_entry_free(entry);! r3_tree_free(n);
  7. Sample 2/2 match_entry * entry = match_entry_create("/blog/post");! entry->request_method = METHOD_GET;!

    ! route *matched_route = r3_tree_match_route(n, entry);! matched_route->data; // The Data! ! match_entry_free(entry);! r3_tree_free(n); Create Entry
  8. Sample 2/2 match_entry * entry = match_entry_create("/blog/post");! entry->request_method = METHOD_GET;!

    ! route *matched_route = r3_tree_match_route(n, entry);! matched_route->data; // The Data! ! match_entry_free(entry);! r3_tree_free(n); Match Route
  9. Sample 2/2 match_entry * entry = match_entry_create("/blog/post");! entry->request_method = METHOD_GET;!

    ! route *matched_route = r3_tree_match_route(n, entry);! matched_route->data; // The Data! ! match_entry_free(entry);! r3_tree_free(n); Route Data
  10. Sample 2/2 match_entry * entry = match_entry_create(“/blog/post/1/2/3“);! entry->request_method = METHOD_GET;

    // Method Condition! ! route *matched_route = r3_tree_match_route(n, entry);! ! matched_route->data; // The Data! entry->vars; //Captured Vars, a string array! ! r3_tree_free(n);
  11. __cdecl val = sumExample(2,3) ; // push arguments to the

    stack, from right to left! push 3 ! push 2 ! ! ; // call the function! call _sumExample ! ! ; // cleanup the stack by adding the size of the arguments to! ; // ESP register! add esp,8 ! ! ; // copy the return value from EAX to a local variable (int c)! mov dword ptr [c],eax
  12. Example var ffi = require('ffi');! ! var libm = ffi.Library('libm',

    {! 'ceil': [ 'double', [ 'double' ] ]! });! ! libm.ceil(1.5); // 2
  13. Example var ffi = require('ffi');! ! var libm = ffi.Library('libm',

    {! 'ceil': [ 'double', [ 'double' ] ]! });! ! libm.ceil(1.5); // 2 Library name! Use dlopen
  14. Example var ffi = require('ffi');! ! var libm = ffi.Library('libm',

    {! 'ceil': [ 'double', [ 'double' ] ]! });! ! libm.ceil(1.5); // 2 A function named ‘ceil’ return double
 Take one double parameter
  15. Example var ffi = require('ffi');! ! var libm = ffi.Library('libm',

    {! 'ceil': [ 'double', [ 'double' ] ]! });! ! libm.ceil(1.5); // 2 return type
  16. Example var ffi = require('ffi');! ! var libm = ffi.Library('libm',

    {! 'ceil': [ 'double', [ 'double' ] ]! });! ! libm.ceil(1.5); // 2 arguments type
  17. Types void bool byte pointer (u)short (u)int (u)int16 (u)int32 (u)int64

    (u)longlong size_t float (u)char string object
  18. Example var ffi = require('ffi');! ! var libm = ffi.Library('libm',

    {! 'ceil': [ 'double', [ 'double' ] ]! });! ! libm.ceil(1.5); // 2 Call ceil
  19. struct _edge {! char * pattern; // 8 bytes! node

    * child; // 8 bytes! unsigned char pattern_len; // 1 byte! unsigned char opcode:4; // 4 bit! unsigned char has_slug:1; // 1 bit! }; var StructType = require('ref-struct');! ! var edge = StructType({! pattern: "string",! child: "pointer",! pattern_len: "ushort",! opcode: "uchar",! has_slug: "uchar"! });
  20. ref-struct ˖ $SFBUF"#*DPNQMJBOUTUSVDUJOTUBODFTPOUPQPG #VFST ˖ "#* "QQMJDBUJPO#JOBSZ*OUFSGBDF  ˖ UIFTJ[FT

    MBZPVU BOEBMJHONFOUPGEBUBUZQFT ˖  https://en.wikipedia.org/wiki/Application_binary_interface
  21. typedef struct {! str_array * vars;! const char * path;

    // current path to dispatch! int path_len; // the length of the current path! int request_method; // current request method! void * data; // route ptr! char * host; // the request host! ! ...
  22. typedef struct {! str_array * vars;! const char * path;

    // current path to dispatch! int path_len; // the length of the current path! int request_method; // current request method! void * data; // route ptr! char * host; // the request host! ! ... var ref = require('ref');! ! var str_array = StructType({ ... });! ! var match_entry = StructType({! vars: ref.refType(str_array),! path: "string",! path_len: "int",! request_method: "int",! data: "pointer",! host: "pointer",! ...
  23. #define r3_tree_insert_path(n,p,d) r3_tree_insert_pathl_ex(n,p,s var libr3 = ffi.Library('libr3', {! "r3_tree_insert_pathl_ex": ["pointer",

    ["pointer", "string", " });! ! ! var r3_tree_insert_path = function (tree, path, data) {! return libr3.r3_tree_insert_pathl_ex(tree, path, path.length, };
  24. Example 1/2 var tree = libr3.r3_tree_create(10);! ! var data =

    new Buffer(data_str + '\u0000');! ! r3_tree_insert_route(tree, 'GET','/path', data);
  25. Example 2/2 var node = libr3.r3_tree_match_route(tree, entry);! ! var data

    = ref.deref(node).data; https://github.com/othree/node-r3/blob/46e29f72bbf68097ed66fd151f9ef42d5a3ede05/node-r3.js
  26. BUT

  27. data = new Buffer(data + '\u0000');! r3_tree_insert_path(this.tree, route, data); var

    node = r3_tree_match(this.tree, path, entry);! ! var data = ref.readCString(node.deref().data, 0);
  28. var i = this.i++;! this.data[i] = data;! ! var iref

    = ref.alloc('int', i);! ! libr3.r3_tree_insert_route(this.tree, method, route, iref); var node = libr3.r3_tree_match_route(this.tree, entry);! ! var index = node.deref().data.reinterpret(4).readUInt32LE(0);! ! var data = this.data[index];
  29. var i = this.i++;! this.data[i] = data;! ! var iref

    = ref.alloc('int', i);! ! libr3.r3_tree_insert_route(this.tree, method, route, iref); var node = libr3.r3_tree_match_route(this.tree, entry);! ! var index = node.deref().data.reinterpret(4).readUInt32LE(0);! ! var data = this.data[index]; Store Data
  30. var i = this.i++;! this.data[i] = data;! ! var iref

    = ref.alloc('int', i);! ! libr3.r3_tree_insert_route(this.tree, method, route, iref); var node = libr3.r3_tree_match_route(this.tree, entry);! ! var index = node.deref().data.reinterpret(4).readUInt32LE(0);! ! var data = this.data[index]; Data for r3
  31. var i = this.i++;! this.data[i] = data;! ! var iref

    = ref.alloc('int', i);! ! libr3.r3_tree_insert_route(this.tree, method, route, iref); var node = libr3.r3_tree_match_route(this.tree, entry);! ! var index = node.deref().data.reinterpret(4).readUInt32LE(0);! ! var data = this.data[index]; Resize Buffer
  32. var i = this.i++;! this.data[i] = data;! ! var iref

    = ref.alloc('int', i);! ! libr3.r3_tree_insert_route(this.tree, method, route, iref); var node = libr3.r3_tree_match_route(this.tree, entry);! ! var index = node.deref().data.reinterpret(4).readUInt32LE(0);! ! var data = this.data[index]; Read Index
  33. How About Foreign Calls ˖ 8IBUXFVTFE ˖ S@USFF@DSFBUF S@USFF@GSFF ˖

    S@USFF@JOTFSU@QBUI ˖ S@USFF@DPNQJMF ˖ NBUDI@FOUSZ@DSFBUF NBUDI@FOUSZ@GSFF ˖ S@USFF@NBUDI@SPVUF
  34. var Router = function (routes) {! var route, data, method,

    route_frag, i = 0;! this.tree = libr3.r3_tree_create(10);! this.data = [];! for (route in routes) {! this.data[i] = routes[route];! data = ref.alloc('int', i);! route = route.trim();! route_frag = route.split(' ');! if (route_frag.length > 1) {! route = route_frag[1];! method = METHODS[route_frag[0].toUpperCase()];! if (!method) { throw new Error(route_frag[0]); }! r3_tree_insert_route(this.tree, method, route, data);! } else {! r3_tree_insert_route(this.tree, 0, route, data);! }! i++;! }! libr3.r3_tree_compile(this.tree);! return this;! };
  35. var Router = function (routes) {! var route, data, method,

    route_frag, i = 0;! this.tree = libr3.r3_tree_create(10);! this.data = [];! for (route in routes) {! this.data[i] = routes[route];! data = ref.alloc('int', i);! route = route.trim();! route_frag = route.split(' ');! if (route_frag.length > 1) {! route = route_frag[1];! method = METHODS[route_frag[0].toUpperCa if (!method) { throw new Error(route_fra r3_tree_insert_route(this.tree, method, } else {! r3_tree_insert_route(this.tree, 0, route }! i++;! }! libr3.r3_tree_compile(this.tree);! return this;! }; WBSJBCMFT
  36. var Router = function (routes) {! var route, data, method,

    route_frag, i = 0;! this.tree = libr3.r3_tree_create(10);! this.data = [];! for (route in routes) {! this.data[i] = routes[route];! data = ref.alloc('int', i);! route = route.trim();! route_frag = route.split(' ');! if (route_frag.length > 1) {! route = route_frag[1];! method = METHODS[route_frag[0].toUpperCa if (!method) { throw new Error(route_fra r3_tree_insert_route(this.tree, method, } else {! r3_tree_insert_route(this.tree, 0, route }! i++;! }! libr3.r3_tree_compile(this.tree);! return this;! }; DSFBUFUSFF
  37. var Router = function (routes) {! var route, data, method,

    route_frag, i = 0;! this.tree = libr3.r3_tree_create(10);! this.data = [];! for (route in routes) {! this.data[i] = routes[route];! data = ref.alloc('int', i);! route = route.trim();! route_frag = route.split(' ');! if (route_frag.length > 1) {! route = route_frag[1];! method = METHODS[route_frag[0].toUpperCa if (!method) { throw new Error(route_fra r3_tree_insert_route(this.tree, method, } else {! r3_tree_insert_route(this.tree, 0, route }! i++;! }! libr3.r3_tree_compile(this.tree);! return this;! }; EBUBTUPSBHF
  38. var Router = function (routes) {! var route, data, method,

    route_frag, i = 0;! this.tree = libr3.r3_tree_create(10);! this.data = [];! for (route in routes) {! this.data[i] = routes[route];! data = ref.alloc('int', i);! route = route.trim();! route_frag = route.split(' ');! if (route_frag.length > 1) {! route = route_frag[1];! method = METHODS[route_frag[0].toUpperCa if (!method) { throw new Error(route_fra r3_tree_insert_route(this.tree, method, } else {! r3_tree_insert_route(this.tree, 0, route }! i++;! }! libr3.r3_tree_compile(this.tree);! return this;! }; QBSTFSPVUFT
  39. var Router = function (routes) {! var route, data, method,

    route_frag, i = 0;! this.tree = libr3.r3_tree_create(10);! this.data = [];! for (route in routes) {! this.data[i] = routes[route];! data = ref.alloc('int', i);! route = route.trim();! route_frag = route.split(' ');! if (route_frag.length > 1) {! route = route_frag[1];! method = METHODS[route_frag[0].toUpperCa if (!method) { throw new Error(route_fra r3_tree_insert_route(this.tree, method, } else {! r3_tree_insert_route(this.tree, 0, route }! i++;! }! libr3.r3_tree_compile(this.tree);! return this;! }; DSFBUFJOEFY
  40. var Router = function (routes) {! var route, data, method,

    route_frag, i = 0;! this.tree = libr3.r3_tree_create(10);! this.data = [];! for (route in routes) {! this.data[i] = routes[route];! data = ref.alloc('int', i);! route = route.trim();! route_frag = route.split(' ');! if (route_frag.length > 1) {! route = route_frag[1];! method = METHODS[route_frag[0].toUpperCa if (!method) { throw new Error(route_fra r3_tree_insert_route(this.tree, method, } else {! r3_tree_insert_route(this.tree, 0, route }! i++;! }! libr3.r3_tree_compile(this.tree);! return this;! }; QBSTFTUSJOH
  41. var Router = function (routes) {! var route, data, method,

    route_frag, i = 0;! this.tree = libr3.r3_tree_create(10);! this.data = [];! for (route in routes) {! this.data[i] = routes[route];! data = ref.alloc('int', i);! route = route.trim();! route_frag = route.split(' ');! if (route_frag.length > 1) {! route = route_frag[1];! method = METHODS[route_frag[0].toUpperCa if (!method) { throw new Error(route_fra r3_tree_insert_route(this.tree, method, } else {! r3_tree_insert_route(this.tree, 0, route }! i++;! }! libr3.r3_tree_compile(this.tree);! return this;! }; NFUIPEDPOEJUJPO
  42. var Router = function (routes) {! var route, data, method,

    route_frag, i = 0;! this.tree = libr3.r3_tree_create(10);! this.data = [];! for (route in routes) {! this.data[i] = routes[route];! data = ref.alloc('int', i);! route = route.trim();! route_frag = route.split(' ');! if (route_frag.length > 1) {! route = route_frag[1];! method = METHODS[route_frag[0].toUpperCa if (!method) { throw new Error(route_fra r3_tree_insert_route(this.tree, method, } else {! r3_tree_insert_route(this.tree, 0, route }! i++;! }! libr3.r3_tree_compile(this.tree);! return this;! }; JOTFSUSPVUF
  43. var Router = function (routes) {! var route, data, method,

    route_frag, i = 0;! this.tree = libr3.r3_tree_create(10);! this.data = [];! for (route in routes) {! this.data[i] = routes[route];! data = ref.alloc('int', i);! route = route.trim();! route_frag = route.split(' ');! if (route_frag.length > 1) {! route = route_frag[1];! method = METHODS[route_frag[0].toUpperCa if (!method) { throw new Error(route_fra r3_tree_insert_route(this.tree, method, } else {! r3_tree_insert_route(this.tree, 0, route }! i++;! }! libr3.r3_tree_compile(this.tree);! return this;! }; DPNQJMFUSFF
  44. var Router = function (routes) {! var route, data, method,

    route_frag, i = 0;! this.tree = libr3.r3_tree_create(10);! this.data = [];! for (route in routes) {! this.data[i] = routes[route];! data = ref.alloc('int', i);! route = route.trim();! route_frag = route.split(' ');! if (route_frag.length > 1) {! route = route_frag[1];! method = METHODS[route_frag[0].toUpperCase()];! if (!method) { throw new Error(route_frag[0]); }! r3_tree_insert_route(this.tree, method, route, data);! } else {! r3_tree_insert_route(this.tree, 0, route, data);! }! i++;! }! libr3.r3_tree_compile(this.tree);! return this;! };
  45. var Router = function (routes) {! var route, data, method,

    route_frag, i = 0;! this.tree = libr3.r3_tree_create(10);! this.data = [];! this.index = [];! for (route in routes) {! this.data[i] = routes[route];! data = ref.alloc('int', i);! this.index[i] = data; // prevent GC! route = route.trim();! route_frag = route.split(' ');! if (route_frag.length > 1) {! route = route_frag[1];! method = METHODS[route_frag[0].toUpperCase()];! if (!method) { throw new Error(route_frag[0]); }! r3_tree_insert_route(this.tree, method, route, data);! } else {! r3_tree_insert_route(this.tree, 0, route, data);! }! i++;! }! libr3.r3_tree_compile(this.tree);! return this;! };
  46. var Router = require('node-r3').Router;! ! var router = new Router({!

    "/foo": "data string",! "/foo/bar": function () {},! "/foo/bar/qoo": {obj: 1},! });! ! var dispatched = router.match("/foo");! ! router.free();
  47. var router = new Router({! "/": handler,! "/foo": fooHandler,! "/foo/{id}":

    fooHandler,! "POST /me": postMeHandler,! "GET /me": getMeHandler,! "POST|GET /post": postHandler,! });! ! var server = http.createServer(! router.httpHandler(notfound)! );