├── .editorconfig ├── .gitignore ├── LICENSE.txt ├── README.md ├── binding.gyp ├── macros.h ├── node_xslt.cc ├── package.json ├── scopeguard.h └── wscript /.editorconfig: -------------------------------------------------------------------------------- 1 | # http://editorconfig.org 2 | root = true 3 | 4 | [{package.json,README.md}] 5 | indent_size = 2 6 | indent_style = space 7 | end_of_line = lf 8 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | build/ 2 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2011 Brian Suh 2 | 3 | This software is provided 'as-is', without any express or implied 4 | warranty. In no event will the authors be held liable for any damages 5 | arising from the use of this software. 6 | 7 | Permission is granted to anyone to use this software for any purpose, 8 | including commercial applications, and to alter it and redistribute it 9 | freely, subject to the following restrictions: 10 | 11 | 1. The origin of this software must not be misrepresented; you must not 12 | claim that you wrote the original software. If you use this software 13 | in a product, an acknowledgment in the product documentation would be 14 | appreciated but is not required. 15 | 16 | 2. Altered source versions must be plainly marked as such, and must not be 17 | misrepresented as being the original software. 18 | 19 | 3. This notice may not be removed or altered from any source 20 | distribution. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # node_xslt 2 | 3 | ## Installation 4 | ``` 5 | npm install node_xslt --save 6 | ``` 7 | 8 | **Or:** 9 | 10 | In the root directory, run `node-gyp rebuild` to generate `./build/Release/node_xslt.node` 11 | 12 | Then: 13 | 14 | ```JS 15 | var xslt = require('node_xslt') 16 | ``` 17 | 18 | ## Requirements 19 | 20 | * [libxml2](http://www.xmlsoft.org/) (libxml2-dev package for Debian-based distros) 21 | * [libxslt](http://xmlsoft.org/xslt/index.html) (libxslt-dev package for Debian-based distros) 22 | * [libexslt](http://xmlsoft.org/xslt/EXSLT/) (libxslt-dev package for Debian-based distros) 23 | * xml2-config (Needs to be on PATH) 24 | 25 | ## API 26 | 27 | | Method | Arguments | Return | Description 28 | | :---: | :---: | :---: | --- 29 | | `readXsltString` | `string` | `Stylesheet {}` | Uses the specified XSLT for transformation 30 | | `readXsltFile` | `string` | `Stylesheet {}` | Loads the XSLT from file 31 | | `readXmlString`, `readHtmlString` | `string` | `Document {}` | Imports XML/HTML from string 32 | | `readXmlFile`, `readHtmlFile` | string | `Document {}` | Imports the XML/HTML file 33 | | `transform` | `Stylesheet`, `Document`, `string[]` | **string** | Transforms the document 34 | 35 | 36 | ### Example 37 | ```JS 38 | xslt.transform( 39 | stylesheet, 40 | document, 41 | [ 42 | 'paramName', 43 | 'paramValue', 44 | 'paramName', 45 | 'paramValue' 46 | ] 47 | ) 48 | ``` 49 | -------------------------------------------------------------------------------- /binding.gyp: -------------------------------------------------------------------------------- 1 | { 2 | "targets": [{ 3 | "target_name": "node_xslt", 4 | "sources": [ "node_xslt.cc" ], 5 | "cflags": [" 5 | // Victor Grishchenko 6 | // ---------------------------------------------------------------------------- 7 | // Creation date : 27-Sep-2008 8 | // Last modification : 19-May-2009 9 | // ---------------------------------------------------------------------------- 10 | 11 | #ifndef __K7_MACROS__ 12 | #define __K7_MACROS__ 13 | 14 | #include 15 | #include 16 | 17 | using namespace v8; 18 | 19 | // ---------------------------------------------------------------------------- 20 | // 21 | // TYPE CONVERSION 22 | // 23 | // ---------------------------------------------------------------------------- 24 | 25 | /** 26 | * These macros are just shorthand to creat V8/JavaScript values that can be 27 | * passed to the V8 API or returned to the JavaScript environment */ 28 | #define JS_CONTEXT v8::Context::GetCurrent() 29 | #define JS_GLOBAL JS_CONTEXT->Global() 30 | #define JS_str(s) v8::String::New(s) 31 | #define JS_str2(s,c) v8::String::New(s,c) 32 | #define JS_int(s) v8::Integer::New(s) 33 | #define JS_undefined v8::Undefined() 34 | #define JS_null v8::Null() 35 | #define JS_fn(f) v8::FunctionTemplate::New(f)->GetFunction() 36 | #define JS_obj(o) v8::Object::New(o) 37 | #define JS_bool(b) v8::Boolean::New(b) 38 | 39 | #define JS_THROW(t, s) ThrowException(Exception::t(String::New(s))) 40 | #define JS_ERROR(s) ThrowException(Exception::Error(String::New(s))) 41 | 42 | // ---------------------------------------------------------------------------- 43 | // 44 | // ARGUMENTS CONVERSION 45 | // 46 | // ---------------------------------------------------------------------------- 47 | 48 | /** 49 | * This set of macro make it easy to declare a function that can be exported to 50 | * the JavaScript environment. 51 | * See the 'posix.cpp' module for examples. */ 52 | #define ARGC args.Length() 53 | #define ARG_COUNT(c) if ( args.Length() != c ) { \ 54 | return ThrowException(String::New("Insufficient arguments")); } 55 | #define ARG_BETWEEN(a,b) if ( a <= args.Length() <= b ) {} 56 | #define ARG_int(n,c) int n=(int)(args[c]->Int32Value()) 57 | #define ARG_str(v,i) v8::String::AsciiValue v(args[i]); 58 | #define ARG_utf8(v,i) v8::String::Utf8Value v(args[i]); 59 | #define ARG_obj(v,i) v8::Local v=args[i]->ToObject(); 60 | #define ARG_obj(v,i) v8::Local v=args[i]->ToObject(); 61 | #define ARG_array(name, c) \ 62 | if (!args[(c)]->IsArray()) { \ 63 | std::ostringstream __k7_e; \ 64 | __k7_e << "Exception: argument error." << __func__ << " expects array for argument " << c << "."; \ 65 | return ThrowException(String::New(__k7_e.str().c_str())); \ 66 | } \ 67 | Handle name = Handle::Cast(args[(c)]); 68 | #define ARG_fn(name, c) \ 69 | Handle name = Handle::Cast(args[(c)]) 70 | 71 | #define THROW(str) return ThrowException(String::New(str)) 72 | #define THROW_VERB(tmpl,...) { char msg[1024]; snprintf(msg,1000,tmpl,__VA_ARGS__); THROW(msg); } 73 | // performance freaks use this THROW_VERB :) 74 | //#define THROW_VERB(tmpl,...) THROW("Invocation error") 75 | 76 | #define FUN_NAME (*String::AsciiValue(args.Callee()->GetName()->ToString())) 77 | 78 | #define PINT(n) 0; if (args.Length()<++_argn || !args[_argn-1]->IsInt32()) {\ 79 | THROW_VERB("Argument %i of %s, must be an integer\n",_argn,FUN_NAME);} \ 80 | int n=(int)(args[_argn-1]->Int32Value()); 0 81 | #define PSTR(n) 0; if (args.Length()<++_argn) {\ 82 | THROW_VERB("Argument %i of %s must be a string\n",_argn,FUN_NAME);} \ 83 | v8::String::AsciiValue n(args[_argn-1]); 0 84 | #define POBJ(n) 0; if (args.Length()<++_argn || !args[_argn-1]->IsObject()) {\ 85 | THROW_VERB("Argument %i of %s, must be an object\n",_argn,FUN_NAME);} \ 86 | v8::Handle n (args[_argn-1]->ToObject()); 0 87 | #define PFUN(n) 0; if (args.Length()<++_argn || !args[_argn-1]->IsFunction()) {\ 88 | THROW_VERB("Argument %i of %s, must be a function\n",_argn,FUN_NAME);} \ 89 | v8::Handle n (v8::Function::Cast(*args[_argn-1])); 0 90 | #define PWRAP(type,var) 0; if (args.Length()<++_argn || !args[_argn-1]->IsExternal()) {\ 91 | THROW_VERB("Argument %i of %s, must be an external\n",_argn,FUN_NAME);} \ 92 | type* var = (type*) v8::External::Cast(*args[_argn-1])->Value(); 0 93 | 94 | // ---------------------------------------------------------------------------- 95 | // 96 | // FUNCTIONS MACROS 97 | // 98 | // ---------------------------------------------------------------------------- 99 | 100 | #define FUNCTION_DECL(f) static v8::Handle f(const v8::Arguments&); 101 | #define FUNCTION(f,...) static v8::Handle f(const v8::Arguments& args) { \ 102 | v8::HandleScope handlescope; \ 103 | int _argn=0; \ 104 | __VA_ARGS__; 105 | #define FUNCTION_C(f) static v8::Handle f(const v8::Arguments& args) { 106 | #define END } 107 | #define THIS args.This() 108 | #define STUB return ThrowException(Exception::Error(String::New("Stub - Function not implemented"))); 109 | #define SET_INTERNAL(ptr) args.This()->SetInternalField(0, External::New((void*)ptr)); 110 | #define GET_INTERNAL(type,var) Local _intfld = args.This()->GetInternalField(0); \ 111 | type var = reinterpret_cast(Handle::Cast(_intfld)->Value()); 112 | #define RETURN_SCOPED(x) return handlescope.Close(x) 113 | #define RETURN_INT(i) return handlescope.Close(Integer::New(i)) 114 | #define RETURN_WRAPPED(ptr) return v8::External::New(ptr) 115 | #define RETURN_UNDEF return JS_undefined 116 | #define RETURN_WATCHED(ptr,f) Persistent watcher = Persistent::New(External::New(ptr)); \ 117 | watcher.MakeWeak(ptr, f); \ 118 | return watcher; 119 | 120 | // ---------------------------------------------------------------------------- 121 | // 122 | // OBJECT MACROS 123 | // 124 | // ---------------------------------------------------------------------------- 125 | 126 | /** 127 | * This set of macros allow you to declare a new object type, usually because 128 | * you want to set internal data in this object. 129 | * See the 'posix.cpp' module for examples. */ 130 | 131 | #define OBJECT(name,fields,...) \ 132 | v8::Handle name(__VA_ARGS__) { \ 133 | v8::HandleScope handlescope;\ 134 | v8::Handle __class__ = v8::FunctionTemplate::New();\ 135 | v8::Handle __object__ = __class__->InstanceTemplate();\ 136 | __object__->SetInternalFieldCount(fields);\ 137 | v8::Handle self = __object__->NewInstance(); 138 | 139 | #define OBJECT_COPY_SLOTS(from,to) \ 140 | { \ 141 | Handle keys = from->GetPropertyNames(); \ 142 | for (int i = 0; i < keys->Length(); i ++) { \ 143 | Handle key = keys->Get(JS_int(i))->ToString(); \ 144 | Handle val = from->Get(key); \ 145 | to->Set(key, val); \ 146 | } \ 147 | } 148 | 149 | #define OBJECT_SET(o,s,v) o->Set(JS_str(s), v) 150 | #define OBJECT_GET(o,s) o->Get(JS_str(s)) 151 | #define OBJECT_UNSET(o,s) o->Set(JS_str(s), JS_undefined) 152 | #define OBJECT_PROTOTYPE(o) o->GetPrototype(); 153 | 154 | 155 | #define INTERNAL(i,value) \ 156 | self->SetInternalField(i, v8::External::New((void*)value)); 157 | 158 | #define EXTERNAL(type,name,object,indice) \ 159 | type name = (type) (v8::Local::Cast(object->GetInternalField(indice))->Value()); 160 | 161 | // ---------------------------------------------------------------------------- 162 | // 163 | // CLASS MACROS 164 | // 165 | // ---------------------------------------------------------------------------- 166 | 167 | #define CLASS(name)\ 168 | { \ 169 | v8::Handle __class_name__ = v8::String::New(name); \ 170 | v8::Handle __class__ = v8::FunctionTemplate::New(); \ 171 | v8::Handle __object__ = __class__->InstanceTemplate(); \ 172 | v8::Handle self = __object__; \ 173 | __class__->SetClassName(v8::String::New(name)); 174 | #define CONSTRUCTOR(c) __class__->SetCallHandler(c); 175 | #define DESTRUCTOR(d) Persistent _weak_handle = Persistent::New(__object__); \ 176 | _weak_handle.MakeWeak(NULL, d); 177 | #define INTERNAL_FIELDS(i) __object__->SetInternalFieldCount(i); 178 | #define HAS_INTERNAL __object__->SetInternalFieldCount(1); 179 | #define END_CLASS __module__->Set(__class_name__,__class__->GetFunction(),v8::PropertyAttribute(v8::ReadOnly|v8::DontDelete));} 180 | 181 | // ---------------------------------------------------------------------------- 182 | // 183 | // MODULE MACROS 184 | // 185 | // ---------------------------------------------------------------------------- 186 | 187 | #define K7_MODULE_CREATOR_T Handle (*moduleCreator)(Handle parent, const char* moduleName, const char* fullName) 188 | #define MODULE \ 189 | extern "C" v8::Handle MODULE_STATIC (v8::Handle __module__) {\ 190 | v8::Handle self = __module__; 191 | 192 | #ifdef AS_PLUGIN 193 | #define END_MODULE \ 194 | return __module__; } \ 195 | extern "C" Handle k7_module_init (Handle global, K7_MODULE_CREATOR_T) { \ 196 | return MODULE_STATIC(moduleCreator(global, MODULE_NAME, NULL)); \ 197 | } 198 | #else 199 | #define END_MODULE \ 200 | return __module__; } 201 | #endif 202 | 203 | // ---------------------------------------------------------------------------- 204 | // 205 | // SCOPE AND BINDING MACROS 206 | // 207 | // ---------------------------------------------------------------------------- 208 | 209 | #define WITH_CLASS { v8::Handle self = __class__; 210 | #define WITH_MODULE { v8::Handle self = __module__; 211 | #define WITH_OBJECT { v8::Handle self = __object__; 212 | 213 | #define SET(s,v) self->Set(JS_str(s),v); 214 | #define SET_int(s,v) self->Set(JS_str(s), JS_int(v)); 215 | #define SET_str(s,v) self->Set(JS_str(s), JS_str(v)); 216 | 217 | #define BIND(s,v) { Handle f = v8::FunctionTemplate::New(v)->GetFunction(); \ 218 | f->SetName(JS_str(s)); \ 219 | self->Set(JS_str(s),f); \ 220 | } 221 | #define METHOD(s,v) __object__->Set(JS_str(s),v8::FunctionTemplate::New(v)->GetFunction()); 222 | #define BIND_CONST(s,v) self->Set(JS_str(s),v); 223 | #define CLASS_METHOD(s,v) __class__->Set(JS_str(s),v8::FunctionTemplate::New(v)->GetFunction()); 224 | 225 | // ---------------------------------------------------------------------------- 226 | // 227 | // API MACROS 228 | // 229 | // ---------------------------------------------------------------------------- 230 | 231 | /** 232 | * These macros allow to declare a module initialization function and register 233 | * FUNCTIONs in this module. */ 234 | #define LINK_TO(lib) 235 | #define IMPORT(function) extern "C" v8::Handle function(v8::Handle module); 236 | #define LOAD(moduleName,function) function(k7::module(global, moduleName, NULL)); 237 | #define EXEC(source) k7::execute(source); 238 | #define EVAL(source) k7::eval(source); 239 | 240 | #endif 241 | // EOF - vim: ts=4 sw=4 et 242 | -------------------------------------------------------------------------------- /node_xslt.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include "macros.h" 10 | #include "scopeguard.h" 11 | 12 | #define OBJ_DESTRUCTOR(d) Persistent _weak_handle = Persistent::New(self); \ 13 | _weak_handle.MakeWeak(NULL, d); 14 | 15 | using namespace v8; 16 | 17 | Handle useErrors = v8::Boolean::New(false); 18 | 19 | void jsXmlDocCleanup(Persistent value, void *) { 20 | HandleScope handlescope; 21 | Local obj = value->ToObject(); 22 | EXTERNAL(xmlDocPtr, doc, obj, 0); 23 | xmlFreeDoc(doc); 24 | return; 25 | } 26 | 27 | void jsXsltStylesheetCleanup(Persistent value, void *) { 28 | HandleScope handlescope; 29 | Local obj = value->ToObject(); 30 | EXTERNAL(xsltStylesheetPtr, style, obj, 0); 31 | xsltFreeStylesheet(style); 32 | return; 33 | } 34 | 35 | OBJECT(jsXmlDoc, 1, xmlDocPtr doc) 36 | INTERNAL(0, doc) 37 | OBJ_DESTRUCTOR(&jsXmlDocCleanup) 38 | RETURN_SCOPED(self); 39 | END 40 | 41 | OBJECT(jsXsltStylesheet, 1, xsltStylesheetPtr style) 42 | INTERNAL(0, style) 43 | OBJ_DESTRUCTOR(&jsXsltStylesheetCleanup) 44 | RETURN_SCOPED(self); 45 | END 46 | 47 | FUNCTION(useInternalErrors) 48 | ARG_COUNT(0) 49 | 50 | useErrors = v8::Boolean::New(true); 51 | return v8::Boolean::New(true); 52 | END 53 | 54 | FUNCTION(readXmlFile) 55 | ARG_COUNT(1) 56 | ARG_utf8(str, 0) 57 | 58 | xmlDocPtr doc = xmlReadFile( 59 | *str, 60 | "UTF-8", 61 | useErrors->BooleanValue() 62 | ? XML_PARSE_RECOVER | XML_PARSE_NOERROR 63 | : 0); 64 | if (!doc) { 65 | return JS_ERROR("Failed to parse XML"); 66 | } 67 | RETURN_SCOPED(jsXmlDoc(doc)); 68 | END 69 | 70 | FUNCTION(readXmlString) 71 | ARG_COUNT(1) 72 | ARG_utf8(str, 0) 73 | 74 | xmlDocPtr doc = xmlReadMemory( 75 | *str, 76 | str.length(), 77 | NULL, 78 | "UTF-8", 79 | useErrors->BooleanValue() 80 | ? XML_PARSE_RECOVER | XML_PARSE_NOERROR 81 | : 0); 82 | if (!doc) { 83 | return JS_ERROR("Failed to parse XML"); 84 | } 85 | RETURN_SCOPED(jsXmlDoc(doc)); 86 | END 87 | 88 | FUNCTION(readHtmlFile) 89 | ARG_COUNT(1) 90 | ARG_utf8(str, 0) 91 | 92 | htmlDocPtr doc = htmlReadFile( 93 | *str, 94 | "UTF-8", 95 | useErrors->BooleanValue() 96 | ? HTML_PARSE_RECOVER | HTML_PARSE_NOERROR 97 | : HTML_PARSE_RECOVER 98 | ); 99 | 100 | if (!doc) { 101 | return JS_ERROR("Failed to parse HTML"); 102 | } 103 | RETURN_SCOPED(jsXmlDoc(doc)); 104 | END 105 | 106 | FUNCTION(readHtmlString) 107 | ARG_COUNT(1) 108 | ARG_utf8(str, 0) 109 | 110 | htmlDocPtr doc = htmlReadMemory( 111 | *str, 112 | str.length(), 113 | NULL, 114 | "UTF-8", 115 | useErrors->BooleanValue() 116 | ? HTML_PARSE_RECOVER | HTML_PARSE_NOERROR 117 | : HTML_PARSE_RECOVER 118 | ); 119 | 120 | if (!doc) { 121 | return JS_ERROR("Failed to parse HTML"); 122 | } 123 | RETURN_SCOPED(jsXmlDoc(doc)); 124 | END 125 | 126 | FUNCTION(readXsltFile) 127 | ARG_COUNT(1) 128 | ARG_utf8(str, 0) 129 | 130 | xmlDocPtr doc = xmlReadFile(*str, "UTF-8", 0); 131 | if (!doc) { 132 | return JS_ERROR("Failed to parse XML"); 133 | } 134 | ScopeGuard guard = MakeGuard(xmlFreeDoc, doc); 135 | 136 | xsltStylesheetPtr stylesheet = xsltParseStylesheetDoc(doc); 137 | if (!stylesheet) { 138 | return JS_ERROR("Failed to parse stylesheet"); 139 | } 140 | guard.Dismiss(); 141 | RETURN_SCOPED(jsXsltStylesheet(stylesheet)); 142 | END 143 | 144 | FUNCTION(readXsltString) 145 | ARG_COUNT(1) 146 | ARG_utf8(str, 0) 147 | 148 | xmlDocPtr doc = xmlReadMemory(*str, str.length(), NULL, "UTF-8", 0); 149 | if (!doc) { 150 | return JS_ERROR("Failed to parse XML"); 151 | } 152 | ScopeGuard guard = MakeGuard(xmlFreeDoc, doc); 153 | 154 | xsltStylesheetPtr stylesheet = xsltParseStylesheetDoc(doc); 155 | if (!stylesheet) { 156 | return JS_ERROR("Failed to parse stylesheet"); 157 | } 158 | guard.Dismiss(); 159 | RETURN_SCOPED(jsXsltStylesheet(stylesheet)); 160 | END 161 | 162 | void freeArray(char **array, int size) { 163 | for (int i = 0; i < size; i++) { 164 | free(array[i]); 165 | } 166 | free(array); 167 | } 168 | 169 | FUNCTION(transform) 170 | ARG_COUNT(3) 171 | ARG_obj(objStylesheet, 0) 172 | ARG_obj(objDocument, 1) 173 | ARG_array(array, 2) 174 | 175 | EXTERNAL(xsltStylesheetPtr, stylesheet, objStylesheet, 0); 176 | EXTERNAL(xmlDocPtr, document, objDocument, 0); 177 | 178 | uint32_t arrayLen = array->Length(); 179 | 180 | if (arrayLen % 2 != 0) { 181 | return JS_ERROR("Array contains an odd number of parameters"); 182 | } 183 | 184 | char** params = (char **)malloc(sizeof(char *) * (arrayLen + 1)); 185 | if (!params) { 186 | return JS_ERROR("Failed to allocate memory"); 187 | } 188 | memset(params, 0, sizeof(char *) * (array->Length() + 1)); 189 | ON_BLOCK_EXIT(freeArray, params, array->Length()); 190 | 191 | for (int i = 0; i < array->Length(); i++) { 192 | Local param = array->Get(JS_int(i))->ToString(); 193 | params[i] = (char *)malloc(sizeof(char) * (param->Length() + 1)); 194 | if (!params[i]) { 195 | return JS_ERROR("Failed to allocate memory"); 196 | } 197 | param->WriteAscii(params[i]); 198 | } 199 | 200 | try { 201 | xmlDocPtr result = xsltApplyStylesheet(stylesheet, document, (const char **)params); 202 | if (!result) { 203 | return JS_ERROR("Failed to apply stylesheet"); 204 | } 205 | ON_BLOCK_EXIT(xmlFreeDoc, result); 206 | 207 | xmlChar *doc_ptr; 208 | int doc_len; 209 | xsltSaveResultToString(&doc_ptr, &doc_len, result, stylesheet); 210 | 211 | if (doc_ptr) { 212 | ON_BLOCK_EXIT(xmlFree, doc_ptr); 213 | 214 | RETURN_SCOPED(JS_str2((const char *)doc_ptr, doc_len)); 215 | } else { 216 | return v8::String::Empty(); 217 | } 218 | } catch (Handle err) { 219 | return err; 220 | } 221 | END 222 | 223 | extern "C" void init(Handle target) 224 | { 225 | HandleScope scope; 226 | 227 | exsltRegisterAll(); 228 | 229 | Handle self = target; 230 | BIND("useInternalErrors", useInternalErrors); 231 | BIND("readXmlString", readXmlString); 232 | BIND("readXmlFile", readXmlFile); 233 | BIND("readHtmlString", readHtmlString); 234 | BIND("readHtmlFile", readHtmlFile); 235 | BIND("readXsltString", readXsltString); 236 | BIND("readXsltFile", readXsltFile); 237 | BIND("transform", transform); 238 | } 239 | 240 | NODE_MODULE(node_xslt, init) 241 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "node_xslt", 3 | "homepage": "https://github.com/bsuh/node_xslt", 4 | "description": "A simple XSLT package for node.js", 5 | "version": "0.1.9", 6 | "main": "./build/Release/node_xslt", 7 | "engines": { 8 | "node": ">=0.1.93" 9 | }, 10 | "scripts": { 11 | "preinstall": "node-gyp rebuild" 12 | }, 13 | "authors": [{ 14 | "name": "Brian Suh", 15 | "email": "brian.j.suh@gmail.com" 16 | }], 17 | "repository": { 18 | "type": "git", 19 | "url": "git://github.com/bsuh/node_xslt.git" 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /scopeguard.h: -------------------------------------------------------------------------------- 1 | #ifndef SCOPEGUARD_H_ 2 | #define SCOPEGUARD_H_ 3 | 4 | /* 5 | Scopeguard, by Andrei Alexandrescu and Petru Marginean, December 2000. 6 | Modified by Joshua Lehrer, FactSet Research Systems, November 2005. 7 | */ 8 | 9 | template 10 | class RefHolder 11 | { 12 | T& ref_; 13 | public: 14 | RefHolder(T& ref) : ref_(ref) {} 15 | operator T& () const 16 | { 17 | return ref_; 18 | } 19 | private: 20 | // Disable assignment - not implemented 21 | RefHolder& operator=(const RefHolder&); 22 | }; 23 | 24 | template 25 | inline RefHolder ByRef(T& t) 26 | { 27 | return RefHolder(t); 28 | } 29 | 30 | class ScopeGuardImplBase 31 | { 32 | ScopeGuardImplBase& operator =(const ScopeGuardImplBase&); 33 | protected: 34 | ~ScopeGuardImplBase() 35 | { 36 | } 37 | ScopeGuardImplBase(const ScopeGuardImplBase& other) throw() 38 | : dismissed_(other.dismissed_) 39 | { 40 | other.Dismiss(); 41 | } 42 | template 43 | static void SafeExecute(J& j) throw() 44 | { 45 | if (!j.dismissed_) 46 | try 47 | { 48 | j.Execute(); 49 | } 50 | catch(...) 51 | { 52 | } 53 | } 54 | 55 | mutable bool dismissed_; 56 | public: 57 | ScopeGuardImplBase() throw() : dismissed_(false) 58 | { 59 | } 60 | void Dismiss() const throw() 61 | { 62 | dismissed_ = true; 63 | } 64 | }; 65 | 66 | typedef const ScopeGuardImplBase& ScopeGuard; 67 | 68 | template 69 | class ScopeGuardImpl0 : public ScopeGuardImplBase 70 | { 71 | public: 72 | static ScopeGuardImpl0 MakeGuard(F fun) 73 | { 74 | return ScopeGuardImpl0(fun); 75 | } 76 | ~ScopeGuardImpl0() throw() 77 | { 78 | SafeExecute(*this); 79 | } 80 | void Execute() 81 | { 82 | fun_(); 83 | } 84 | protected: 85 | ScopeGuardImpl0(F fun) : fun_(fun) 86 | { 87 | } 88 | F fun_; 89 | }; 90 | 91 | template 92 | inline ScopeGuardImpl0 MakeGuard(F fun) 93 | { 94 | return ScopeGuardImpl0::MakeGuard(fun); 95 | } 96 | 97 | template 98 | class ScopeGuardImpl1 : public ScopeGuardImplBase 99 | { 100 | public: 101 | static ScopeGuardImpl1 MakeGuard(F fun, P1 p1) 102 | { 103 | return ScopeGuardImpl1(fun, p1); 104 | } 105 | ~ScopeGuardImpl1() throw() 106 | { 107 | SafeExecute(*this); 108 | } 109 | void Execute() 110 | { 111 | fun_(p1_); 112 | } 113 | protected: 114 | ScopeGuardImpl1(F fun, P1 p1) : fun_(fun), p1_(p1) 115 | { 116 | } 117 | F fun_; 118 | const P1 p1_; 119 | }; 120 | 121 | template 122 | inline ScopeGuardImpl1 MakeGuard(F fun, P1 p1) 123 | { 124 | return ScopeGuardImpl1::MakeGuard(fun, p1); 125 | } 126 | 127 | template 128 | class ScopeGuardImpl2: public ScopeGuardImplBase 129 | { 130 | public: 131 | static ScopeGuardImpl2 MakeGuard(F fun, P1 p1, P2 p2) 132 | { 133 | return ScopeGuardImpl2(fun, p1, p2); 134 | } 135 | ~ScopeGuardImpl2() throw() 136 | { 137 | SafeExecute(*this); 138 | } 139 | void Execute() 140 | { 141 | fun_(p1_, p2_); 142 | } 143 | protected: 144 | ScopeGuardImpl2(F fun, P1 p1, P2 p2) : fun_(fun), p1_(p1), p2_(p2) 145 | { 146 | } 147 | F fun_; 148 | const P1 p1_; 149 | const P2 p2_; 150 | }; 151 | 152 | template 153 | inline ScopeGuardImpl2 MakeGuard(F fun, P1 p1, P2 p2) 154 | { 155 | return ScopeGuardImpl2::MakeGuard(fun, p1, p2); 156 | } 157 | 158 | template 159 | class ScopeGuardImpl3 : public ScopeGuardImplBase 160 | { 161 | public: 162 | static ScopeGuardImpl3 MakeGuard(F fun, P1 p1, P2 p2, P3 p3) 163 | { 164 | return ScopeGuardImpl3(fun, p1, p2, p3); 165 | } 166 | ~ScopeGuardImpl3() throw() 167 | { 168 | SafeExecute(*this); 169 | } 170 | void Execute() 171 | { 172 | fun_(p1_, p2_, p3_); 173 | } 174 | protected: 175 | ScopeGuardImpl3(F fun, P1 p1, P2 p2, P3 p3) : fun_(fun), p1_(p1), p2_(p2), p3_(p3) 176 | { 177 | } 178 | F fun_; 179 | const P1 p1_; 180 | const P2 p2_; 181 | const P3 p3_; 182 | }; 183 | 184 | template 185 | inline ScopeGuardImpl3 MakeGuard(F fun, P1 p1, P2 p2, P3 p3) 186 | { 187 | return ScopeGuardImpl3::MakeGuard(fun, p1, p2, p3); 188 | } 189 | 190 | //************************************************************ 191 | 192 | template 193 | class ObjScopeGuardImpl0 : public ScopeGuardImplBase 194 | { 195 | public: 196 | static ObjScopeGuardImpl0 MakeObjGuard(Obj& obj, MemFun memFun) 197 | { 198 | return ObjScopeGuardImpl0(obj, memFun); 199 | } 200 | ~ObjScopeGuardImpl0() throw() 201 | { 202 | SafeExecute(*this); 203 | } 204 | void Execute() 205 | { 206 | (obj_.*memFun_)(); 207 | } 208 | protected: 209 | ObjScopeGuardImpl0(Obj& obj, MemFun memFun) 210 | : obj_(obj), memFun_(memFun) {} 211 | Obj& obj_; 212 | MemFun memFun_; 213 | }; 214 | 215 | template 216 | inline ObjScopeGuardImpl0 MakeObjGuard(Obj& obj, MemFun memFun) 217 | { 218 | return ObjScopeGuardImpl0::MakeObjGuard(obj, memFun); 219 | } 220 | 221 | template 222 | inline ObjScopeGuardImpl0 MakeGuard(Ret(Obj2::*memFun)(), Obj1 &obj) { 223 | return ObjScopeGuardImpl0::MakeObjGuard(obj,memFun); 224 | } 225 | 226 | template 227 | inline ObjScopeGuardImpl0 MakeGuard(Ret(Obj2::*memFun)(), Obj1 *obj) { 228 | return ObjScopeGuardImpl0::MakeObjGuard(*obj,memFun); 229 | } 230 | 231 | template 232 | class ObjScopeGuardImpl1 : public ScopeGuardImplBase 233 | { 234 | public: 235 | static ObjScopeGuardImpl1 MakeObjGuard(Obj& obj, MemFun memFun, P1 p1) 236 | { 237 | return ObjScopeGuardImpl1(obj, memFun, p1); 238 | } 239 | ~ObjScopeGuardImpl1() throw() 240 | { 241 | SafeExecute(*this); 242 | } 243 | void Execute() 244 | { 245 | (obj_.*memFun_)(p1_); 246 | } 247 | protected: 248 | ObjScopeGuardImpl1(Obj& obj, MemFun memFun, P1 p1) 249 | : obj_(obj), memFun_(memFun), p1_(p1) {} 250 | Obj& obj_; 251 | MemFun memFun_; 252 | const P1 p1_; 253 | }; 254 | 255 | template 256 | inline ObjScopeGuardImpl1 MakeObjGuard(Obj& obj, MemFun memFun, P1 p1) 257 | { 258 | return ObjScopeGuardImpl1::MakeObjGuard(obj, memFun, p1); 259 | } 260 | 261 | template 262 | inline ObjScopeGuardImpl1 MakeGuard(Ret(Obj2::*memFun)(P1a), Obj1 &obj, P1b p1) { 263 | return ObjScopeGuardImpl1::MakeObjGuard(obj,memFun,p1); 264 | } 265 | 266 | template 267 | inline ObjScopeGuardImpl1 MakeGuard(Ret(Obj2::*memFun)(P1a), Obj1 *obj, P1b p1) { 268 | return ObjScopeGuardImpl1::MakeObjGuard(*obj,memFun,p1); 269 | } 270 | 271 | template 272 | class ObjScopeGuardImpl2 : public ScopeGuardImplBase 273 | { 274 | public: 275 | static ObjScopeGuardImpl2 MakeObjGuard(Obj& obj, MemFun memFun, P1 p1, P2 p2) 276 | { 277 | return ObjScopeGuardImpl2(obj, memFun, p1, p2); 278 | } 279 | ~ObjScopeGuardImpl2() throw() 280 | { 281 | SafeExecute(*this); 282 | } 283 | void Execute() 284 | { 285 | (obj_.*memFun_)(p1_, p2_); 286 | } 287 | protected: 288 | ObjScopeGuardImpl2(Obj& obj, MemFun memFun, P1 p1, P2 p2) 289 | : obj_(obj), memFun_(memFun), p1_(p1), p2_(p2) {} 290 | Obj& obj_; 291 | MemFun memFun_; 292 | const P1 p1_; 293 | const P2 p2_; 294 | }; 295 | 296 | template 297 | inline ObjScopeGuardImpl2 MakeObjGuard(Obj& obj, MemFun memFun, P1 p1, P2 p2) 298 | { 299 | return ObjScopeGuardImpl2::MakeObjGuard(obj, memFun, p1, p2); 300 | } 301 | 302 | template 303 | inline ObjScopeGuardImpl2 MakeGuard(Ret(Obj2::*memFun)(P1a,P2a), Obj1 &obj, P1b p1, P2b p2) { 304 | return ObjScopeGuardImpl2::MakeObjGuard(obj,memFun,p1,p2); 305 | } 306 | 307 | template 308 | inline ObjScopeGuardImpl2 MakeGuard(Ret(Obj2::*memFun)(P1a,P2a), Obj1 *obj, P1b p1, P2b p2) { 309 | return ObjScopeGuardImpl2::MakeObjGuard(*obj,memFun,p1,p2); 310 | } 311 | 312 | 313 | #define CONCATENATE_DIRECT(s1, s2) s1##s2 314 | #define CONCATENATE(s1, s2) CONCATENATE_DIRECT(s1, s2) 315 | #define ANONYMOUS_VARIABLE(str) CONCATENATE(str, __LINE__) 316 | 317 | #define ON_BLOCK_EXIT ScopeGuard ANONYMOUS_VARIABLE(scopeGuard) = MakeGuard 318 | #define ON_BLOCK_EXIT_OBJ ScopeGuard ANONYMOUS_VARIABLE(scopeGuard) = MakeObjGuard 319 | 320 | #endif //SCOPEGUARD_H_ 321 | -------------------------------------------------------------------------------- /wscript: -------------------------------------------------------------------------------- 1 | import subprocess 2 | 3 | srcdir = '.' 4 | blddir = 'build' 5 | 6 | def set_options(opt): 7 | opt.tool_options('compiler_cxx') 8 | 9 | def configure(conf): 10 | conf.check_tool('compiler_cxx') 11 | conf.check_tool('node_addon') 12 | conf.check(lib=['xml2', 'xslt', 'exslt'], uselib_store='M', mandatory=True) 13 | conf.env.set_variant('Release') 14 | 15 | def build(bld): 16 | obj = bld.new_task_gen('cxx', 'shlib', 'node_addon') 17 | obj.target = 'node_xslt' 18 | obj.source = 'node_xslt.cc' 19 | obj.cxxflags = subprocess.Popen(["xml2-config", "--cflags"], stdout=subprocess.PIPE).communicate()[0].strip().split() 20 | obj.lib = ['xml2', 'xslt', 'exslt'] 21 | obj.libpath = ['/usr/lib'] 22 | 23 | --------------------------------------------------------------------------------