300x250 AD TOP

Search This Blog

Pages

Paling Dilihat

Powered by Blogger.

Showing posts with label templates. Show all posts
Showing posts with label templates. Show all posts

Tuesday, December 13, 2016

Node js C++ Addon Overload Resolution - Refactor & Add C++ Type Converter

Remember node-overload-resolution ?

I've been working on it for a while to see how I can support automatic async support.

I always believed if you can work a little harder to save a lot of time later, its most likely going to pay off, one of the biggest motivation to write the node-overload-resolution project was to easily convert C++ libraries to Node js without changing the API too much.

One of the major roadblocks in the last version of node-overload-resolution to this goal is that v8 objects are not accessible through any other thread other than node js main thread since node doesn't release the locker on v8 vm. To solve this issue I thought and implemented a way to parse and store the v8 objects as their projected C++ objects. in essence copying v8::String to std::string, v8::Number to double and so on.

Some issues I've encountered with this approach is how to store v8 Objects, C++ Class wrappers and Arrays, but if I can actually tell the resolution module which C++ types each v8 type translates to, maybe it could work.

I've been working on this premise and implemented a converter and value holder on top of the working overload resolution module and currently it supports Number, Function, String, Buffer, a typed struct and ObjectWrap.

Currently there are issues with Function, its implemented as or::Callback, but the actual function is not called yet.

Other issues is that I couldn't find a translation for Promise, Proxy and RegExp.

I think this module is on the correct path at the moment, it should be relatively easy to support async function calls by adding a check if the matched function have an additional function callback parameter, caching the parameter value as C++ type, pushing the function call to libuv threadpool and executing the return value conversion and callbacks activation when the thread finishes execution.

You can find the code on the native_types branch.

The code is concentrated in 3 main components, the value_holder, the value_converter and the generic_value_holder. 

The value_holder is a derived template, storing the Value inside a template type.

template<typename T>
class value_holder : public value_holder_base {
public:
    T Value;
    value_holder() : value_holder_base() {}
    value_holder(T val) : value_holder_base(), Value(val) {}
    virtual ~value_holder() {}
};



The value_converter is a derived template with template specialization for each major type handled, the specialization is both for primitives (including v8 basic types) and for derived classes for IStructuredObject and ObjectWrap classes, allowing a more specific behavior for structures and C++ classes, such as parsing/creating new v8 objects as well as ObjectWrap::Wrap and ObjectWrap::Unwrap.

for example, this template specialization is for all derived classes of ObjectWrap, it wraps/unwraps to/from v8::Object:
template<typename T>
class value_converter<T*, typename std::enable_if<std::is_base_of<ObjectWrap, T>::value>::type> : publicvalue_converter_base {
public:

    virtual T* convert(v8::Local<v8::Value> from) {
        return or::ObjectWrap::Unwrap<T>(from.As<v8::Object>());
    }


    virtual v8::Local<v8::Value> convert(T* from) {
        return from->Wrap();
    }

    virtual v8::Local<v8::Value> convert(std::shared_ptr<value_holder_base> from) {
        auto from_value = std::dynamic_pointer_cast<value_holder<T*>>(from);
        return from_value->Value->Wrap();
    }

    virtual std::shared_ptr<value_holder_base> read(v8::Local<v8::Value> val) {
        auto parsed_value = std::make_shared<value_holder<T*>>();
        parsed_value->Value = convert(val);
        return parsed_value;
    }

};

lastly the generic_value_holder stores a pair of value_holder and value_converter and by that it can act as some sort of non-convertible variant that can return a v8 object from intended C++ types.

class generic_value_holder {
private:
    std::shared_ptr< or ::value_converter_base> _prefetcher;
    std::shared_ptr< or ::value_holder_base> _value;
public:
    void Set(std::shared_ptr< or ::value_converter_base> value_converter, std::shared_ptr< or ::value_holder_base> value) {
        _prefetcher = value_converter;
        _value = value;
    }

    template<typename T>
    void Set(T returnValue) {
        //store value_converter type
        auto returnPrefetcher = std::make_shared < or ::value_converter<T>>();

        //store value inside a valueholder
        auto valueHolder = std::make_shared < or ::value_holder<T>>();
        valueHolder->Value = returnValue;

        Set(returnPrefetcher, valueHolder);
    }

    v8::Local<v8::Value> Get() {
        return _prefetcher->convert(_value);
    }
};

