[node-osmium] 05/10: Imported Upstream version 0.1.2

Sebastiaan Couwenberg sebastic at moszumanska.debian.org
Fri Mar 6 17:09:13 UTC 2015


This is an automated email from the git hooks/post-receive script.

sebastic pushed a commit to branch master
in repository node-osmium.

commit 9a9a819fc63ceb7e7b8358d21c2199c4e0d34ad6
Author: Bas Couwenberg <sebastic at xs4all.nl>
Date:   Fri Mar 6 15:16:35 2015 +0100

    Imported Upstream version 0.1.2
---
 .gitignore                    |   2 +-
 .travis.yml                   |  13 +--
 CHANGELOG.md                  |   7 ++
 Makefile                      |  17 ++--
 binding.gyp                   |   1 +
 common.gypi                   |   1 +
 lib/osmium.js                 |   6 +-
 package.json                  |  11 ++-
 src/buffer.hpp                |  88 -------------------
 src/file_wrap.cpp             |  11 +--
 src/file_wrap.hpp             |  20 ++---
 src/handler.cpp               | 191 +++++++++++++++++++++++++++++++++++++++++-
 src/handler.hpp               |  54 ++++++------
 src/location_handler_wrap.cpp |  38 +++++++++
 src/location_handler_wrap.hpp |  75 +++++++++++++++++
 src/node_osmium.cpp           |   4 +-
 src/osm_node_wrap.cpp         |  41 +++++----
 src/osm_node_wrap.hpp         |  13 ++-
 src/osm_object_wrap.cpp       |  35 ++++++++
 src/osm_object_wrap.hpp       |  21 ++++-
 src/osm_relation_wrap.cpp     |  20 ++---
 src/osm_relation_wrap.hpp     |  11 +--
 src/osm_way_wrap.cpp          |  26 +++---
 src/osm_way_wrap.hpp          |  11 +--
 src/reader_wrap.cpp           | 170 ++++++++++++++++++++++++++-----------
 src/reader_wrap.hpp           |  38 ++++-----
 test/osmium.test.js           | 104 ++++++++++++++++++-----
 27 files changed, 714 insertions(+), 315 deletions(-)

diff --git a/.gitignore b/.gitignore
index 31fef51..b13eb67 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,5 +1,5 @@
 node_modules
-lib/osmium.node
+lib/binding
 .DS_Store
 build
 berlin-latest.osm.pbf
diff --git a/.travis.yml b/.travis.yml
index 0f23dda..eb695f4 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -4,16 +4,19 @@ node_js:
  - "0.10"
 
 before_install:
+ # we need c++11 compatible g++
+ - sudo apt-add-repository --yes ppa:ubuntu-toolchain-r/test
+ - sudo apt-get -y update
+ - sudo apt-get -y install gcc-4.7 g++-4.7
  # first test install of binary
- - npm install --verbose
- - make test
+# - npm install --verbose
+# - make test
 
 install:
  # next test source compile, so get dependencies
  - sudo apt-add-repository --yes ppa:mapnik/boost
- - sudo apt-add-repository --yes ppa:ubuntu-toolchain-r/test
  - sudo apt-get -y update -qq
- - sudo apt-get -y install git gcc-4.7 g++-4.7 build-essential libboost-dev zlib1g-dev protobuf-compiler libprotobuf-lite7 libprotobuf-dev libexpat1-dev libsparsehash-dev
+ - sudo apt-get -y install git build-essential libboost-dev zlib1g-dev protobuf-compiler libprotobuf-lite7 libprotobuf-dev libexpat1-dev libsparsehash-dev
  - git clone https://github.com/scrosby/OSM-binary.git
  - cd OSM-binary/src
  - make && sudo make install
@@ -21,7 +24,7 @@ install:
 
 before_script:
  - git clone https://github.com/osmcode/libosmium.git ../libosmium
- - CXX=g++-4.7 npm install
+ - CXX=g++-4.7 npm install --build-from-source
 
 script:
  - make test
diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
index 0000000..c320724
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,7 @@
+## Changelog
+
+### 0.1.2
+
+ - Upgraded node-pre-gyp to 0.5.10
+
+
diff --git a/Makefile b/Makefile
index bca59f3..645cb37 100755
--- a/Makefile
+++ b/Makefile
@@ -1,10 +1,13 @@
 all: osmium.node
 
-./build:
-	`npm explore npm -g -- pwd`/bin/node-gyp-bin/node-gyp configure
+./node_modules/.bin/node-gyp:
+	npm install node-gyp
 
-osmium.node: binding.gyp Makefile ./build
-	`npm explore npm -g -- pwd`/bin/node-gyp-bin/node-gyp --verbose build
+./build: binding.gyp ./node_modules/.bin/node-gyp
+	./node_modules/.bin/node-gyp configure
+
+osmium.node: Makefile ./build
+	./node_modules/.bin/node-gyp build
 
 clean:
 	rm -rf ./build
@@ -14,11 +17,7 @@ rebuild:
 	@make clean
 	@make
 
-test/data/berlin-latest.osm.pbf:
-	cd test/data; \
-	wget http://download.geofabrik.de/europe/germany/berlin-latest.osm.pbf
-
-test: test/data/berlin-latest.osm.pbf
+test:
 	@PATH="./node_modules/mocha/bin:${PATH}" && NODE_PATH="./lib:$(NODE_PATH)" mocha -R spec --timeout 10000
 
 indent:
