rgeo 2.3.1 → 2.4.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -10,6 +10,8 @@
10
10
  #include <ruby.h>
11
11
  #include <geos_c.h>
12
12
 
13
+ #include "globals.h"
14
+
13
15
  #include "factory.h"
14
16
  #include "geometry.h"
15
17
  #include "point.h"
@@ -36,82 +38,89 @@ static void message_handler(const char* fmt, ...)
36
38
  // objects that have been created for the factory, and then destroy
37
39
  // the GEOS context, before freeing the factory data itself.
38
40
 
39
- static void destroy_factory_func(RGeo_FactoryData* data)
41
+ static void destroy_factory_func(void* data)
40
42
  {
43
+ RGeo_FactoryData* factory_data;
41
44
  GEOSContextHandle_t context;
42
45
 
43
- context = data->geos_context;
44
- if (data->wkt_reader) {
45
- GEOSWKTReader_destroy_r(context, data->wkt_reader);
46
+ factory_data = (RGeo_FactoryData*)data;
47
+ context = factory_data->geos_context;
48
+ if (factory_data->wkt_reader) {
49
+ GEOSWKTReader_destroy_r(context, factory_data->wkt_reader);
46
50
  }
47
- if (data->wkb_reader) {
48
- GEOSWKBReader_destroy_r(context, data->wkb_reader);
51
+ if (factory_data->wkb_reader) {
52
+ GEOSWKBReader_destroy_r(context, factory_data->wkb_reader);
49
53
  }
50
- if (data->wkt_writer) {
51
- GEOSWKTWriter_destroy_r(context, data->wkt_writer);
54
+ if (factory_data->wkt_writer) {
55
+ GEOSWKTWriter_destroy_r(context, factory_data->wkt_writer);
52
56
  }
53
- if (data->wkb_writer) {
54
- GEOSWKBWriter_destroy_r(context, data->wkb_writer);
57
+ if (factory_data->wkb_writer) {
58
+ GEOSWKBWriter_destroy_r(context, factory_data->wkb_writer);
55
59
  }
56
- if (data->psych_wkt_reader) {
57
- GEOSWKTReader_destroy_r(context, data->psych_wkt_reader);
60
+ if (factory_data->psych_wkt_reader) {
61
+ GEOSWKTReader_destroy_r(context, factory_data->psych_wkt_reader);
58
62
  }
59
- if (data->marshal_wkb_reader) {
60
- GEOSWKBReader_destroy_r(context, data->marshal_wkb_reader);
63
+ if (factory_data->marshal_wkb_reader) {
64
+ GEOSWKBReader_destroy_r(context, factory_data->marshal_wkb_reader);
61
65
  }
62
- if (data->psych_wkt_writer) {
63
- GEOSWKTWriter_destroy_r(context, data->psych_wkt_writer);
66
+ if (factory_data->psych_wkt_writer) {
67
+ GEOSWKTWriter_destroy_r(context, factory_data->psych_wkt_writer);
64
68
  }
65
- if (data->marshal_wkb_writer) {
66
- GEOSWKBWriter_destroy_r(context, data->marshal_wkb_writer);
69
+ if (factory_data->marshal_wkb_writer) {
70
+ GEOSWKBWriter_destroy_r(context, factory_data->marshal_wkb_writer);
67
71
  }
68
72
  finishGEOS_r(context);
69
- free(data);
73
+ free(factory_data);
70
74
  }
71
75
 
72
76
 
73
77
  // Destroy function for geometry data. We destroy the internal
74
78
  // GEOS geometry (if present) before freeing the data itself.
75
79
 
76
- static void destroy_geometry_func(RGeo_GeometryData* data)
80
+ static void destroy_geometry_func(void* data)
77
81
  {
82
+ RGeo_GeometryData* geometry_data;
78
83
  const GEOSPreparedGeometry* prep;
79
84
 
80
- if (data->geom) {
81
- GEOSGeom_destroy_r(data->geos_context, data->geom);
85
+ geometry_data = (RGeo_GeometryData*)data;
86
+ if (geometry_data->geom) {
87
+ GEOSGeom_destroy_r(geometry_data->geos_context, geometry_data->geom);
82
88
  }
83
- prep = data->prep;
89
+ prep = geometry_data->prep;
84
90
  if (prep && prep != (const GEOSPreparedGeometry*)1 && prep != (const GEOSPreparedGeometry*)2 &&
85
91
  prep != (const GEOSPreparedGeometry*)3)
86
92
  {
87
- GEOSPreparedGeom_destroy_r(data->geos_context, prep);
93
+ GEOSPreparedGeom_destroy_r(geometry_data->geos_context, prep);
88
94
  }
89
- free(data);
95
+ free(geometry_data);
90
96
  }
91
97
 
92
98
 
93
99
  // Mark function for factory data. This marks the wkt and wkb generator
94
100
  // handles so they don't get collected.
95
101
 
96
- static void mark_factory_func(RGeo_FactoryData* data)
102
+ static void mark_factory_func(void* data)
97
103
  {
98
- if (!NIL_P(data->wkrep_wkt_generator)) {
99
- rb_gc_mark(data->wkrep_wkt_generator);
104
+ RGeo_FactoryData* factory_data;
105
+
106
+ factory_data = (RGeo_FactoryData*)data;
107
+ if (!NIL_P(factory_data->wkrep_wkt_generator)) {
108
+ mark(factory_data->wkrep_wkt_generator);
100
109
  }
101
- if (!NIL_P(data->wkrep_wkb_generator)) {
102
- rb_gc_mark(data->wkrep_wkb_generator);
110
+ if (!NIL_P(factory_data->wkrep_wkb_generator)) {
111
+ mark(factory_data->wkrep_wkb_generator);
103
112
  }
104
- if (!NIL_P(data->wkrep_wkt_parser)) {
105
- rb_gc_mark(data->wkrep_wkt_parser);
113
+ if (!NIL_P(factory_data->wkrep_wkt_parser)) {
114
+ mark(factory_data->wkrep_wkt_parser);
106
115
  }
107
- if (!NIL_P(data->wkrep_wkb_parser)) {
108
- rb_gc_mark(data->wkrep_wkb_parser);
116
+ if (!NIL_P(factory_data->wkrep_wkb_parser)) {
117
+ mark(factory_data->wkrep_wkb_parser);
109
118
  }
110
- if (!NIL_P(data->proj4_obj)) {
111
- rb_gc_mark(data->proj4_obj);
119
+ if (!NIL_P(factory_data->proj4_obj)) {
120
+ mark(factory_data->proj4_obj);
112
121
  }
113
- if (!NIL_P(data->coord_sys_obj)) {
114
- rb_gc_mark(data->coord_sys_obj);
122
+ if (!NIL_P(factory_data->coord_sys_obj)) {
123
+ mark(factory_data->coord_sys_obj);
115
124
  }
116
125
  }
117
126
 
@@ -119,32 +128,83 @@ static void mark_factory_func(RGeo_FactoryData* data)
119
128
  // Mark function for geometry data. This marks the factory and klasses
120
129
  // held by the geometry so those don't get collected.
121
130
 
122
- static void mark_geometry_func(RGeo_GeometryData* data)
131
+ static void mark_geometry_func(void* data)
123
132
  {
124
- if (!NIL_P(data->factory)) {
125
- rb_gc_mark(data->factory);
133
+ RGeo_GeometryData* geometry_data;
134
+
135
+ geometry_data = (RGeo_GeometryData*)data;
136
+ if (!NIL_P(geometry_data->factory)) {
137
+ mark(geometry_data->factory);
126
138
  }
127
- if (!NIL_P(data->klasses)) {
128
- rb_gc_mark(data->klasses);
139
+ if (!NIL_P(geometry_data->klasses)) {
140
+ mark(geometry_data->klasses);
129
141
  }
130
142
  }
131
143
 
132
144
 
133
- // Destroy function for globals data. We don't need to destroy any
134
- // auxiliary data for now...
135
-
136
- static void destroy_globals_func(RGeo_Globals* data)
145
+ #ifdef HAVE_RB_GC_MARK_MOVABLE
146
+ static void compact_factory_func(void* data)
137
147
  {
138
- free(data);
139
- }
148
+ RGeo_FactoryData* factory_data;
140
149
 
150
+ factory_data = (RGeo_FactoryData*)data;
151
+ if (!NIL_P(factory_data->wkrep_wkt_generator)) {
152
+ factory_data->wkrep_wkt_generator = rb_gc_location(factory_data->wkrep_wkt_generator);
153
+ }
154
+ if (!NIL_P(factory_data->wkrep_wkb_generator)) {
155
+ factory_data->wkrep_wkb_generator = rb_gc_location(factory_data->wkrep_wkb_generator);
156
+ }
157
+ if (!NIL_P(factory_data->wkrep_wkt_parser)) {
158
+ factory_data->wkrep_wkt_parser = rb_gc_location(factory_data->wkrep_wkt_parser);
159
+ }
160
+ if (!NIL_P(factory_data->wkrep_wkb_parser)) {
161
+ factory_data->wkrep_wkb_parser = rb_gc_location(factory_data->wkrep_wkb_parser);
162
+ }
163
+ if (!NIL_P(factory_data->proj4_obj)) {
164
+ factory_data->proj4_obj = rb_gc_location(factory_data->proj4_obj);
165
+ }
166
+ if (!NIL_P(factory_data->coord_sys_obj)) {
167
+ factory_data->coord_sys_obj = rb_gc_location(factory_data->coord_sys_obj);
168
+ }
169
+ }
141
170
 
142
- // Mark function for globals data. This should mark any globals that
143
- // need to be held through garbage collection (none at the moment.)
144
171
 
145
- static void mark_globals_func(RGeo_Globals* data)
172
+ static void compact_geometry_func(void* data)
146
173
  {
174
+ RGeo_GeometryData* geometry_data;
175
+
176
+ geometry_data = (RGeo_GeometryData*)data;
177
+ if (!NIL_P(geometry_data->factory)) {
178
+ geometry_data->factory = rb_gc_location(geometry_data->factory);
179
+ }
180
+ if (!NIL_P(geometry_data->klasses)) {
181
+ geometry_data->klasses = rb_gc_location(geometry_data->klasses);
182
+ }
147
183
  }
184
+ #endif
185
+
186
+
187
+ const rb_data_type_t rgeo_factory_type = {
188
+ .wrap_struct_name = "RGeo/Factory",
189
+ .function = {
190
+ .dmark = mark_factory_func,
191
+ .dfree = destroy_factory_func,
192
+ #ifdef HAVE_RB_GC_MARK_MOVABLE
193
+ .dcompact = compact_factory_func,
194
+ #endif
195
+ }
196
+ };
197
+
198
+ const rb_data_type_t rgeo_geometry_type = {
199
+ .wrap_struct_name = "RGeo/Geometry",
200
+ .function = {
201
+ .dmark = mark_geometry_func,
202
+ .dfree = destroy_geometry_func,
203
+ #ifdef HAVE_RB_GC_MARK_MOVABLE
204
+ .dcompact = compact_geometry_func,
205
+ #endif
206
+ }
207
+ };
148
208
 
149
209
 
150
210
  /**** RUBY METHOD DEFINITIONS ****/
@@ -248,7 +308,6 @@ static VALUE method_factory_read_for_marshal(VALUE self, VALUE str)
248
308
  return result;
249
309
  }
250
310
 
251
-
252
311
  static VALUE method_factory_read_for_psych(VALUE self, VALUE str)
253
312
  {
254
313
  RGeo_FactoryData* self_data;
@@ -275,6 +334,9 @@ static VALUE method_factory_read_for_psych(VALUE self, VALUE str)
275
334
  return result;
276
335
  }
277
336
 
337
+ #ifndef RGEO_GEOS_SUPPORTS_SETOUTPUTDIMENSION
338
+ static VALUE marshal_wkb_generator;
339
+ #endif
278
340
 
279
341
  static VALUE method_factory_write_for_marshal(VALUE self, VALUE obj)
280
342
  {
@@ -286,25 +348,18 @@ static VALUE method_factory_write_for_marshal(VALUE self, VALUE obj)
286
348
  char* str;
287
349
  size_t size;
288
350
  char has_3d;
289
- #ifndef RGEO_GEOS_SUPPORTS_SETOUTPUTDIMENSION
290
- RGeo_Globals* globals;
291
- VALUE wkb_generator;
292
- #endif
293
351
 
294
352
  self_data = RGEO_FACTORY_DATA_PTR(self);
295
353
  self_context = self_data->geos_context;
296
354
  has_3d = self_data->flags & RGEO_FACTORYFLAGS_SUPPORTS_Z_OR_M;
297
355
  #ifndef RGEO_GEOS_SUPPORTS_SETOUTPUTDIMENSION
298
356
  if (has_3d) {
299
- globals = self_data->globals;
300
- wkb_generator = globals->marshal_wkb_generator;
301
- if (NIL_P(wkb_generator)) {
302
- wkb_generator = rb_funcall(
303
- rb_const_get_at(globals->geos_module, rb_intern("Utils")),
357
+ if (NIL_P(marshal_wkb_generator)) {
358
+ marshal_wkb_generator = rb_funcall(
359
+ rb_const_get_at(rgeo_geos_module, rb_intern("Utils")),
304
360
  rb_intern("marshal_wkb_generator"), 0);
305
- globals->marshal_wkb_generator = wkb_generator;
306
361
  }
307
- return rb_funcall(wkb_generator, globals->id_generate, 1, obj);
362
+ return rb_funcall(marshal_wkb_generator, rb_intern("generate"), 1, obj);
308
363
  }
309
364
  #endif
310
365
  wkb_writer = self_data->marshal_wkb_writer;
@@ -329,6 +384,9 @@ static VALUE method_factory_write_for_marshal(VALUE self, VALUE obj)
329
384
  return result;
330
385
  }
331
386
 
387
+ #ifndef RGEO_GEOS_SUPPORTS_SETOUTPUTDIMENSION
388
+ static VALUE psych_wkt_generator;
389
+ #endif
332
390
 
333
391
  static VALUE method_factory_write_for_psych(VALUE self, VALUE obj)
334
392
  {
@@ -339,25 +397,18 @@ static VALUE method_factory_write_for_psych(VALUE self, VALUE obj)
339
397
  VALUE result;
340
398
  char* str;
341
399
  char has_3d;
342
- #ifndef RGEO_GEOS_SUPPORTS_SETOUTPUTDIMENSION
343
- RGeo_Globals* globals;
344
- VALUE wkt_generator;
345
- #endif
346
400
 
347
401
  self_data = RGEO_FACTORY_DATA_PTR(self);
348
402
  self_context = self_data->geos_context;
349
403
  has_3d = self_data->flags & RGEO_FACTORYFLAGS_SUPPORTS_Z_OR_M;
350
404
  #ifndef RGEO_GEOS_SUPPORTS_SETOUTPUTDIMENSION
351
405
  if (has_3d) {
352
- globals = self_data->globals;
353
- wkt_generator = globals->psych_wkt_generator;
354
- if (NIL_P(wkt_generator)) {
355
- wkt_generator = rb_funcall(
356
- rb_const_get_at(globals->geos_module, rb_intern("Utils")),
406
+ if (NIL_P(psych_wkt_generator)) {
407
+ psych_wkt_generator = rb_funcall(
408
+ rb_const_get_at(rgeo_geos_module, rb_intern("Utils")),
357
409
  rb_intern("psych_wkt_generator"), 0);
358
- globals->psych_wkt_generator = wkt_generator;
359
410
  }
360
- return rb_funcall(wkt_generator, globals->id_generate, 1, obj);
411
+ return rb_funcall(psych_wkt_generator, rb_intern("generate"), 1, obj);
361
412
  }
362
413
  #endif
363
414
  wkt_writer = self_data->psych_wkt_writer;
@@ -404,15 +455,12 @@ static VALUE cmethod_factory_create(VALUE klass, VALUE flags, VALUE srid, VALUE
404
455
  VALUE result;
405
456
  RGeo_FactoryData* data;
406
457
  GEOSContextHandle_t context;
407
- VALUE wrapped_globals;
408
458
 
409
459
  result = Qnil;
410
460
  data = ALLOC(RGeo_FactoryData);
411
461
  if (data) {
412
462
  context = initGEOS_r(message_handler, message_handler);
413
463
  if (context) {
414
- wrapped_globals = rb_const_get_at(klass, rb_intern("INTERNAL_CGLOBALS"));
415
- data->globals = (RGeo_Globals*)DATA_PTR(wrapped_globals);
416
464
  data->geos_context = context;
417
465
  data->flags = NUM2INT(flags);
418
466
  data->srid = NUM2INT(srid);
@@ -431,7 +479,7 @@ static VALUE cmethod_factory_create(VALUE klass, VALUE flags, VALUE srid, VALUE
431
479
  data->wkrep_wkb_parser = Qnil;
432
480
  data->proj4_obj = proj4_obj;
433
481
  data->coord_sys_obj = coord_sys_obj;
434
- result = Data_Wrap_Struct(klass, mark_factory_func, destroy_factory_func, data);
482
+ result = TypedData_Wrap_Struct(klass, &rgeo_factory_type, data);
435
483
  }
436
484
  else {
437
485
  free(data);
@@ -496,7 +544,7 @@ static VALUE method_factory_initialize_copy(VALUE self, VALUE orig)
496
544
  self_data->coord_sys_obj = Qnil;
497
545
 
498
546
  // Copy new data from original object
499
- if (TYPE(orig) == T_DATA && RDATA(orig)->dfree == (RUBY_DATA_FUNC)destroy_factory_func) {
547
+ if (RGEO_FACTORY_TYPEDDATA_P(orig)) {
500
548
  orig_data = RGEO_FACTORY_DATA_PTR(orig);
501
549
  self_data->flags = orig_data->flags;
502
550
  self_data->srid = orig_data->srid;
@@ -569,48 +617,20 @@ static VALUE alloc_geometry(VALUE klass)
569
617
  /**** INITIALIZATION FUNCTION ****/
570
618
 
571
619
 
572
- RGeo_Globals* rgeo_init_geos_factory()
620
+ void rgeo_init_geos_factory()
573
621
  {
574
- RGeo_Globals* globals;
575
- VALUE rgeo_module;
576
622
  VALUE geos_factory_class;
577
- VALUE wrapped_globals;
578
- VALUE feature_module;
579
-
580
- rgeo_module = rb_define_module("RGeo");
581
-
582
- globals = ALLOC(RGeo_Globals);
583
-
584
- // Cache some modules so we don't have to look them up by name every time
585
- feature_module = rb_define_module_under(rgeo_module, "Feature");
586
- globals->feature_module = feature_module;
587
- globals->geos_module = rb_define_module_under(rgeo_module, "Geos");
588
- globals->feature_geometry = rb_const_get_at(feature_module, rb_intern("Geometry"));
589
- globals->feature_point = rb_const_get_at(feature_module, rb_intern("Point"));
590
- globals->feature_line_string = rb_const_get_at(feature_module, rb_intern("LineString"));
591
- globals->feature_linear_ring = rb_const_get_at(feature_module, rb_intern("LinearRing"));
592
- globals->feature_line = rb_const_get_at(feature_module, rb_intern("Line"));
593
- globals->feature_polygon = rb_const_get_at(feature_module, rb_intern("Polygon"));
594
- globals->feature_geometry_collection = rb_const_get_at(feature_module, rb_intern("GeometryCollection"));
595
- globals->feature_multi_point = rb_const_get_at(feature_module, rb_intern("MultiPoint"));
596
- globals->feature_multi_line_string = rb_const_get_at(feature_module, rb_intern("MultiLineString"));
597
- globals->feature_multi_polygon = rb_const_get_at(feature_module, rb_intern("MultiPolygon"));
598
-
599
- // Cache some commonly used names
600
- globals->id_cast = rb_intern("cast");
601
- globals->id_eql = rb_intern("eql?");
602
- globals->id_generate = rb_intern("generate");
603
- globals->id_enum_for = rb_intern("enum_for");
604
- globals->id_hash = rb_intern("hash");
605
- globals->sym_force_new = ID2SYM(rb_intern("force_new"));
606
- globals->sym_keep_subtype = ID2SYM(rb_intern("keep_subtype"));
623
+
607
624
  #ifndef RGEO_GEOS_SUPPORTS_SETOUTPUTDIMENSION
608
- globals->psych_wkt_generator = Qnil;
609
- globals->marshal_wkb_generator = Qnil;
625
+ /* We favor rb_gc_register_address over rb_gc_register_mark_object because the value changes at runtime */
626
+ psych_wkt_generator = Qnil;
627
+ rb_gc_register_address(&psych_wkt_generator);
628
+ marshal_wkb_generator = Qnil;
629
+ rb_gc_register_address(&marshal_wkb_generator);
610
630
  #endif
611
631
 
612
632
  // Add C methods to the factory.
613
- geos_factory_class = rb_define_class_under(globals->geos_module, "CAPIFactory", rb_cObject);
633
+ geos_factory_class = rb_define_class_under(rgeo_geos_module, "CAPIFactory", rb_cObject);
614
634
  rb_define_alloc_func(geos_factory_class, alloc_factory);
615
635
  rb_define_method(geos_factory_class, "initialize_copy", method_factory_initialize_copy, 1);
616
636
  rb_define_method(geos_factory_class, "_parse_wkt_impl", method_factory_parse_wkt, 1);
@@ -633,34 +653,17 @@ RGeo_Globals* rgeo_init_geos_factory()
633
653
  rb_define_module_function(geos_factory_class, "_geos_version", cmethod_factory_geos_version, 0);
634
654
  rb_define_module_function(geos_factory_class, "_supports_unary_union?", cmethod_factory_supports_unary_union, 0);
635
655
 
636
- // Pre-define implementation classes and set up allocation methods
637
- globals->geos_geometry = rb_define_class_under(globals->geos_module, "CAPIGeometryImpl", rb_cObject);
638
- rb_define_alloc_func(globals->geos_geometry, alloc_geometry);
639
- globals->geos_point = rb_define_class_under(globals->geos_module, "CAPIPointImpl", rb_cObject);
640
- rb_define_alloc_func(globals->geos_point, alloc_geometry);
641
- globals->geos_line_string = rb_define_class_under(globals->geos_module, "CAPILineStringImpl", rb_cObject);
642
- rb_define_alloc_func(globals->geos_line_string, alloc_geometry);
643
- globals->geos_linear_ring = rb_define_class_under(globals->geos_module, "CAPILinearRingImpl", rb_cObject);
644
- rb_define_alloc_func(globals->geos_linear_ring, alloc_geometry);
645
- globals->geos_line = rb_define_class_under(globals->geos_module, "CAPILineImpl", rb_cObject);
646
- rb_define_alloc_func(globals->geos_line, alloc_geometry);
647
- globals->geos_polygon = rb_define_class_under(globals->geos_module, "CAPIPolygonImpl", rb_cObject);
648
- rb_define_alloc_func(globals->geos_polygon, alloc_geometry);
649
- globals->geos_geometry_collection = rb_define_class_under(globals->geos_module, "CAPIGeometryCollectionImpl", rb_cObject);
650
- rb_define_alloc_func(globals->geos_geometry_collection, alloc_geometry);
651
- globals->geos_multi_point = rb_define_class_under(globals->geos_module, "CAPIMultiPointImpl", rb_cObject);
652
- rb_define_alloc_func(globals->geos_multi_point, alloc_geometry);
653
- globals->geos_multi_line_string = rb_define_class_under(globals->geos_module, "CAPIMultiLineStringImpl", rb_cObject);
654
- rb_define_alloc_func(globals->geos_multi_line_string, alloc_geometry);
655
- globals->geos_multi_polygon = rb_define_class_under(globals->geos_module, "CAPIMultiPolygonImpl", rb_cObject);
656
- rb_define_alloc_func(globals->geos_multi_polygon, alloc_geometry);
657
-
658
- // Wrap the globals in a Ruby object and store it off so we have access
659
- // to it later. Each factory instance will reference it internally.
660
- wrapped_globals = Data_Wrap_Struct(rb_cObject, mark_globals_func, destroy_globals_func, globals);
661
- rb_define_const(geos_factory_class, "INTERNAL_CGLOBALS", wrapped_globals);
662
-
663
- return globals;
656
+ // Define allocation methods for global class types
657
+ rb_define_alloc_func(rgeo_geos_geometry_class, alloc_geometry);
658
+ rb_define_alloc_func(rgeo_geos_point_class, alloc_geometry);
659
+ rb_define_alloc_func(rgeo_geos_line_string_class, alloc_geometry);
660
+ rb_define_alloc_func(rgeo_geos_linear_ring_class, alloc_geometry);
661
+ rb_define_alloc_func(rgeo_geos_line_class, alloc_geometry);
662
+ rb_define_alloc_func(rgeo_geos_polygon_class, alloc_geometry);
663
+ rb_define_alloc_func(rgeo_geos_geometry_collection_class, alloc_geometry);
664
+ rb_define_alloc_func(rgeo_geos_multi_point_class, alloc_geometry);
665
+ rb_define_alloc_func(rgeo_geos_multi_line_string_class, alloc_geometry);
666
+ rb_define_alloc_func(rgeo_geos_multi_polygon_class, alloc_geometry);
664
667
  }
665
668
 
666
669
 
@@ -673,7 +676,6 @@ VALUE rgeo_wrap_geos_geometry(VALUE factory, GEOSGeometry* geom, VALUE klass)
673
676
  RGeo_FactoryData* factory_data;
674
677
  GEOSContextHandle_t factory_context;
675
678
  VALUE klasses;
676
- RGeo_Globals* globals;
677
679
  VALUE inferred_klass;
678
680
  char is_collection;
679
681
  RGeo_GeometryData* data;
@@ -682,7 +684,6 @@ VALUE rgeo_wrap_geos_geometry(VALUE factory, GEOSGeometry* geom, VALUE klass)
682
684
  if (geom || !NIL_P(klass)) {
683
685
  factory_data = NIL_P(factory) ? NULL : RGEO_FACTORY_DATA_PTR(factory);
684
686
  factory_context = factory_data ? factory_data->geos_context : NULL;
685
- globals = factory_data ? factory_data->globals : NULL;
686
687
 
687
688
  // We don't allow "empty" points, so replace such objects with
688
689
  // an empty collection.
@@ -690,7 +691,7 @@ VALUE rgeo_wrap_geos_geometry(VALUE factory, GEOSGeometry* geom, VALUE klass)
690
691
  if (GEOSGeomTypeId_r(factory_context, geom) == GEOS_POINT && GEOSGetNumCoordinates_r(factory_context, geom) == 0) {
691
692
  GEOSGeom_destroy_r(factory_context, geom);
692
693
  geom = GEOSGeom_createCollection_r(factory_context, GEOS_GEOMETRYCOLLECTION, NULL, 0);
693
- klass = globals->geos_geometry_collection;
694
+ klass = rgeo_geos_geometry_collection_class;
694
695
  }
695
696
  }
696
697
 
@@ -700,35 +701,35 @@ VALUE rgeo_wrap_geos_geometry(VALUE factory, GEOSGeometry* geom, VALUE klass)
700
701
  is_collection = 0;
701
702
  switch (GEOSGeomTypeId_r(factory_context, geom)) {
702
703
  case GEOS_POINT:
703
- inferred_klass = globals->geos_point;
704
+ inferred_klass = rgeo_geos_point_class;
704
705
  break;
705
706
  case GEOS_LINESTRING:
706
- inferred_klass = globals->geos_line_string;
707
+ inferred_klass = rgeo_geos_line_string_class;
707
708
  break;
708
709
  case GEOS_LINEARRING:
709
- inferred_klass = globals->geos_linear_ring;
710
+ inferred_klass = rgeo_geos_linear_ring_class;
710
711
  break;
711
712
  case GEOS_POLYGON:
712
- inferred_klass = globals->geos_polygon;
713
+ inferred_klass = rgeo_geos_polygon_class;
713
714
  break;
714
715
  case GEOS_MULTIPOINT:
715
- inferred_klass = globals->geos_multi_point;
716
+ inferred_klass = rgeo_geos_multi_point_class;
716
717
  is_collection = 1;
717
718
  break;
718
719
  case GEOS_MULTILINESTRING:
719
- inferred_klass = globals->geos_multi_line_string;
720
+ inferred_klass = rgeo_geos_multi_line_string_class;
720
721
  is_collection = 1;
721
722
  break;
722
723
  case GEOS_MULTIPOLYGON:
723
- inferred_klass = globals->geos_multi_polygon;
724
+ inferred_klass = rgeo_geos_multi_polygon_class;
724
725
  is_collection = 1;
725
726
  break;
726
727
  case GEOS_GEOMETRYCOLLECTION:
727
- inferred_klass = globals->geos_geometry_collection;
728
+ inferred_klass = rgeo_geos_geometry_collection_class;
728
729
  is_collection = 1;
729
730
  break;
730
731
  default:
731
- inferred_klass = globals->geos_geometry;
732
+ inferred_klass = rgeo_geos_geometry_class;
732
733
  break;
733
734
  }
734
735
  if (TYPE(klass) == T_ARRAY && is_collection) {
@@ -747,13 +748,12 @@ VALUE rgeo_wrap_geos_geometry(VALUE factory, GEOSGeometry* geom, VALUE klass)
747
748
  (GEOSPreparedGeometry*)1 : NULL;
748
749
  data->factory = factory;
749
750
  data->klasses = klasses;
750
- result = Data_Wrap_Struct(klass, mark_geometry_func, destroy_geometry_func, data);
751
+ result = TypedData_Wrap_Struct(klass, &rgeo_geometry_type, data);
751
752
  }
752
753
  }
753
754
  return result;
754
755
  }
755
756
 
756
-
757
757
  VALUE rgeo_wrap_geos_geometry_clone(VALUE factory, const GEOSGeometry* geom, VALUE klass)
758
758
  {
759
759
  VALUE result;
@@ -773,19 +773,17 @@ VALUE rgeo_wrap_geos_geometry_clone(VALUE factory, const GEOSGeometry* geom, VAL
773
773
  const GEOSGeometry* rgeo_convert_to_geos_geometry(VALUE factory, VALUE obj, VALUE type)
774
774
  {
775
775
  VALUE object;
776
- RGeo_Globals* globals;
777
776
 
778
- if (NIL_P(type) && TYPE(obj) == T_DATA && RDATA(obj)->dfree == (RUBY_DATA_FUNC)destroy_geometry_func && RGEO_GEOMETRY_DATA_PTR(obj)->factory == factory) {
777
+ if (NIL_P(type) && RGEO_GEOMETRY_TYPEDDATA_P(obj) && RGEO_GEOMETRY_DATA_PTR(obj)->factory == factory) {
779
778
  object = obj;
780
779
  }
781
780
  else {
782
- globals = RGEO_FACTORY_DATA_PTR(factory)->globals;
783
- object = rb_funcall(globals->feature_module, globals->id_cast, 3, obj, factory, type);
781
+ object = rb_funcall(rgeo_feature_module, rb_intern("cast"), 3, obj, factory, type);
784
782
  }
785
783
  if (NIL_P(object))
786
784
  return NULL;
787
785
 
788
- Check_Type(object, T_DATA);
786
+ Check_TypedStruct(object, &rgeo_geometry_type);
789
787
  return RGEO_GEOMETRY_DATA_PTR(object)->geom;
790
788
  }
791
789
 
@@ -796,13 +794,11 @@ GEOSGeometry* rgeo_convert_to_detached_geos_geometry(VALUE obj, VALUE factory, V
796
794
  GEOSGeometry* geom;
797
795
  RGeo_GeometryData* object_data;
798
796
  const GEOSPreparedGeometry* prep;
799
- RGeo_Globals* globals;
800
797
 
801
798
  if (klasses) {
802
799
  *klasses = Qnil;
803
800
  }
804
- globals = RGEO_FACTORY_DATA_PTR(factory)->globals;
805
- object = rb_funcall(globals->feature_module, globals->id_cast, 5, obj, factory, type, globals->sym_force_new, globals->sym_keep_subtype);
801
+ object = rb_funcall(rgeo_feature_module, rb_intern("cast"), 5, obj, factory, type, ID2SYM(rb_intern("force_new")), ID2SYM(rb_intern("keep_subtype")));
806
802
  geom = NULL;
807
803
  if (!NIL_P(object)) {
808
804
  object_data = RGEO_GEOMETRY_DATA_PTR(object);
@@ -829,7 +825,7 @@ GEOSGeometry* rgeo_convert_to_detached_geos_geometry(VALUE obj, VALUE factory, V
829
825
 
830
826
  char rgeo_is_geos_object(VALUE obj)
831
827
  {
832
- return (TYPE(obj) == T_DATA && RDATA(obj)->dfree == (RUBY_DATA_FUNC)destroy_geometry_func) ? 1 : 0;
828
+ return RGEO_GEOMETRY_TYPEDDATA_P(obj) ? 1 : 0;
833
829
  }
834
830
 
835
831
  void rgeo_check_geos_object(VALUE obj)
@@ -842,7 +838,7 @@ void rgeo_check_geos_object(VALUE obj)
842
838
 
843
839
  const GEOSGeometry* rgeo_get_geos_geometry_safe(VALUE obj)
844
840
  {
845
- return (TYPE(obj) == T_DATA && RDATA(obj)->dfree == (RUBY_DATA_FUNC)destroy_geometry_func) ? (const GEOSGeometry*)(RGEO_GEOMETRY_DATA_PTR(obj)->geom) : NULL;
841
+ return RGEO_GEOMETRY_TYPEDDATA_P(obj) ? (const GEOSGeometry*)(RGEO_GEOMETRY_DATA_PTR(obj)->geom) : NULL;
846
842
  }
847
843
 
848
844
 
@@ -930,7 +926,8 @@ VALUE rgeo_geos_klasses_and_factories_eql(VALUE obj1, VALUE obj2)
930
926
  }
931
927
  else {
932
928
  factory = RGEO_GEOMETRY_DATA_PTR(obj1)->factory;
933
- result = rb_funcall(factory, RGEO_FACTORY_DATA_PTR(factory)->globals->id_eql, 1, RGEO_GEOMETRY_DATA_PTR(obj2)->factory);
929
+ /* No need to cache the internal here (https://ips.fastruby.io/4x) */
930
+ result = rb_funcall(factory, rb_intern("eql?"), 1, RGEO_GEOMETRY_DATA_PTR(obj2)->factory);
934
931
  }
935
932
  return result;
936
933
  }
@@ -983,7 +980,7 @@ st_index_t rgeo_geos_objbase_hash(VALUE factory, VALUE type_module, st_index_t h
983
980
  ID hash_method;
984
981
  RGeo_Objbase_Hash_Struct hash_struct;
985
982
 
986
- hash_method = RGEO_FACTORY_DATA_PTR(factory)->globals->id_hash;
983
+ hash_method = rb_intern("hash");
987
984
  hash_struct.seed_hash = hash;
988
985
  hash_struct.h1 = FIX2LONG(rb_funcall(factory, hash_method, 0));
989
986
  hash_struct.h2 = FIX2LONG(rb_funcall(type_module, hash_method, 0));