shapelib 0.7.0 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -3,17 +3,21 @@ require 'mkmf'
3
3
 
4
4
  HEADER_DIRS = [
5
5
  '/opt/local/include',
6
+ '/opt/homebrew/include',
6
7
  '/usr/local/include',
7
8
  '/usr/include',
8
9
  ]
9
10
 
10
11
  LIB_DIRS = [
11
12
  '/opt/local/lib',
13
+ '/opt/homebrew/lib',
12
14
  '/usr/local/lib',
13
15
  '/usr/lib',
14
16
  ]
15
17
 
16
18
  dir_config('shapelib', HEADER_DIRS, LIB_DIRS)
17
- have_header('shapefil.h') or have_header('libshp/shapefil.h') or raise 'shapefil.h not found'
19
+ header = %w[shapefil.h libshp/shapefil.h].find { |name| have_header(name) }
20
+ raise 'shapefil.h not found' unless header
18
21
  have_library('shp') or raise 'libshp not found'
22
+ have_const('FTDate', header)
19
23
  create_makefile('shapelib_ext')
@@ -37,6 +37,27 @@ static VALUE cMultiPatch;
37
37
 
38
38
  /* code begins here */
39
39
 
40
+ static void shape_free(void *ptr)
41
+ {
42
+ shape_close(ptr);
43
+ }
44
+
45
+ static void shapefile_free(void *ptr)
46
+ {
47
+ shapefile_close(ptr);
48
+ xfree(ptr);
49
+ }
50
+
51
+ static const rb_data_type_t shape_data_type = {
52
+ "Shapelib::Shape", { 0, shape_free, 0 }
53
+ };
54
+
55
+ static const rb_data_type_t shapefile_data_type = {
56
+ "Shapelib::ShapeFile", { 0, shapefile_free, 0 }
57
+ };
58
+
59
+ static VALUE WrapShape(VALUE klass, shape_t *shape);
60
+
40
61
  #include "valconv.h"
41
62
  #include "sfcode.h"
42
63
  #include "sflist.h"
@@ -64,20 +85,36 @@ void Init_shapelib_ext()
64
85
  {
65
86
  mShapeLib = rb_define_module("Shapelib");
66
87
  cShapeFile = rb_define_class_under(mShapeLib, "ShapeFile", rb_cObject);
88
+ rb_undef_alloc_func(cShapeFile);
67
89
  cShape = rb_define_class_under(mShapeLib, "Shape", rb_cObject);
90
+ rb_undef_alloc_func(cShape);
68
91
  cPoint = rb_define_class_under(mShapeLib, "Point", cShape);
92
+ rb_undef_alloc_func(cPoint);
69
93
  cPointM = rb_define_class_under(mShapeLib, "PointM", cPoint);
94
+ rb_undef_alloc_func(cPointM);
70
95
  cPointZ = rb_define_class_under(mShapeLib, "PointZ", cPointM);
96
+ rb_undef_alloc_func(cPointZ);
71
97
  cArc = rb_define_class_under(mShapeLib, "Arc", cShape);
98
+ rb_undef_alloc_func(cArc);
72
99
  cArcM = rb_define_class_under(mShapeLib, "ArcM", cArc);
100
+ rb_undef_alloc_func(cArcM);
73
101
  cArcZ = rb_define_class_under(mShapeLib, "ArcZ", cArcM);
102
+ rb_undef_alloc_func(cArcZ);
74
103
  cPolygon = rb_define_class_under(mShapeLib, "Polygon", cShape);
104
+ rb_undef_alloc_func(cPolygon);
75
105
  cPolygonM = rb_define_class_under(mShapeLib, "PolygonM", cPolygon);
106
+ rb_undef_alloc_func(cPolygonM);
76
107
  cPolygonZ = rb_define_class_under(mShapeLib, "PolygonZ", cPolygonM);
108
+ rb_undef_alloc_func(cPolygonZ);
77
109
  cMultiPoint = rb_define_class_under(mShapeLib, "MultiPoint", cShape);
110
+ rb_undef_alloc_func(cMultiPoint);
78
111
  cMultiPointM = rb_define_class_under(mShapeLib, "MultiPointM", cMultiPoint);
112
+ rb_undef_alloc_func(cMultiPointM);
79
113
  cMultiPointZ = rb_define_class_under(mShapeLib, "MultiPointZ", cMultiPointM);
114
+ rb_undef_alloc_func(cMultiPointZ);
80
115
  cMultiPatch = rb_define_class_under(mShapeLib, "MultiPatch", cShape);
116
+ rb_undef_alloc_func(cMultiPatch);
117
+
81
118
  rb_define_module_function(mShapeLib, "new_point", sl_m_new_point, -1);
82
119
  rb_define_singleton_method(cShapeFile, "new", sf_s_new, -1);
83
120
  rb_define_singleton_method(cShapeFile, "open", sf_s_open, -1);
@@ -11,7 +11,6 @@ static VALUE sf_add_field(int argc, VALUE *args, VALUE obj)
11
11
 
12
12
  rb_scan_args(argc, args, "31",
13
13
  &name, &field_type, &field_width, &decimal_place);
14
- SECURE(name);
15
14
  StringValue(name);
16
15
  atype = Ruby2FieldType(field_type);
17
16
  width = NUM2INT(field_width);
@@ -19,15 +18,15 @@ static VALUE sf_add_field(int argc, VALUE *args, VALUE obj)
19
18
  if (atype == FTDouble && argc == 3) {
20
19
  rb_raise(rb_eArgError, "specify decimal places for Float attribute");
21
20
  }
22
- Data_Get_Struct(obj, shapefile_t, self);
23
- r = shapefile_add_field(self, RSTRING_PTR(name), atype, width, wdeci);
21
+ TypedData_Get_Struct(obj, shapefile_t, &shapefile_data_type, self);
22
+ r = shapefile_add_field(self, StringValueCStr(name), atype, width, wdeci);
24
23
  return obj;
25
24
  }