diff --git a/binding.gyp b/binding.gyp
index e262a27..740c262 100644
--- a/binding.gyp
+++ b/binding.gyp
@@ -10,6 +10,7 @@
       "sources": [
         "src/node_osmium.cpp",
         "src/handler.cpp",
+        "src/location_handler_wrap.cpp",
         "src/file_wrap.cpp",
         "src/reader_wrap.cpp",
         "src/osm_object_wrap.cpp",
diff --git a/common.gypi b/common.gypi
index f59efdf..3e0d5de 100644
--- a/common.gypi
+++ b/common.gypi
@@ -13,6 +13,7 @@
           'Release': {
               'xcode_settings': {
                 'GCC_OPTIMIZATION_LEVEL': 's',
+                'OTHER_CPLUSPLUSFLAGS':['-gline-tables-only','-fno-omit-frame-pointer'],
               },
               'ldflags': [
                     '-Wl,-s'
diff --git a/lib/osmium.js b/lib/osmium.js
index ccbb5cd..1722bfb 100644
--- a/lib/osmium.js
+++ b/lib/osmium.js
@@ -1,3 +1,7 @@
-var osmium = require('./osmium.node');
+var osmium = require('./binding/osmium.node');
 exports = module.exports = osmium;
 exports.version = require('../package').version;
+
+exports.Node.prototype.date = function() {
+    return new Date(1000*this.timestamp);
+}
\ No newline at end of file
diff --git a/package.json b/package.json
index f2cd1de..d9509ba 100644
--- a/package.json
+++ b/package.json
@@ -7,7 +7,7 @@
     "contributors": [
         "Jochen Topf <joto>"
     ],
-    "version": "0.1.1",
+    "version": "0.1.2",
     "main": "./lib/osmium.js",
     "bugs": {
         "email": "dane at mapbox.com",
@@ -25,12 +25,11 @@
     },
     "binary": {
         "module_name": "osmium",
-        "module_path": "./lib",
-        "remote_uri": "http://node-osmium.s3.amazonaws.com",
-        "template": "{module_name}-v{major}.{minor}.{patch}-{node_abi}-{platform}-{arch}.tar.gz"
+        "module_path": "./lib/binding/",
+        "host": "https://node-osmium.s3.amazonaws.com"
     },
     "dependencies": {
-        "node-pre-gyp": "~0.1.4"
+        "node-pre-gyp": "~0.5.10"
     },
     "bundledDependencies":["node-pre-gyp"],
     "devDependencies": {
@@ -41,7 +40,7 @@
         "node": ">= 0.6.13 < 0.11.0"
     },
     "scripts": {
-        "install": "node-pre-gyp rebuild",
+        "install": "node-pre-gyp install --fallback-to-build",
         "test": "mocha -R spec"
     }
 }
diff --git a/src/buffer.hpp b/src/buffer.hpp
deleted file mode 100644
index ccb28a1..0000000
--- a/src/buffer.hpp
+++ /dev/null
@@ -1,88 +0,0 @@
-// c++11
-#include <sstream>
-
-// v8
-#include <v8.h>
-
-// node.js
-#include <node.h>
-#include <node_version.h>
-#include <node_object_wrap.h>
-
-// osmium
-#include <osmium/memory/buffer.hpp>
-#include <osmium/osm/dump.hpp>
-#include <osmium/visitor.hpp>
-
-using namespace v8;
-
-namespace node_osmium {
-
-    class Buffer : public node::ObjectWrap {
-
-    public:
-
-        static Persistent<FunctionTemplate> constructor;
-        static void Initialize(Handle<Object> target);
-        static Handle<Value> New(const Arguments& args);
-        static Handle<Value> dump(const Arguments& args);
-        Buffer(reader_ptr reader);
-        void _ref() {
-            Ref();
-        }
-        void _unref() {
-            Unref();
-        }
-        osmium::memory::Buffer buf;
-
-    private:
-
-        ~Buffer();
-    };
-
-    Persistent<FunctionTemplate> Buffer::constructor;
-
-    void Buffer::Initialize(Handle<Object> target) {
-        HandleScope scope;
-        constructor = Persistent<FunctionTemplate>::New(FunctionTemplate::New(Buffer::New));
-        constructor->InstanceTemplate()->SetInternalFieldCount(1);
-        constructor->SetClassName(String::NewSymbol("Buffer"));
-        NODE_SET_PROTOTYPE_METHOD(constructor, "dump", dump);
-        target->Set(String::NewSymbol("Buffer"), constructor->GetFunction());
-    }
-
-    Buffer::Buffer(reader_ptr reader) :
-        ObjectWrap(),
-        buf(reader.get()->read()) {
-    }
-
-    Buffer::~Buffer() {
-    }
-
-    Handle<Value> Buffer::New(const Arguments& args) {
-        HandleScope scope;
-        if (args[0]->IsExternal()) {
-            Local<External> ext = Local<External>::Cast(args[0]);
-            void* ptr = ext->Value();
-            Buffer* b =  static_cast<Buffer*>(ptr);
-            b->Wrap(args.This());
-            return args.This();
-        } else {
-            return ThrowException(Exception::TypeError(String::New("osmium.Buffer cannot be created in Javascript")));
-        }
-        return Undefined();
-    }
-
-
-    Handle<Value> Buffer::dump(const Arguments& args) {
-        HandleScope scope;
-        Buffer* b = node::ObjectWrap::Unwrap<Buffer>(args.This());
-        std::ostringstream ss;
-        osmium::osm::Dump dump(ss);
-        osmium::apply(b->buf, dump);
-        Local<String> obj = String::New(ss.str().c_str());
-        return scope.Close(obj);
-    }
-
-} // namespace node_osmium
-
diff --git a/src/file_wrap.cpp b/src/file_wrap.cpp
index c3abc55..64ea8e0 100644
--- a/src/file_wrap.cpp
+++ b/src/file_wrap.cpp
@@ -1,4 +1,10 @@
 
+// c++
+#include <exception>
+
+// v8
+#include <v8.h>
+
 #include "file_wrap.hpp"
 
 namespace node_osmium {
@@ -13,11 +19,6 @@ namespace node_osmium {
         target->Set(String::NewSymbol("File"), constructor->GetFunction());
     }
 
-    FileWrap::FileWrap(const std::string& filename, const std::string& format) :
-        ObjectWrap(),
-        this_(std::make_shared<osmium::io::File>(filename, format)) {
-    }
-
     Handle<Value> FileWrap::New(const Arguments& args) {
         HandleScope scope;
         if (!args.IsConstructCall()) {
diff --git a/src/file_wrap.hpp b/src/file_wrap.hpp
index 6a521c6..70ff142 100644
--- a/src/file_wrap.hpp
+++ b/src/file_wrap.hpp
@@ -1,8 +1,7 @@
 #ifndef FILE_WRAP_HPP
 #define FILE_WRAP_HPP
 
-// c++11
-#include <exception>
+// c++
 #include <memory>
 #include <string>
 
@@ -10,8 +9,6 @@
 #include <v8.h>
 
 // node.js
-#include <node.h>
-#include <node_version.h>
 #include <node_object_wrap.h>
 
 // osmium
@@ -31,18 +28,13 @@ namespace node_osmium {
         static void Initialize(Handle<Object> target);
         static Handle<Value> New(const Arguments& args);
 
-        FileWrap(const std::string& filename = "", const std::string& format = "");
-
-        void _ref() {
-            Ref();
-        }
-
-        void _unref() {
-            Unref();
+        FileWrap(const std::string& filename, const std::string& format) :
+            ObjectWrap(),
+            m_this(std::make_shared<osmium::io::File>(filename, format)) {
         }
 
         file_ptr get() {
-            return this_;
+            return m_this;
         }
 
     private:
@@ -50,7 +42,7 @@ namespace node_osmium {
         ~FileWrap() {
         }
 
-        file_ptr this_;
+        file_ptr m_this;
 
     };
 
diff --git a/src/handler.cpp b/src/handler.cpp
index 77d52c9..e842c17 100644
--- a/src/handler.cpp
+++ b/src/handler.cpp
@@ -1,4 +1,18 @@
 
+// c++
+#include <string>
+
+// v8
+#include <v8.h>
+
+// node
+#include <node.h>
+#include <node_object_wrap.h>
+
+// osmium
+#include <osmium/osm/object.hpp>
+
+// node-osmium
 #include "handler.hpp"
 #include "osm_node_wrap.hpp"
 #include "osm_way_wrap.hpp"
@@ -95,6 +109,41 @@ namespace node_osmium {
                 handler->relation_cb.Dispose();
             }
             handler->relation_cb = Persistent<Function>::New(callback);
+        } else if (callback_name == "init") {
+            if (!handler->init_cb.IsEmpty()) {
+                handler->init_cb.Dispose();
+            }
+            handler->init_cb = Persistent<Function>::New(callback);
+        } else if (callback_name == "before_nodes") {
+            if (!handler->before_nodes_cb.IsEmpty()) {
+                handler->before_nodes_cb.Dispose();
+            }
+            handler->before_nodes_cb = Persistent<Function>::New(callback);
+        } else if (callback_name == "after_nodes") {
+            if (!handler->after_nodes_cb.IsEmpty()) {
+                handler->after_nodes_cb.Dispose();
+            }
+            handler->after_nodes_cb = Persistent<Function>::New(callback);
+        } else if (callback_name == "before_ways") {
+            if (!handler->before_ways_cb.IsEmpty()) {
+                handler->before_ways_cb.Dispose();
+            }
+            handler->before_ways_cb = Persistent<Function>::New(callback);
+        } else if (callback_name == "after_ways") {
+            if (!handler->after_ways_cb.IsEmpty()) {
+                handler->after_ways_cb.Dispose();
+            }
+            handler->after_ways_cb = Persistent<Function>::New(callback);
+        } else if (callback_name == "before_relations") {
+            if (!handler->before_relations_cb.IsEmpty()) {
+                handler->before_relations_cb.Dispose();
+            }
+            handler->before_relations_cb = Persistent<Function>::New(callback);
+        } else if (callback_name == "after_relations") {
+            if (!handler->after_relations_cb.IsEmpty()) {
+                handler->after_relations_cb.Dispose();
+            }
+            handler->after_relations_cb = Persistent<Function>::New(callback);
         } else if (callback_name == "done") {
             if (!handler->done_cb.IsEmpty()) {
                 handler->done_cb.Dispose();
@@ -104,7 +153,7 @@ namespace node_osmium {
         return scope.Close(Undefined());
     }
 
-    void JSHandler::dispatch_object(const osmium::io::InputIterator<osmium::io::Reader, osmium::Object>& it) {
+    void JSHandler::dispatch_object(const input_iterator& it) {
         HandleScope scope;
         switch (it->type()) {
             case osmium::item_type::node:
@@ -166,5 +215,145 @@ namespace node_osmium {
         }
     }
 
+    void JSHandler::init() {
+        if (!init_cb.IsEmpty()) {
+            Local<Value> argv[0] = { };
+            TryCatch trycatch;
+            Handle<Value> v = init_cb->Call(Context::GetCurrent()->Global(), 0, argv);
+            if (v.IsEmpty()) {
+                Handle<Value> exception = trycatch.Exception();
+                String::AsciiValue exception_str(exception);
+                printf("Exception: %s\n", *exception_str);
+                exit(1);
+            }
+        }
+    }
+
+    void JSHandler::before_nodes() {
+        if (!before_nodes_cb.IsEmpty()) {
+            Local<Value> argv[0] = { };
+            TryCatch trycatch;
+            Handle<Value> v = before_nodes_cb->Call(Context::GetCurrent()->Global(), 0, argv);
+            if (v.IsEmpty()) {
+                Handle<Value> exception = trycatch.Exception();
+                String::AsciiValue exception_str(exception);
+                printf("Exception: %s\n", *exception_str);
+                exit(1);
+            }
+        }
+    }
+
+    void JSHandler::after_nodes() {
+        if (!after_nodes_cb.IsEmpty()) {
+            Local<Value> argv[0] = { };
+            TryCatch trycatch;
+            Handle<Value> v = after_nodes_cb->Call(Context::GetCurrent()->Global(), 0, argv);
+            if (v.IsEmpty()) {
+                Handle<Value> exception = trycatch.Exception();
+                String::AsciiValue exception_str(exception);
+                printf("Exception: %s\n", *exception_str);
+                exit(1);
+            }
+        }
+    }
+
+    void JSHandler::before_ways() {
+        if (!before_ways_cb.IsEmpty()) {
+            Local<Value> argv[0] = { };
+            TryCatch trycatch;
+            Handle<Value> v = before_ways_cb->Call(Context::GetCurrent()->Global(), 0, argv);
+            if (v.IsEmpty()) {
+                Handle<Value> exception = trycatch.Exception();
+                String::AsciiValue exception_str(exception);
+                printf("Exception: %s\n", *exception_str);
+                exit(1);
+            }
+        }
+    }
+
+    void JSHandler::after_ways() {
+        if (!after_ways_cb.IsEmpty()) {
+            Local<Value> argv[0] = { };
+            TryCatch trycatch;
+            Handle<Value> v = after_ways_cb->Call(Context::GetCurrent()->Global(), 0, argv);
+            if (v.IsEmpty()) {
+                Handle<Value> exception = trycatch.Exception();
+                String::AsciiValue exception_str(exception);
+                printf("Exception: %s\n", *exception_str);
+                exit(1);
+            }
+        }
+    }
+
+    void JSHandler::before_relations() {
+        if (!before_relations_cb.IsEmpty()) {
+            Local<Value> argv[0] = { };
+            TryCatch trycatch;
+            Handle<Value> v = before_relations_cb->Call(Context::GetCurrent()->Global(), 0, argv);
+            if (v.IsEmpty()) {
+                Handle<Value> exception = trycatch.Exception();
+                String::AsciiValue exception_str(exception);
+                printf("Exception: %s\n", *exception_str);
+                exit(1);
+            }
+        }
+    }
+
+    void JSHandler::after_relations() {
+        if (!after_relations_cb.IsEmpty()) {
+            Local<Value> argv[0] = { };
+            TryCatch trycatch;
+            Handle<Value> v = after_relations_cb->Call(Context::GetCurrent()->Global(), 0, argv);
+            if (v.IsEmpty()) {
+                Handle<Value> exception = trycatch.Exception();
+                String::AsciiValue exception_str(exception);
+                printf("Exception: %s\n", *exception_str);
+                exit(1);
+            }
+        }
+    }
+
+    void JSHandler::before_changesets() {
+        if (!before_changesets_cb.IsEmpty()) {
+            Local<Value> argv[0] = { };
+            TryCatch trycatch;
+            Handle<Value> v = before_changesets_cb->Call(Context::GetCurrent()->Global(), 0, argv);
+            if (v.IsEmpty()) {
+                Handle<Value> exception = trycatch.Exception();
+                String::AsciiValue exception_str(exception);
+                printf("Exception: %s\n", *exception_str);
+                exit(1);
+            }
+        }
+    }
+
+    void JSHandler::after_changesets() {
+        if (!after_changesets_cb.IsEmpty()) {
+            Local<Value> argv[0] = { };
+            TryCatch trycatch;
+            Handle<Value> v = after_changesets_cb->Call(Context::GetCurrent()->Global(), 0, argv);
+            if (v.IsEmpty()) {
+                Handle<Value> exception = trycatch.Exception();
+                String::AsciiValue exception_str(exception);
+                printf("Exception: %s\n", *exception_str);
+                exit(1);
+            }
+        }
+    }
+
+    void JSHandler::done() {
+        if (!done_cb.IsEmpty()) {
+            Local<Value> argv[0] = { };
+            TryCatch trycatch;
+            Handle<Value> v = done_cb->Call(Context::GetCurrent()->Global(), 0, argv);
+            if (v.IsEmpty()) {
+                Handle<Value> exception = trycatch.Exception();
+                String::AsciiValue exception_str(exception);
+                printf("Exception: %s\n", *exception_str);
+                exit(1);
+            }
+        }
+    }
+
 } // namespace node_osmium
 
diff --git a/src/handler.hpp b/src/handler.hpp
index 351f319..d529bc7 100644
--- a/src/handler.hpp
+++ b/src/handler.hpp
@@ -1,22 +1,12 @@
-// c++11
-#include <string>
 
 // v8
 #include <v8.h>
 
 // node.js
-#include <node.h>
-#include <node_version.h>
 #include <node_object_wrap.h>
-#include <node_buffer.h>
 
-// osmium
-#include <osmium/handler.hpp>
-#include <osmium/osm.hpp>
-#include <osmium/io/input_iterator.hpp>
-#include <osmium/io/reader.hpp>
-#include <osmium/geom/wkb.hpp>
-#include <osmium/geom/wkt.hpp>
+// node-osmium
+#include "osm_object_wrap.hpp"
 
 namespace node_osmium {
 
@@ -33,27 +23,39 @@ namespace node_osmium {
         static Handle<Value> options(const Arguments& args);
         JSHandler();
 
-        void _ref() {
-            Ref();
-        }
+        void dispatch_object(const input_iterator& it);
 
-        void _unref() {
-            Unref();
-        }
+        void init();
+        void before_nodes();
+        void after_nodes();
+        void before_ways();
+        void after_ways();
+        void before_relations();
+        void after_relations();
+        void before_changesets();
+        void after_changesets();
+        void done();
 
-        void dispatch_object(const osmium::io::InputIterator<osmium::io::Reader, osmium::Object>& it);
+        bool node_callback_for_tagged_only;
 
-        void done() {
-            if (!done_cb.IsEmpty()) {
-                Local<Value> argv[0] = { };
-                done_cb->Call(Context::GetCurrent()->Global(), 0, argv);
-            }
-        }
+        Persistent<Function> init_cb;
 
-        bool node_callback_for_tagged_only;
+        Persistent<Function> before_nodes_cb;
         Persistent<Function> node_cb;
+        Persistent<Function> after_nodes_cb;
+
+        Persistent<Function> before_ways_cb;
         Persistent<Function> way_cb;
+        Persistent<Function> after_ways_cb;
+
+        Persistent<Function> before_relations_cb;
         Persistent<Function> relation_cb;
+        Persistent<Function> after_relations_cb;
+
+        Persistent<Function> before_changesets_cb;
+        Persistent<Function> changeset_cb;
+        Persistent<Function> after_changesets_cb;
+
         Persistent<Function> done_cb;
 
     private:
diff --git a/src/location_handler_wrap.cpp b/src/location_handler_wrap.cpp
new file mode 100644
index 0000000..617df2c
--- /dev/null
+++ b/src/location_handler_wrap.cpp
@@ -0,0 +1,38 @@
+
+#include "location_handler_wrap.hpp"
+
+namespace node_osmium {
+
+    Persistent<FunctionTemplate> LocationHandlerWrap::constructor;
+
+    void LocationHandlerWrap::Initialize(Handle<Object> target) {
+        HandleScope scope;
+        constructor = Persistent<FunctionTemplate>::New(FunctionTemplate::New(LocationHandlerWrap::New));
+        constructor->InstanceTemplate()->SetInternalFieldCount(1);
+        constructor->SetClassName(String::NewSymbol("LocationHandler"));
+        NODE_SET_PROTOTYPE_METHOD(constructor, "clear", clear);
+        target->Set(String::NewSymbol("LocationHandler"), constructor->GetFunction());
+    }
+
+    Handle<Value> LocationHandlerWrap::New(const Arguments& args) {
+        HandleScope scope;
+        try {
+            if (!args.IsConstructCall()) {
+                return ThrowException(Exception::Error(String::New("Cannot call constructor as function, you need to use 'new' keyword")));
+            }
+            LocationHandlerWrap* q = new LocationHandlerWrap();
+            q->Wrap(args.This());
+            return args.This();
+        } catch (const std::exception& ex) {
+            return ThrowException(Exception::TypeError(String::New(ex.what())));
+        }
+    }
+
+    Handle<Value> LocationHandlerWrap::clear(const Arguments& args) {
+        HandleScope scope;
+        // XXX do something here
+        return scope.Close(Undefined());
+    }
+
+} // namespace node_osmium
+
diff --git a/src/location_handler_wrap.hpp b/src/location_handler_wrap.hpp
new file mode 100644
index 0000000..4d058ad
--- /dev/null
+++ b/src/location_handler_wrap.hpp
@@ -0,0 +1,75 @@
+#ifndef LOCATION_HANDLER_WRAP_HPP
+#define LOCATION_HANDLER_WRAP_HPP
+
+// c++
+#include <memory>
+
+// v8
+#include <v8.h>
+
+// node.js
+#include <node_object_wrap.h>
+
+// osmium
+#include <osmium/handler/node_locations_for_ways.hpp>
+#include <osmium/index/map/dummy.hpp>
+#include <osmium/index/map/stl_map.hpp>
+#include <osmium/index/map/sparse_table.hpp>
+
+using namespace v8;
+
+namespace node_osmium {
+
+    typedef osmium::index::map::Dummy<osmium::unsigned_object_id_type, osmium::Location> index_neg_type;
+    typedef osmium::index::map::SparseTable<osmium::unsigned_object_id_type, osmium::Location> index_pos_type;
+    typedef osmium::handler::NodeLocationsForWays<index_pos_type, index_neg_type> location_handler_type;
+
+    typedef std::shared_ptr<location_handler_type> location_handler_ptr;
+
+    class LocationHandlerWrap : public node::ObjectWrap {
+
+    public:
+
+        static Persistent<FunctionTemplate> constructor;
+
+        static void Initialize(Handle<Object> target);
+        static Handle<Value> New(const Arguments& args);
+        static Handle<Value> clear(const Arguments& args);
+
+        static location_handler_type& wrapped(Local<Object> object) {
+            return *(node::ObjectWrap::Unwrap<LocationHandlerWrap>(object)->get());
+        }
+
+        LocationHandlerWrap() :
+            ObjectWrap(),
+            m_index_pos(),
+            m_index_neg(),
+            m_this(std::make_shared<location_handler_type>(m_index_pos, m_index_neg)) {
+        }
+
+        void _ref() {
+            Ref();
+        }
+
+        void _unref() {
+            Unref();
+        }
+
+        location_handler_ptr get() {
+            return m_this;
+        }
+
+    private:
+
+        ~LocationHandlerWrap() {
+        }
+
+        index_pos_type m_index_pos;
+        index_neg_type m_index_neg;
+        location_handler_ptr m_this;
+
+    };
+
+} // namespace node_osmium
+
+#endif //  LOCATION_HANDLER_WRAP_HPP
diff --git a/src/node_osmium.cpp b/src/node_osmium.cpp
index 268d67c..5d6b456 100644
--- a/src/node_osmium.cpp
+++ b/src/node_osmium.cpp
@@ -13,9 +13,9 @@
 #include "osm_way_wrap.hpp"
 #include "osm_relation_wrap.hpp"
 #include "handler.hpp"
+#include "location_handler_wrap.hpp"
 #include "file_wrap.hpp"
 #include "reader_wrap.hpp"
-#include "buffer.hpp"
 
 namespace node_osmium {
 
@@ -25,8 +25,8 @@ namespace node_osmium {
             node_osmium::OSMNodeWrap::Initialize(target);
             node_osmium::OSMWayWrap::Initialize(target);
             node_osmium::OSMRelationWrap::Initialize(target);
+            node_osmium::LocationHandlerWrap::Initialize(target);
             node_osmium::JSHandler::Initialize(target);
-//            node_osmium::Buffer::Initialize(target);
             node_osmium::FileWrap::Initialize(target);
             node_osmium::ReaderWrap::Initialize(target);
         }
diff --git a/src/osm_node_wrap.cpp b/src/osm_node_wrap.cpp
index d67b3c9..82ba6bc 100644
--- a/src/osm_node_wrap.cpp
+++ b/src/osm_node_wrap.cpp
@@ -19,6 +19,17 @@ namespace node_osmium {
         NODE_SET_PROTOTYPE_METHOD(constructor, "tags", tags);
         NODE_SET_PROTOTYPE_METHOD(constructor, "wkb", wkb);
         NODE_SET_PROTOTYPE_METHOD(constructor, "wkt", wkt);
+        enum PropertyAttribute attributes =
+            static_cast<PropertyAttribute>(v8::ReadOnly | v8::DontDelete);
+        SET_ACCESSOR(constructor, "id", get_id, attributes);
+        SET_ACCESSOR(constructor, "version", get_version, attributes);
+        SET_ACCESSOR(constructor, "changeset", get_changeset, attributes);
+        SET_ACCESSOR(constructor, "visible", get_visible, attributes);
+        SET_ACCESSOR(constructor, "timestamp", get_timestamp, attributes);
+        SET_ACCESSOR(constructor, "uid", get_uid, attributes);
+        SET_ACCESSOR(constructor, "user", get_user, attributes);
+        SET_ACCESSOR(constructor, "lon", get_lon, attributes);
+        SET_ACCESSOR(constructor, "lat", get_lat, attributes);
         target->Set(String::NewSymbol("Node"), constructor->GetFunction());
     }
 
@@ -36,30 +47,27 @@ namespace node_osmium {
             void* ptr = ext->Value();
             OSMNodeWrap* node = static_cast<OSMNodeWrap*>(ptr);
             node->Wrap(args.This());
-            osmium::Node& obj = static_cast<osmium::Node&>(*(node->m_it));
-            args.This()->Set(String::New("id"), Number::New(obj.id()));
-            args.This()->Set(String::New("version"), Number::New(obj.version()));
-            args.This()->Set(String::New("changeset"), Number::New(obj.changeset()));
-            args.This()->Set(String::New("visible"), Boolean::New(obj.visible()));
-            args.This()->Set(String::New("timestamp"), Number::New(obj.timestamp()));
-            args.This()->Set(String::New("timestamp_iso"), String::New(obj.timestamp().to_iso().c_str(), obj.timestamp().to_iso().size()));
-            args.This()->Set(String::New("uid"), Number::New(obj.uid()));
-            args.This()->Set(String::New("user"), String::New(obj.user()));
-            args.This()->Set(String::New("lon"), Number::New(obj.lon()));
-            args.This()->Set(String::New("lat"), Number::New(obj.lat()));
-
             return args.This();
         } else {
             return ThrowException(Exception::TypeError(String::New("osmium.Node cannot be created in Javascript")));
         }
-        return Undefined();
+        return scope.Close(Undefined());
+    }
+
+    Handle<Value> OSMNodeWrap::get_lon(Local<String> property,const AccessorInfo& info) {
+        HandleScope scope;
+        return scope.Close(Number::New(wrapped(info.This()).lon()));
+    }
+
+    Handle<Value> OSMNodeWrap::get_lat(Local<String> property,const AccessorInfo& info) {
+        HandleScope scope;
+        return scope.Close(Number::New(wrapped(info.This()).lat()));
     }
 
     Handle<Value> OSMNodeWrap::wkb(const Arguments& args) {
         HandleScope scope;
-        osmium::Node& node = static_cast<osmium::Node&>(*(node::ObjectWrap::Unwrap<OSMNodeWrap>(args.This())->m_it));
 
-        std::string wkb { wkb_factory.create_point(node) };
+        std::string wkb { wkb_factory.create_point(wrapped(args.This())) };
 #if NODE_VERSION_AT_LEAST(0, 10, 0)
         return scope.Close(node::Buffer::New(wkb.data(), wkb.size())->handle_);
 #else
@@ -69,9 +77,8 @@ namespace node_osmium {
 
     Handle<Value> OSMNodeWrap::wkt(const Arguments& args) {
         HandleScope scope;
-        osmium::Node& node = static_cast<osmium::Node&>(*(node::ObjectWrap::Unwrap<OSMNodeWrap>(args.This())->m_it));
 
-        std::string wkt { wkt_factory.create_point(node) };
+        std::string wkt { wkt_factory.create_point(wrapped(args.This())) };
 
         return scope.Close(String::New(wkt.c_str()));
     }
diff --git a/src/osm_node_wrap.hpp b/src/osm_node_wrap.hpp
index 4994f01..0a92d4f 100644
--- a/src/osm_node_wrap.hpp
+++ b/src/osm_node_wrap.hpp
@@ -30,18 +30,17 @@ namespace node_osmium {
         static Handle<Value> New(const Arguments& args);
         static Handle<Value> wkb(const Arguments& args);
         static Handle<Value> wkt(const Arguments& args);
-        OSMNodeWrap(const input_iterator&);
+        static Handle<Value> get_lon(Local<String> property,const AccessorInfo& info);
+        static Handle<Value> get_lat(Local<String> property,const AccessorInfo& info);
 
-        void _ref() {
-            Ref();
+        static osmium::Node& wrapped(Local<Object> object) {
+            return static_cast<osmium::Node&>(OSMObjectWrap::wrapped(object));
         }
 
-        void _unref() {
-            Unref();
-        }
+        OSMNodeWrap(const input_iterator&);
 
         osmium::Node& object() {
-            return static_cast<osmium::Node&>(*m_it);
+            return static_cast<osmium::Node&>(*get());
         }
 
     private:
diff --git a/src/osm_object_wrap.cpp b/src/osm_object_wrap.cpp
index 0caacc4..f5801b4 100644
--- a/src/osm_object_wrap.cpp
+++ b/src/osm_object_wrap.cpp
@@ -25,4 +25,39 @@ namespace node_osmium {
         return Undefined();
     }
 
+    Handle<Value> OSMObjectWrap::get_id(Local<String> property,const AccessorInfo& info) {
+        HandleScope scope;
+        return scope.Close(Number::New(wrapped(info.This()).id()));
+    }
+
+    Handle<Value> OSMObjectWrap::get_version(Local<String> property,const AccessorInfo& info) {
+        HandleScope scope;
+        return scope.Close(Number::New(wrapped(info.This()).version()));
+    }
+
+    Handle<Value> OSMObjectWrap::get_changeset(Local<String> property,const AccessorInfo& info) {
+        HandleScope scope;
+        return scope.Close(Number::New(wrapped(info.This()).changeset()));
+    }
+
+    Handle<Value> OSMObjectWrap::get_visible(Local<String> property,const AccessorInfo& info) {
+        HandleScope scope;
+        return scope.Close(Boolean::New(wrapped(info.This()).visible()));
+    }
+
+    Handle<Value> OSMObjectWrap::get_timestamp(Local<String> property,const AccessorInfo& info) {
+        HandleScope scope;
+        return scope.Close(Number::New(wrapped(info.This()).timestamp()));
+    }
+
+    Handle<Value> OSMObjectWrap::get_uid(Local<String> property,const AccessorInfo& info) {
+        HandleScope scope;
+        return scope.Close(Number::New(wrapped(info.This()).uid()));
+    }
+
+    Handle<Value> OSMObjectWrap::get_user(Local<String> property,const AccessorInfo& info) {
+        HandleScope scope;
+        return scope.Close(String::New(wrapped(info.This()).user()));
+    }
+
 } // namespace node_osmium
diff --git a/src/osm_object_wrap.hpp b/src/osm_object_wrap.hpp
index 805d3e7..e5fd50a 100644
--- a/src/osm_object_wrap.hpp
+++ b/src/osm_object_wrap.hpp
@@ -17,24 +17,41 @@
 
 using namespace v8;
 
+#define SET_ACCESSOR(t, name, getter,attributes)                                         \
+    t->InstanceTemplate()->SetAccessor(String::NewSymbol(name),getter,NULL,Handle<Value>(),v8::DEFAULT,attributes); \
+ 
+
 namespace node_osmium {
 
     typedef osmium::io::InputIterator<osmium::io::Reader, osmium::Object> input_iterator;
 
     class OSMObjectWrap : public node::ObjectWrap {
 
-    protected:
-
         input_iterator m_it;
 
     public:
 
         static Handle<Value> tags(const Arguments& args);
+        static Handle<Value> get_id(Local<String> property,const AccessorInfo& info);
+        static Handle<Value> get_version(Local<String> property,const AccessorInfo& info);
+        static Handle<Value> get_changeset(Local<String> property,const AccessorInfo& info);
+        static Handle<Value> get_visible(Local<String> property,const AccessorInfo& info);
+        static Handle<Value> get_timestamp(Local<String> property,const AccessorInfo& info);
+        static Handle<Value> get_uid(Local<String> property,const AccessorInfo& info);
+        static Handle<Value> get_user(Local<String> property,const AccessorInfo& info);
+
+        static osmium::Object& wrapped(Local<Object> object) {
+            return *(node::ObjectWrap::Unwrap<OSMObjectWrap>(object)->get());
+        }
 
         OSMObjectWrap(const input_iterator& it) :
             m_it(it) {
         }
 
+        input_iterator& get() {
+            return m_it;
+        }
+
     }; // class OSMObjectWrap
 
 } // namespace node_osmium
diff --git a/src/osm_relation_wrap.cpp b/src/osm_relation_wrap.cpp
index 1c16b16..21e7d60 100644
--- a/src/osm_relation_wrap.cpp
+++ b/src/osm_relation_wrap.cpp
@@ -12,6 +12,15 @@ namespace node_osmium {
         constructor->SetClassName(String::NewSymbol("Relation"));
         NODE_SET_PROTOTYPE_METHOD(constructor, "tags", tags);
         NODE_SET_PROTOTYPE_METHOD(constructor, "members", members);
+        enum PropertyAttribute attributes =
+            static_cast<PropertyAttribute>(v8::ReadOnly | v8::DontDelete);
+        SET_ACCESSOR(constructor, "id", get_id, attributes);
+        SET_ACCESSOR(constructor, "version", get_version, attributes);
+        SET_ACCESSOR(constructor, "changeset", get_changeset, attributes);
+        SET_ACCESSOR(constructor, "visible", get_visible, attributes);
+        SET_ACCESSOR(constructor, "timestamp", get_timestamp, attributes);
+        SET_ACCESSOR(constructor, "uid", get_uid, attributes);
+        SET_ACCESSOR(constructor, "user", get_user, attributes);
         target->Set(String::NewSymbol("Relation"), constructor->GetFunction());
     }
 
@@ -29,15 +38,6 @@ namespace node_osmium {
             void* ptr = ext->Value();
             OSMRelationWrap* relation = static_cast<OSMRelationWrap*>(ptr);
             relation->Wrap(args.This());
-            osmium::Relation& obj = static_cast<osmium::Relation&>(*(relation->m_it));
-            args.This()->Set(String::New("id"), Number::New(obj.id()));
-            args.This()->Set(String::New("version"), Number::New(obj.version()));
-            args.This()->Set(String::New("changeset"), Number::New(obj.changeset()));
-            args.This()->Set(String::New("visible"), Boolean::New(obj.visible()));
-            args.This()->Set(String::New("timestamp"), Number::New(obj.timestamp()));
-            args.This()->Set(String::New("timestamp_iso"), String::New(obj.timestamp().to_iso().c_str(), obj.timestamp().to_iso().size()));
-            args.This()->Set(String::New("uid"), Number::New(obj.uid()));
-            args.This()->Set(String::New("user"), String::New(obj.user()));
             return args.This();
         } else {
             return ThrowException(Exception::TypeError(String::New("osmium.Relation cannot be created in Javascript")));
@@ -47,7 +47,7 @@ namespace node_osmium {
 
     Handle<Value> OSMRelationWrap::members(const Arguments& args) {
         HandleScope scope;
-        osmium::Relation& relation = static_cast<osmium::Relation&>(*(node::ObjectWrap::Unwrap<OSMRelationWrap>(args.This())->m_it));
+        osmium::Relation& relation = wrapped(args.This());
 
         if (args.Length() == 0) {
             Local<Array> members = Array::New();
diff --git a/src/osm_relation_wrap.hpp b/src/osm_relation_wrap.hpp
index d65877e..60386b3 100644
--- a/src/osm_relation_wrap.hpp
+++ b/src/osm_relation_wrap.hpp
@@ -31,18 +31,15 @@ namespace node_osmium {
         static void Initialize(Handle<Object> target);
         static Handle<Value> New(const Arguments& args);
         static Handle<Value> members(const Arguments& args);
-        OSMRelationWrap(const input_iterator&);
 
-        void _ref() {
-            Ref();
+        static osmium::Relation& wrapped(Local<Object> object) {
+            return static_cast<osmium::Relation&>(OSMObjectWrap::wrapped(object));
         }
 
-        void _unref() {
-            Unref();
-        }
+        OSMRelationWrap(const input_iterator&);
 
         osmium::Relation& object() {
-            return static_cast<osmium::Relation&>(*m_it);
+            return static_cast<osmium::Relation&>(*get());
         }
 
     private:
diff --git a/src/osm_way_wrap.cpp b/src/osm_way_wrap.cpp
index a3a3723..d3be9e7 100644
--- a/src/osm_way_wrap.cpp
+++ b/src/osm_way_wrap.cpp
@@ -20,6 +20,15 @@ namespace node_osmium {
         NODE_SET_PROTOTYPE_METHOD(constructor, "wkb", wkb);
         NODE_SET_PROTOTYPE_METHOD(constructor, "wkt", wkt);
         NODE_SET_PROTOTYPE_METHOD(constructor, "nodes", nodes);
+        enum PropertyAttribute attributes =
+            static_cast<PropertyAttribute>(v8::ReadOnly | v8::DontDelete);
+        SET_ACCESSOR(constructor, "id", get_id, attributes);
+        SET_ACCESSOR(constructor, "version", get_version, attributes);
+        SET_ACCESSOR(constructor, "changeset", get_changeset, attributes);
+        SET_ACCESSOR(constructor, "visible", get_visible, attributes);
+        SET_ACCESSOR(constructor, "timestamp", get_timestamp, attributes);
+        SET_ACCESSOR(constructor, "uid", get_uid, attributes);
+        SET_ACCESSOR(constructor, "user", get_user, attributes);
         target->Set(String::NewSymbol("Way"), constructor->GetFunction());
     }
 
@@ -37,15 +46,6 @@ namespace node_osmium {
             void* ptr = ext->Value();
             OSMWayWrap* way = static_cast<OSMWayWrap*>(ptr);
             way->Wrap(args.This());
-            osmium::Way& obj = static_cast<osmium::Way&>(*(way->m_it));
-            args.This()->Set(String::New("id"), Number::New(obj.id()));
-            args.This()->Set(String::New("version"), Number::New(obj.version()));
-            args.This()->Set(String::New("changeset"), Number::New(obj.changeset()));
-            args.This()->Set(String::New("visible"), Boolean::New(obj.visible()));
-            args.This()->Set(String::New("timestamp"), Number::New(obj.timestamp()));
-            args.This()->Set(String::New("timestamp_iso"), String::New(obj.timestamp().to_iso().c_str(), obj.timestamp().to_iso().size()));
-            args.This()->Set(String::New("uid"), Number::New(obj.uid()));
-            args.This()->Set(String::New("user"), String::New(obj.user()));
             return args.This();
         } else {
             return ThrowException(Exception::TypeError(String::New("osmium.Way cannot be created in Javascript")));
@@ -55,10 +55,9 @@ namespace node_osmium {
 
     Handle<Value> OSMWayWrap::wkb(const Arguments& args) {
         HandleScope scope;
-        osmium::Way& way = static_cast<osmium::Way&>(*(node::ObjectWrap::Unwrap<OSMWayWrap>(args.This())->m_it));
 
         try {
-            std::string wkb { wkb_factory.create_linestring(way) };
+            std::string wkb { wkb_factory.create_linestring(wrapped(args.This())) };
 #if NODE_VERSION_AT_LEAST(0, 10, 0)
             return scope.Close(node::Buffer::New(wkb.data(), wkb.size())->handle_);
 #else
@@ -71,10 +70,9 @@ namespace node_osmium {
 
     Handle<Value> OSMWayWrap::wkt(const Arguments& args) {
         HandleScope scope;
-        osmium::Way& way = static_cast<osmium::Way&>(*(node::ObjectWrap::Unwrap<OSMWayWrap>(args.This())->m_it));
 
         try {
-            std::string wkt { wkt_factory.create_linestring(way) };
+            std::string wkt { wkt_factory.create_linestring(wrapped(args.This())) };
             return scope.Close(String::New(wkt.c_str()));
         } catch (osmium::geom::geometry_error&) {
             return scope.Close(Undefined());
@@ -83,7 +81,7 @@ namespace node_osmium {
 
     Handle<Value> OSMWayWrap::nodes(const Arguments& args) {
         HandleScope scope;
-        osmium::Way& way = static_cast<osmium::Way&>(*(node::ObjectWrap::Unwrap<OSMWayWrap>(args.This())->m_it));
+        osmium::Way& way = static_cast<osmium::Way&>(*(node::ObjectWrap::Unwrap<OSMWayWrap>(args.This())->get()));
 
         if (args.Length() == 0) {
             Local<Array> nodes = Array::New(way.nodes().size());
diff --git a/src/osm_way_wrap.hpp b/src/osm_way_wrap.hpp
index 9de530e..d381acc 100644
--- a/src/osm_way_wrap.hpp
+++ b/src/osm_way_wrap.hpp
@@ -30,18 +30,15 @@ namespace node_osmium {
         static Handle<Value> wkb(const Arguments& args);
         static Handle<Value> wkt(const Arguments& args);
         static Handle<Value> nodes(const Arguments& args);
-        OSMWayWrap(const input_iterator&);
 
-        void _ref() {
-            Ref();
+        static osmium::Way& wrapped(Local<Object> object) {
+            return static_cast<osmium::Way&>(OSMObjectWrap::wrapped(object));
         }
 
-        void _unref() {
-            Unref();
-        }
+        OSMWayWrap(const input_iterator&);
 
         osmium::Way& object() {
-            return static_cast<osmium::Way&>(*m_it);
+            return static_cast<osmium::Way&>(*get());
         }
 
     private:
diff --git a/src/reader_wrap.cpp b/src/reader_wrap.cpp
index 73f6c2b..d9e4884 100644
--- a/src/reader_wrap.cpp
+++ b/src/reader_wrap.cpp
@@ -1,7 +1,25 @@
 
+// c++
+#include <exception>
+#include <string>
+#include <vector>
+
+// boost
+#include <boost/variant.hpp>
+
+// node.js
+#include <node.h>
+#include <node_object_wrap.h>
+
+// osmium
+#include <osmium/visitor.hpp>
+
+// node-osmium
 #include "reader_wrap.hpp"
 #include "file_wrap.hpp"
 #include "handler.hpp"
+#include "location_handler_wrap.hpp"
+#include "osm_object_wrap.hpp"
 
 namespace node_osmium {
 
@@ -18,14 +36,6 @@ namespace node_osmium {
         target->Set(String::NewSymbol("Reader"), constructor->GetFunction());
     }
 
-    ReaderWrap::ReaderWrap(osmium::io::File& file, osmium::osm_entity::flags entities) :
-        ObjectWrap(),
-        this_(std::make_shared<osmium::io::Reader>(file, entities)),
-        header_(this_->header()) {
-    }
-
-    ReaderWrap::~ReaderWrap() { }
-
     Handle<Value> ReaderWrap::New(const Arguments& args) {
         HandleScope scope;
         if (!args.IsConstructCall()) {
@@ -83,7 +93,7 @@ namespace node_osmium {
         HandleScope scope;
         Local<Object> obj = Object::New();
         ReaderWrap* reader = node::ObjectWrap::Unwrap<ReaderWrap>(args.This());
-        const osmium::io::Header& header = reader->header_;
+        const osmium::io::Header& header = reader->m_this->header();
         obj->Set(String::New("generator"), String::New(header.get("generator").c_str()));
         const osmium::Box& bounds = header.box();
         Local<Array> arr = Array::New(4);
@@ -95,69 +105,131 @@ namespace node_osmium {
         return scope.Close(obj);
     }
 
-    Handle<Value> ReaderWrap::apply(const Arguments& args) {
-        HandleScope scope;
+    struct visitor_type : public boost::static_visitor<> {
+
+        input_iterator& m_it;
 
-        if (args.Length() != 1 && args.Length() != 2) {
-            return ThrowException(Exception::TypeError(String::New("please provide a single handler object")));
+        visitor_type(input_iterator& it) :
+            m_it(it) {
         }
-        if (!args[0]->IsObject()) {
-            return ThrowException(Exception::TypeError(String::New("please provide a single handler object")));
+
+        void operator()(JSHandler& handler) const {
+            handler.dispatch_object(m_it);
         }
-        Local<Object> obj = args[0]->ToObject();
-        if (obj->IsNull() || obj->IsUndefined() || !JSHandler::constructor->HasInstance(obj)) {
-            return ThrowException(Exception::TypeError(String::New("please provide a valid handler object")));
+
+        void operator()(location_handler_type& handler) const {
+            osmium::apply_item(*m_it, handler);
         }
 
-        bool with_location_handler = false;
+    }; // visitor_type
+
+    struct visitor_before_after_type : public boost::static_visitor<> {
+
+        osmium::item_type m_last;
+        osmium::item_type m_current;
+
+        visitor_before_after_type(osmium::item_type last, osmium::item_type current) :
+            m_last(last),
+            m_current(current) {
+        }
 
-        if (args.Length() == 2) {
-            if (!args[1]->IsObject()) {
-                return ThrowException(Exception::TypeError(String::New("second argument must be 'option' object")));
+        template <class TVisitor>
+        void operator()(TVisitor& visitor) const {
+            switch (m_last) {
+                case osmium::item_type::undefined:
+                    visitor.init();
+                    break;
+                case osmium::item_type::node:
+                    visitor.after_nodes();
+                    break;
+                case osmium::item_type::way:
+                    visitor.after_ways();
+                    break;
+                case osmium::item_type::relation:
+                    visitor.after_relations();
+                    break;
+                case osmium::item_type::changeset:
+                    visitor.after_changesets();
+                    break;
+                default:
+                    break;
             }
-            Local<Value> wlh = args[1]->ToObject()->Get(String::New("with_location_handler"));
-            if (wlh->BooleanValue()) {
-                with_location_handler = true;
+            switch (m_current) {
+                case osmium::item_type::undefined:
+                    visitor.done();
+                    break;
+                case osmium::item_type::node:
+                    visitor.before_nodes();
+                    break;
+                case osmium::item_type::way:
+                    visitor.before_ways();
+                    break;
+                case osmium::item_type::relation:
+                    visitor.before_relations();
+                    break;
+                case osmium::item_type::changeset:
+                    visitor.before_changesets();
+                    break;
+                default:
+                    break;
             }
         }
 
-        JSHandler* handler = node::ObjectWrap::Unwrap<JSHandler>(obj);
-        ReaderWrap* reader = node::ObjectWrap::Unwrap<ReaderWrap>(args.This());
-        reader_ptr r_ptr = reader->get();
-
-        if (with_location_handler) {
-            index_pos_type index_pos;
-            index_neg_type index_neg;
-            location_handler_type location_handler(index_pos, index_neg);
+    }; // visitor_before_after
 
-            osmium::io::InputIterator<osmium::io::Reader, osmium::Object> it(*r_ptr);
-            osmium::io::InputIterator<osmium::io::Reader, osmium::Object> end;
+    Handle<Value> ReaderWrap::apply(const Arguments& args) {
+        HandleScope scope;
 
-            for (; it != end; ++it) {
-                osmium::apply_item(*it, location_handler);
-                handler->dispatch_object(it);
+        typedef boost::variant<location_handler_type&, JSHandler&> some_handler_type;
+        std::vector<some_handler_type> handlers;
+
+        for (int i=0; i != args.Length(); ++i) {
+            if (args[i]->IsObject()) {
+                Local<Object> obj = args[i]->ToObject();
+                if (JSHandler::constructor->HasInstance(obj)) {
+                    handlers.push_back(*node::ObjectWrap::Unwrap<JSHandler>(obj));
+                } else if (LocationHandlerWrap::constructor->HasInstance(obj)) {
+                    location_handler_type* lh = node::ObjectWrap::Unwrap<LocationHandlerWrap>(obj)->get().get();
+                    handlers.push_back(*lh);
+                }
+            } else {
+                return ThrowException(Exception::TypeError(String::New("please provide a handler object")));
             }
+        }
+
+        osmium::io::Reader& reader = wrapped(args.This());
 
-            handler->done();
-        } else {
-            osmium::io::InputIterator<osmium::io::Reader, osmium::Object> it(*r_ptr);
-            osmium::io::InputIterator<osmium::io::Reader, osmium::Object> end;
+        input_iterator it(reader);
+        input_iterator end;
 
-            for (; it != end; ++it) {
-                handler->dispatch_object(it);
+        osmium::item_type last_type = osmium::item_type::undefined;
+
+        for (; it != end; ++it) {
+            visitor_before_after_type visitor_before_after(last_type, it->type());
+            visitor_type visitor(it);
+
+            for (some_handler_type& handler : handlers) {
+                if (last_type != it->type()) {
+                    boost::apply_visitor(visitor_before_after, handler);
+                }
+                boost::apply_visitor(visitor, handler);
+            }
+
+            if (last_type != it->type()) {
+                last_type = it->type();
             }
+        }
 
-            handler->done();
+        visitor_before_after_type visitor_before_after(last_type, osmium::item_type::undefined);
+        for (auto handler : handlers) {
+            boost::apply_visitor(visitor_before_after, handler);
         }
 
         return Undefined();
     }
 
     Handle<Value> ReaderWrap::close(const Arguments& args) {
-        HandleScope scope;
-        ReaderWrap* reader = node::ObjectWrap::Unwrap<ReaderWrap>(args.This());
-        reader_ptr r_ptr = reader->get();
-        r_ptr->close();
+        wrapped(args.This()).close();
         return Undefined();
     }
 
diff --git a/src/reader_wrap.hpp b/src/reader_wrap.hpp
index 2c4f757..11a8b95 100644
--- a/src/reader_wrap.hpp
+++ b/src/reader_wrap.hpp
@@ -1,30 +1,21 @@
 #ifndef READER_WRAP_HPP
 #define READER_WRAP_HPP
 
-// c++11
-#include <exception>
+// c++
 #include <memory>
 
 // v8
 #include <v8.h>
 
 // node.js
-#include <node.h>
-#include <node_version.h>
 #include <node_object_wrap.h>
 
 // osmium
 #include <osmium/io/any_input.hpp>
-#include <osmium/io/input_iterator.hpp>
-#include <osmium/visitor.hpp>
-#include <osmium/handler/node_locations_for_ways.hpp>
-#include <osmium/index/map/dummy.hpp>
-#include <osmium/index/map/stl_map.hpp>
-#include <osmium/index/map/sparse_table.hpp>
-
-typedef osmium::index::map::Dummy<osmium::unsigned_object_id_type, osmium::Location> index_neg_type;
-typedef osmium::index::map::SparseTable<osmium::unsigned_object_id_type, osmium::Location> index_pos_type;
-typedef osmium::handler::NodeLocationsForWays<index_pos_type, index_neg_type> location_handler_type;
+#include <osmium/io/reader.hpp>
+#include <osmium/osm/entity_flags.hpp>
+#include <osmium/osm/location.hpp>
+#include <osmium/osm/types.hpp>
 
 using namespace v8;
 
@@ -42,25 +33,26 @@ namespace node_osmium {
         static Handle<Value> header(const Arguments& args);
         static Handle<Value> apply(const Arguments& args);
         static Handle<Value> close(const Arguments& args);
-        ReaderWrap(osmium::io::File& infile, osmium::osm_entity::flags entities);
 
-        void _ref() {
-            Ref();
+        static osmium::io::Reader& wrapped(Local<Object> object) {
+            return *(node::ObjectWrap::Unwrap<ReaderWrap>(object)->get());
         }
 
-        void _unref() {
-            Unref();
+        ReaderWrap(const osmium::io::File& file, osmium::osm_entity::flags entities) :
+            ObjectWrap(),
+            m_this(std::make_shared<osmium::io::Reader>(file, entities)) {
         }
 
         reader_ptr get() {
-            return this_;
+            return m_this;
         }
 
     private:
 
-        ~ReaderWrap();
-        reader_ptr this_;
-        osmium::io::Header header_;
+        ~ReaderWrap() {
+        }
+
+        reader_ptr m_this;
     };
 
 } // namespace node_osmium
diff --git a/test/osmium.test.js b/test/osmium.test.js
index 40659f2..c5ea5c6 100644
--- a/test/osmium.test.js
+++ b/test/osmium.test.js
@@ -4,12 +4,12 @@ var assert = require('assert');
 describe('osmium', function() {
 
     it('should be able to create an osmium.Reader', function(done) {
-        var file = new osmium.File(__dirname+"/data/berlin-latest.osm.pbf");
+        var file = new osmium.File(__dirname+"/data/winthrop.osm");
         var reader = new osmium.Reader(file, {});
         var header = reader.header();
-        assert.equal(header.generator, 'Osmium (http://wiki.openstreetmap.org/wiki/Osmium)');
+        assert.equal(header.generator, 'CGImap 0.2.0');
         var bounds = header.bounds;
-        var expected = [ 13.08283, 52.33446, 13.76136, 52.6783 ];
+        var expected = [ -120.2024, 48.4636, -120.1569, 48.4869 ];
         assert.ok(Math.abs(bounds[0] - expected[0]) < .000000001);
         assert.ok(Math.abs(bounds[1] - expected[1]) < .000000001);
         assert.ok(Math.abs(bounds[2] - expected[2]) < .000000001);
@@ -18,28 +18,19 @@ describe('osmium', function() {
         done();
     });
 
-    it('should be able to apply a handler to a reader', function(done) {
+   it('should be able to read ISO time from node', function(done) {
         var handler = new osmium.Handler();
-        var nodes = 0;
+        var count = 0;
         handler.on('node',function(node) {
-            ++nodes;
-        });
-        handler.on('done',function() {
-            assert.equal(nodes >= 1993505, true);
+            if (count == 0) {
+                assert.equal(node.date().toISOString(),'2009-11-17T00:10:56.000Z');
+                done();
+            }
+            count++;
         });
-        var file = new osmium.File(__dirname+"/data/berlin-latest.osm.pbf");
-        var reader = new osmium.Reader(file);
+        var file = new osmium.File(__dirname+"/data/winthrop.osm");
+        var reader = new osmium.Reader(file, {node:true});
         reader.apply(handler);
-
-        // since reader.apply is sync, we can re-use handlers
-        var file2 = new osmium.File(__dirname+"/data/winthrop.osm");
-        var reader2 = new osmium.Reader(file2);
-        nodes = 0;
-        handler.on('done',function() {
-            assert.equal(nodes, 1525);
-            done();
-        });
-        reader2.apply(handler);
     });
 
     it('should be able to get node data from handler parameter', function(done) {
@@ -85,4 +76,75 @@ describe('osmium', function() {
         reader.apply(handler);
     });
 
+    it('should be able to use location handler', function(done) {
+        var location_handler = new osmium.LocationHandler();
+        var handler = new osmium.Handler();
+        var ways = 0;
+        handler.on('way', function(way) {
+            if (ways == 0) {
+                assert.equal(way.wkt(), "LINESTRING(-120.1872774 48.4715898,-120.188291 48.472511,-120.188374 48.472591,-120.188496 48.472707,-120.188625 48.47283,-120.18914 48.473561)");
+            }
+            ++ways;
+        });
+        handler.on('done', function() {
+            done();
+        });
+        var reader = new osmium.Reader(__dirname+"/data/winthrop.osm", { 'node': true, 'way': true });
+        reader.apply(location_handler, handler);
+    });
+
+    it('should be able to call before and after callbacks', function(done) {
+        var handler = new osmium.Handler();
+        var nodes = 0;
+        var before_nodes = 0, after_nodes = 0;
+
+        handler.on('init', function() {
+            assert.equal(nodes, 0);
+        });
+        handler.on('before_nodes', function() {
+            assert.equal(nodes, 0);
+            before_nodes++;
+        });
+        handler.on('node',function(node) {
+            ++nodes;
+        });
+        handler.on('after_nodes', function() {
+            assert.equal(nodes >= 1500, true);
+            after_nodes++;
+        });
+        handler.on('done',function() {
+            assert.equal(nodes >= 1500, true);
+            done();
+        });
+
+        var file = new osmium.File(__dirname+"/data/winthrop.osm");
+        var reader = new osmium.Reader(file);
+        reader.apply(handler);
+
+        assert.equal(before_nodes, 1);
+        assert.equal(after_nodes, 1);
+    });
+
+    it('should be able to call two handlers one after the other', function(done) {
+        var handler1 = new osmium.Handler();
+        var handler2 = new osmium.Handler();
+
+        var count=0;
+        handler1.on('init', function() {
+            assert.equal(count, 0);
+            count++;
+        });
+        handler2.on('init', function() {
+            assert.equal(count, 1);
+            count++;
+        });
+
+        var file = new osmium.File(__dirname+"/data/winthrop.osm");
+        var reader = new osmium.Reader(file);
+        reader.apply(handler1, handler2);
+
+        assert.equal(count, 2);
+        done();
+    });
+
 });

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-grass/node-osmium.git



More information about the Pkg-grass-devel mailing list