[node-osmium] 09/10: Imported Upstream version 0.3.0
Sebastiaan Couwenberg
sebastic at moszumanska.debian.org
Fri Mar 6 17:09:14 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 38391dbafd15a97c071294c3269db47740af9df6
Author: Bas Couwenberg <sebastic at xs4all.nl>
Date: Fri Mar 6 15:16:44 2015 +0100
Imported Upstream version 0.3.0
---
.npmignore | 10 +
Makefile | 1 +
binding.gyp | 3 +
demo/converter/README.md | 14 +
demo/converter/index.js | 117 +++++++++
demo/converter/package.json | 7 +
demo/converter/roads-from-buffer.js | 94 +++++++
demo/converter/roads.js | 92 +++++++
demo/count/README.md | 8 +
demo/count/index.js | 35 +++
demo/count/package.json | 6 +
demo/histstat/README.md | 13 +
demo/histstat/index.js | 46 ++++
demo/histstat/package.json | 6 +
demo/multipolygon/README.md | 12 +
demo/multipolygon/index.js | 41 +++
demo/multipolygon/package.json | 7 +
doc/tutorial.md | 111 ++++++++
lib/osmium.js | 291 +++++++++++++++++++++
package.json | 2 +-
src/apply.cpp | 13 +-
src/apply.hpp | 8 +-
src/buffer_wrap.cpp | 71 +++--
src/buffer_wrap.hpp | 29 +-
src/file_wrap.cpp | 9 +-
src/file_wrap.hpp | 19 +-
src/handler.cpp | 27 +-
src/handler.hpp | 12 +-
src/{apply.hpp => include_v8.hpp} | 13 +-
src/location_handler_wrap.cpp | 6 +-
src/location_handler_wrap.hpp | 18 +-
src/multipolygon_collector_wrap.cpp | 97 +++++++
src/multipolygon_collector_wrap.hpp | 46 ++++
src/multipolygon_handler_wrap.cpp | 33 +++
src/multipolygon_handler_wrap.hpp | 42 +++
src/node_osmium.cpp | 75 +++++-
src/node_osmium.hpp | 45 ++++
src/osm_area_wrap.cpp | 71 +++++
src/osm_area_wrap.hpp | 52 ++++
src/osm_changeset_wrap.cpp | 15 +-
src/osm_changeset_wrap.hpp | 17 +-
src/osm_entity_wrap.cpp | 6 +-
src/osm_entity_wrap.hpp | 14 +-
src/osm_node_wrap.cpp | 29 +-
src/osm_node_wrap.hpp | 16 +-
src/osm_object_wrap.cpp | 14 +-
src/osm_object_wrap.hpp | 12 +-
src/osm_relation_wrap.cpp | 24 +-
src/osm_relation_wrap.hpp | 18 +-
src/osm_way_wrap.cpp | 21 +-
src/osm_way_wrap.hpp | 16 +-
src/reader_wrap.cpp | 50 ++--
src/reader_wrap.hpp | 25 +-
src/utils.cpp | 5 +-
src/utils.hpp | 20 +-
test/changesets.test.js | 1 +
test/data/coordinates-problems.osm | 6 +
...reation.test.js => osm-object-creation.test.js} | 0
test/osm-objects.test.js | 27 ++
test/reader.test.js | 18 ++
60 files changed, 1713 insertions(+), 243 deletions(-)
diff --git a/.npmignore b/.npmignore
new file mode 100644
index 0000000..f6a4e2e
--- /dev/null
+++ b/.npmignore
@@ -0,0 +1,10 @@
+.gitignore
+.gitmodules
+.npmignore
+.travis.yml
+Makefile
+build
+demo
+node_modules
+scripts
+test
diff --git a/Makefile b/Makefile
index f5e5d06..5ee8736 100644
--- a/Makefile
+++ b/Makefile
@@ -9,6 +9,7 @@ INCLUDES_REPORT_FILES := $(subst src,check_reports,$(INCLUDE_FILES:.hpp=.compile
DEMOS := $(shell find demo -mindepth 1 -maxdepth 1 -type d)
all: build
+.PHONY: all build
./node_modules:
npm install --build-from-source
diff --git a/binding.gyp b/binding.gyp
index fd4eb2b..6dae20d 100644
--- a/binding.gyp
+++ b/binding.gyp
@@ -13,7 +13,10 @@
"src/file_wrap.cpp",
"src/handler.cpp",
"src/location_handler_wrap.cpp",
+ "src/multipolygon_collector_wrap.cpp",
+ "src/multipolygon_handler_wrap.cpp",
"src/node_osmium.cpp",
+ "src/osm_area_wrap.cpp",
"src/osm_changeset_wrap.cpp",
"src/osm_entity_wrap.cpp",
"src/osm_node_wrap.cpp",
diff --git a/demo/converter/README.md b/demo/converter/README.md
new file mode 100644
index 0000000..9f7af87
--- /dev/null
+++ b/demo/converter/README.md
@@ -0,0 +1,14 @@
+# converter
+
+Convert OSM file into spatialite database.
+
+## Install
+
+ npm install
+
+## Usage
+
+ ./index.js ../../test/data/winthrop.osm winthrop.db
+
+You will get a spatialite database with several tables.
+
diff --git a/demo/converter/index.js b/demo/converter/index.js
new file mode 100755
index 0000000..3121e75
--- /dev/null
+++ b/demo/converter/index.js
@@ -0,0 +1,117 @@
+#!/usr/bin/env node
+
+var osmium = require('../../');
+
+if (process.argv.length != 4) {
+ console.log("Usage: " + process.argv[0] + ' ' + process.argv[1] + " OSMFILE DBFILE");
+ process.exit(1);
+}
+
+var input_file = process.argv[2];
+var output_file = process.argv[3];
+
+var converter = new osmium.Converter({ output: output_file, show_layers: true });
+
+converter.create_layer('natural_pois', 'point').
+ with_attribute('osm_id', 'string').
+ with_attribute('type', 'string').
+ with_attribute('name', 'string');
+
+converter.create_layer('roads', 'linestring').
+ with_attribute('osm_id', 'integer').
+ with_attribute('type', 'string').
+ with_attribute('name', 'string').
+ with_attribute('ref', 'string').
+ with_attribute('oneway', 'integer').
+ with_attribute('maxspeed', 'integer');
+
+converter.create_layer('cycleways', 'linestring').
+ with_attribute('osm_id', 'integer').
+ with_attribute('name', 'string');
+
+converter.create_layer('railways', 'linestring').
+ with_attribute('osm_id', 'integer').
+ with_attribute('name', 'string');
+
+converter.create_layer('waterways', 'linestring').
+ with_attribute('osm_id', 'integer').
+ with_attribute('type', 'string').
+ with_attribute('name', 'string');
+
+converter.create_layer('boundaries', 'multipolygon').
+ with_attribute('osm_id', 'integer').
+ with_attribute('level', 'integer').
+ with_attribute('name', 'string');
+
+converter.create_layer('landuse', 'multipolygon').
+ with_attribute('osm_id', 'integer').
+ with_attribute('type', 'string').
+ with_attribute('name', 'string');
+
+converter.create_layer('water', 'multipolygon').
+ with_attribute('osm_id', 'integer').
+ with_attribute('type', 'string').
+ with_attribute('name', 'string');
+
+// ---- rules ----
+
+converter.add_nodes().
+ matching('natural', 'tree|peak|spring').
+ to_layer('natural_pois').
+ with_attribute('type', 'natural').
+ with_attribute('name');
+
+converter.add_ways().
+ matching('waterway', 'stream|river|ditch|canal|drain').
+ to_layer('waterways').
+ with_attribute('type', 'waterway').
+ with_attribute('name');
+
+converter.add_ways().
+ matching('highway', /^(motorway|trunk|primary|secondary)(_link)?$/).
+ to_layer('roads').
+ with_attribute('type', 'highway').
+ with_attribute('ref').
+ with_attribute('name').
+ with_attribute('oneway', function(tags) {
+ var o = tags['oneway'];
+ if (o == 'yes' || o == 'true' || o == '1') {
+ return 1;
+ } else if (o == "-1") {
+ return -1;
+ } else {
+ return 0;
+ }
+ }).
+ with_attribute('maxspeed')
+
+converter.add_ways().
+ matching('highway', 'cycleway').
+ to_layer('cycleways').
+ with_attribute('name');
+
+converter.add_ways().
+ matching('railway', 'rail').
+ to_layer('railways').
+ with_attribute('name');
+
+converter.add_areas().
+ matching('boundary', 'administrative').
+ to_layer('boundaries').
+ with_attribute('level', 'admin_level').
+ with_attribute('name');
+
+converter.add_areas().
+ matching('landuse', 'forest|grass|residential|farm|meadow|farmland|industrial|farmyard|cemetery|commercial|quarry|orchard|vineyard|allotments|retail|construction|recreation_ground|village_green').
+ to_layer('landuse').
+ with_attribute('type', 'landuse').
+ with_attribute('name');
+
+converter.add_areas().
+ matching('natural', 'water').
+ to_layer('water').
+ with_attribute('type', 'natural').
+ with_attribute('name');
+
+converter.convert(input_file);
+
diff --git a/demo/converter/package.json b/demo/converter/package.json
new file mode 100644
index 0000000..1339b30
--- /dev/null
+++ b/demo/converter/package.json
@@ -0,0 +1,7 @@
+{
+ "name": "test",
+ "version": "0.0.0",
+ "dependencies": {
+ "spatialite": "*"
+ }
+}
diff --git a/demo/converter/roads-from-buffer.js b/demo/converter/roads-from-buffer.js
new file mode 100755
index 0000000..66adad4
--- /dev/null
+++ b/demo/converter/roads-from-buffer.js
@@ -0,0 +1,94 @@
+#!/usr/bin/env node
+
+var osmium = require('../../');
+
+if (process.argv.length != 4) {
+ console.log("Usage: " + process.argv[0] + ' ' + process.argv[1] + " OSMFILE DBFILE");
+ process.exit(1);
+}
+
+var input_file = process.argv[2];
+var output_file = process.argv[3];
+
+var converter = new osmium.Converter({ output: output_file, show_layers: true });
+
+// ---- layers ----
+
+converter.create_layer('turning_circles').
+ with_attribute('osm_id', 'string');
+
+converter.create_layer('traffic_signals').
+ with_attribute('osm_id', 'string');
+
+converter.create_layer('major_roads', 'linestring').
+ with_attribute('osm_id', 'integer').
+ with_attribute('type', 'string').
+ with_attribute('name', 'string').
+ with_attribute('ref', 'string').
+ with_attribute('oneway', 'integer').
+ with_attribute('maxspeed', 'integer');
+
+converter.create_layer('minor_roads', 'linestring').
+ with_attribute('osm_id', 'integer').
+ with_attribute('type', 'string').
+ with_attribute('name', 'string').
+ with_attribute('ref', 'string').
+ with_attribute('oneway', 'integer').
+ with_attribute('maxspeed', 'integer');
+
+converter.create_layer('plazas', 'multipolygon').
+ with_attribute('osm_id', 'integer').
+ with_attribute('name', 'string');
+
+
+// ---- rules ----
+
+converter.add_nodes().
+ matching('highway', 'traffic_signals').
+ to_layer('traffic_signals');
+
+converter.add_nodes().
+ matching('highway', 'turning_circle').
+ to_layer('turning_circles');
+
+function convert_oneway(tags) {
+ var o = tags['oneway'];
+ if (o == 'yes' || o == 'true' || o == '1') {
+ return 1;
+ } else if (o == "-1") {
+ return -1;
+ } else {
+ return 0;
+ }
+}
+
+converter.add_ways().
+ matching('highway', /^(motorway|trunk|primary|secondary)(_link)?$/).
+ to_layer('major_roads').
+ with_attribute('type', 'highway').
+ with_attribute('ref').
+ with_attribute('name').
+ with_attribute('oneway', convert_oneway).
+ with_attribute('maxspeed')
+
+var minor_roads = 'tertiary|unclassified|residential|living_street|pedestrian|service|track|path|footway|cycleway|road|steps';
+
+converter.add_ways().
+ matching('highway', minor_roads).
+ to_layer('minor_roads').
+ with_attribute('type', 'highway').
+ with_attribute('ref').
+ with_attribute('name').
+ with_attribute('oneway', convert_oneway).
+ with_attribute('maxspeed');
+
+converter.add_areas().
+ matching('highway', minor_roads).
+ matching('area', 'yes').
+ to_layer('plazas').
+ with_attribute('name');
+
+var reader = new osmium.Reader(input_file);
+var buffer = reader.read_all();
+converter.convert(buffer);
+
diff --git a/demo/converter/roads.js b/demo/converter/roads.js
new file mode 100755
index 0000000..1ff6de0
--- /dev/null
+++ b/demo/converter/roads.js
@@ -0,0 +1,92 @@
+#!/usr/bin/env node
+
+var osmium = require('../../');
+
+if (process.argv.length != 4) {
+ console.log("Usage: " + process.argv[0] + ' ' + process.argv[1] + " OSMFILE DBFILE");
+ process.exit(1);
+}
+
+var input_file = process.argv[2];
+var output_file = process.argv[3];
+
+var converter = new osmium.Converter({ output: output_file, show_layers: true });
+
+// ---- layers ----
+
+converter.create_layer('turning_circles').
+ with_attribute('osm_id', 'string');
+
+converter.create_layer('traffic_signals').
+ with_attribute('osm_id', 'string');
+
+converter.create_layer('major_roads', 'linestring').
+ with_attribute('osm_id', 'integer').
+ with_attribute('type', 'string').
+ with_attribute('name', 'string').
+ with_attribute('ref', 'string').
+ with_attribute('oneway', 'integer').
+ with_attribute('maxspeed', 'integer');
+
+converter.create_layer('minor_roads', 'linestring').
+ with_attribute('osm_id', 'integer').
+ with_attribute('type', 'string').
+ with_attribute('name', 'string').
+ with_attribute('ref', 'string').
+ with_attribute('oneway', 'integer').
+ with_attribute('maxspeed', 'integer');
+
+converter.create_layer('plazas', 'multipolygon').
+ with_attribute('osm_id', 'integer').
+ with_attribute('name', 'string');
+
+
+// ---- rules ----
+
+converter.add_nodes().
+ matching('highway', 'traffic_signals').
+ to_layer('traffic_signals');
+
+converter.add_nodes().
+ matching('highway', 'turning_circle').
+ to_layer('turning_circles');
+
+function convert_oneway(tags) {
+ var o = tags['oneway'];
+ if (o == 'yes' || o == 'true' || o == '1') {
+ return 1;
+ } else if (o == "-1") {
+ return -1;
+ } else {
+ return 0;
+ }
+}
+
+converter.add_ways().
+ matching('highway', /^(motorway|trunk|primary|secondary)(_link)?$/).
+ to_layer('major_roads').
+ with_attribute('type', 'highway').
+ with_attribute('ref').
+ with_attribute('name').
+ with_attribute('oneway', convert_oneway).
+ with_attribute('maxspeed')
+
+var minor_roads = 'tertiary|unclassified|residential|living_street|pedestrian|service|track|path|footway|cycleway|road|steps';
+
+converter.add_ways().
+ matching('highway', minor_roads).
+ to_layer('minor_roads').
+ with_attribute('type', 'highway').
+ with_attribute('ref').
+ with_attribute('name').
+ with_attribute('oneway', convert_oneway).
+ with_attribute('maxspeed');
+
+converter.add_areas().
+ matching('highway', minor_roads).
+ matching('area', 'yes').
+ to_layer('plazas').
+ with_attribute('name');
+
+converter.convert(input_file);
+
diff --git a/demo/count/README.md b/demo/count/README.md
new file mode 100644
index 0000000..0e8cdbf
--- /dev/null
+++ b/demo/count/README.md
@@ -0,0 +1,8 @@
+# count
+
+Count the number of nodes, ways, and relations in an OSM file.
+
+## Usage
+
+ ./index.js ../../test/data/winthrop.osm
+
diff --git a/demo/count/index.js b/demo/count/index.js
new file mode 100755
index 0000000..87bcadb
--- /dev/null
+++ b/demo/count/index.js
@@ -0,0 +1,35 @@
+#!/usr/bin/env node
+
+var osmium = require('../../');
+
+if (process.argv.length != 3) {
+ console.log("Usage: " + process.argv[0] + ' ' + process.argv[1] + " OSMFILE");
+ process.exit(1);
+}
+
+var input_filename = process.argv[2];
+
+// =====================================
+
+var handler = new osmium.Handler();
+
+var nodes=0, ways=0, relations=0;
+
+handler.on('node', function(node) {
+ nodes++;
+});
+
+handler.on('way', function(way) {
+ ways++;
+});
+
+handler.on('relation', function(relation) {
+ relations++;
+});
+
+var reader = new osmium.Reader(input_filename);
+osmium.apply(reader, handler);
+console.log("Nodes: " + nodes);
+console.log("Ways: " + ways);
+console.log("Relations: " + relations);
+
diff --git a/demo/count/package.json b/demo/count/package.json
new file mode 100644
index 0000000..71993f6
--- /dev/null
+++ b/demo/count/package.json
@@ -0,0 +1,6 @@
+{
+ "name": "test",
+ "version": "0.0.0",
+ "dependencies": {
+ }
+}
diff --git a/demo/histstat/README.md b/demo/histstat/README.md
new file mode 100644
index 0000000..2e556a4
--- /dev/null
+++ b/demo/histstat/README.md
@@ -0,0 +1,13 @@
+# histstat
+
+Reads OSM history file and outputs the number of highways at the beginning of
+each year.
+
+## Install
+
+ npm install
+
+## Usage
+
+ ./index.js OSMFILE
+
diff --git a/demo/histstat/index.js b/demo/histstat/index.js
new file mode 100755
index 0000000..fb2c666
--- /dev/null
+++ b/demo/histstat/index.js
@@ -0,0 +1,46 @@
+#!/usr/bin/env node
+
+var osmium = require('../../');
+
+if (process.argv.length != 3) {
+ console.log("Usage: " + process.argv[0] + ' ' + process.argv[1] + " OSMFILE");
+ process.exit(1);
+}
+
+var input_filename = process.argv[2];
+
+// =====================================
+
+var handler = new osmium.Handler();
+
+var count = 0;
+handler.on('way', function(way) {
+ if (way.tags('highway')) {
+ count++;
+ }
+});
+
+console.log("Reading input file into memory...\n");
+var reader = new osmium.Reader(input_filename);
+var buffer = reader.read_all();
+reader.close();
+
+
+var year = 2008;
+var endyear = (new Date()).getYear() + 1900;
+
+console.log("Calculating stats for years " + year + " to " + endyear + "\n");
+
+while (year <= endyear) {
+ var date = new Date(year, 1, 1);
+
+ var tbuffer = buffer.filter_point_in_time(date);
+
+ osmium.apply(tbuffer, handler);
+ tbuffer.clear();
+ console.log(year + ": " + count);
+
+ count = 0;
+ year++;
+}
+
diff --git a/demo/histstat/package.json b/demo/histstat/package.json
new file mode 100644
index 0000000..71993f6
--- /dev/null
+++ b/demo/histstat/package.json
@@ -0,0 +1,6 @@
+{
+ "name": "test",
+ "version": "0.0.0",
+ "dependencies": {
+ }
+}
diff --git a/demo/multipolygon/README.md b/demo/multipolygon/README.md
new file mode 100644
index 0000000..d209f2c
--- /dev/null
+++ b/demo/multipolygon/README.md
@@ -0,0 +1,12 @@
+# multipolygon
+
+Reads OSM file and outputs some data for landuse areas.
+
+## Install
+
+ npm install
+
+## Usage
+
+ ./index.js ../../test/data/winthrop.osm winthrop.csv
+
diff --git a/demo/multipolygon/index.js b/demo/multipolygon/index.js
new file mode 100755
index 0000000..f536a75
--- /dev/null
+++ b/demo/multipolygon/index.js
@@ -0,0 +1,41 @@
+#!/usr/bin/env node
+
+var osmium = require('../../');
+var buffered_writer = require('buffered-writer');
+
+if (process.argv.length != 4) {
+ console.log("Usage: " + process.argv[0] + ' ' + process.argv[1] + " OSMFILE OUTFILE");
+ process.exit(1);
+}
+
+var input_filename = process.argv[2];
+var output_filename = process.argv[3];
+
+var stream = buffered_writer.open(output_filename);
+
+// =====================================
+
+var handler = new osmium.Handler();
+
+handler.on('area', function(area) {
+ var landuse = area.tags('landuse');
+ if (landuse) {
+ stream.write('a' + area.id + ' ' + landuse + ' ' + (area.tags('name') || '') + ' ' + area.wkt() + "\n");
+ }
+});
+
+handler.on('done', function() {
+ stream.close();
+});
+
+var mp = new osmium.MultipolygonCollector();
+
+var reader = new osmium.Reader(input_filename);
+mp.read_relations(reader);
+reader.close();
+
+reader = new osmium.Reader(input_filename);
+var location_handler = new osmium.LocationHandler();
+osmium.apply(reader, location_handler, handler, mp.handler(handler));
+reader.close();
+
diff --git a/demo/multipolygon/package.json b/demo/multipolygon/package.json
new file mode 100644
index 0000000..2635237
--- /dev/null
+++ b/demo/multipolygon/package.json
@@ -0,0 +1,7 @@
+{
+ "name": "test",
+ "version": "0.0.0",
+ "dependencies": {
+ "buffered-writer": "*"
+ }
+}
diff --git a/doc/tutorial.md b/doc/tutorial.md
index 32931c9..5150a3c 100644
--- a/doc/tutorial.md
+++ b/doc/tutorial.md
@@ -357,6 +357,117 @@ This is, of course, only the "geometry part" of a full feature, you have to
add the rest yourself. See the `demo/geojson-stream` example for a complete
program using the GeoJSON function.
+## Working with Multipolygons
+
+OSM doesn't have a data type for areas or polygons. Instead areas are stored
+as closed ways (ie first node == last node) or relations tagged as
+`type=multipolygon`. Osmium can hide this complexity and create pseudo-objects
+called "Areass" that are either based on closed ways or on those multipoygon
+relations. Usually OSM files have to be read twice to allow this, though. In
+the first pass, relations are read and prepared, in the second pass nodes and
+ways are read and everything is assembled. In addition to the `node`, `way`,
+and `relation` callbacks, you can define an `area` callback.
+
+Here is an example:
+
+ var handler = new osmium.Handler();
+
+ handler.on('area', function(area) {
+ var landuse = area.tags('landuse');
+ if (landuse) {
+ console.log(area.wkt() + ' ' + landuse);
+ }
+ });
+
+ var mp = new osmium.MultipolygonCollector();
+
+ var reader = new osmium.Reader(input_filename);
+ mp.read_relations(reader);
+ reader.close();
+
+ reader = new osmium.Reader(input_filename);
+ var location_handler = new osmium.LocationHandler();
+ osmium.apply(reader, location_handler, handler, mp.handler(handler));
+ reader.close();
+
+The code looks a bit complicated, because it is modelled after the C++ it is
+based on. It is likely we'll make this easier at some point. You can not re-use
+the reader from the first pass, you have to create a new one for the second
+pass.
+
+
+## Working With Buffers
+
+Instead of calling `apply()` you can call `read()` on the Reader and you'll get
+an `osmium.Buffer` with zero or more OSM entities in it. If there is no more
+data in the file, `read()` returns `undefined`:
+
+ var reader = new osmium.Reader("foo.osm");
+ var buffer;
+ while (buffer = reader.read()) {
+ // do something here
+ }
+
+You can call `apply()` with a `Buffer` and handlers, just like you would do
+with the `Reader`:
+
+ osmium.apply(buffer, handler1, handler2);
+
+There are no guarantees how many entities are in one of those buffers. They can
+even be empty, but usually they will contain a few thousand entities, so they
+are "small" in comparison to a big OSM data file. So if you call `apply()` on a
+`Buffer` it will return much sooner than when calling `apply()` on the
+`Reader`. This allows you some amount of control over how fast the input is
+read.
+
+ var reader = new osmium.Reader("foo.osm");
+ var buffer;
+ while (buffer = reader.read()) {
+ osmium.apply(buffer, handler1, handler2);
+ // wait here if needed to slow down reading the file
+ }
+
+Note that calling `apply()` repeatedly in this way on the buffers instead of
+once on the `Reader`, confuses the `done`, `init`, and `before_*` and `after_*`
+handlers. You will get those handlers called for each `apply()` separately.
+
+### Iterating Over the Contents of a Buffer
+
+Instead of calling `apply()` you can iterate over the contents of the buffer by
+calling `next()`:
+
+ var object;
+ while (object = buffer.next()) {
+ console.log(object.id());
+ }
+
+`buffer.next()` returns `undefined` when there is no more data.
+
+If you use the `buffer.next()` call, you'll get the next object, whatever that
+is, you have to check with `object instanceof osmium.Node` or so if you got the
+right type. Note that you can not use the `LocationHandler` this way.
+
+Together you can read the content of a file like this:
+
+ var reader = new osmium.Reader("foo.osm");
+ var buffer;
+ while (buffer = reader.read()) {
+ var object;
+ while (object = buffer.next()) {
+ // do something here with object
+ }
+ }
+
+### Creating an Osmium Buffer From a Node Buffer
+
+You can also create an `osmium.Buffer` from a `node.Buffer`:
+
+ var node_buffer = new node.Buffer;
+ // fill it with OSM data somehow
+ var osmium_buffer = new osmium.Buffer(node_buffer);
+
+This buffer can now be used like the buffers we got from the `Reader`.
+
## A Complete Example
Finally here is a complete example to get you started: This parses an OSM file
diff --git a/lib/osmium.js b/lib/osmium.js
index f31365c..2f76c5a 100644
--- a/lib/osmium.js
+++ b/lib/osmium.js
@@ -56,3 +56,294 @@ exports.Way.prototype.geojson = function() {
};
}
+exports.Converter = function(args) {
+ if (args === undefined) {
+ args = {};
+ }
+
+ this.show_layers = args.show_layers ? true : false;
+ this.output_name = args.output || "out.db";
+
+ function Layer(name, geom_type) {
+ this.name = name;
+ this.geom_type = geom_type.toUpperCase();
+
+ if (this.geom_type != 'POINT' && this.geom_type != 'LINESTRING' && this.geom_type != 'MULTIPOLYGON') {
+ throw new Error('Unknown geometry type: "' + geom_type + '" (allowed are: "POINT", "LINESTRING", and "MULTIPOLYGON")');
+ }
+
+ this.attributes = [];
+ this.attribute_names = {};
+
+ this.with_attribute = function(name, type) {
+ var attribute_type = type.toUpperCase();
+ if (attribute_type != 'INTEGER' && attribute_type != 'STRING' && attribute_type != 'BOOL' && attribute_type != 'REAL') {
+ throw new Error('Unknown attribute type: ' + type);
+ }
+ var attribute = { name: name, type: attribute_type };
+ this.attributes.push(attribute);
+ this.attribute_names[name] = attribute;
+ return this;
+ }
+ }
+
+ var layers = {};
+
+ function Filter(key, value) {
+ this.key = key;
+
+ if (value == '*') {
+ this.value = null;
+ } else {
+ this.value = value;
+ }
+
+ if (typeof(value) == 'string' && value.match(/\|/)) {
+ value = value.split('|');
+ }
+
+ if (value == null) {
+ this.match = function(obj) {
+ return !!obj.tags(key);
+ };
+ } else if (typeof(value) == 'string') {
+ this.match = function(obj) {
+ return obj.tags(key) == value;
+ };
+ } else if (value instanceof Array) {
+ this.match = function(obj) {
+ var val = obj.tags(key);
+ if (! val) {
+ return false;
+ }
+ return value.indexOf(val) != -1;
+ };
+ } else if (value instanceof RegExp) {
+ this.match = function(obj) {
+ return obj.tags(key) && value.test(obj.tags(key));
+ }
+ } else {
+ throw new Error('Can not understand rule');
+ }
+ }
+
+ function Rule(type) {
+ this.type = type;
+
+ this.layer = null;
+ this.filters = [];
+ this.attrs = {};
+
+ this.matching = function(key, value) {
+ this.filters.push(new Filter(key, value));
+ return this;
+ };
+
+ this.to_layer = function(name) {
+ if (! layers[name]) {
+ throw new Error('Unknown layer: ' + name);
+ }
+ this.layer = name;
+ return this;
+ };
+
+ this.with_attribute = function(attr, key) {
+ if (this.layer == null) {
+ throw new Error('Layer not set for rule ' + key + '=' + value);
+ }
+
+ if (! layers[this.layer].attribute_names[attr]) {
+ throw new Error("There is no attribute named '" + attr + "' in layer '" + this.layer + "'");
+ }
+
+ if (key instanceof Function) {
+ this.attrs[attr] = key;
+ } else if (key == null) {
+ this.attrs[attr] = function(tags) {
+ return tags[attr];
+ };
+ } else {
+ this.attrs[attr] = function(tags) {
+ return tags[key];
+ };
+ }
+
+ return this;
+ };
+
+ this.match = function(osm_object) {
+ var result = true;
+ this.filters.forEach(function(filter) {
+ if (!filter.match(osm_object)) {
+ result = false;
+ }
+ });
+ return result;
+ };
+ }
+
+ this.create_layer = function(name, geom_type) {
+ if (geom_type == undefined) {
+ geom_type = 'POINT';
+ }
+ var layer = new Layer(name, geom_type);
+ layers[name] = layer;
+ return layer;
+ }
+
+ var rules = {
+ node: [],
+ way: [],
+ area: []
+ };
+
+ this.rule = function(object_type) {
+ var rule = new Rule(object_type);
+ rules[object_type].push(rule);
+ return rule;
+ }
+
+ this.add_nodes = function() {
+ return this.rule('node');
+ }
+
+ this.add_ways = function() {
+ return this.rule('way');
+ }
+
+ this.add_areas = function() {
+ return this.rule('area');
+ }
+
+ function tags2attributes(id, tags, attrs) {
+ var obj = { osm_id: id };
+ for (var a in attrs) {
+ obj[a] = attrs[a](tags);
+ }
+ return obj;
+ }
+
+ function convert(osm_object) {
+ rules[osm_object.type].forEach(function(rule) {
+ if (rule.match(osm_object)) {
+ try {
+ var attributes = tags2attributes(osm_object.id, osm_object.tags(), rule.attrs);
+ var p = [osm_object.wkb()];
+ var layer = layers[rule.layer];
+ layer.attributes.forEach(function(attribute) {
+ p.push(attributes[attribute.name]);
+ });
+ layer.insert.run.apply(layer.insert, p);
+ } catch (e) {
+ // ignore broken geometries
+ }
+ }
+ });
+ }
+
+ var handler = new osmium.Handler;
+ handler.on('node', convert);
+ handler.on('way', convert);
+ handler.on('area', convert);
+
+ this.convert = function(input) {
+
+ var fs = require('fs');
+ if (fs.existsSync(this.output_name)) {
+ console.log("Output database file '" + this.output_name + "' exists. Refusing to overwrite it.");
+ process.exit(1);
+ }
+
+ // setup database
+ var sqlite = require('spatialite');
+ var db = new sqlite.Database(this.output_name);
+ db.serialize();
+
+ db.spatialite();
+ db.run("PRAGMA synchronous = OFF;"); // otherwise it is very slow
+ db.run("SELECT InitSpatialMetaData('WGS84');");
+
+ var show_layers = this.show_layers;
+
+ // setup layers in database
+ for (var t in layers) {
+ var layer = layers[t];
+
+ if (show_layers) {
+ console.log('Layer: ' + layer.name + ' (' + layer.geom_type + ')');
+ }
+
+ db.run("CREATE TABLE " + layer.name + " (id INTEGER PRIMARY KEY);");
+ db.run("SELECT AddGeometryColumn('" + layer.name + "', 'geom', 4326, '" + layer.geom_type + "', 2);");
+
+ var insert = "INSERT INTO " + layer.name + " (geom";
+ var qm = '';
+
+ layer.attributes.forEach(function(attribute) {
+ if (show_layers) {
+ console.log(' ' + (attribute.name + ' ').substr(0, 11) + attribute.type);
+ }
+ db.run("ALTER TABLE " + layer.name + " ADD COLUMN " + attribute.name + " " + attribute.type + ";");
+ insert += ", " + attribute.name;
+ qm += ", ?";
+ });
+
+ insert += ") VALUES (GeomFromWKB(?, 4326)" + qm + ");";
+
+ layer.insert = db.prepare(insert);
+ if (show_layers) {
+ console.log('');
+ }
+ }
+
+ // convert data
+ console.log("Converting data...");
+ if (rules.area.length > 0) {
+ console.log(" First pass. Reading relations...");
+ var mp = new osmium.MultipolygonCollector();
+
+ if (input instanceof osmium.Buffer) {
+ mp.read_relations(input);
+ } else {
+ var reader = new osmium.Reader(input, { 'relation': true });
+ mp.read_relations(reader);
+ reader.close();
+ }
+
+ console.log(" Second pass. Reading nodes and ways...");
+ var location_handler = new osmium.LocationHandler();
+ location_handler.ignoreErrors();
+ if (input instanceof osmium.Buffer) {
+ osmium.apply(input, location_handler, handler, mp.handler(handler));
+ } else {
+ reader = new osmium.Reader(input, { 'node': true, 'way': true });
+ osmium.apply(reader, location_handler, handler, mp.handler(handler));
+ reader.close();
+ }
+ } else {
+ console.log(" Reading everything in one pass...");
+
+ var location_handler = new osmium.LocationHandler();
+ location_handler.ignoreErrors();
+ if (input instanceof osmium.Buffer) {
+ osmium.apply(input, location_handler, handler);
+ } else {
+ var reader = new osmium.Reader(input);
+ osmium.apply(reader, location_handler, handler);
+ reader.close();
+ }
+ }
+
+ // cleanup
+ console.log("Cleanup...");
+ for (var layer in layers) {
+ layers[layer].insert.finalize();
+ }
+
+ db.close(function() {
+ console.log("Done.");
+ });
+ };
+
+};
+
diff --git a/package.json b/package.json
index 28707e4..46e21cd 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "osmium",
- "version": "0.2.0",
+ "version": "0.3.0",
"description": "Node.js bindings to Osmium",
"url": "https://github.com/osmcode/node-osmium",
"homepage": "http://osmcode.org/node-osmium",
diff --git a/src/apply.cpp b/src/apply.cpp
index 9c5f8ff..18fa436 100644
--- a/src/apply.cpp
+++ b/src/apply.cpp
@@ -16,6 +16,8 @@
#include "buffer_wrap.hpp"
#include "handler.hpp"
#include "location_handler_wrap.hpp"
+#include "multipolygon_collector_wrap.hpp"
+#include "multipolygon_handler_wrap.hpp"
#include "reader_wrap.hpp"
#include "utils.hpp"
@@ -37,6 +39,10 @@ namespace node_osmium {
osmium::apply_item(m_entity, handler);
}
+ void operator()(osmium::area::MultipolygonCollector<osmium::area::Assembler>::HandlerPass2& handler) const {
+ osmium::apply_item(m_entity, handler);
+ }
+
}; // struct visitor_type
struct visitor_before_after_type : public boost::static_visitor<> {
@@ -57,6 +63,9 @@ namespace node_osmium {
void operator()(location_handler_type& visitor) const {
}
+ void operator()(osmium::area::MultipolygonCollector<osmium::area::Assembler>::HandlerPass2& handler) const {
+ }
+
void operator()(JSHandler& visitor) const {
switch (m_last) {
case osmium::item_type::undefined:
@@ -100,7 +109,7 @@ namespace node_osmium {
}; // struct visitor_before_after
- typedef boost::variant<location_handler_type&, JSHandler&> some_handler_type;
+ typedef boost::variant<location_handler_type&, JSHandler&, osmium::area::MultipolygonCollector<osmium::area::Assembler>::HandlerPass2&> some_handler_type;
template <class TIter>
v8::Handle<v8::Value> apply_iterator(TIter it, TIter end, std::vector<some_handler_type>& handlers) {
@@ -165,6 +174,8 @@ namespace node_osmium {
handlers.push_back(unwrap<JSHandler>(obj));
} else if (LocationHandlerWrap::constructor->HasInstance(obj)) {
handlers.push_back(unwrap<LocationHandlerWrap>(obj));
+ } else if (MultipolygonHandlerWrap::constructor->HasInstance(obj)) {
+ handlers.push_back(unwrap<MultipolygonHandlerWrap>(obj));
}
}
diff --git a/src/apply.hpp b/src/apply.hpp
index 903327f..e0a5115 100644
--- a/src/apply.hpp
+++ b/src/apply.hpp
@@ -1,12 +1,8 @@
#ifndef APPLY_HPP
#define APPLY_HPP
-// v8
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wctor-dtor-privacy"
-#pragma GCC diagnostic ignored "-Wunused-parameter"
-#include <v8.h>
-#pragma GCC diagnostic pop
+// v8/node
+#include "include_v8.hpp"
namespace node_osmium {
diff --git a/src/buffer_wrap.cpp b/src/buffer_wrap.cpp
index 6f38cb2..0e03ec5 100644
--- a/src/buffer_wrap.cpp
+++ b/src/buffer_wrap.cpp
@@ -2,11 +2,16 @@
// node
#include <node_buffer.h>
+// osmium
+#include <osmium/diff_iterator.hpp>
+
// node-osmium
+#include "node_osmium.hpp"
#include "buffer_wrap.hpp"
#include "osm_node_wrap.hpp"
#include "osm_way_wrap.hpp"
#include "osm_relation_wrap.hpp"
+#include "osm_area_wrap.hpp"
#include "osm_changeset_wrap.hpp"
#include "utils.hpp"
@@ -18,9 +23,11 @@ namespace node_osmium {
v8::HandleScope scope;
constructor = v8::Persistent<v8::FunctionTemplate>::New(v8::FunctionTemplate::New(BufferWrap::New));
constructor->InstanceTemplate()->SetInternalFieldCount(1);
- constructor->SetClassName(v8::String::NewSymbol("Buffer"));
+ constructor->SetClassName(symbol_Buffer);
+ node::SetPrototypeMethod(constructor, "clear", clear);
node::SetPrototypeMethod(constructor, "next", next);
- target->Set(v8::String::NewSymbol("Buffer"), constructor->GetFunction());
+ node::SetPrototypeMethod(constructor, "filter_point_in_time", filter_point_in_time);
+ target->Set(symbol_Buffer, constructor->GetFunction());
}
v8::Handle<v8::Value> BufferWrap::New(const v8::Arguments& args) {
@@ -32,8 +39,8 @@ namespace node_osmium {
auto obj = args[0]->ToObject();
if (node::Buffer::HasInstance(obj)) {
osmium::memory::Buffer buffer(reinterpret_cast<unsigned char*>(node::Buffer::Data(obj)), node::Buffer::Length(obj));
- BufferWrap* bw = new BufferWrap(std::move(buffer));
- bw->Wrap(args.This());
+ BufferWrap* buffer_wrap = new BufferWrap(std::move(buffer));
+ buffer_wrap->Wrap(args.This());
return args.This();
}
}
@@ -43,31 +50,26 @@ namespace node_osmium {
v8::Handle<v8::Value> BufferWrap::next(const v8::Arguments& args) {
BufferWrap* buffer_wrap = node::ObjectWrap::Unwrap<BufferWrap>(args.This());
v8::HandleScope scope;
- if (buffer_wrap->m_iterator == buffer_wrap->m_this->end()) {
+ if (buffer_wrap->m_iterator == buffer_wrap->m_this.end()) {
return scope.Close(v8::Undefined());
}
osmium::OSMEntity& entity = *buffer_wrap->m_iterator;
++buffer_wrap->m_iterator;
switch (entity.type()) {
case osmium::item_type::node: {
- v8::Handle<v8::Value> ext = v8::External::New(new OSMNodeWrap(entity));
- v8::Local<v8::Object> obj = OSMNodeWrap::constructor->GetFunction()->NewInstance(1, &ext);
- return scope.Close(obj);
+ return scope.Close(new_external<OSMNodeWrap>(entity));
}
case osmium::item_type::way: {
- v8::Handle<v8::Value> ext = v8::External::New(new OSMWayWrap(entity));
- v8::Local<v8::Object> obj = OSMWayWrap::constructor->GetFunction()->NewInstance(1, &ext);
- return scope.Close(obj);
+ return scope.Close(new_external<OSMWayWrap>(entity));
}
case osmium::item_type::relation: {
- v8::Handle<v8::Value> ext = v8::External::New(new OSMRelationWrap(entity));
- v8::Local<v8::Object> obj = OSMRelationWrap::constructor->GetFunction()->NewInstance(1, &ext);
- return scope.Close(obj);
+ return scope.Close(new_external<OSMRelationWrap>(entity));
+ }
+ case osmium::item_type::area: {
+ return scope.Close(new_external<OSMAreaWrap>(entity));
}
case osmium::item_type::changeset: {
- v8::Handle<v8::Value> ext = v8::External::New(new OSMChangesetWrap(entity));
- v8::Local<v8::Object> obj = OSMChangesetWrap::constructor->GetFunction()->NewInstance(1, &ext);
- return scope.Close(obj);
+ return scope.Close(new_external<OSMChangesetWrap>(entity));
}
default:
break;
@@ -75,5 +77,40 @@ namespace node_osmium {
return scope.Close(v8::Undefined());
}
+ v8::Handle<v8::Value> BufferWrap::filter_point_in_time(const v8::Arguments& args) {
+ v8::HandleScope scope;
+ if (args.Length() != 1) {
+ return ThrowException(v8::Exception::TypeError(v8::String::New("please provide a point in time as first and only argument")));
+ }
+
+ osmium::Timestamp point_in_time;
+ if (args[0]->IsInt32()) {
+ point_in_time = args[0]->Int32Value();
+ } else if (args[0]->IsString()) {
+ point_in_time = osmium::Timestamp(*v8::String::Utf8Value(args[0]->ToString()));
+ } else if (args[0]->IsDate()) {
+ point_in_time = osmium::Timestamp(static_cast<int32_t>(v8::Date::Cast(*args[0])->NumberValue() / 1000));
+ }
+
+ typedef osmium::DiffIterator<osmium::memory::Buffer::t_iterator<osmium::OSMObject>> diff_iterator;
+ osmium::memory::Buffer& buffer = unwrap<BufferWrap>(args.This());
+ osmium::memory::Buffer fbuffer(buffer.committed(), osmium::memory::Buffer::auto_grow::yes);
+ {
+ auto dbegin = diff_iterator(buffer.begin<osmium::OSMObject>(), buffer.end<osmium::OSMObject>());
+ auto dend = diff_iterator(buffer.end<osmium::OSMObject>(), buffer.end<osmium::OSMObject>());
+
+ std::for_each(dbegin, dend, [point_in_time, &fbuffer](const osmium::DiffObject& d) {
+ if (((d.end_time() == 0 || d.end_time() > point_in_time) &&
+ d.start_time() <= point_in_time) &&
+ d.curr().visible()) {
+ fbuffer.add_item(d.curr());
+ fbuffer.commit();
+ }
+ });
+ }
+
+ return scope.Close(new_external<BufferWrap>(std::move(fbuffer)));
+ }
+
} // namespace node_osmium
diff --git a/src/buffer_wrap.hpp b/src/buffer_wrap.hpp
index c2db592..c218fe4 100644
--- a/src/buffer_wrap.hpp
+++ b/src/buffer_wrap.hpp
@@ -4,16 +4,8 @@
// c++
#include <memory>
-// v8
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wctor-dtor-privacy"
-#pragma GCC diagnostic ignored "-Wunused-parameter"
-#include <v8.h>
-#pragma GCC diagnostic pop
-
-// node
-#include <node.h>
-#include <node_version.h>
+// v8/node
+#include "include_v8.hpp"
#include <node_object_wrap.h>
// osmium
@@ -23,10 +15,16 @@ namespace node_osmium {
class BufferWrap : public node::ObjectWrap {
- std::shared_ptr<osmium::memory::Buffer> m_this;
+ osmium::memory::Buffer m_this;
osmium::memory::Buffer::iterator m_iterator;
+ static v8::Handle<v8::Value> clear(const v8::Arguments& args) {
+ BufferWrap* buffer_wrap = node::ObjectWrap::Unwrap<BufferWrap>(args.This());
+ buffer_wrap->m_this = std::move(osmium::memory::Buffer());
+ }
+
static v8::Handle<v8::Value> next(const v8::Arguments& args);
+ static v8::Handle<v8::Value> filter_point_in_time(const v8::Arguments& args);
public:
@@ -35,18 +33,17 @@ namespace node_osmium {
static v8::Handle<v8::Value> New(const v8::Arguments& args);
BufferWrap(osmium::memory::Buffer&& buffer) :
ObjectWrap(),
- m_this(std::make_shared<osmium::memory::Buffer>(std::move(buffer))),
- m_iterator(m_this->begin()) {
+ m_this(std::move(buffer)),
+ m_iterator(m_this.begin()) {
}
osmium::memory::Buffer& get() {
- return *m_this;
+ return m_this;
}
private:
- ~BufferWrap() {
- }
+ ~BufferWrap() = default;
}; // class BufferWrap
diff --git a/src/file_wrap.cpp b/src/file_wrap.cpp
index 0bacd01..78e6dea 100644
--- a/src/file_wrap.cpp
+++ b/src/file_wrap.cpp
@@ -2,12 +2,11 @@
// c++
#include <exception>
-// v8
-#include <v8.h>
-
// node
#include <node_buffer.h>
+// node-osmium
+#include "node_osmium.hpp"
#include "file_wrap.hpp"
namespace node_osmium {
@@ -18,8 +17,8 @@ namespace node_osmium {
v8::HandleScope scope;
constructor = v8::Persistent<v8::FunctionTemplate>::New(v8::FunctionTemplate::New(FileWrap::New));
constructor->InstanceTemplate()->SetInternalFieldCount(1);
- constructor->SetClassName(v8::String::NewSymbol("File"));
- target->Set(v8::String::NewSymbol("File"), constructor->GetFunction());
+ constructor->SetClassName(symbol_File);
+ target->Set(symbol_File, constructor->GetFunction());
}
v8::Handle<v8::Value> FileWrap::New(const v8::Arguments& args) {
diff --git a/src/file_wrap.hpp b/src/file_wrap.hpp
index 2020d5e..195c3f5 100644
--- a/src/file_wrap.hpp
+++ b/src/file_wrap.hpp
@@ -5,14 +5,8 @@
#include <memory>
#include <string>
-// v8
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wctor-dtor-privacy"
-#pragma GCC diagnostic ignored "-Wunused-parameter"
-#include <v8.h>
-#pragma GCC diagnostic pop
-
-// node
+// v8/node
+#include "include_v8.hpp"
#include <node_object_wrap.h>
// osmium
@@ -22,7 +16,7 @@ namespace node_osmium {
class FileWrap : public node::ObjectWrap {
- std::shared_ptr<osmium::io::File> m_this;
+ osmium::io::File m_this;
public:
@@ -32,17 +26,16 @@ namespace node_osmium {
FileWrap(osmium::io::File&& file) :
node::ObjectWrap(),
- m_this(std::make_shared<osmium::io::File>(file)) {
+ m_this(std::move(file)) {
}
osmium::io::File& get() {
- return *m_this;
+ return m_this;
}
private:
- ~FileWrap() {
- }
+ ~FileWrap() = default;
}; // class FileWrap
diff --git a/src/handler.cpp b/src/handler.cpp
index 5482fd1..bbce412 100644
--- a/src/handler.cpp
+++ b/src/handler.cpp
@@ -2,9 +2,6 @@
// c++
#include <string>
-// v8
-#include <v8.h>
-
// node
#include <node.h>
#include <node_object_wrap.h>
@@ -13,10 +10,12 @@
#include <osmium/osm/object.hpp>
// node-osmium
+#include "node_osmium.hpp"
#include "handler.hpp"
#include "osm_node_wrap.hpp"
#include "osm_way_wrap.hpp"
#include "osm_relation_wrap.hpp"
+#include "osm_area_wrap.hpp"
#include "osm_changeset_wrap.hpp"
#include "utils.hpp"
@@ -29,10 +28,10 @@ namespace node_osmium {
v8::HandleScope scope;
constructor = v8::Persistent<v8::FunctionTemplate>::New(v8::FunctionTemplate::New(JSHandler::New));
constructor->InstanceTemplate()->SetInternalFieldCount(1);
- constructor->SetClassName(v8::String::NewSymbol("Handler"));
+ constructor->SetClassName(symbol_Handler);
node::SetPrototypeMethod(constructor, "on", on);
node::SetPrototypeMethod(constructor, "options", options);
- target->Set(v8::String::NewSymbol("Handler"), constructor->GetFunction());
+ target->Set(symbol_Handler, constructor->GetFunction());
symbol_tagged_nodes_only = NODE_PSYMBOL("tagged_nodes_only");
}
@@ -57,6 +56,8 @@ namespace node_osmium {
relation_cb.Dispose();
after_relations_cb.Dispose();
+ area_cb.Dispose();
+
before_changesets_cb.Dispose();
changeset_cb.Dispose();
after_changesets_cb.Dispose();
@@ -76,8 +77,8 @@ namespace node_osmium {
b->Wrap(args.This());
return args.This();
} else {
- JSHandler* h = new JSHandler();
- h->Wrap(args.This());
+ JSHandler* jshandler = new JSHandler();
+ jshandler->Wrap(args.This());
return args.This();
}
return scope.Close(v8::Undefined());
@@ -118,6 +119,9 @@ namespace node_osmium {
} else if (callback_name == "relation") {
handler.relation_cb.Dispose();
handler.relation_cb = v8::Persistent<v8::Function>::New(callback);
+ } else if (callback_name == "area") {
+ handler.area_cb.Dispose();
+ handler.area_cb = v8::Persistent<v8::Function>::New(callback);
} else if (callback_name == "changeset") {
handler.changeset_cb.Dispose();
handler.changeset_cb = v8::Persistent<v8::Function>::New(callback);
@@ -165,9 +169,7 @@ namespace node_osmium {
}
v8::HandleScope scope;
- v8::Handle<v8::Value> ext = v8::External::New(new TWrapped(entity));
- v8::Local<v8::Object> obj = TWrapped::constructor->GetFunction()->NewInstance(1, &ext);
- v8::Local<v8::Value> argv[1] = { obj };
+ v8::Local<v8::Value> argv[1] = { new_external<TWrapped>(entity) };
function->Call(v8::Context::GetCurrent()->Global(), 1, argv);
}
@@ -198,6 +200,11 @@ namespace node_osmium {
call_callback_with_entity<OSMRelationWrap>(relation_cb, entity);
}
break;
+ case osmium::item_type::area:
+ if (!area_cb.IsEmpty()) {
+ call_callback_with_entity<OSMAreaWrap>(area_cb, entity);
+ }
+ break;
case osmium::item_type::changeset:
if (!changeset_cb.IsEmpty()) {
call_callback_with_entity<OSMChangesetWrap>(changeset_cb, entity);
diff --git a/src/handler.hpp b/src/handler.hpp
index 843874e..922ef5c 100644
--- a/src/handler.hpp
+++ b/src/handler.hpp
@@ -1,14 +1,8 @@
#ifndef HANDLER_HPP
#define HANDLER_HPP
-// v8
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wctor-dtor-privacy"
-#pragma GCC diagnostic ignored "-Wunused-parameter"
-#include <v8.h>
-#pragma GCC diagnostic pop
-
-// node
+// v8/node
+#include "include_v8.hpp"
#include <node_object_wrap.h>
// osmium
@@ -38,6 +32,8 @@ namespace node_osmium {
v8::Persistent<v8::Function> relation_cb;
v8::Persistent<v8::Function> after_relations_cb;
+ v8::Persistent<v8::Function> area_cb;
+
v8::Persistent<v8::Function> before_changesets_cb;
v8::Persistent<v8::Function> changeset_cb;
v8::Persistent<v8::Function> after_changesets_cb;
diff --git a/src/apply.hpp b/src/include_v8.hpp
similarity index 50%
copy from src/apply.hpp
copy to src/include_v8.hpp
index 903327f..6b72ffd 100644
--- a/src/apply.hpp
+++ b/src/include_v8.hpp
@@ -1,17 +1,10 @@
-#ifndef APPLY_HPP
-#define APPLY_HPP
+#ifndef INCLUDE_V8_HPP
+#define INCLUDE_V8_HPP
-// v8
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wctor-dtor-privacy"
#pragma GCC diagnostic ignored "-Wunused-parameter"
#include <v8.h>
#pragma GCC diagnostic pop
-namespace node_osmium {
-
- v8::Handle<v8::Value> apply(const v8::Arguments& args);
-
-} // namespace node_osmium
-
-#endif // APPLY_HPP
+#endif // INCLUDE_V8_HPP
diff --git a/src/location_handler_wrap.cpp b/src/location_handler_wrap.cpp
index 63a2e10..b7b9e8b 100644
--- a/src/location_handler_wrap.cpp
+++ b/src/location_handler_wrap.cpp
@@ -1,4 +1,6 @@
+// node-osmium
+#include "node_osmium.hpp"
#include "location_handler_wrap.hpp"
#include "utils.hpp"
@@ -10,10 +12,10 @@ namespace node_osmium {
v8::HandleScope scope;
constructor = v8::Persistent<v8::FunctionTemplate>::New(v8::FunctionTemplate::New(LocationHandlerWrap::New));
constructor->InstanceTemplate()->SetInternalFieldCount(1);
- constructor->SetClassName(v8::String::NewSymbol("LocationHandler"));
+ constructor->SetClassName(symbol_LocationHandler);
node::SetPrototypeMethod(constructor, "clear", clear);
node::SetPrototypeMethod(constructor, "ignoreErrors", ignoreErrors);
- target->Set(v8::String::NewSymbol("LocationHandler"), constructor->GetFunction());
+ target->Set(symbol_LocationHandler, constructor->GetFunction());
}
v8::Handle<v8::Value> LocationHandlerWrap::New(const v8::Arguments& args) {
diff --git a/src/location_handler_wrap.hpp b/src/location_handler_wrap.hpp
index 1d47a6e..70e85b2 100644
--- a/src/location_handler_wrap.hpp
+++ b/src/location_handler_wrap.hpp
@@ -3,15 +3,10 @@
// c++
#include <memory>
+#include <string>
-// v8
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wctor-dtor-privacy"
-#pragma GCC diagnostic ignored "-Wunused-parameter"
-#include <v8.h>
-#pragma GCC diagnostic pop
-
-// node
+// v8/node
+#include "include_v8.hpp"
#include <node_object_wrap.h>
// osmium
@@ -67,7 +62,7 @@ namespace node_osmium {
std::unique_ptr<index_pos_type> m_index_pos;
std::unique_ptr<index_neg_type> m_index_neg;
- std::shared_ptr<location_handler_type> m_this;
+ std::unique_ptr<location_handler_type> m_this;
static v8::Handle<v8::Value> clear(const v8::Arguments& args);
static v8::Handle<v8::Value> ignoreErrors(const v8::Arguments& args);
@@ -82,7 +77,7 @@ namespace node_osmium {
ObjectWrap(),
m_index_pos(node_cache_factory(cache_type)),
m_index_neg(new index_neg_type),
- m_this(std::make_shared<location_handler_type>(*m_index_pos, *m_index_neg)) {
+ m_this(new location_handler_type(*m_index_pos, *m_index_neg)) {
if (!m_index_pos) {
throw std::runtime_error("unknown node cache type");
}
@@ -94,8 +89,7 @@ namespace node_osmium {
private:
- ~LocationHandlerWrap() {
- }
+ ~LocationHandlerWrap() = default;
}; // class LocationHandlerWrap
diff --git a/src/multipolygon_collector_wrap.cpp b/src/multipolygon_collector_wrap.cpp
new file mode 100644
index 0000000..cedad87
--- /dev/null
+++ b/src/multipolygon_collector_wrap.cpp
@@ -0,0 +1,97 @@
+
+// node
+#include <node_buffer.h>
+
+// node-osmium
+#include "node_osmium.hpp"
+#include "multipolygon_collector_wrap.hpp"
+#include "multipolygon_handler_wrap.hpp"
+#include "handler.hpp"
+#include "buffer_wrap.hpp"
+#include "reader_wrap.hpp"
+#include "utils.hpp"
+#include "apply.hpp"
+
+namespace node_osmium {
+
+ v8::Persistent<v8::FunctionTemplate> MultipolygonCollectorWrap::constructor;
+
+ void MultipolygonCollectorWrap::Initialize(v8::Handle<v8::Object> target) {
+ v8::HandleScope scope;
+ constructor = v8::Persistent<v8::FunctionTemplate>::New(v8::FunctionTemplate::New(MultipolygonCollectorWrap::New));
+ constructor->InstanceTemplate()->SetInternalFieldCount(1);
+ constructor->SetClassName(symbol_MultipolygonCollector);
+ node::SetPrototypeMethod(constructor, "read_relations", read_relations);
+ node::SetPrototypeMethod(constructor, "handler", handler);
+ target->Set(symbol_MultipolygonCollector, constructor->GetFunction());
+ }
+
+ v8::Handle<v8::Value> MultipolygonCollectorWrap::New(const v8::Arguments& args) {
+ v8::HandleScope scope;
+
+ if (!args.IsConstructCall()) {
+ return ThrowException(v8::Exception::Error(v8::String::New("Cannot call constructor as function, you need to use 'new' keyword")));
+ }
+
+ if (args.Length() != 0) {
+ return ThrowException(v8::Exception::TypeError(v8::String::New("MultipolygonCollector is constructed without arguments")));
+ }
+
+ try {
+ MultipolygonCollectorWrap* multipolygon_collector_wrap = new MultipolygonCollectorWrap();
+ multipolygon_collector_wrap->Wrap(args.This());
+ return args.This();
+ } catch (const std::exception& e) {
+ return ThrowException(v8::Exception::TypeError(v8::String::New(e.what())));
+ }
+
+ return scope.Close(v8::Undefined());
+ }
+
+ v8::Handle<v8::Value> MultipolygonCollectorWrap::read_relations(const v8::Arguments& args) {
+ v8::HandleScope scope;
+ if (args.Length() != 1 || !args[0]->IsObject()) {
+ return ThrowException(v8::Exception::Error(v8::String::New("call MultipolygonCollector.read_relation() with Reader or Buffer object")));
+ }
+ try {
+ if (ReaderWrap::constructor->HasInstance(args[0]->ToObject())) {
+ osmium::io::Reader& reader = unwrap<ReaderWrap>(args[0]->ToObject());
+ unwrap<MultipolygonCollectorWrap>(args.This()).read_relations(reader);
+ } else if (BufferWrap::constructor->HasInstance(args[0]->ToObject())) {
+ osmium::memory::Buffer& buffer = unwrap<BufferWrap>(args[0]->ToObject());
+ unwrap<MultipolygonCollectorWrap>(args.This()).read_relations(buffer.begin(), buffer.end());
+ } else {
+ return ThrowException(v8::Exception::Error(v8::String::New("call MultipolygonCollector.read_relation() with Reader or Buffer object")));
+ }
+ } catch (const std::exception& e) {
+ std::string msg("osmium error: ");
+ msg += e.what();
+ return ThrowException(v8::Exception::Error(v8::String::New(msg.c_str())));
+ }
+ return scope.Close(v8::Undefined());
+ }
+
+ v8::Handle<v8::Value> MultipolygonCollectorWrap::handler(const v8::Arguments& args) {
+ v8::HandleScope scope;
+ if (args.Length() != 1 || !args[0]->IsObject() || !JSHandler::constructor->HasInstance(args[0]->ToObject())) {
+ return ThrowException(v8::Exception::Error(v8::String::New("call MultipolygonCollector.handler() with Handler object")));
+ }
+ try {
+ JSHandler& handler = unwrap<JSHandler>(args[0]->ToObject());
+ auto& mc_handler = unwrap<MultipolygonCollectorWrap>(args.This()).handler([&handler](const osmium::memory::Buffer& area_buffer) {
+ for (const osmium::OSMEntity& entity : area_buffer) {
+ handler.dispatch_entity(entity);
+ }
+ });
+ return scope.Close(new_external<MultipolygonHandlerWrap>(mc_handler));
+
+ } catch (const std::exception& e) {
+ std::string msg("osmium error: ");
+ msg += e.what();
+ return ThrowException(v8::Exception::Error(v8::String::New(msg.c_str())));
+ }
+ return scope.Close(v8::Undefined());
+ }
+
+} // namespace node_osmium
+
diff --git a/src/multipolygon_collector_wrap.hpp b/src/multipolygon_collector_wrap.hpp
new file mode 100644
index 0000000..b59c5fb
--- /dev/null
+++ b/src/multipolygon_collector_wrap.hpp
@@ -0,0 +1,46 @@
+#ifndef MULTIPOLYGON_COLLECTOR_WRAP_HPP
+#define MULTIPOLYGON_COLLECTOR_WRAP_HPP
+
+// v8/node
+#include "include_v8.hpp"
+#include <node_object_wrap.h>
+
+// osmium
+#include <osmium/area/multipolygon_collector.hpp>
+#include <osmium/area/assembler.hpp>
+
+namespace node_osmium {
+
+ class MultipolygonCollectorWrap : public node::ObjectWrap {
+
+ static v8::Handle<v8::Value> read_relations(const v8::Arguments& args);
+ static v8::Handle<v8::Value> handler(const v8::Arguments& args);
+
+ osmium::area::Assembler::config_type m_assembler_config;
+ osmium::area::MultipolygonCollector<osmium::area::Assembler> m_collector;
+
+ public:
+
+ static v8::Persistent<v8::FunctionTemplate> constructor;
+ static void Initialize(v8::Handle<v8::Object> target);
+ static v8::Handle<v8::Value> New(const v8::Arguments& args);
+
+ MultipolygonCollectorWrap() :
+ node::ObjectWrap(),
+ m_assembler_config(),
+ m_collector(m_assembler_config) {
+ }
+
+ osmium::area::MultipolygonCollector<osmium::area::Assembler>& get() {
+ return m_collector;
+ }
+
+ private:
+
+ ~MultipolygonCollectorWrap() = default;
+
+ }; // class MultipolygonCollectorWrap
+
+} // namespace node_osmium
+
+#endif // MULTIPOLYGON_COLLECTOR_WRAP_HPP
diff --git a/src/multipolygon_handler_wrap.cpp b/src/multipolygon_handler_wrap.cpp
new file mode 100644
index 0000000..e715bfe
--- /dev/null
+++ b/src/multipolygon_handler_wrap.cpp
@@ -0,0 +1,33 @@
+
+// node
+#include <node_buffer.h>
+
+// node-osmium
+#include "node_osmium.hpp"
+#include "multipolygon_handler_wrap.hpp"
+#include "utils.hpp"
+
+namespace node_osmium {
+
+ v8::Persistent<v8::FunctionTemplate> MultipolygonHandlerWrap::constructor;
+
+ void MultipolygonHandlerWrap::Initialize(v8::Handle<v8::Object> target) {
+ v8::HandleScope scope;
+ constructor = v8::Persistent<v8::FunctionTemplate>::New(v8::FunctionTemplate::New(MultipolygonHandlerWrap::New));
+ constructor->InstanceTemplate()->SetInternalFieldCount(1);
+ constructor->SetClassName(symbol_MultipolygonHandler);
+ target->Set(symbol_MultipolygonHandler, constructor->GetFunction());
+ }
+
+ v8::Handle<v8::Value> MultipolygonHandlerWrap::New(const v8::Arguments& args) {
+ if (args.Length() == 1 && args[0]->IsExternal()) {
+ v8::Local<v8::External> ext = v8::Local<v8::External>::Cast(args[0]);
+ static_cast<MultipolygonHandlerWrap*>(ext->Value())->Wrap(args.This());
+ return args.This();
+ } else {
+ return ThrowException(v8::Exception::TypeError(v8::String::New("osmium.MultipolygonHandler cannot be created in Javascript")));
+ }
+ }
+
+} // namespace node_osmium
+
diff --git a/src/multipolygon_handler_wrap.hpp b/src/multipolygon_handler_wrap.hpp
new file mode 100644
index 0000000..155cae1
--- /dev/null
+++ b/src/multipolygon_handler_wrap.hpp
@@ -0,0 +1,42 @@
+#ifndef MULTIPOLYGON_HANDLER_WRAP_HPP
+#define MULTIPOLYGON_HANDLER_WRAP_HPP
+
+// v8/node
+#include "include_v8.hpp"
+#include <node_object_wrap.h>
+
+// osmium
+#include <osmium/area/multipolygon_collector.hpp>
+#include <osmium/area/assembler.hpp>
+
+namespace node_osmium {
+
+ class MultipolygonHandlerWrap : public node::ObjectWrap {
+
+ typedef osmium::area::MultipolygonCollector<osmium::area::Assembler>::HandlerPass2 handler_type;
+ handler_type m_handler;
+
+ public:
+
+ static v8::Persistent<v8::FunctionTemplate> constructor;
+ static void Initialize(v8::Handle<v8::Object> target);
+ static v8::Handle<v8::Value> New(const v8::Arguments& args);
+
+ MultipolygonHandlerWrap(handler_type& handler) :
+ node::ObjectWrap(),
+ m_handler(handler) {
+ }
+
+ handler_type& get() {
+ return m_handler;
+ }
+
+ private:
+
+ ~MultipolygonHandlerWrap() = default;
+
+ }; // class MultipolygonHandlerWrap
+
+} // namespace node_osmium
+
+#endif // MULTIPOLYGON_HANDLER_WRAP_HPP
diff --git a/src/node_osmium.cpp b/src/node_osmium.cpp
index 16b6e47..fc439d8 100644
--- a/src/node_osmium.cpp
+++ b/src/node_osmium.cpp
@@ -1,9 +1,3 @@
-// v8
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wctor-dtor-privacy"
-#pragma GCC diagnostic ignored "-Wunused-parameter"
-#include <v8.h>
-#pragma GCC diagnostic pop
// node
#include <node.h>
@@ -21,6 +15,9 @@
#include "file_wrap.hpp"
#include "handler.hpp"
#include "location_handler_wrap.hpp"
+#include "multipolygon_collector_wrap.hpp"
+#include "multipolygon_handler_wrap.hpp"
+#include "osm_area_wrap.hpp"
#include "osm_changeset_wrap.hpp"
#include "osm_node_wrap.hpp"
#include "osm_relation_wrap.hpp"
@@ -33,6 +30,41 @@ namespace node_osmium {
osmium::geom::WKBFactory<> wkb_factory;
osmium::geom::WKTFactory<> wkt_factory;
+ v8::Persistent<v8::String> symbol_OSMEntity;
+ v8::Persistent<v8::String> symbol_OSMObject;
+
+ v8::Persistent<v8::String> symbol_Node;
+ v8::Persistent<v8::String> symbol_node;
+
+ v8::Persistent<v8::String> symbol_Way;
+ v8::Persistent<v8::String> symbol_way;
+
+ v8::Persistent<v8::String> symbol_Relation;
+ v8::Persistent<v8::String> symbol_relation;
+ v8::Persistent<v8::String> symbol_type;
+ v8::Persistent<v8::String> symbol_ref;
+ v8::Persistent<v8::String> symbol_role;
+
+ v8::Persistent<v8::String> symbol_Area;
+ v8::Persistent<v8::String> symbol_area;
+
+ v8::Persistent<v8::String> symbol_Changeset;
+ v8::Persistent<v8::String> symbol_changeset;
+
+ v8::Persistent<v8::String> symbol_Coordinates;
+ v8::Persistent<v8::String> symbol_Box;
+
+ v8::Persistent<v8::String> symbol_generator;
+ v8::Persistent<v8::String> symbol_bounds;
+
+ v8::Persistent<v8::String> symbol_Buffer;
+ v8::Persistent<v8::String> symbol_File;
+ v8::Persistent<v8::String> symbol_Handler;
+ v8::Persistent<v8::String> symbol_LocationHandler;
+ v8::Persistent<v8::String> symbol_MultipolygonCollector;
+ v8::Persistent<v8::String> symbol_MultipolygonHandler;
+ v8::Persistent<v8::String> symbol_Reader;
+
extern "C" {
static void start(v8::Handle<v8::Object> target) {
v8::HandleScope scope;
@@ -40,12 +72,43 @@ namespace node_osmium {
node::SetMethod(target, "apply", node_osmium::apply);
+ symbol_OSMEntity = NODE_PSYMBOL("OSMEntity");
+ symbol_OSMObject = NODE_PSYMBOL("OSMObject");
+ symbol_Node = NODE_PSYMBOL("Node");
+ symbol_node = NODE_PSYMBOL("node");
+ symbol_Way = NODE_PSYMBOL("Way");
+ symbol_way = NODE_PSYMBOL("way");
+ symbol_Relation = NODE_PSYMBOL("Relation");
+ symbol_relation = NODE_PSYMBOL("relation");
+ symbol_type = NODE_PSYMBOL("type");
+ symbol_ref = NODE_PSYMBOL("ref");
+ symbol_role = NODE_PSYMBOL("role");
+ symbol_Area = NODE_PSYMBOL("Area");
+ symbol_area = NODE_PSYMBOL("area");
+ symbol_Changeset = NODE_PSYMBOL("Changeset");
+ symbol_changeset = NODE_PSYMBOL("changeset");
+ symbol_Coordinates = NODE_PSYMBOL("Coordinates");
+ symbol_Box = NODE_PSYMBOL("Box");
+ symbol_generator = NODE_PSYMBOL("generator");
+ symbol_bounds = NODE_PSYMBOL("bounds");
+
+ symbol_Buffer = NODE_PSYMBOL("Buffer");
+ symbol_File = NODE_PSYMBOL("File");
+ symbol_Handler = NODE_PSYMBOL("Handler");
+ symbol_LocationHandler = NODE_PSYMBOL("LocationHandler");
+ symbol_MultipolygonCollector = NODE_PSYMBOL("MultipolygonCollector");
+ symbol_MultipolygonHandler = NODE_PSYMBOL("MultipolygonHandler");
+ symbol_Reader = NODE_PSYMBOL("Reader");
+
node_osmium::OSMEntityWrap::Initialize(target);
node_osmium::OSMObjectWrap::Initialize(target);
node_osmium::OSMNodeWrap::Initialize(target);
node_osmium::OSMWayWrap::Initialize(target);
node_osmium::OSMRelationWrap::Initialize(target);
+ node_osmium::OSMAreaWrap::Initialize(target);
node_osmium::OSMChangesetWrap::Initialize(target);
+ node_osmium::MultipolygonCollectorWrap::Initialize(target);
+ node_osmium::MultipolygonHandlerWrap::Initialize(target);
node_osmium::LocationHandlerWrap::Initialize(target);
node_osmium::JSHandler::Initialize(target);
node_osmium::FileWrap::Initialize(target);
diff --git a/src/node_osmium.hpp b/src/node_osmium.hpp
new file mode 100644
index 0000000..8ab7915
--- /dev/null
+++ b/src/node_osmium.hpp
@@ -0,0 +1,45 @@
+#ifndef NODE_OSMIUM
+#define NODE_OSMIUM
+
+#include "include_v8.hpp"
+
+namespace node_osmium {
+
+ extern v8::Persistent<v8::String> symbol_OSMEntity;
+ extern v8::Persistent<v8::String> symbol_OSMObject;
+
+ extern v8::Persistent<v8::String> symbol_Node;
+ extern v8::Persistent<v8::String> symbol_node;
+
+ extern v8::Persistent<v8::String> symbol_Way;
+ extern v8::Persistent<v8::String> symbol_way;
+
+ extern v8::Persistent<v8::String> symbol_Relation;
+ extern v8::Persistent<v8::String> symbol_relation;
+ extern v8::Persistent<v8::String> symbol_type;
+ extern v8::Persistent<v8::String> symbol_ref;
+ extern v8::Persistent<v8::String> symbol_role;
+
+ extern v8::Persistent<v8::String> symbol_Area;
+ extern v8::Persistent<v8::String> symbol_area;
+
+ extern v8::Persistent<v8::String> symbol_Changeset;
+ extern v8::Persistent<v8::String> symbol_changeset;
+
+ extern v8::Persistent<v8::String> symbol_Coordinates;
+ extern v8::Persistent<v8::String> symbol_Box;
+
+ extern v8::Persistent<v8::String> symbol_generator;
+ extern v8::Persistent<v8::String> symbol_bounds;
+
+ extern v8::Persistent<v8::String> symbol_Buffer;
+ extern v8::Persistent<v8::String> symbol_File;
+ extern v8::Persistent<v8::String> symbol_Handler;
+ extern v8::Persistent<v8::String> symbol_LocationHandler;
+ extern v8::Persistent<v8::String> symbol_MultipolygonCollector;
+ extern v8::Persistent<v8::String> symbol_MultipolygonHandler;
+ extern v8::Persistent<v8::String> symbol_Reader;
+
+} // namespace node_osmium
+
+#endif // NODE_OSMIUM
diff --git a/src/osm_area_wrap.cpp b/src/osm_area_wrap.cpp
new file mode 100644
index 0000000..5bf59db
--- /dev/null
+++ b/src/osm_area_wrap.cpp
@@ -0,0 +1,71 @@
+
+// node
+#include <node_buffer.h>
+#include <node_version.h>
+
+// osmium
+#include <osmium/geom/wkb.hpp>
+#include <osmium/geom/wkt.hpp>
+
+// node-osmium
+#include "osm_area_wrap.hpp"
+
+namespace node_osmium {
+
+ extern osmium::geom::WKBFactory<> wkb_factory;
+ extern osmium::geom::WKTFactory<> wkt_factory;
+ extern v8::Persistent<v8::Object> module;
+
+ v8::Persistent<v8::FunctionTemplate> OSMAreaWrap::constructor;
+
+ void OSMAreaWrap::Initialize(v8::Handle<v8::Object> target) {
+ v8::HandleScope scope;
+ constructor = v8::Persistent<v8::FunctionTemplate>::New(v8::FunctionTemplate::New(OSMAreaWrap::New));
+ constructor->Inherit(OSMObjectWrap::constructor);
+ constructor->InstanceTemplate()->SetInternalFieldCount(1);
+ constructor->SetClassName(symbol_Area);
+ auto attributes = static_cast<v8::PropertyAttribute>(v8::ReadOnly | v8::DontDelete);
+ set_accessor(constructor, "type", get_type, attributes);
+ node::SetPrototypeMethod(constructor, "wkb", wkb);
+ node::SetPrototypeMethod(constructor, "wkt", wkt);
+ target->Set(symbol_Area, constructor->GetFunction());
+ }
+
+ v8::Handle<v8::Value> OSMAreaWrap::New(const v8::Arguments& args) {
+ if (args.Length() == 1 && args[0]->IsExternal()) {
+ v8::Local<v8::External> ext = v8::Local<v8::External>::Cast(args[0]);
+ static_cast<OSMAreaWrap*>(ext->Value())->Wrap(args.This());
+ return args.This();
+ } else {
+ return ThrowException(v8::Exception::TypeError(v8::String::New("osmium.Area cannot be created in Javascript")));
+ }
+ }
+
+ v8::Handle<v8::Value> OSMAreaWrap::wkb(const v8::Arguments& args) {
+ v8::HandleScope scope;
+
+ try {
+ std::string wkb { wkb_factory.create_multipolygon(wrapped(args.This())) };
+#if NODE_VERSION_AT_LEAST(0, 10, 0)
+ return scope.Close(node::Buffer::New(wkb.data(), wkb.size())->handle_);
+#else
+ return scope.Close(node::Buffer::New(const_cast<char*>(wkb.data()), wkb.size())->handle_);
+#endif
+ } catch (std::runtime_error& e) {
+ return ThrowException(v8::Exception::Error(v8::String::New(e.what())));
+ }
+ }
+
+ v8::Handle<v8::Value> OSMAreaWrap::wkt(const v8::Arguments& args) {
+ v8::HandleScope scope;
+
+ try {
+ std::string wkt { wkt_factory.create_multipolygon(wrapped(args.This())) };
+ return scope.Close(v8::String::New(wkt.c_str()));
+ } catch (std::runtime_error& e) {
+ return ThrowException(v8::Exception::Error(v8::String::New(e.what())));
+ }
+ }
+
+} // namespace node_osmium
+
diff --git a/src/osm_area_wrap.hpp b/src/osm_area_wrap.hpp
new file mode 100644
index 0000000..f62aaf7
--- /dev/null
+++ b/src/osm_area_wrap.hpp
@@ -0,0 +1,52 @@
+#ifndef OSM_AREA_WRAP_HPP
+#define OSM_AREA_WRAP_HPP
+
+// v8/node
+#include "include_v8.hpp"
+
+// osmium
+#include <osmium/osm/area.hpp>
+namespace osmium {
+ class OSMEntity;
+}
+
+// node-osmium
+#include "node_osmium.hpp"
+#include "osm_entity_wrap.hpp"
+#include "osm_object_wrap.hpp"
+#include "utils.hpp"
+
+namespace node_osmium {
+
+ class OSMAreaWrap : public OSMObjectWrap {
+
+ static v8::Handle<v8::Value> get_type(v8::Local<v8::String> property, const v8::AccessorInfo& info) {
+ return symbol_area;
+ }
+
+ static v8::Handle<v8::Value> wkb(const v8::Arguments& args);
+ static v8::Handle<v8::Value> wkt(const v8::Arguments& args);
+
+ public:
+
+ static v8::Persistent<v8::FunctionTemplate> constructor;
+ static void Initialize(v8::Handle<v8::Object> target);
+ static v8::Handle<v8::Value> New(const v8::Arguments& args);
+
+ static const osmium::Area& wrapped(const v8::Local<v8::Object>& object) {
+ return static_cast<const osmium::Area&>(unwrap<OSMEntityWrap>(object));
+ }
+
+ OSMAreaWrap(const osmium::OSMEntity& entity) :
+ OSMObjectWrap(entity) {
+ }
+
+ private:
+
+ ~OSMAreaWrap() = default;
+
+ }; // class OSMAreaWrap
+
+} // namespace node_osmium
+
+#endif // OSM_AREA_WRAP_HPP
diff --git a/src/osm_changeset_wrap.cpp b/src/osm_changeset_wrap.cpp
index f8a02ca..e2c78f5 100644
--- a/src/osm_changeset_wrap.cpp
+++ b/src/osm_changeset_wrap.cpp
@@ -1,4 +1,5 @@
+// node-osmium
#include "osm_changeset_wrap.hpp"
#include "utils.hpp"
@@ -10,11 +11,13 @@ namespace node_osmium {
void OSMChangesetWrap::Initialize(v8::Handle<v8::Object> target) {
v8::HandleScope scope;
+
constructor = v8::Persistent<v8::FunctionTemplate>::New(v8::FunctionTemplate::New(OSMChangesetWrap::New));
constructor->Inherit(OSMEntityWrap::constructor);
constructor->InstanceTemplate()->SetInternalFieldCount(1);
- constructor->SetClassName(v8::String::NewSymbol("Changeset"));
+ constructor->SetClassName(symbol_Changeset);
auto attributes = static_cast<v8::PropertyAttribute>(v8::ReadOnly | v8::DontDelete);
+ set_accessor(constructor, "type", get_type, attributes);
set_accessor(constructor, "id", get_id, attributes);
set_accessor(constructor, "uid", get_uid, attributes);
set_accessor(constructor, "user", get_user, attributes);
@@ -25,7 +28,7 @@ namespace node_osmium {
set_accessor(constructor, "closed", get_closed, attributes);
set_accessor(constructor, "bounds", get_bounds, attributes);
node::SetPrototypeMethod(constructor, "tags", tags);
- target->Set(v8::String::NewSymbol("Changeset"), constructor->GetFunction());
+ target->Set(symbol_Changeset, constructor->GetFunction());
}
v8::Handle<v8::Value> OSMChangesetWrap::New(const v8::Arguments& args) {
@@ -49,7 +52,7 @@ namespace node_osmium {
v8::Handle<v8::Value> OSMChangesetWrap::get_uid(v8::Local<v8::String> /* property */, const v8::AccessorInfo& info) {
v8::HandleScope scope;
- return scope.Close(v8::Number::New(wrapped(info.This()).uid()));
+ return scope.Close(v8::Uint32::New(wrapped(info.This()).uid()));
}
v8::Handle<v8::Value> OSMChangesetWrap::get_user(v8::Local<v8::String> /* property */, const v8::AccessorInfo& info) {
@@ -59,17 +62,17 @@ namespace node_osmium {
v8::Handle<v8::Value> OSMChangesetWrap::get_num_changes(v8::Local<v8::String> /* property */, const v8::AccessorInfo& info) {
v8::HandleScope scope;
- return scope.Close(v8::Number::New(wrapped(info.This()).num_changes()));
+ return scope.Close(v8::Uint32::New(wrapped(info.This()).num_changes()));
}
v8::Handle<v8::Value> OSMChangesetWrap::get_created_at(v8::Local<v8::String> /* property */, const v8::AccessorInfo& info) {
v8::HandleScope scope;
- return scope.Close(v8::Number::New(wrapped(info.This()).created_at()));
+ return scope.Close(v8::Uint32::New(wrapped(info.This()).created_at()));
}
v8::Handle<v8::Value> OSMChangesetWrap::get_closed_at(v8::Local<v8::String> /* property */, const v8::AccessorInfo& info) {
v8::HandleScope scope;
- return scope.Close(v8::Number::New(wrapped(info.This()).closed_at()));
+ return scope.Close(v8::Uint32::New(wrapped(info.This()).closed_at()));
}
v8::Handle<v8::Value> OSMChangesetWrap::get_open(v8::Local<v8::String> /* property */, const v8::AccessorInfo& info) {
diff --git a/src/osm_changeset_wrap.hpp b/src/osm_changeset_wrap.hpp
index ca605f9..b490045 100644
--- a/src/osm_changeset_wrap.hpp
+++ b/src/osm_changeset_wrap.hpp
@@ -1,12 +1,8 @@
#ifndef OSM_CHANGESET_WRAP_HPP
#define OSM_CHANGESET_WRAP_HPP
-// v8
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wctor-dtor-privacy"
-#pragma GCC diagnostic ignored "-Wunused-parameter"
-#include <v8.h>
-#pragma GCC diagnostic pop
+// v8/node
+#include "include_v8.hpp"
// osmium
#include <osmium/osm/changeset.hpp>
@@ -15,6 +11,7 @@ namespace osmium {
}
// node-osmium
+#include "node_osmium.hpp"
#include "osm_entity_wrap.hpp"
#include "utils.hpp"
@@ -22,6 +19,10 @@ namespace node_osmium {
class OSMChangesetWrap : public OSMEntityWrap {
+ static v8::Handle<v8::Value> get_type(v8::Local<v8::String> property, const v8::AccessorInfo& info) {
+ return symbol_changeset;
+ }
+
static v8::Handle<v8::Value> get_id(v8::Local<v8::String> property, const v8::AccessorInfo& info);
static v8::Handle<v8::Value> get_uid(v8::Local<v8::String> property, const v8::AccessorInfo& info);
static v8::Handle<v8::Value> get_user(v8::Local<v8::String> property, const v8::AccessorInfo& info);
@@ -47,6 +48,10 @@ namespace node_osmium {
OSMEntityWrap(entity) {
}
+ private:
+
+ ~OSMChangesetWrap() = default;
+
}; // class OSMChangesetWrap
} // namespace node_osmium
diff --git a/src/osm_entity_wrap.cpp b/src/osm_entity_wrap.cpp
index 91191f0..51122bd 100644
--- a/src/osm_entity_wrap.cpp
+++ b/src/osm_entity_wrap.cpp
@@ -1,4 +1,6 @@
+// node-osmium
+#include "node_osmium.hpp"
#include "osm_entity_wrap.hpp"
namespace node_osmium {
@@ -9,8 +11,8 @@ namespace node_osmium {
v8::HandleScope scope;
constructor = v8::Persistent<v8::FunctionTemplate>::New(v8::FunctionTemplate::New(OSMEntityWrap::New));
constructor->InstanceTemplate()->SetInternalFieldCount(1);
- constructor->SetClassName(v8::String::NewSymbol("OSMEntity"));
- target->Set(v8::String::NewSymbol("OSMEntity"), constructor->GetFunction());
+ constructor->SetClassName(symbol_OSMEntity);
+ target->Set(symbol_OSMEntity, constructor->GetFunction());
}
v8::Handle<v8::Value> OSMEntityWrap::New(const v8::Arguments& args) {
diff --git a/src/osm_entity_wrap.hpp b/src/osm_entity_wrap.hpp
index bf25136..0e14587 100644
--- a/src/osm_entity_wrap.hpp
+++ b/src/osm_entity_wrap.hpp
@@ -1,14 +1,8 @@
#ifndef OSM_ENTITY_WRAP_HPP
#define OSM_ENTITY_WRAP_HPP
-// v8
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wctor-dtor-privacy"
-#pragma GCC diagnostic ignored "-Wunused-parameter"
-#include <v8.h>
-#pragma GCC diagnostic pop
-
-// node
+// v8/node
+#include "include_v8.hpp"
#include <node_object_wrap.h>
// osmium
@@ -71,6 +65,10 @@ namespace node_osmium {
return *m_entity;
}
+ protected:
+
+ virtual ~OSMEntityWrap() = default;
+
}; // class OSMEntityWrap
} // namespace node_osmium
diff --git a/src/osm_node_wrap.cpp b/src/osm_node_wrap.cpp
index 57a0f2c..3d21eb5 100644
--- a/src/osm_node_wrap.cpp
+++ b/src/osm_node_wrap.cpp
@@ -23,15 +23,16 @@ namespace node_osmium {
constructor = v8::Persistent<v8::FunctionTemplate>::New(v8::FunctionTemplate::New(OSMNodeWrap::New));
constructor->Inherit(OSMObjectWrap::constructor);
constructor->InstanceTemplate()->SetInternalFieldCount(1);
- constructor->SetClassName(v8::String::NewSymbol("Node"));
+ constructor->SetClassName(symbol_Node);
node::SetPrototypeMethod(constructor, "wkb", wkb);
node::SetPrototypeMethod(constructor, "wkt", wkt);
auto attributes = static_cast<v8::PropertyAttribute>(v8::ReadOnly | v8::DontDelete);
+ set_accessor(constructor, "type", get_type, attributes);
set_accessor(constructor, "location", get_coordinates, attributes);
set_accessor(constructor, "coordinates", get_coordinates, attributes);
set_accessor(constructor, "lon", get_lon, attributes);
set_accessor(constructor, "lat", get_lat, attributes);
- target->Set(v8::String::NewSymbol("Node"), constructor->GetFunction());
+ target->Set(symbol_Node, constructor->GetFunction());
}
v8::Handle<v8::Value> OSMNodeWrap::New(const v8::Arguments& args) {
@@ -47,24 +48,36 @@ namespace node_osmium {
v8::Handle<v8::Value> OSMNodeWrap::get_coordinates(v8::Local<v8::String> /* property */, const v8::AccessorInfo& info) {
v8::HandleScope scope;
- auto lon = v8::Number::New(wrapped(info.This()).location().lon());
- auto lat = v8::Number::New(wrapped(info.This()).location().lat());
-
- auto cf = module->Get(v8::String::NewSymbol("Coordinates"));
+ auto cf = module->Get(symbol_Coordinates);
assert(cf->IsFunction());
+ const osmium::Location& location = wrapped(info.This()).location();
+ if (!location) {
+ return scope.Close(v8::Local<v8::Function>::Cast(cf)->NewInstance());
+ }
+
+ v8::Local<v8::Value> lon = v8::Number::New(location.lon_without_check());
+ v8::Local<v8::Value> lat = v8::Number::New(location.lat_without_check());
v8::Local<v8::Value> argv[2] = { lon, lat };
return scope.Close(v8::Local<v8::Function>::Cast(cf)->NewInstance(2, argv));
}
v8::Handle<v8::Value> OSMNodeWrap::get_lon(v8::Local<v8::String> /* property */, const v8::AccessorInfo& info) {
v8::HandleScope scope;
- return scope.Close(v8::Number::New(wrapped(info.This()).location().lon()));
+ try {
+ return scope.Close(v8::Number::New(wrapped(info.This()).location().lon()));
+ } catch (osmium::invalid_location&) {
+ return scope.Close(v8::Undefined());
+ }
}
v8::Handle<v8::Value> OSMNodeWrap::get_lat(v8::Local<v8::String> /* property */, const v8::AccessorInfo& info) {
v8::HandleScope scope;
- return scope.Close(v8::Number::New(wrapped(info.This()).location().lat()));
+ try {
+ return scope.Close(v8::Number::New(wrapped(info.This()).location().lat()));
+ } catch (osmium::invalid_location&) {
+ return scope.Close(v8::Undefined());
+ }
}
v8::Handle<v8::Value> OSMNodeWrap::wkb(const v8::Arguments& args) {
diff --git a/src/osm_node_wrap.hpp b/src/osm_node_wrap.hpp
index 157df91..5ae12da 100644
--- a/src/osm_node_wrap.hpp
+++ b/src/osm_node_wrap.hpp
@@ -1,12 +1,8 @@
#ifndef OSM_NODE_WRAP_HPP
#define OSM_NODE_WRAP_HPP
-// v8
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wctor-dtor-privacy"
-#pragma GCC diagnostic ignored "-Wunused-parameter"
-#include <v8.h>
-#pragma GCC diagnostic pop
+// v8/node
+#include "include_v8.hpp"
// osmium
#include <osmium/osm/node.hpp>
@@ -15,6 +11,7 @@ namespace osmium {
}
// node-osmium
+#include "node_osmium.hpp"
#include "osm_entity_wrap.hpp"
#include "osm_object_wrap.hpp"
#include "utils.hpp"
@@ -23,6 +20,10 @@ namespace node_osmium {
class OSMNodeWrap : public OSMObjectWrap {
+ static v8::Handle<v8::Value> get_type(v8::Local<v8::String> property, const v8::AccessorInfo& info) {
+ return symbol_node;
+ }
+
static v8::Handle<v8::Value> get_coordinates(v8::Local<v8::String> property, const v8::AccessorInfo& info);
static v8::Handle<v8::Value> get_lon(v8::Local<v8::String> property, const v8::AccessorInfo& info);
static v8::Handle<v8::Value> get_lat(v8::Local<v8::String> property, const v8::AccessorInfo& info);
@@ -45,8 +46,7 @@ namespace node_osmium {
private:
- ~OSMNodeWrap() {
- }
+ ~OSMNodeWrap() = default;
}; // class OSMNodeWrap
diff --git a/src/osm_object_wrap.cpp b/src/osm_object_wrap.cpp
index 710018a..b771947 100644
--- a/src/osm_object_wrap.cpp
+++ b/src/osm_object_wrap.cpp
@@ -1,4 +1,6 @@
+// node-osmium
+#include "node_osmium.hpp"
#include "osm_object_wrap.hpp"
namespace node_osmium {
@@ -9,7 +11,7 @@ namespace node_osmium {
v8::HandleScope scope;
constructor = v8::Persistent<v8::FunctionTemplate>::New(v8::FunctionTemplate::New(OSMObjectWrap::New));
constructor->InstanceTemplate()->SetInternalFieldCount(1);
- constructor->SetClassName(v8::String::NewSymbol("OSMObject"));
+ constructor->SetClassName(symbol_OSMObject);
auto attributes = static_cast<v8::PropertyAttribute>(v8::ReadOnly | v8::DontDelete);
set_accessor(constructor, "id", get_id, attributes);
set_accessor(constructor, "version", get_version, attributes);
@@ -19,7 +21,7 @@ namespace node_osmium {
set_accessor(constructor, "uid", get_uid, attributes);
set_accessor(constructor, "user", get_user, attributes);
node::SetPrototypeMethod(constructor, "tags", tags);
- target->Set(v8::String::NewSymbol("OSMObject"), constructor->GetFunction());
+ target->Set(symbol_OSMObject, constructor->GetFunction());
}
v8::Handle<v8::Value> OSMObjectWrap::New(const v8::Arguments& args) {
@@ -43,12 +45,12 @@ namespace node_osmium {
v8::Handle<v8::Value> OSMObjectWrap::get_version(v8::Local<v8::String> /* property */, const v8::AccessorInfo& info) {
v8::HandleScope scope;
- return scope.Close(v8::Number::New(wrapped(info.This()).version()));
+ return scope.Close(v8::Uint32::New(wrapped(info.This()).version()));
}
v8::Handle<v8::Value> OSMObjectWrap::get_changeset(v8::Local<v8::String> /* property */, const v8::AccessorInfo& info) {
v8::HandleScope scope;
- return scope.Close(v8::Number::New(wrapped(info.This()).changeset()));
+ return scope.Close(v8::Uint32::New(wrapped(info.This()).changeset()));
}
v8::Handle<v8::Value> OSMObjectWrap::get_visible(v8::Local<v8::String> /* property */, const v8::AccessorInfo& info) {
@@ -58,12 +60,12 @@ namespace node_osmium {
v8::Handle<v8::Value> OSMObjectWrap::get_timestamp(v8::Local<v8::String> /* property */, const v8::AccessorInfo& info) {
v8::HandleScope scope;
- return scope.Close(v8::Number::New(wrapped(info.This()).timestamp()));
+ return scope.Close(v8::Uint32::New(wrapped(info.This()).timestamp()));
}
v8::Handle<v8::Value> OSMObjectWrap::get_uid(v8::Local<v8::String> /* property */, const v8::AccessorInfo& info) {
v8::HandleScope scope;
- return scope.Close(v8::Number::New(wrapped(info.This()).uid()));
+ return scope.Close(v8::Uint32::New(wrapped(info.This()).uid()));
}
v8::Handle<v8::Value> OSMObjectWrap::get_user(v8::Local<v8::String> /* property */, const v8::AccessorInfo& info) {
diff --git a/src/osm_object_wrap.hpp b/src/osm_object_wrap.hpp
index a735d93..2bf27f3 100644
--- a/src/osm_object_wrap.hpp
+++ b/src/osm_object_wrap.hpp
@@ -1,12 +1,8 @@
#ifndef OSM_OBJECT_WRAP_HPP
#define OSM_OBJECT_WRAP_HPP
-// v8
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wctor-dtor-privacy"
-#pragma GCC diagnostic ignored "-Wunused-parameter"
-#include <v8.h>
-#pragma GCC diagnostic pop
+// v8/node
+#include "include_v8.hpp"
// osmium
#include <osmium/osm/object.hpp>
@@ -45,6 +41,10 @@ namespace node_osmium {
OSMEntityWrap(entity) {
}
+ protected:
+
+ virtual ~OSMObjectWrap() = default;
+
}; // class OSMObjectWrap
} // namespace node_osmium
diff --git a/src/osm_relation_wrap.cpp b/src/osm_relation_wrap.cpp
index fc8b225..db30e22 100644
--- a/src/osm_relation_wrap.cpp
+++ b/src/osm_relation_wrap.cpp
@@ -1,29 +1,25 @@
+// node
#include <node.h>
-#include <osm_relation_wrap.hpp>
+// node-osmium
+#include "osm_relation_wrap.hpp"
namespace node_osmium {
v8::Persistent<v8::FunctionTemplate> OSMRelationWrap::constructor;
- v8::Persistent<v8::String> OSMRelationWrap::symbol_type;
- v8::Persistent<v8::String> OSMRelationWrap::symbol_ref;
- v8::Persistent<v8::String> OSMRelationWrap::symbol_role;
void OSMRelationWrap::Initialize(v8::Handle<v8::Object> target) {
v8::HandleScope scope;
constructor = v8::Persistent<v8::FunctionTemplate>::New(v8::FunctionTemplate::New(OSMRelationWrap::New));
constructor->Inherit(OSMObjectWrap::constructor);
constructor->InstanceTemplate()->SetInternalFieldCount(1);
- constructor->SetClassName(v8::String::NewSymbol("Relation"));
+ constructor->SetClassName(symbol_Relation);
auto attributes = static_cast<v8::PropertyAttribute>(v8::ReadOnly | v8::DontDelete);
+ set_accessor(constructor, "type", get_type, attributes);
set_accessor(constructor, "members_count", get_members_count, attributes);
node::SetPrototypeMethod(constructor, "members", members);
- target->Set(v8::String::NewSymbol("Relation"), constructor->GetFunction());
-
- symbol_type = NODE_PSYMBOL("type");
- symbol_ref = NODE_PSYMBOL("ref");
- symbol_role = NODE_PSYMBOL("role");
+ target->Set(symbol_Relation, constructor->GetFunction());
}
v8::Handle<v8::Value> OSMRelationWrap::New(const v8::Arguments& args) {
@@ -38,7 +34,7 @@ namespace node_osmium {
v8::Handle<v8::Value> OSMRelationWrap::get_members_count(v8::Local<v8::String> /* property */, const v8::AccessorInfo& info) {
v8::HandleScope scope;
- return scope.Close(v8::Number::New(wrapped(info.This()).members().size()));
+ return scope.Close(v8::Uint32::New(wrapped(info.This()).members().size()));
}
v8::Handle<v8::Value> OSMRelationWrap::members(const v8::Arguments& args) {
@@ -63,11 +59,11 @@ namespace node_osmium {
return scope.Close(members);
}
case 1: {
- if (!args[0]->IsNumber()) {
+ if (!args[0]->IsUint32()) {
return ThrowException(v8::Exception::TypeError(v8::String::New("call members() without parameters or the index of the member you want")));
}
- int n = static_cast<int>(args[0]->ToNumber()->Value());
- if (n >= 0 && n < static_cast<int>(relation.members().size())) {
+ uint32_t n = args[0]->ToUint32()->Value();
+ if (n < relation.members().size()) {
auto it = relation.members().begin();
std::advance(it, n);
const osmium::RelationMember& member = *it;
diff --git a/src/osm_relation_wrap.hpp b/src/osm_relation_wrap.hpp
index 534fe48..cc88ce9 100644
--- a/src/osm_relation_wrap.hpp
+++ b/src/osm_relation_wrap.hpp
@@ -1,12 +1,8 @@
#ifndef OSM_RELATION_WRAP_HPP
#define OSM_RELATION_WRAP_HPP
-// v8
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wctor-dtor-privacy"
-#pragma GCC diagnostic ignored "-Wunused-parameter"
-#include <v8.h>
-#pragma GCC diagnostic pop
+// v8/node
+#include "include_v8.hpp"
// osmium
#include <osmium/osm/relation.hpp>
@@ -15,6 +11,7 @@ namespace osmium {
}
// node-osmium
+#include "node_osmium.hpp"
#include "osm_entity_wrap.hpp"
#include "osm_object_wrap.hpp"
#include "utils.hpp"
@@ -23,9 +20,9 @@ namespace node_osmium {
class OSMRelationWrap : public OSMObjectWrap {
- static v8::Persistent<v8::String> symbol_type;
- static v8::Persistent<v8::String> symbol_ref;
- static v8::Persistent<v8::String> symbol_role;
+ static v8::Handle<v8::Value> get_type(v8::Local<v8::String> property, const v8::AccessorInfo& info) {
+ return symbol_relation;
+ }
static v8::Handle<v8::Value> get_members_count(v8::Local<v8::String> /* property */, const v8::AccessorInfo& info);
static v8::Handle<v8::Value> members(const v8::Arguments& args);
@@ -46,8 +43,7 @@ namespace node_osmium {
private:
- ~OSMRelationWrap() {
- }
+ ~OSMRelationWrap() = default;
}; // class OSMRelationWrap
diff --git a/src/osm_way_wrap.cpp b/src/osm_way_wrap.cpp
index 86991e3..b26c92e 100644
--- a/src/osm_way_wrap.cpp
+++ b/src/osm_way_wrap.cpp
@@ -23,14 +23,15 @@ namespace node_osmium {
constructor = v8::Persistent<v8::FunctionTemplate>::New(v8::FunctionTemplate::New(OSMWayWrap::New));
constructor->Inherit(OSMObjectWrap::constructor);
constructor->InstanceTemplate()->SetInternalFieldCount(1);
- constructor->SetClassName(v8::String::NewSymbol("Way"));
+ constructor->SetClassName(symbol_Way);
auto attributes = static_cast<v8::PropertyAttribute>(v8::ReadOnly | v8::DontDelete);
+ set_accessor(constructor, "type", get_type, attributes);
set_accessor(constructor, "nodes_count", get_nodes_count, attributes);
node::SetPrototypeMethod(constructor, "node_refs", node_refs);
node::SetPrototypeMethod(constructor, "node_coordinates", node_coordinates);
node::SetPrototypeMethod(constructor, "wkb", wkb);
node::SetPrototypeMethod(constructor, "wkt", wkt);
- target->Set(v8::String::NewSymbol("Way"), constructor->GetFunction());
+ target->Set(symbol_Way, constructor->GetFunction());
}
v8::Handle<v8::Value> OSMWayWrap::New(const v8::Arguments& args) {
@@ -71,7 +72,7 @@ namespace node_osmium {
v8::Handle<v8::Value> OSMWayWrap::get_nodes_count(v8::Local<v8::String> /* property */, const v8::AccessorInfo& info) {
v8::HandleScope scope;
- return scope.Close(v8::Number::New(wrapped(info.This()).nodes().size()));
+ return scope.Close(v8::Uint32::New(wrapped(info.This()).nodes().size()));
}
v8::Handle<v8::Value> OSMWayWrap::node_refs(const v8::Arguments& args) {
@@ -90,11 +91,11 @@ namespace node_osmium {
return scope.Close(nodes);
}
case 1: {
- if (!args[0]->IsNumber()) {
+ if (!args[0]->IsUint32()) {
return ThrowException(v8::Exception::TypeError(v8::String::New("call node_refs() without parameters or the index of the node you want")));
}
- int n = static_cast<int>(args[0]->ToNumber()->Value());
- if (n >= 0 && n < static_cast<int>(way.nodes().size())) {
+ uint32_t n = args[0]->ToUint32()->Value();
+ if (n < way.nodes().size()) {
return scope.Close(v8::Number::New(way.nodes()[n].ref()));
} else {
return ThrowException(v8::Exception::RangeError(v8::String::New("argument to node_refs() out of range")));
@@ -108,7 +109,7 @@ namespace node_osmium {
v8::Handle<v8::Value> OSMWayWrap::node_coordinates(const v8::Arguments& args) {
v8::HandleScope scope;
- auto cf = module->Get(v8::String::NewSymbol("Coordinates"));
+ auto cf = module->Get(symbol_Coordinates);
assert(cf->IsFunction());
const osmium::Way& way = wrapped(args.This());
@@ -130,11 +131,11 @@ namespace node_osmium {
}
}
case 1: {
- if (!args[0]->IsNumber()) {
+ if (!args[0]->IsUint32()) {
return ThrowException(v8::Exception::TypeError(v8::String::New("call node_coordinates() without parameters or the index of the node you want")));
}
- int n = static_cast<int>(args[0]->ToNumber()->Value());
- if (n >= 0 && n < static_cast<int>(way.nodes().size())) {
+ uint32_t n = args[0]->ToUint32()->Value();
+ if (n < way.nodes().size()) {
const osmium::Location location = way.nodes()[n].location();
if (location.valid()) {
v8::Local<v8::Value> argv[2] = { v8::Number::New(location.lon()), v8::Number::New(location.lat()) };
diff --git a/src/osm_way_wrap.hpp b/src/osm_way_wrap.hpp
index 229c4bb..1cf2724 100644
--- a/src/osm_way_wrap.hpp
+++ b/src/osm_way_wrap.hpp
@@ -1,12 +1,8 @@
#ifndef OSM_WAY_WRAP_HPP
#define OSM_WAY_WRAP_HPP
-// v8
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wctor-dtor-privacy"
-#pragma GCC diagnostic ignored "-Wunused-parameter"
-#include <v8.h>
-#pragma GCC diagnostic pop
+// v8/node
+#include "include_v8.hpp"
// osmium
#include <osmium/osm/way.hpp>
@@ -15,6 +11,7 @@ namespace osmium {
}
// node-osmium
+#include "node_osmium.hpp"
#include "osm_entity_wrap.hpp"
#include "osm_object_wrap.hpp"
#include "utils.hpp"
@@ -23,6 +20,10 @@ namespace node_osmium {
class OSMWayWrap : public OSMObjectWrap {
+ static v8::Handle<v8::Value> get_type(v8::Local<v8::String> property, const v8::AccessorInfo& info) {
+ return symbol_way;
+ }
+
static v8::Handle<v8::Value> get_nodes_count(v8::Local<v8::String> /* property */, const v8::AccessorInfo& info);
static v8::Handle<v8::Value> node_refs(const v8::Arguments& args);
static v8::Handle<v8::Value> node_coordinates(const v8::Arguments& args);
@@ -45,8 +46,7 @@ namespace node_osmium {
private:
- ~OSMWayWrap() {
- }
+ ~OSMWayWrap() = default;
}; // class OSMWayWrap
diff --git a/src/reader_wrap.cpp b/src/reader_wrap.cpp
index cdf507e..a1e2986 100644
--- a/src/reader_wrap.cpp
+++ b/src/reader_wrap.cpp
@@ -8,6 +8,7 @@
#include <node.h>
// node-osmium
+#include "node_osmium.hpp"
#include "buffer_wrap.hpp"
#include "file_wrap.hpp"
#include "handler.hpp"
@@ -26,11 +27,12 @@ namespace node_osmium {
v8::HandleScope scope;
constructor = v8::Persistent<v8::FunctionTemplate>::New(v8::FunctionTemplate::New(ReaderWrap::New));
constructor->InstanceTemplate()->SetInternalFieldCount(1);
- constructor->SetClassName(v8::String::NewSymbol("Reader"));
+ constructor->SetClassName(symbol_Reader);
node::SetPrototypeMethod(constructor, "header", header);
node::SetPrototypeMethod(constructor, "close", close);
node::SetPrototypeMethod(constructor, "read", read);
- target->Set(v8::String::NewSymbol("Reader"), constructor->GetFunction());
+ node::SetPrototypeMethod(constructor, "read_all", read_all);
+ target->Set(symbol_Reader, constructor->GetFunction());
}
v8::Handle<v8::Value> ReaderWrap::New(const v8::Arguments& args) {
@@ -50,22 +52,22 @@ namespace node_osmium {
read_which_entities = osmium::osm_entity_bits::nothing;
v8::Local<v8::Object> options = args[1]->ToObject();
- v8::Local<v8::Value> want_nodes = options->Get(v8::String::NewSymbol("node"));
+ v8::Local<v8::Value> want_nodes = options->Get(symbol_node);
if (want_nodes->IsBoolean() && want_nodes->BooleanValue()) {
read_which_entities |= osmium::osm_entity_bits::node;
}
- v8::Local<v8::Value> want_ways = options->Get(v8::String::NewSymbol("way"));
+ v8::Local<v8::Value> want_ways = options->Get(symbol_way);
if (want_ways->IsBoolean() && want_ways->BooleanValue()) {
read_which_entities |= osmium::osm_entity_bits::way;
}
- v8::Local<v8::Value> want_relations = options->Get(v8::String::NewSymbol("relation"));
+ v8::Local<v8::Value> want_relations = options->Get(symbol_relation);
if (want_relations->IsBoolean() && want_relations->BooleanValue()) {
read_which_entities |= osmium::osm_entity_bits::relation;
}
- v8::Local<v8::Value> want_changesets = options->Get(v8::String::NewSymbol("changeset"));
+ v8::Local<v8::Value> want_changesets = options->Get(symbol_changeset);
if (want_changesets->IsBoolean() && want_changesets->BooleanValue()) {
read_which_entities |= osmium::osm_entity_bits::changeset;
}
@@ -73,13 +75,13 @@ namespace node_osmium {
}
if (args[0]->IsString()) {
osmium::io::File file(*v8::String::Utf8Value(args[0]));
- ReaderWrap* q = new ReaderWrap(file, read_which_entities);
- q->Wrap(args.This());
+ ReaderWrap* reader_wrap = new ReaderWrap(file, read_which_entities);
+ reader_wrap->Wrap(args.This());
return args.This();
} else if (args[0]->IsObject() && FileWrap::constructor->HasInstance(args[0]->ToObject())) {
v8::Local<v8::Object> file_obj = args[0]->ToObject();
- ReaderWrap* q = new ReaderWrap(unwrap<FileWrap>(file_obj), read_which_entities);
- q->Wrap(args.This());
+ ReaderWrap* reader_wrap = new ReaderWrap(unwrap<FileWrap>(file_obj), read_which_entities);
+ reader_wrap->Wrap(args.This());
return args.This();
} else {
return ThrowException(v8::Exception::TypeError(v8::String::New("please provide a File object or string for the first argument when creating a Reader")));
@@ -94,7 +96,7 @@ namespace node_osmium {
v8::HandleScope scope;
v8::Local<v8::Object> obj = v8::Object::New();
const osmium::io::Header& header = unwrap<ReaderWrap>(args.This()).header();
- obj->Set(v8::String::NewSymbol("generator"), v8::String::New(header.get("generator").c_str()));
+ obj->Set(symbol_generator, v8::String::New(header.get("generator").c_str()));
auto bounds_array = v8::Array::New(header.boxes().size());
@@ -103,7 +105,7 @@ namespace node_osmium {
bounds_array->Set(i++, create_js_box(box));
}
- obj->Set(v8::String::NewSymbol("bounds"), bounds_array);
+ obj->Set(symbol_bounds, bounds_array);
return scope.Close(obj);
}
@@ -124,9 +126,27 @@ namespace node_osmium {
try {
osmium::memory::Buffer buffer = unwrap<ReaderWrap>(args.This()).read();
if (buffer) {
- v8::Handle<v8::Value> ext = v8::External::New(new BufferWrap(std::move(buffer)));
- v8::Local<v8::Object> obj = BufferWrap::constructor->GetFunction()->NewInstance(1, &ext);
- return scope.Close(obj);
+ return scope.Close(new_external<BufferWrap>(std::move(buffer)));
+ }
+ } catch (const std::exception& e) {
+ std::string msg("osmium error: ");
+ msg += e.what();
+ return ThrowException(v8::Exception::Error(v8::String::New(msg.c_str())));
+ }
+ return scope.Close(v8::Undefined());
+ }
+
+ v8::Handle<v8::Value> ReaderWrap::read_all(const v8::Arguments& args) {
+ osmium::memory::Buffer buffer(1024*1024, osmium::memory::Buffer::auto_grow::yes);
+ v8::HandleScope scope;
+ try {
+ osmium::io::Reader& reader = unwrap<ReaderWrap>(args.This());
+ while (osmium::memory::Buffer read_buffer = reader.read()) {
+ buffer.add_buffer(read_buffer);
+ buffer.commit();
+ }
+ if (buffer) {
+ return scope.Close(new_external<BufferWrap>(std::move(buffer)));
}
} catch (const std::exception& e) {
std::string msg("osmium error: ");
diff --git a/src/reader_wrap.hpp b/src/reader_wrap.hpp
index 084c7ef..1d313cd 100644
--- a/src/reader_wrap.hpp
+++ b/src/reader_wrap.hpp
@@ -1,19 +1,8 @@
#ifndef READER_WRAP_HPP
#define READER_WRAP_HPP
-// c++
-#include <memory>
-
-// v8
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wctor-dtor-privacy"
-#pragma GCC diagnostic ignored "-Wunused-parameter"
-#include <v8.h>
-#pragma GCC diagnostic pop
-
-// node
-#include <node.h>
-#include <node_version.h>
+// v8/node
+#include "include_v8.hpp"
#include <node_object_wrap.h>
// osmium
@@ -30,8 +19,9 @@ namespace node_osmium {
static v8::Handle<v8::Value> header(const v8::Arguments& args);
static v8::Handle<v8::Value> close(const v8::Arguments& args);
static v8::Handle<v8::Value> read(const v8::Arguments& args);
+ static v8::Handle<v8::Value> read_all(const v8::Arguments& args);
- std::shared_ptr<osmium::io::Reader> m_this;
+ osmium::io::Reader m_this;
public:
@@ -41,17 +31,16 @@ namespace node_osmium {
ReaderWrap(const osmium::io::File& file, osmium::osm_entity_bits::type entities) :
ObjectWrap(),
- m_this(std::make_shared<osmium::io::Reader>(file, entities)) {
+ m_this(file, entities) {
}
osmium::io::Reader& get() {
- return *m_this;
+ return m_this;
}
private:
- ~ReaderWrap() {
- }
+ ~ReaderWrap() = default;
}; // class ReaderWrap
diff --git a/src/utils.cpp b/src/utils.cpp
index df40fdb..b4cde2e 100644
--- a/src/utils.cpp
+++ b/src/utils.cpp
@@ -2,6 +2,7 @@
// osmium
#include <osmium/osm/box.hpp>
+#include "node_osmium.hpp"
#include "utils.hpp"
namespace node_osmium {
@@ -15,9 +16,9 @@ namespace node_osmium {
return scope.Close(v8::Undefined());
}
- auto cf = module->Get(v8::String::NewSymbol("Coordinates"));
+ auto cf = module->Get(symbol_Coordinates);
assert(cf->IsFunction());
- auto bf = module->Get(v8::String::NewSymbol("Box"));
+ auto bf = module->Get(symbol_Box);
assert(bf->IsFunction());
v8::Local<v8::Value> argv_bl[2] = { v8::Number::New(box.bottom_left().lon()), v8::Number::New(box.bottom_left().lat()) };
diff --git a/src/utils.hpp b/src/utils.hpp
index 331be88..a2bc4b1 100644
--- a/src/utils.hpp
+++ b/src/utils.hpp
@@ -1,14 +1,11 @@
#ifndef UTILS_HPP
#define UTILS_HPP
-// v8
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wctor-dtor-privacy"
-#pragma GCC diagnostic ignored "-Wunused-parameter"
-#include <v8.h>
-#pragma GCC diagnostic pop
-
-// node
+// c++
+#include <utility>
+
+// v8/node
+#include "include_v8.hpp"
#include <node_object_wrap.h>
// osmium
@@ -23,6 +20,13 @@ namespace node_osmium {
return node::ObjectWrap::Unwrap<T>(object)->get();
}
+ template<class T, class... Args>
+ v8::Local<v8::Object> new_external(Args&&... args) {
+ v8::HandleScope scope;
+ v8::Handle<v8::Value> ext = v8::External::New(new T(std::forward<Args>(args)...));
+ return scope.Close(T::constructor->GetFunction()->NewInstance(1, &ext));
+ }
+
v8::Handle<v8::Value> create_js_box(const osmium::Box& box);
} // namespace node_osmium
diff --git a/test/changesets.test.js b/test/changesets.test.js
index da4b366..31fd00b 100644
--- a/test/changesets.test.js
+++ b/test/changesets.test.js
@@ -8,6 +8,7 @@ describe('changesets', function() {
var count = 0;
handler.on('changeset', function(changeset) {
if (count++ == 0) {
+ assert.equal(changeset.type, "changeset");
assert.equal(changeset.id, 15449957);
assert.equal(changeset.user, "Elbert");
assert.equal(changeset.uid, 1237205);
diff --git a/test/data/coordinates-problems.osm b/test/data/coordinates-problems.osm
new file mode 100644
index 0000000..cd61132
--- /dev/null
+++ b/test/data/coordinates-problems.osm
@@ -0,0 +1,6 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<osm version="0.6" generator="testdata" upload="false">
+ <node id="1" version="1" timestamp="2014-01-01T00:00:00Z" uid="1" user="test" changeset="1" lon="1.02" lat="2.03"/> <!-- lon/lat okay -->
+ <node id="2" version="1" timestamp="2014-01-01T00:00:00Z" uid="1" user="test" changeset="1"/> <!-- lon/lat missing -->
+ <node id="3" version="1" timestamp="2014-01-01T00:00:00Z" uid="1" user="test" changeset="1" lon="190" lat="190"/> <!-- outside valid range -->
+</osm>
diff --git a/test/osm_object_creation.test.js b/test/osm-object-creation.test.js
similarity index 100%
rename from test/osm_object_creation.test.js
rename to test/osm-object-creation.test.js
diff --git a/test/osm-objects.test.js b/test/osm-objects.test.js
index 7b10669..491be4d 100644
--- a/test/osm-objects.test.js
+++ b/test/osm-objects.test.js
@@ -8,6 +8,7 @@ describe('basic', function() {
var count = 0;
handler.on('node', function(node) {
if (count++ == 0) {
+ assert.equal(node.type, "node");
assert.equal(node.id, 50031066);
assert.equal(node.visible, true);
assert.equal(node.version, 2);
@@ -36,6 +37,7 @@ describe('basic', function() {
var count = 0;
handler.on('way', function(way) {
if (count++ == 0) {
+ assert.equal(way.type, "way");
assert.equal(way.id, 6091729);
assert.equal(way.visible, true);
assert.equal(way.version, 1);
@@ -57,6 +59,7 @@ describe('basic', function() {
var count = 0;
handler.on('relation', function(relation) {
if (count++ == 0) {
+ assert.equal(relation.type, "relation");
assert.equal(relation.id, 237891);
assert.equal(relation.visible, true);
assert.equal(relation.version, 2);
@@ -174,4 +177,28 @@ describe('basic', function() {
osmium.apply(reader, handler);
});
+ it('should be able to handle missing and invalid coordinates', function() {
+ var handler = new osmium.Handler();
+ var count = 0;
+ handler.on('node', function(node) {
+ count++;
+ if (count == 1) {
+ assert.equal(node.coordinates.lon, 1.02);
+ assert.equal(node.coordinates.lat, 2.03);
+ assert.equal(node.coordinates.valid(), true);
+ } else if (count == 2) {
+ assert.equal(node.coordinates.lon, undefined);
+ assert.equal(node.coordinates.lat, undefined);
+ assert.equal(node.coordinates.valid(), false);
+ } else if (count == 3) {
+ assert.equal(node.coordinates.lon, 190);
+ assert.equal(node.coordinates.lat, 190);
+ assert.equal(node.coordinates.valid(), false);
+ }
+ });
+ var file = new osmium.File(__dirname + "/data/coordinates-problems.osm");
+ var reader = new osmium.Reader(file, {node: true});
+ osmium.apply(reader, handler);
+ });
+
});
diff --git a/test/reader.test.js b/test/reader.test.js
index b71a8a3..fb4cb60 100644
--- a/test/reader.test.js
+++ b/test/reader.test.js
@@ -65,5 +65,23 @@ describe('reader', function() {
osmium.apply(reader, handler);
});
+ it('should read a whole file with Reader.read_all()', function(done) {
+ var file = new osmium.File(__dirname + "/data/winthrop.osm");
+ var reader = new osmium.Reader(file);
+ var buffer = reader.read_all();
+
+ var handler = new osmium.Handler();
+
+ var count = 0;
+ handler.on('node', function(node) {
+ if (count++ == 0) {
+ assert.equal(node.id, 50031066);
+ done();
+ }
+ });
+
+ osmium.apply(buffer, handler);
+ });
+
});
--
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