26
25
 
27
26
  static VALUE sf_close(VALUE obj)
28
27
  {
29
28
  shapefile_t *self;
30
- Data_Get_Struct(obj, shapefile_t, self);
29
+ TypedData_Get_Struct(obj, shapefile_t, &shapefile_data_type, self);
31
30
  return INT2FIX(shapefile_close(self));
32
31
  }
33
32
 
@@ -35,7 +34,7 @@ static VALUE sf_field_count(VALUE obj)
35
34
  {
36
35
  shapefile_t *self;
37
36
  int r;
38
- Data_Get_Struct(obj, shapefile_t, self);
37
+ TypedData_Get_Struct(obj, shapefile_t, &shapefile_data_type, self);
39
38
  r = shapefile_field_count(self);
40
39
  return INT2FIX(r);
41
40
  }
@@ -45,15 +44,14 @@ static int Ruby2FieldIndex(shapefile_t *sfile, VALUE field)
45
44
  if (FIXNUM_P(field)) {
46
45
  return FIX2INT(field);
47
46
  } else {
48
- SECURE(field);
49
- return shapefile_field_index(sfile, StringValuePtr(field));
47
+ return shapefile_field_index(sfile, StringValueCStr(field));
50
48
  }
51
49
  }
52
50
 
53
51
  static VALUE sf_delete_shape(VALUE obj, VALUE ishape)
54
52
  {
55
53
  shapefile_t *self;
56
- Data_Get_Struct(obj, shapefile_t, self);
54
+ TypedData_Get_Struct(obj, shapefile_t, &shapefile_data_type, self);
57
55
  shapefile_delete_shape(self, NUM2INT(ishape));
58
56
  return Qnil;
59
57
  }
@@ -62,7 +60,7 @@ static VALUE sf_field_index(VALUE obj, VALUE name)
62
60
  {
63
61
  shapefile_t *self;
64
62
  int ifield;
65
- Data_Get_Struct(obj, shapefile_t, self);
63
+ TypedData_Get_Struct(obj, shapefile_t, &shapefile_data_type, self);
66
64
  ifield = Ruby2FieldIndex(self, name);
67
65
  return (ifield < 0) ? Qnil : INT2FIX(ifield);
68
66
  }
@@ -71,7 +69,7 @@ static VALUE sf_field_name(VALUE obj, VALUE index)
71
69
  {
72
70
  shapefile_t *self;
73
71
  const char *name;
74
- Data_Get_Struct(obj, shapefile_t, self);
72
+ TypedData_Get_Struct(obj, shapefile_t, &shapefile_data_type, self);
75
73
  name = shapefile_field_name(self, NUM2INT(index));
76
74
  return name ? rb_str_new2(name) : Qnil;
77
75
  }
@@ -80,7 +78,7 @@ static VALUE sf_field_type(VALUE obj, VALUE field)
80
78
  {
81
79
  shapefile_t *self;
82
80
  int ifield;
83
- Data_Get_Struct(obj, shapefile_t, self);
81
+ TypedData_Get_Struct(obj, shapefile_t, &shapefile_data_type, self);
84
82
  ifield = Ruby2FieldIndex(self, field);
85
83
  return FieldType2Ruby(shapefile_field_type(self, ifield));
86
84
  }
