Commits

Nikhil Marathe  committed 413fd34

Initial import

Right now yajljs::Handle creates a new yajl_handle
It registers for null and boolean listeners and notifies upstream Javascript.
Handle::Parse does nothing.
test.js is a JS implementation of the reformatter example from yajl.

  • Participants

Comments (0)

Files changed (11)

+syntax: glob
+
+.lock-wscript
+yajl.node
+build/.wafpickle-7
+build/config.log
+build/default/src/yajl_1.o
+build/c4che
+Copyright 2010, Nikhil Marathe <nsm.nikhil@gmail.com> All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+    * Neither the name of Nikhil Marathe nor the names of its
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+all: yajl-js doc
+
+yajl-js:
+	node-waf configure build
+
+install: yajl-js
+	node-waf install
+
+clean:
+	node-waf clean
+
+distclean:
+	node-waf distclean
+
+uninstall:
+	node-waf uninstall
+
+doc: doc/README.html
+
+doc/README.html: doc/README.txt
+	asciidoc -a toc -a linkcss -o doc/README.html doc/README.txt

File doc/README.txt

+Yajl-js
+=======
+Nikhil Marathe <nsm.nikhil@gmail.com>
+Version, 0.1, 30th Jan 2010
+
+yajl-js aims to be a complete binding to the http://lloyd.github.com/yajl/[yajl] JSON parser by Lloyd Hilaiel.
+yajl is a SAX-style event-driven parser well suited to JavaScript programming style.
+
+
+* Implement public API bindings
+* Make it more object-oriented compared to the C version
+* Provide some higher level wraps around things like onStartArray/Map so that applications can instead
+  hook onto onArray or onMap

File src/callbacks.cc

+#include <iostream>
+#include <v8.h>
+#include <node.h>
+#include <yajl/yajl_parse.h>
+
+#include "callbacks.h"
+#include "yajl.h"
+
+using namespace v8;
+using namespace node;
+
+namespace yajljs {
+int onNull( void *ctx )
+{
+    Handle *yh = static_cast<Handle *>( ctx );
+    yh->Emit( v8::String::New("null"), 0, NULL );
+}
+
+int onBoolean( void *ctx, int b )
+{
+    HandleScope scope;
+    Handle *yh = static_cast<Handle *>( ctx );
+
+    Local<Value> args[] = { Integer::New( b ) };
+    yh->Emit( v8::String::New("boolean"), 1, args );
+}
+
+void
+FillCallbacks( Local<Object> obj, yajl_callbacks *cbs )
+{
+    Local<Array> props = obj->GetPropertyNames();
+    for( int i = 0; i < props->Length(); i++ )
+    {
+        Local<Value> k = props->Get(Number::New(i));
+        String::AsciiValue key(k->ToString());
+        String::AsciiValue val( obj->Get( k->ToString() )->ToString() );
+        std::cout << *key << ":" << *val << "\n";
+    }
+}
+}

File src/callbacks.h