Update 2016-12-14:
The automatic async has been partially implemented, at this moment, the tests are working as far as I can see. what happens is that the overload resolution is checking the last argument passed to the function, if its not part of the function parameters and its type is a function, its assumed to be an async request. so the overload resolution engine stores all the function arguments in memory as C++ objects, calls the function and post process the return value and lastly calls the callback function supplied.

for example, assuming you have a function test(arg1 : string, arg2 : number), if a match is found that contains test("a",1), it will execute the function synchronously. But if a match is found as test("a",1,function(err,val){}), it will be executed asynchronously (note that there is no way to know which parameters are defined for function(err,val), so the example above is for clarity sake.

The functions implementation have to use info.at<T>(index) to read the parameters and have to use info.SetReturnValue<T>(value) to return a value, otherwise the implementation will fail because node js keeps the vm locked and there's no access to v8 objects through normal info[index] mechanism, if the implementer insists on using info[index], an access violation will occur and the application will crash when executing as async.

TODO:
- Finish the callback implementation.
- Implement Async call detection and execution - partial.
- This() access from inside a class member function
- cleanup
Tags: , , , ,

Tuesday, August 21, 2012

NVelocity Template Engine

Note: The NVelocity project was abandoned in 2009, I've wanted to write this article back in November 2010, but I've found a few minutes only recently and in the hope its not a complete waste of time, here you have it with a some modifications and updates.

Velocity was one of the more advanced string templating engines around that time, it didn't take long to port it to .NET which became NVelocity. if you're porting an old application and need a transition time that all your templates will work before you can convert them to one of the more recent and advanced templating engines such as Razor, you may have found the demo program you needed.

I've tried both Castle NVelocity and Terri Liang's NVelocity port, I'm not sure which came before which, if one is an improvement of the other, but I needed something that supports recursive macros and string templates (instead of file/resource templates) which Castle didn't, so I've used the one from Terri Liang, which did.

Apache's velocity has the documentation for the syntax.

First instantiate a new engine:


NVelocity.App.VelocityEngine engine = new NVelocity.App.VelocityEngine();

//set log class type
engine.SetProperty(NVelocity.Runtime.RuntimeConstants.RUNTIME_LOG_LOGSYSTEM_CLASS, typeof(TemplateEngineLog));

//switch to local context, this way each macro/recursive execution uses its own variables.
engine.SetProperty(NVelocity.Runtime.RuntimeConstants.VM_CONTEXT_LOCALSCOPE, "true");

//allows #set to accept null values in the right hand side.
engine.SetProperty(NVelocity.Runtime.RuntimeConstants.SET_NULL_ALLOWED, "true");

//set template resource loader to strings
engine.SetProperty("resource.loader", "string");
engine.SetProperty("string.resource.loader.class", "NVelocity.Runtime.Resource.Loader.StringResourceLoader");

//initialize engine.
engine.Init();


Then assign a new logger if error reporting is desired:


TemplateEngineLog log = new TemplateEngineLog();
engine.SetProperty(NVelocity.Runtime.RuntimeConstants.RUNTIME_LOG_LOGSYSTEM, log);


Then create a context, its similar to ViewData:


//create a context
NVelocity.VelocityContext vcontext = new NVelocity.VelocityContext();

//put default values
vcontext.Put("null", null);
vcontext.Put("true", true);

//add the context values
foreach (var key in context.Keys)
    vcontext.Put(key, context[key]);


Then we have two options, either a one time execution of a template with this:


engine.Evaluate(vcontext, sw, "", template)


or multiple executions - meaning, the template will be compiled  so it will execute a lot faster:


//gets the string resource repository
var repo = NVelocity.Runtime.Resource.Loader.StringResourceLoader.GetRepository();
Guid guidcode = Guid.NewGuid();

//puts a new template inside it
repo.PutStringResource(guidcode.ToString(), template);

nvtemplate = engine.GetTemplate(guidcode.ToString(), "UTF-8");


and for the execution:


//merge uses a saved template
nvtemplate.Merge(vcontext, sw);


The demo project is located at:
https://github.com/drorgl/ForBlog/tree/master/NVelocityDemo
Tags: , ,

Monday, May 16, 2011

Using Razor Templates In Your Application

We needed a templating engine that will work in a medium trust environment, after reviewing StringTemplate and NVelocity and we came to the conclusion that Razor can do all we need and more, plus it comes with the framework so no need for external dependencies.

You should be aware that Razor is compiling .NET code, it can and will create security breeches in your application if you allow users to change the templates, you can alleviate some of these security issues by segregating your code and giving the razor section access only to the parts it needs, think this through.

The project contains a few important parts.
1. It should have its own TemplatesController, its just an empty controller for the engine to run against.
2. Templates views directory, this is where we're storing the templates for the engine to execute.
3. Templates.cs is where some of the magic happens.
4. For the sake of the demo, I've added a custom WebViewPage called RazorBaseWebViewPage and a SimpleModel.


Templates.cs contains the following:
1. Execute - executes a view against a controller, with ViewData and Model.


/// <summary>
/// Generates a controller and context, hands them off to be rendered by the view engine and 
/// returns the result string
/// </summary>
/// <param name="viewName">Template Name</param>
/// <param name="model">Model for the view</param>
/// <param name="viewData">ViewData</param>
/// <returns>rendered string</returns>
private static string Execute(string viewName, ViewDataDictionary viewData, object model)
{
    var controller = new TemplatesController();
    controller.ControllerContext = new ControllerContext();
    controller.ControllerContext.HttpContext = new HttpContextWrapper(HttpContext.Current);
    controller.RouteData.DataTokens.Add("controller", "Templates");
    controller.RouteData.Values.Add("controller", "Templates");
    controller.ViewData = viewData;
    return RenderView(controller, viewName, model);
}


2. GetViewName - gets or writes a new template to the templates directory, it uses a hash of the template for the first part of the filename. Same trick as a hash table.


/// <summary>
/// Retrieves the view name by template and model
/// </summary>
private static string GetViewName(string template,Type modelType)
{
    //gets the razor template from a text template
    var razortemplate = GetViewContentFromTemplate(template, modelType);

    //gets the hash string from the razor template
    string hashstring = BitConverter.ToString(BitConverter.GetBytes(razortemplate.GetHashCode()));

    //check if view exists in folder
    var files = Directory.GetFiles(ViewDirectory, hashstring + "*.cshtml");
    foreach (var file in files)
    {
        if (File.ReadAllText(file, Encoding.UTF8) == razortemplate)
            return Path.GetFileNameWithoutExtension(file);
    }

    //if not, add it
    string filename = Path.Combine(ViewDirectory, hashstring + "_" + Guid.NewGuid().ToString() + ".cshtml");
    File.WriteAllText(filename, razortemplate,Encoding.UTF8);

    return Path.GetFileNameWithoutExtension(filename);
}


3. RenderView - calls the razor engine's Render. executed from Execute. (Origin)


/// <summary>
/// Renders a PartialView to String
/// </summary>
private static string RenderView(Controller controller, string viewName, object model)
{
    //origin http://craftycodeblog.com/2010/05/15/asp-net-mvc-render-partial-view-to-string/
    if (string.IsNullOrEmpty(viewName))
    {
        return string.Empty;
    }

    controller.ViewData.Model = model;
    try
    {
        StringBuilder sb = new StringBuilder();
        using (StringWriter sw = new StringWriter(sb))
        {
            IView viewResult = GetPartialView(controller, viewName);
            ViewContext viewContext = new ViewContext(controller.ControllerContext, viewResult, controller.ViewData, controller.TempData, sw);
            viewResult.Render(viewContext, sw);
        }
        return sb.ToString();

    }
    catch (Exception ex)
    {
        return ex.ToString();
    }
}


4. Render - the exposed method to do the actual rendering.


/// <summary>
/// Renders a template with parameters to string
/// </summary>
/// <param name="template">template text to render</param>
/// <param name="model">the model to give the template</param>
/// <param name="parameters">the ViewData for the execution</param>
/// <returns>rendered template</returns>
public static string Render(string template, object model, ViewDataDictionary parameters)
{
    //if empty
    if (string.IsNullOrEmpty(template))
        return string.Empty;

    //if doesn't contain razor code
    if (template.IndexOf("@") == -1)
        return template;

    //get View filename
    string fileName = GetViewName(template, (model != null) ? model.GetType() : typeof(object));

    //Execute template
    return Execute(fileName, parameters, model);
}



I've ran some analysis on the code's performance, a few places might be helpful to optimize is the GetPartialView and GetViewName are slow.

You can find the project here:
https://github.com/drorgl/ForBlog/tree/master/RazorTemplateDemo
Tags: , ,