@@ -89,7 +87,7 @@ static VALUE sf_field_width(VALUE obj, VALUE field)
89
87
  {
90
88
  shapefile_t *self;
91
89
  int ifield;
92
- Data_Get_Struct(obj, shapefile_t, self);
90
+ TypedData_Get_Struct(obj, shapefile_t, &shapefile_data_type, self);
93
91
  ifield = Ruby2FieldIndex(self, field);
94
92
  return INT2FIX(shapefile_field_width(self, ifield));
95
93
  }
@@ -98,7 +96,7 @@ static VALUE sf_field_decimals(VALUE obj, VALUE field)
98
96
  {
99
97
  shapefile_t *self;
100
98
  int ifield;
101
- Data_Get_Struct(obj, shapefile_t, self);
99
+ TypedData_Get_Struct(obj, shapefile_t, &shapefile_data_type, self);
102
100
  ifield = Ruby2FieldIndex(self, field);
103
101
  return INT2FIX(shapefile_field_decimals(self, ifield));
104
102
  }
@@ -108,7 +106,7 @@ static VALUE sf_fields(VALUE obj)
108
106
  shapefile_t *self;
109
107
  VALUE r;
110
108
  int fc, i;
111
- Data_Get_Struct(obj, shapefile_t, self);
109
+ TypedData_Get_Struct(obj, shapefile_t, &shapefile_data_type, self);
112
110
  fc = shapefile_field_count(self);
113
111
  if (fc < 0)
114
112
  return Qnil;
@@ -126,12 +124,12 @@ static VALUE sf_maxbound(VALUE obj)
126
124
  shapefile_t *self;
127
125
  double bound[4];
128
126
  double z;
129
- Data_Get_Struct(obj, shapefile_t, self);
127
+ TypedData_Get_Struct(obj, shapefile_t, &shapefile_data_type, self);
130
128
  shapefile_bound(self, NULL, bound);
131
129
  z = bound[2];
132
130
  bound[2] = bound[3];
133
131
  bound[3] = z;
134
- return DoubleUnpack(bound, 4);
132
+ return DoubleUnpackM(bound, 4, 2);
135
133
  }
136
134
 
137
135
  static VALUE sf_minbound(VALUE obj)
@@ -139,34 +137,33 @@ static VALUE sf_minbound(VALUE obj)
139
137
  shapefile_t *self;
140
138
  double bound[4];
141
139
  double z;
142
- Data_Get_Struct(obj, shapefile_t, self);
140
+ TypedData_Get_Struct(obj, shapefile_t, &shapefile_data_type, self);
143
141
  shapefile_bound(self, bound, NULL);
144
142
  z = bound[2];
145
143
  bound[2] = bound[3];
146
144
  bound[3] = z;
147
- return DoubleUnpack(bound, 4);
145
+ return DoubleUnpackM(bound, 4, 2);
148
146
  }
149
147
 
150
148
  static VALUE sf_read(int argc, VALUE *args, VALUE obj)
151
149
  {
152
150
  shapefile_t *self;
153
151
  shape_t *s;
154
- VALUE ishape, r;
152
+ VALUE ishape;
155
153
  int irec;
156
154
  rb_scan_args(argc, args, "01", &ishape);
157
- Data_Get_Struct(obj, shapefile_t, self);
155
+ TypedData_Get_Struct(obj, shapefile_t, &shapefile_data_type, self);
158
156
  irec = NIL_P(ishape) ? -1 : NUM2INT(ishape);
159
157
  s = shapefile_read(self, irec);
160
158
  if (s == NULL)
161
159
  return Qnil;
162
- r = Data_Wrap_Struct(cShape, 0, shape_close, s);
163
- return r;
160
+ return WrapShape(cShape, s);
164
161
  }
165
162
 
166
163
  static VALUE sf_rewind(VALUE obj)
167
164
  {
168
165
  shapefile_t *self;
169
- Data_Get_Struct(obj, shapefile_t, self);
166
+ TypedData_Get_Struct(obj, shapefile_t, &shapefile_data_type, self);
170
167
  self->irec = 0;
171
168
  return obj;
172
169
  }
@@ -187,7 +184,7 @@ static VALUE sf_each(VALUE obj)
187
184
  static VALUE sf_shape_type(VALUE obj)