+#ifndef YAJLJS_CALLBACKS_H
+#define YAJLJS_CALLBACKS_H
+
+#include <v8.h>
+#include <yajl/yajl_parse.h>
+
+namespace yajljs {
+
+int onNull( void *ctx );
+
+int onBoolean( void *ctx, int b );
+
+}
+
+#endif
+#include <iostream>
+
+#include <yajl/yajl_parse.h>
+#include <yajl/yajl_gen.h>
+
+#include <v8.h>
+#include <node.h>
+#include <node/node_events.h>
+
+#include "callbacks.h"
+#include "yajl.h"
+
+using namespace v8;
+using namespace node;
+
+namespace yajljs {
+void Handle::Initialize ( v8::Handle<v8::Object> target )
+{
+    v8::HandleScope scope;
+
+    v8::Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(New);
+
+    t->Inherit( EventEmitter::constructor_template );
+    t->InstanceTemplate()->SetInternalFieldCount(1);
+
+    NODE_SET_PROTOTYPE_METHOD( t, "parse", Parse );
+    target->Set( v8::String::NewSymbol( "Handle"), t->GetFunction() );
+}
+
+v8::Handle<v8::Value>
+Handle::New (const v8::Arguments& args)
+{
+    v8::HandleScope scope;
+
+    yajl_parser_config cfg;
+
+    if( args.Length() < 1 || !args[0]->IsObject() )
+    {
+        return ThrowException( Exception::TypeError(
+                    String::New( "Argument 0 must be a yajl_parser_config like object" ) ) );
+    }
+
+    Local<Object> obj = args[0]->ToObject();
+
+    Local<Integer> allowComments = obj->Get( String::New( "allowComments" ) )->ToInteger();
+
+    cfg.allowComments = allowComments->Value();
+    Handle *handle = new Handle( cfg );
+    handle->Wrap( args.This() );
+    return args.This();
+}
+
+Handle::Handle( yajl_parser_config cfg ) : EventEmitter()
+{
+    callbacks.yajl_null = onNull;
+    callbacks.yajl_boolean = onBoolean;
+    
+    // TODO expose
+    yc_handle = yajl_alloc( &callbacks, &cfg, NULL, NULL );
+}
+
+Handle::~Handle()
+{
+    yajl_free( yc_handle );
+}
+
+}
+
+v8::Handle<Value> yajljs::Handle::Parse( const Arguments& args )
+{
+    HandleScope scope;
+    std::cerr << "PARSING\n";
+    return args.This();
+}
+
+extern "C" void
+init (v8::Handle<v8::Object> target)
+{
+    v8::HandleScope scope;
+    yajljs::Handle::Initialize(target);
+}
+#ifndef YAJLJS_H
+#define YAJLJS_H
+
+#include <yajl/yajl_parse.h>
+#include <yajl/yajl_gen.h>
+
+#include <v8.h>
+#include <node.h>
+#include <node/node_events.h>
+
+namespace yajljs {
+class Handle : public node::EventEmitter
+{
+  public:
+    static void
+    Initialize ( v8::Handle<v8::Object> target );
+
+    static v8::Handle<v8::Value> Parse( const v8::Arguments& args );
+
+  protected:
+    static v8::Handle<v8::Value>
+    New (const v8::Arguments& args);
+
+    Handle( yajl_parser_config cfg );
+    ~Handle();
+
+  private:
+    yajl_handle yc_handle;
+    yajl_callbacks callbacks;
+};
+}
+
+#endif
+var yajl = require('./binding_yajl');
+exports.Generator = function( conf ) {
+}
+
+/**
+ * Create a new YAJL handle to parse JSON
+ * Parameters:
+ *   parser_config - a literal object (optional)
+ *     default:
+ *      { allowComments : true, checkUTF8 : true }
+ */
+exports.createHandle = function(parser_config) {
+    cfg = process.mixin( {
+                allowComments : true
+              , checkUTF8 : true
+            }, parser_config );
+    return new yajl.Handle( cfg );
+}
+// The complete reformatter in javascript
+var sys = require('sys');
+var posix = require('posix');
+var yajl = require('./src/yajl');
+
+var callbacks = {
+    onNull : function(gen) {
+        gen.addNull();
+    },
+    onBoolean : function(gen, bool) {
+        gen.boolean( bool );
+    },
+    onNumber : function(gen, str) {
+        gen.number( str );
+    },
+    onString : function(gen, str) {
+        gen.string( str );
+    },
+    onMapKey : function(gen, key) {
+        gen.string( key );
+    },
+    onStartMap : function(gen) {
+        g.openMap();
+    },
+    onEndMap : function(gen) {
+        g.closeMap();
+    },
+    onStartArray : function(gen) {
+        g.openArray();
+    },
+    onEndArray : function(gen) {
+        g.closeArray();
+    }
+};
+
+function usage() {
+    sys.error( "Usage: %s <filename>\n"
+               +"    -m Minimize json rather than beautify (default)\n"
+               +"    -u allow invalid UTF8 inside strings during parsing\n");
+    process.exit(1);
+}
+
+var conf = {
+    beautify: 1,
+    indentString: "  "
+};
+
+var cfg = {
+    allowComments: 1,
+    checkUTF8: 1
+};
+
+if( process.ARGV.length == 3 ) {
+    if( process.ARGV[2] == "-m" )
+        conf.beautify = 0;
+    else if( process.ARGV[2] == "-u" )
+        cfg.checkUTF8 = 0;
+    else
+        usage();
+}
+else if( process.ARGV.length != 2 ) {
+    usage();
+}
+
+var g = new yajl.Generator( conf, null );
+
+var handle = yajl.createHandle();
+handle.addListener( "null", function() {
+    sys.debug("Nullify");
+});
+
+var done = false;
+
+process.stdio.open();
+process.stdio.addListener( "data", function( data ) {
+    var stat = handle.parse(data);
+//    if( stat != yajl.STATUS_OK &&
+//        stat != yajl.STATUS_INSUFFICIENT_DATA ) {
+//        sys.error( handle.error( yajl.ERROR_VERBOSE, data ) );
+//    }
+});
+//
+//process.stdio.addListener( "close", function() {
+//    var stat = handle.parseComplete();
+//    if( stat != yajl.STATUS_OK )
+//        sys.error( handle.error( yajl.ERROR_VERBOSE, data ) );
+//    else
+//        process.stdio.write( g.buffer() );
+//});
+import Options
+from os import popen, unlink, symlink, getcwd
+from os.path import exists
+
+srcdir = "."
+blddir = "build"
+VERSION = "0.0.1"
+
+def set_options(opt):
+  opt.tool_options("compiler_cxx")
+
+def configure(conf):
+  conf.check_tool("compiler_cxx")
+  conf.check_tool("node_addon")
+
+def build(bld):
+  obj = bld.new_task_gen("cxx", "shlib", "node_addon")
+  obj.target = "src/binding_yajl"
+  #obj.source = "src/*.cc"
+  obj.find_sources_in_dirs("src")
+  obj.lib = "yajl"
+
+def shutdown(bld):
+  # HACK to get binding.node out of build directory.
+  # better way to do this?
+  if Options.commands['clean']:
+    if exists('src/binding_yajl.node'): unlink('src/binding_yajl.node')
+  else:
+    if exists('build/default/src/binding_yajl.node') and not exists('src/binding_yajl.node'):
+      symlink(getcwd()+'/build/default/src/binding_yajl.node', 'src/binding_yajl.node')