188
185
  {
189
186
  shapefile_t *self;
190
- Data_Get_Struct(obj, shapefile_t, self);
187
+ TypedData_Get_Struct(obj, shapefile_t, &shapefile_data_type, self);
191
188
  return ShapeType2Ruby(shapefile_shape_type(self));
192
189
  }
193
190
 
@@ -195,7 +192,7 @@ static VALUE sf_size(VALUE obj)
195
192
  {
196
193
  shapefile_t *self;
197
194
  int r;
198
- Data_Get_Struct(obj, shapefile_t, self);
195
+ TypedData_Get_Struct(obj, shapefile_t, &shapefile_data_type, self);
199
196
  r = shapefile_size(self);
200
197
  if (r < 0)
201
198
  rb_raise(rb_eRuntimeError, "size %d", r);
@@ -210,9 +207,9 @@ static VALUE sf_write(int argc, VALUE *args, VALUE obj)
210
207
  if (argc < 1 || argc > 2) {
211
208
  rb_raise(rb_eArgError, "usage: Shapefile#write shape, [irec = -1]");
212
209
  }
213
- Data_Get_Struct(obj, shapefile_t, self);
214
- Data_Get_Struct(args[0], shape_t, shape);
215
- irec = ((argc == 2) ? NUM2INT(args[1]) : -1);
210
+ TypedData_Get_Struct(obj, shapefile_t, &shapefile_data_type, self);
211
+ TypedData_Get_Struct(args[0], shape_t, &shape_data_type, shape);
212
+ irec = (argc == 2 && !NIL_P(args[1])) ? NUM2INT(args[1]) : -1;
216
213
  r = shapefile_write(self, irec, shape);
217
214
  return INT2FIX(r);
218
215
  }
@@ -221,12 +218,41 @@ static VALUE sf_write(int argc, VALUE *args, VALUE obj)
221
218
  * constructor
222
219
  */
223
220
 
221
+ struct shapefile_wrap_args {
222
+ VALUE klass;
223
+ shapefile_t *sfile;
224
+ };
225
+
226
+ static VALUE WrapShapeFileProtected(VALUE ptr)
227
+ {
228
+ struct shapefile_wrap_args *args = (struct shapefile_wrap_args *)ptr;
229
+ return TypedData_Wrap_Struct(args->klass, &shapefile_data_type, args->sfile);
230
+ }
231
+
232
+ static VALUE WrapShapeFile(VALUE klass, shapefile_t *sfile)
233
+ {
234
+ struct shapefile_wrap_args args = { klass, sfile };
235
+ int state;
236
+ VALUE sf = rb_protect(WrapShapeFileProtected, (VALUE)&args, &state);
237
+ if (state) {
238
+ shapefile_free(sfile);
239
+ rb_jump_tag(state);
240
+ }
241
+ return sf;
242
+ }
243
+
244
+ static VALUE CallShapeFileBlock(VALUE args)
245
+ {
246
+ rb_funcall(rb_ary_entry(args, 0), rb_intern("call"), 1,
247
+ rb_ary_entry(args, 1));
248
+ return Qnil;
249
+ }
250
+
224
251
  static VALUE YieldIfPossible(VALUE proc, VALUE sf)
225
252
  {
226
253
  if (!NIL_P(proc)) {
227
- rb_funcall(proc, rb_intern("call"), 1, sf);
228
- sf_close(sf);
229
- return Qnil;
254
+ return rb_ensure(CallShapeFileBlock, rb_ary_new_from_args(2, proc, sf),
255
+ sf_close, sf);
230
256
  } else {
231
257
  return sf;
232
258
  }
@@ -237,11 +263,14 @@ static VALUE sf_s_open(int argc, VALUE *argv, VALUE klass)
237
263
  VALUE fnam, mode, sf, proc;
238
264
  shapefile_t *sfile;
239
265
  rb_scan_args(argc, argv, "11&", &fnam, &mode, &proc);
240
- SECURE(fnam);
241
- sfile = shapefile_open(StringValuePtr(fnam),
242
- (NIL_P(mode) ? "rb" : StringValuePtr(mode))
266
+ /* Finish Ruby callbacks before taking pointers into either string. */
267
+ StringValue(fnam);
268
+ if (!NIL_P(mode))
269
+ StringValue(mode);
270
+ sfile = shapefile_open(StringValueCStr(fnam),
271
+ (NIL_P(mode) ? "rb" : StringValueCStr(mode))
243
272
  );
244
- sf = Data_Wrap_Struct(klass, 0, shapefile_close, sfile);
273
+ sf = WrapShapeFile(klass, sfile);
245
274
  return YieldIfPossible(proc, sf);
246
275
  }
247
276
 
@@ -253,11 +282,10 @@ static VALUE sf_s_new(int argc, VALUE *argv, VALUE klass)
253
282
  int i;
254
283
  if (argc > 3 || argc < 2) {
255
284
  rb_raise(rb_eArgError,
256
- "usage: ShapeLib::Shapefile.new filename, shapetype, attrs = []");
285
+ "usage: Shapelib::ShapeFile.new filename, shapetype, attrs = []");
257
286
  return Qnil;
258
287
  }
259
288
  rb_scan_args(argc, argv, "21&", &fnam, &shapetype, &attrs, &proc);
260
- SECURE(fnam);
261
289
  if ((stype = Ruby2ShapeType(shapetype)) == -1) {
262
290
  rb_raise(rb_eArgError, "shapetype must be Shape subclass");
263
291
  }
@@ -266,11 +294,11 @@ static VALUE sf_s_new(int argc, VALUE *argv, VALUE klass)
266
294
  rb_raise(rb_eArgError, "attrs must be Array");
267
295
  }
268
296
  }
269
- sfile = shapefile_new(StringValuePtr(fnam), stype);
297
+ sfile = shapefile_new(StringValueCStr(fnam), stype);
270
298
  if (sfile == NULL) {
271
299
  rb_raise(rb_eRuntimeError, "shapefile_new failed");
272
300
  }
273
- sf = Data_Wrap_Struct(klass, 0, shapefile_close, sfile);
301
+ sf = WrapShapeFile(klass, sfile);
274
302
  if (argc > 2) {
275
303
  for (i = 0; i < RARRAY_LEN(attrs); i++) {
276
304
  VALUE p = RARRAY_PTR(attrs)[i];
@@ -1,21 +1,21 @@
1
1
  static method_table_entry sf_methods[] = {
2
- { "add_field", sf_add_field, -1 },
3
- { "close", sf_close, 0 },
4
- { "delete_shape", sf_delete_shape, 1 },
5
- { "each", sf_each, 0 },
6
- { "field_count", sf_field_count, 0 },
7
- { "field_index", sf_field_index, 1 },
8
- { "field_name", sf_field_name, 1 },
9
- { "field_type", sf_field_type, 1 },
10
- { "field_width", sf_field_width, 1 },
11
- { "field_decimals", sf_field_decimals, 1 },
12
- { "fields", sf_fields, 0 },
13
- { "minbound", sf_minbound, 0 },
14
- { "maxbound", sf_maxbound, 0 },
15
- { "read", sf_read, -1 },
16
- { "rewind", sf_rewind, 0 },
17
- { "shape_type", sf_shape_type, 0 },
18
- { "size", sf_size, 0 },
19
- { "write", sf_write, -1 },
2
+ { "add_field", RUBY_METHOD_FUNC(sf_add_field), -1 },
3
+ { "close", RUBY_METHOD_FUNC(sf_close), 0 },
4
+ { "delete_shape", RUBY_METHOD_FUNC(sf_delete_shape), 1 },
5
+ { "each", RUBY_METHOD_FUNC(sf_each), 0 },
6
+ { "field_count", RUBY_METHOD_FUNC(sf_field_count), 0 },
7
+ { "field_index", RUBY_METHOD_FUNC(sf_field_index), 1 },
8
+ { "field_name", RUBY_METHOD_FUNC(sf_field_name), 1 },
9
+ { "field_type", RUBY_METHOD_FUNC(sf_field_type), 1 },
10
+ { "field_width", RUBY_METHOD_FUNC(sf_field_width), 1 },
11
+ { "field_decimals", RUBY_METHOD_FUNC(sf_field_decimals), 1 },
12
+ { "fields", RUBY_METHOD_FUNC(sf_fields), 0 },
13
+ { "minbound", RUBY_METHOD_FUNC(sf_minbound), 0 },
14
+ { "maxbound", RUBY_METHOD_FUNC(sf_maxbound), 0 },
15
+ { "read", RUBY_METHOD_FUNC(sf_read), -1 },
16
+ { "rewind", RUBY_METHOD_FUNC(sf_rewind), 0 },
17
+ { "shape_type", RUBY_METHOD_FUNC(sf_shape_type), 0 },
18
+ { "size", RUBY_METHOD_FUNC(sf_size), 0 },
19
+ { "write", RUBY_METHOD_FUNC(sf_write), -1 },
20
20
  { NULL, NULL, 0 }
21
21
  };