tg_geometry 0.3.3 → 0.3.4

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 27136bafb4a0114a2921af0413c047391bfffb38a6ff41f6c4f011f7cf4ab2ad
4
- data.tar.gz: 7b2148e42f78fa74b3d5ac41e492e78673dd2617aa887c0023affcfa8fe555bf
3
+ metadata.gz: 6541db9668ecda1e7fc6a645cffac29fb80528a17b8d05e7b8c0aa2a0f7ef59c
4
+ data.tar.gz: 26d9350239007d0d853e307260d739390cc24f906c13b873f7350619c66242b7
5
5
  SHA512:
6
- metadata.gz: e91a5dd12b3240540e9f6171c9c8a3c0f959d9e24779e392ae6c02c2e478712d2585bff5e37b3524bdf7d3b8581ebb30e14029b4aa038eb549229f92f0eee388
7
- data.tar.gz: 806918f8eaaa7025b0693ef07e6d244e37cdb4998ff4cc5845a752c4b200f2cb341391a43f37afbdb696525e18d3415f55833c8d09712c31161eb2e879e179f5
6
+ metadata.gz: 88954a796fc76ff9c52c060cf6a71f6ec38de7132623bd041aac1cc2ca80192ae6840195ad2f1736eff92087330113bcf6a76705204951c77ff177383c74bf3d
7
+ data.tar.gz: a2c4fb5d1fe739069231e9b709538bbb93cfe5d5cc56fabd04e34c66a4816cdfd65d75b694cc49ddc9faae34f275d1d9d914cd6eeedc0884ff4c3ce32b552a2b
data/CHANGELOG.md CHANGED
@@ -1,5 +1,12 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.3.4 - 28.10.2026
4
+
5
+ ### Changed
6
+
7
+ - Split the complex geometry traversal, index construction, FeatureSource preparation and file-read paths into focused helpers. The public API and runtime behavior are unchanged.
8
+ - Split native extension initialization into registration helpers without changing registration order.
9
+
3
10
  ## 0.3.3 - 28.10.2026
4
11
 
5
12
  ### Changed
@@ -3222,9 +3222,46 @@ static bool tg_distance_accum_poly(tg_distance_accum_t *accum, const struct tg_p
3222
3222
  return true;
3223
3223
  }
3224
3224
 
3225
- static bool tg_distance_accum_geom(tg_distance_accum_t *accum, const struct tg_geom *geom) {
3226
- int count;
3225
+ static bool tg_distance_accum_geom(tg_distance_accum_t *accum, const struct tg_geom *geom);
3226
+
3227
+ static void tg_distance_accum_multipoint(tg_distance_accum_t *accum,
3228
+ const struct tg_geom *geom) {
3229
+ int count = tg_geom_num_points(geom);
3230
+ for (int i = 0; i < count; i++)
3231
+ tg_distance_accum_point(accum, tg_geom_point_at(geom, i));
3232
+ }
3233
+
3234
+ static bool tg_distance_accum_multiline(tg_distance_accum_t *accum,
3235
+ const struct tg_geom *geom) {
3236
+ int count = tg_geom_num_lines(geom);
3237
+ for (int i = 0; i < count; i++) {
3238
+ if (!tg_distance_accum_line(accum, tg_geom_line_at(geom, i)))
3239
+ return false;
3240
+ }
3241
+ return true;
3242
+ }
3227
3243
 
3244
+ static bool tg_distance_accum_multipoly(tg_distance_accum_t *accum,
3245
+ const struct tg_geom *geom) {
3246
+ int count = tg_geom_num_polys(geom);
3247
+ for (int i = 0; i < count; i++) {
3248
+ if (!tg_distance_accum_poly(accum, tg_geom_poly_at(geom, i)))
3249
+ return false;
3250
+ }
3251
+ return true;
3252
+ }
3253
+
3254
+ static bool tg_distance_accum_collection(tg_distance_accum_t *accum,
3255
+ const struct tg_geom *geom) {
3256
+ int count = tg_geom_num_geometries(geom);
3257
+ for (int i = 0; i < count; i++) {
3258
+ if (!tg_distance_accum_geom(accum, tg_geom_geometry_at(geom, i)))
3259
+ return false;
3260
+ }
3261
+ return true;
3262
+ }
3263
+
3264
+ static bool tg_distance_accum_geom(tg_distance_accum_t *accum, const struct tg_geom *geom) {
3228
3265
  if (!geom || tg_geom_is_empty(geom)) {
3229
3266
  return true;
3230
3267
  }
@@ -3234,39 +3271,18 @@ static bool tg_distance_accum_geom(tg_distance_accum_t *accum, const struct tg_g
3234
3271
  tg_distance_accum_point(accum, tg_geom_point(geom));
3235
3272
  return true;
3236
3273
  case TG_MULTIPOINT:
3237
- count = tg_geom_num_points(geom);
3238
- for (int i = 0; i < count; i++) {
3239
- tg_distance_accum_point(accum, tg_geom_point_at(geom, i));
3240
- }
3274
+ tg_distance_accum_multipoint(accum, geom);
3241
3275
  return true;
3242
3276
  case TG_LINESTRING:
3243
3277
  return tg_distance_accum_line(accum, tg_geom_line(geom));
3244
3278
  case TG_MULTILINESTRING:
3245
- count = tg_geom_num_lines(geom);
3246
- for (int i = 0; i < count; i++) {
3247
- if (!tg_distance_accum_line(accum, tg_geom_line_at(geom, i))) {
3248
- return false;
3249
- }
3250
- }
3251
- return true;
3279
+ return tg_distance_accum_multiline(accum, geom);
3252
3280
  case TG_POLYGON:
3253
3281
  return tg_distance_accum_poly(accum, tg_geom_poly(geom));
3254
3282
  case TG_MULTIPOLYGON:
3255
- count = tg_geom_num_polys(geom);
3256
- for (int i = 0; i < count; i++) {
3257
- if (!tg_distance_accum_poly(accum, tg_geom_poly_at(geom, i))) {
3258
- return false;
3259
- }
3260
- }
3261
- return true;
3283
+ return tg_distance_accum_multipoly(accum, geom);
3262
3284
  case TG_GEOMETRYCOLLECTION:
3263
- count = tg_geom_num_geometries(geom);
3264
- for (int i = 0; i < count; i++) {
3265
- if (!tg_distance_accum_geom(accum, tg_geom_geometry_at(geom, i))) {
3266
- return false;
3267
- }
3268
- }
3269
- return true;
3285
+ return tg_distance_accum_collection(accum, geom);
3270
3286
  }
3271
3287
 
3272
3288
  return true;
@@ -4412,6 +4428,14 @@ typedef struct {
4412
4428
  enum tg_index geometry_index;
4413
4429
  } tg_index_build_args_t;
4414
4430
 
4431
+ typedef struct {
4432
+ VALUE entries;
4433
+ enum tg_geometry_index_via via;
4434
+ enum tg_geometry_index_strategy strategy;
4435
+ enum tg_geometry_index_predicate predicate;
4436
+ enum tg_index geometry_index;
4437
+ } tg_index_build_options_t;
4438
+
4415
4439
  static void index_expand_bbox(tg_index_t *idx, struct tg_rect bbox) {
4416
4440
  if (!idx->has_bbox) {
4417
4441
  idx->bbox = bbox;
@@ -4586,30 +4610,20 @@ static VALUE index_build_body(VALUE arg) {
4586
4610
  return Qnil;
4587
4611
  }
4588
4612
 
4589
- static VALUE rb_tg_geometry_index_build(int argc, VALUE *argv, VALUE klass) {
4590
- VALUE entries_value;
4613
+ static void parse_index_build_options(int argc, VALUE *argv, tg_index_build_options_t *options) {
4591
4614
  VALUE kwargs;
4592
4615
  VALUE via_value;
4593
4616
  VALUE strategy_value;
4594
4617
  VALUE predicate_value;
4595
4618
  VALUE geometry_index_value;
4596
- enum tg_geometry_index_via via;
4597
- enum tg_geometry_index_strategy strategy;
4598
- enum tg_geometry_index_predicate predicate;
4599
- enum tg_index geometry_index;
4600
- long len;
4601
- tg_index_t *idx;
4602
- VALUE wrapper;
4603
- tg_index_build_args_t args;
4604
- int state = 0;
4605
4619
 
4606
- rb_scan_args(argc, argv, "1:", &entries_value, &kwargs);
4620
+ rb_scan_args(argc, argv, "1:", &options->entries, &kwargs);
4607
4621
  {
4608
4622
  ID allowed[] = {id_via, id_strategy, id_predicate, id_geometry_index};
4609
4623
  validate_keywords(kwargs, allowed, sizeof(allowed) / sizeof(allowed[0]));
4610
4624
  }
4611
4625
 
4612
- if (!RB_TYPE_P(entries_value, T_ARRAY)) {
4626
+ if (!RB_TYPE_P(options->entries, T_ARRAY)) {
4613
4627
  rb_raise(rb_eTypeError, "entries must be Array");
4614
4628
  }
4615
4629
 
@@ -4618,18 +4632,23 @@ static VALUE rb_tg_geometry_index_build(int argc, VALUE *argv, VALUE klass) {
4618
4632
  predicate_value = kwargs_value(kwargs, id_predicate, ID2SYM(id_covers));
4619
4633
  geometry_index_value = kwargs_value(kwargs, id_geometry_index, ID2SYM(id_ystripes));
4620
4634
 
4621
- via = parse_index_via_symbol(via_value);
4622
- strategy = parse_index_strategy_symbol(strategy_value);
4623
- predicate = parse_index_predicate_symbol(predicate_value);
4624
- geometry_index = parse_index_symbol(geometry_index_value);
4635
+ options->via = parse_index_via_symbol(via_value);
4636
+ options->strategy = parse_index_strategy_symbol(strategy_value);
4637
+ options->predicate = parse_index_predicate_symbol(predicate_value);
4638
+ options->geometry_index = parse_index_symbol(geometry_index_value);
4639
+ }
4640
+
4641
+ static VALUE allocate_index_wrapper(VALUE klass, const tg_index_build_options_t *options,
4642
+ tg_index_t **idx_out) {
4643
+ long len = RARRAY_LEN(options->entries);
4644
+ tg_index_t *idx;
4645
+ VALUE wrapper = TypedData_Make_Struct(klass, tg_index_t, &tg_index_type, idx);
4625
4646
 
4626
- len = RARRAY_LEN(entries_value);
4627
- wrapper = TypedData_Make_Struct(klass, tg_index_t, &tg_index_type, idx);
4628
4647
  idx->len = len;
4629
4648
  idx->capacity = len;
4630
4649
  idx->initialized = 0;
4631
- idx->strategy = strategy;
4632
- idx->predicate = predicate;
4650
+ idx->strategy = options->strategy;
4651
+ idx->predicate = options->predicate;
4633
4652
  idx->rtree = NULL;
4634
4653
  idx->frozen = false;
4635
4654
  idx->has_bbox = false;
@@ -4654,17 +4673,29 @@ static VALUE rb_tg_geometry_index_build(int argc, VALUE *argv, VALUE klass) {
4654
4673
  idx->entries_bytes = (size_t)len * sizeof(tg_index_entry_t);
4655
4674
  rb_gc_adjust_memory_usage((ssize_t)idx->entries_bytes);
4656
4675
  }
4676
+ *idx_out = idx;
4677
+ return wrapper;
4678
+ }
4679
+
4680
+ static VALUE rb_tg_geometry_index_build(int argc, VALUE *argv, VALUE klass) {
4681
+ tg_index_build_options_t options;
4682
+ tg_index_build_args_t args;
4683
+ tg_index_t *idx;
4684
+ VALUE wrapper;
4685
+ int state = 0;
4657
4686
 
4687
+ parse_index_build_options(argc, argv, &options);
4688
+ wrapper = allocate_index_wrapper(klass, &options, &idx);
4658
4689
  args.idx = idx;
4659
- args.entries = entries_value;
4660
- args.via = via;
4661
- args.geometry_index = geometry_index;
4690
+ args.entries = options.entries;
4691
+ args.via = options.via;
4692
+ args.geometry_index = options.geometry_index;
4662
4693
 
4663
4694
  rb_protect(index_build_body, (VALUE)&args, &state);
4664
4695
 
4665
4696
  if (state) {
4666
4697
  index_dispose(idx);
4667
- RB_GC_GUARD(entries_value);
4698
+ RB_GC_GUARD(options.entries);
4668
4699
  RB_GC_GUARD(wrapper);
4669
4700
  rb_jump_tag(state);
4670
4701
  }
@@ -4677,7 +4708,7 @@ static VALUE rb_tg_geometry_index_build(int argc, VALUE *argv, VALUE klass) {
4677
4708
  idx->frozen = true;
4678
4709
  rb_obj_freeze(wrapper);
4679
4710
 
4680
- RB_GC_GUARD(entries_value);
4711
+ RB_GC_GUARD(options.entries);
4681
4712
  RB_GC_GUARD(wrapper);
4682
4713
  return wrapper;
4683
4714
  }
@@ -5474,26 +5505,15 @@ static bool fs_extract_id(fs_source_t *source, fs_options_t *opts, struct json f
5474
5505
  return true;
5475
5506
  }
5476
5507
 
5477
- static bool fs_feature_prepare(fs_source_t *source, fs_options_t *opts, fs_mode_t mode,
5478
- struct json feature, long feature_index, bool materialize_id,
5479
- fs_feature_result_t *result) {
5508
+ static bool fs_feature_geometry_info(struct json feature, fs_feature_result_t *result,
5509
+ struct json *geometry_out, unsigned int *geom_bit_out) {
5480
5510
  struct json geometry;
5481
5511
  struct json geometry_type;
5482
- struct json properties;
5483
- unsigned int geom_bit;
5484
- VALUE id = Qnil;
5485
- VALUE error_message = Qnil;
5486
-
5487
- memset(result, 0, sizeof(*result));
5488
- result->feature = feature;
5489
- result->id = Qnil;
5490
- result->reason_value = Qnil;
5491
5512
 
5492
5513
  if (!json_exists(feature) || json_type(feature) != JSON_OBJECT) {
5493
5514
  result->reason = "feature is not an object";
5494
5515
  return false;
5495
5516
  }
5496
-
5497
5517
  geometry = json_object_get(feature, "geometry");
5498
5518
  if (!json_exists(geometry) || json_type(geometry) == JSON_NULL) {
5499
5519
  result->reason = "missing geometry";
@@ -5510,12 +5530,50 @@ static bool fs_feature_prepare(fs_source_t *source, fs_options_t *opts, fs_mode_
5510
5530
  return false;
5511
5531
  }
5512
5532
 
5513
- geom_bit = fs_geometry_type_bit(geometry_type);
5514
- if (geom_bit == 0) {
5533
+ *geom_bit_out = fs_geometry_type_bit(geometry_type);
5534
+ if (*geom_bit_out == 0) {
5515
5535
  result->reason = "unsupported geometry.type";
5516
5536
  return false;
5517
5537
  }
5518
5538
 
5539
+ *geometry_out = geometry;
5540
+ return true;
5541
+ }
5542
+
5543
+ static bool fs_feature_prepare_properties(fs_mode_t mode, struct json feature,
5544
+ fs_feature_result_t *result) {
5545
+ struct json properties;
5546
+
5547
+ if (mode != FS_MODE_READ_FEATURES)
5548
+ return true;
5549
+
5550
+ properties = json_object_get(feature, "properties");
5551
+ if (json_exists(properties) && json_type(properties) != JSON_NULL &&
5552
+ json_type(properties) != JSON_OBJECT) {
5553
+ result->reason = "properties must be an object or null";
5554
+ return false;
5555
+ }
5556
+
5557
+ result->properties = properties;
5558
+ return true;
5559
+ }
5560
+
5561
+ static bool fs_feature_prepare(fs_source_t *source, fs_options_t *opts, fs_mode_t mode,
5562
+ struct json feature, long feature_index, bool materialize_id,
5563
+ fs_feature_result_t *result) {
5564
+ struct json geometry;
5565
+ unsigned int geom_bit;
5566
+ VALUE id = Qnil;
5567
+ VALUE error_message = Qnil;
5568
+
5569
+ memset(result, 0, sizeof(*result));
5570
+ result->feature = feature;
5571
+ result->id = Qnil;
5572
+ result->reason_value = Qnil;
5573
+
5574
+ if (!fs_feature_geometry_info(feature, result, &geometry, &geom_bit))
5575
+ return false;
5576
+
5519
5577
  if (!opts->only_all && (opts->only_mask & geom_bit) == 0) {
5520
5578
  result->filtered = true;
5521
5579
  return true;
@@ -5527,16 +5585,8 @@ static bool fs_feature_prepare(fs_source_t *source, fs_options_t *opts, fs_mode_
5527
5585
  return false;
5528
5586
  }
5529
5587
 
5530
- if (mode == FS_MODE_READ_FEATURES) {
5531
- properties = json_object_get(feature, "properties");
5532
- if (!json_exists(properties) || json_type(properties) == JSON_NULL) {
5533
- /* returned as "null" */
5534
- } else if (json_type(properties) != JSON_OBJECT) {
5535
- result->reason = "properties must be an object or null";
5536
- return false;
5537
- }
5538
- result->properties = properties;
5539
- }
5588
+ if (!fs_feature_prepare_properties(mode, feature, result))
5589
+ return false;
5540
5590
 
5541
5591
  result->accepted = true;
5542
5592
  result->id = id;
@@ -5964,21 +6014,16 @@ typedef struct {
5964
6014
  const char *reason;
5965
6015
  } fs_safe_feature_t;
5966
6016
 
5967
- static bool fs_safe_prepare_feature(fs_safe_job_t *job, struct json feature, long feature_index,
5968
- fs_mode_t mode, fs_safe_feature_t *out) {
6017
+ static bool fs_safe_feature_geometry_info(struct json feature, fs_safe_feature_t *out,
6018
+ struct json *geometry_out,
6019
+ unsigned int *geom_bit_out) {
5969
6020
  struct json geometry;
5970
6021
  struct json geometry_type;
5971
- struct json properties;
5972
- unsigned int geom_bit;
5973
-
5974
- memset(out, 0, sizeof(*out));
5975
- out->feature = feature;
5976
6022
 
5977
6023
  if (!json_exists(feature) || json_type(feature) != JSON_OBJECT) {
5978
6024
  out->reason = "feature is not an object";
5979
6025
  return false;
5980
6026
  }
5981
-
5982
6027
  geometry = json_object_get(feature, "geometry");
5983
6028
  if (!json_exists(geometry) || json_type(geometry) == JSON_NULL) {
5984
6029
  out->reason = "missing geometry";
@@ -5995,12 +6040,46 @@ static bool fs_safe_prepare_feature(fs_safe_job_t *job, struct json feature, lon
5995
6040
  return false;
5996
6041
  }
5997
6042
 
5998
- geom_bit = fs_safe_geometry_type_bit(geometry_type);
5999
- if (geom_bit == 0) {
6043
+ *geom_bit_out = fs_safe_geometry_type_bit(geometry_type);
6044
+ if (*geom_bit_out == 0) {
6000
6045
  out->reason = "unsupported geometry.type";
6001
6046
  return false;
6002
6047
  }
6003
6048
 
6049
+ *geometry_out = geometry;
6050
+ return true;
6051
+ }
6052
+
6053
+ static bool fs_safe_feature_properties(fs_mode_t mode, struct json feature,
6054
+ fs_safe_feature_t *out) {
6055
+ struct json properties;
6056
+
6057
+ if (mode != FS_MODE_READ_FEATURES)
6058
+ return true;
6059
+
6060
+ properties = json_object_get(feature, "properties");
6061
+ if (!json_exists(properties) || json_type(properties) == JSON_NULL) {
6062
+ out->properties_null = true;
6063
+ } else if (json_type(properties) != JSON_OBJECT) {
6064
+ out->reason = "properties must be an object or null";
6065
+ return false;
6066
+ } else {
6067
+ out->properties = properties;
6068
+ }
6069
+ return true;
6070
+ }
6071
+
6072
+ static bool fs_safe_prepare_feature(fs_safe_job_t *job, struct json feature, long feature_index,
6073
+ fs_mode_t mode, fs_safe_feature_t *out) {
6074
+ struct json geometry;
6075
+ unsigned int geom_bit;
6076
+
6077
+ memset(out, 0, sizeof(*out));
6078
+ out->feature = feature;
6079
+
6080
+ if (!fs_safe_feature_geometry_info(feature, out, &geometry, &geom_bit))
6081
+ return false;
6082
+
6004
6083
  if (!job->opts.only_all && (job->opts.only_mask & geom_bit) == 0) {
6005
6084
  out->filtered = true;
6006
6085
  return true;
@@ -6011,17 +6090,8 @@ static bool fs_safe_prepare_feature(fs_safe_job_t *job, struct json feature, lon
6011
6090
  return false;
6012
6091
  }
6013
6092
 
6014
- if (mode == FS_MODE_READ_FEATURES) {
6015
- properties = json_object_get(feature, "properties");
6016
- if (!json_exists(properties) || json_type(properties) == JSON_NULL) {
6017
- out->properties_null = true;
6018
- } else if (json_type(properties) != JSON_OBJECT) {
6019
- out->reason = "properties must be an object or null";
6020
- return false;
6021
- } else {
6022
- out->properties = properties;
6023
- }
6024
- }
6093
+ if (!fs_safe_feature_properties(mode, feature, out))
6094
+ return false;
6025
6095
 
6026
6096
  out->accepted = true;
6027
6097
  out->geometry = geometry;
@@ -6275,78 +6345,87 @@ static bool fs_safe_fill_build(fs_safe_job_t *job, struct json features) {
6275
6345
  return true;
6276
6346
  }
6277
6347
 
6278
- static bool fs_safe_read_file_no_gvl(fs_safe_job_t *job) {
6279
- int fd;
6348
+ static bool fs_safe_allocate_read_buffer(fs_safe_job_t *job, int fd, char **buf_out,
6349
+ size_t *cap_out) {
6280
6350
  struct stat st;
6281
- char *buf = NULL;
6282
6351
  size_t cap = 0;
6283
- size_t len = 0;
6284
-
6285
- fd = open(job->path, O_RDONLY);
6286
- if (fd < 0) {
6287
- fs_safe_set_system_error(job, errno);
6288
- return false;
6289
- }
6290
6352
 
6291
6353
  if (fstat(fd, &st) == 0 && st.st_size >= 0) {
6292
6354
  cap = (size_t)st.st_size;
6293
6355
  if (cap > SIZE_MAX - 1) {
6294
- close(fd);
6295
6356
  fs_safe_set_error(job, FS_SAFE_ERROR_NOMEM, "FeatureSource file is too large");
6296
6357
  return false;
6297
6358
  }
6298
- buf = (char *)malloc(cap + 1);
6299
- if (!buf) {
6300
- close(fd);
6301
- fs_safe_set_error(job, FS_SAFE_ERROR_NOMEM, "FeatureSource file allocation failed");
6302
- return false;
6303
- }
6304
6359
  } else {
6305
6360
  cap = 8192;
6306
- buf = (char *)malloc(cap + 1);
6307
- if (!buf) {
6308
- close(fd);
6309
- fs_safe_set_error(job, FS_SAFE_ERROR_NOMEM, "FeatureSource file allocation failed");
6310
- return false;
6311
- }
6312
6361
  }
6313
6362
 
6363
+ *buf_out = (char *)malloc(cap + 1);
6364
+ if (!*buf_out) {
6365
+ fs_safe_set_error(job, FS_SAFE_ERROR_NOMEM, "FeatureSource file allocation failed");
6366
+ return false;
6367
+ }
6368
+ *cap_out = cap;
6369
+ return true;
6370
+ }
6371
+
6372
+ static bool fs_safe_grow_read_buffer(fs_safe_job_t *job, char **buf, size_t *cap) {
6373
+ size_t new_cap = *cap < 8192 ? 8192 : *cap * 2;
6374
+ char *grown;
6375
+
6376
+ if (new_cap < *cap || new_cap > SIZE_MAX - 1) {
6377
+ fs_safe_set_error(job, FS_SAFE_ERROR_NOMEM, "FeatureSource file allocation overflow");
6378
+ return false;
6379
+ }
6380
+ grown = (char *)realloc(*buf, new_cap + 1);
6381
+ if (!grown) {
6382
+ fs_safe_set_error(job, FS_SAFE_ERROR_NOMEM, "FeatureSource file allocation failed");
6383
+ return false;
6384
+ }
6385
+ *buf = grown;
6386
+ *cap = new_cap;
6387
+ return true;
6388
+ }
6389
+
6390
+ static bool fs_safe_read_file_contents(fs_safe_job_t *job, int fd, char **buf, size_t *cap,
6391
+ size_t *len) {
6314
6392
  for (;;) {
6315
6393
  ssize_t n;
6316
- if (len == cap) {
6317
- size_t new_cap = cap < 8192 ? 8192 : cap * 2;
6318
- char *grown;
6319
- if (new_cap < cap || new_cap > SIZE_MAX - 1) {
6320
- free(buf);
6321
- close(fd);
6322
- fs_safe_set_error(job, FS_SAFE_ERROR_NOMEM,
6323
- "FeatureSource file allocation overflow");
6324
- return false;
6325
- }
6326
- grown = (char *)realloc(buf, new_cap + 1);
6327
- if (!grown) {
6328
- free(buf);
6329
- close(fd);
6330
- fs_safe_set_error(job, FS_SAFE_ERROR_NOMEM, "FeatureSource file allocation failed");
6394
+ if (*len == *cap) {
6395
+ if (!fs_safe_grow_read_buffer(job, buf, cap))
6331
6396
  return false;
6332
- }
6333
- buf = grown;
6334
- cap = new_cap;
6335
6397
  }
6336
6398
 
6337
- n = read(fd, buf + len, cap - len);
6399
+ n = read(fd, *buf + *len, *cap - *len);
6338
6400
  if (n < 0) {
6339
6401
  if (errno == EINTR)
6340
6402
  continue;
6341
- int err = errno;
6342
- free(buf);
6343
- close(fd);
6344
- fs_safe_set_system_error(job, err);
6403
+ fs_safe_set_system_error(job, errno);
6345
6404
  return false;
6346
6405
  }
6347
6406
  if (n == 0)
6348
6407
  break;
6349
- len += (size_t)n;
6408
+ *len += (size_t)n;
6409
+ }
6410
+
6411
+ return true;
6412
+ }
6413
+
6414
+ static bool fs_safe_read_file_no_gvl(fs_safe_job_t *job) {
6415
+ int fd = open(job->path, O_RDONLY);
6416
+ char *buf = NULL;
6417
+ size_t cap = 0;
6418
+ size_t len = 0;
6419
+
6420
+ if (fd < 0) {
6421
+ fs_safe_set_system_error(job, errno);
6422
+ return false;
6423
+ }
6424
+ if (!fs_safe_allocate_read_buffer(job, fd, &buf, &cap) ||
6425
+ !fs_safe_read_file_contents(job, fd, &buf, &cap, &len)) {
6426
+ free(buf);
6427
+ close(fd);
6428
+ return false;
6350
6429
  }
6351
6430
 
6352
6431
  if (close(fd) != 0) {
@@ -7122,9 +7201,7 @@ static VALUE rb_tg_feature_source_build_index_io(int argc, VALUE *argv, VALUE se
7122
7201
  return fs_safe_dispatch_json(json_string, kwargs, FS_MODE_BUILD_INDEX);
7123
7202
  }
7124
7203
 
7125
- RUBY_FUNC_EXPORTED void Init_tg_geometry_ext_geometry_ext(void) {
7126
- tg_geometry_vendor_header_sanity();
7127
-
7204
+ static void tg_geometry_init_ids(void) {
7128
7205
  id_format = rb_intern("format");
7129
7206
  id_index = rb_intern("index");
7130
7207
  id_srid = rb_intern("srid");
@@ -7167,7 +7244,9 @@ RUBY_FUNC_EXPORTED void Init_tg_geometry_ext_geometry_ext(void) {
7167
7244
  id_exterior = rb_intern("exterior");
7168
7245
  id_holes = rb_intern("holes");
7169
7246
  id_sort = rb_intern("sort");
7247
+ }
7170
7248
 
7249
+ static void tg_geometry_init_core(void) {
7171
7250
  mTG = rb_define_module("TG");
7172
7251
  mTGGeometry = rb_define_module_under(mTG, "Geometry");
7173
7252
 
@@ -7200,7 +7279,9 @@ RUBY_FUNC_EXPORTED void Init_tg_geometry_ext_geometry_ext(void) {
7200
7279
  rb_define_singleton_method(mTGGeometry, "line_string", rb_tg_geometry_line_string, -1);
7201
7280
  rb_define_singleton_method(mTGGeometry, "polygon", rb_tg_geometry_polygon, -1);
7202
7281
  rb_define_singleton_method(mTGGeometry, "multi_polygon", rb_tg_geometry_multi_polygon, -1);
7282
+ }
7203
7283
 
7284
+ static void tg_geometry_init_geom(void) {
7204
7285
  cTGGeometryGeom = rb_define_class_under(mTGGeometry, "Geom", rb_cObject);
7205
7286
  rb_undef_alloc_func(cTGGeometryGeom);
7206
7287
  rb_define_method(cTGGeometryGeom, "type", rb_tg_geometry_geom_type, 0);
@@ -7260,7 +7341,9 @@ RUBY_FUNC_EXPORTED void Init_tg_geometry_ext_geometry_ext(void) {
7260
7341
  rb_define_method(cTGGeometryGeom, "num_geometries", rb_tg_geometry_geom_num_geometries, 0);
7261
7342
  rb_define_method(cTGGeometryGeom, "geometry_at", rb_tg_geometry_geom_geometry_at, 1);
7262
7343
  rb_define_method(cTGGeometryGeom, "geometries", rb_tg_geometry_geom_geometries, 0);
7344
+ }
7263
7345
 
7346
+ static void tg_geometry_init_line(void) {
7264
7347
  cTGGeometryLine = rb_define_class_under(mTGGeometry, "Line", rb_cObject);
7265
7348
  rb_undef_alloc_func(cTGGeometryLine);
7266
7349
  rb_define_method(cTGGeometryLine, "bbox", rb_tg_geometry_line_bbox, 0);
@@ -7273,7 +7356,9 @@ RUBY_FUNC_EXPORTED void Init_tg_geometry_ext_geometry_ext(void) {
7273
7356
  rb_define_method(cTGGeometryLine, "length", rb_tg_geometry_line_length, 0);
7274
7357
  rb_define_method(cTGGeometryLine, "clockwise?", rb_tg_geometry_line_clockwise_p, 0);
7275
7358
  rb_define_method(cTGGeometryLine, "nearest_segment", rb_tg_geometry_line_nearest_segment, 2);
7359
+ }
7276
7360
 
7361
+ static void tg_geometry_init_ring(void) {
7277
7362
  cTGGeometryRing = rb_define_class_under(mTGGeometry, "Ring", rb_cObject);
7278
7363
  rb_undef_alloc_func(cTGGeometryRing);
7279
7364
  rb_define_method(cTGGeometryRing, "bbox", rb_tg_geometry_ring_bbox, 0);
@@ -7288,7 +7373,9 @@ RUBY_FUNC_EXPORTED void Init_tg_geometry_ext_geometry_ext(void) {
7288
7373
  rb_define_method(cTGGeometryRing, "clockwise?", rb_tg_geometry_ring_clockwise_p, 0);
7289
7374
  rb_define_method(cTGGeometryRing, "convex?", rb_tg_geometry_ring_convex_p, 0);
7290
7375
  rb_define_method(cTGGeometryRing, "nearest_segment", rb_tg_geometry_ring_nearest_segment, 2);
7376
+ }
7291
7377
 
7378
+ static void tg_geometry_init_polygon(void) {
7292
7379
  cTGGeometryPolygon = rb_define_class_under(mTGGeometry, "Polygon", rb_cObject);
7293
7380
  rb_undef_alloc_func(cTGGeometryPolygon);
7294
7381
  rb_define_method(cTGGeometryPolygon, "bbox", rb_tg_geometry_polygon_bbox, 0);
@@ -7297,7 +7384,9 @@ RUBY_FUNC_EXPORTED void Init_tg_geometry_ext_geometry_ext(void) {
7297
7384
  rb_define_method(cTGGeometryPolygon, "hole_at", rb_tg_geometry_polygon_hole_at, 1);
7298
7385
  rb_define_method(cTGGeometryPolygon, "holes", rb_tg_geometry_polygon_holes, 0);
7299
7386
  rb_define_method(cTGGeometryPolygon, "clockwise?", rb_tg_geometry_polygon_clockwise_p, 0);
7387
+ }
7300
7388
 
7389
+ static void tg_geometry_init_segment(void) {
7301
7390
  cTGGeometrySegment = rb_define_class_under(mTGGeometry, "Segment", rb_cObject);
7302
7391
  rb_undef_alloc_func(cTGGeometrySegment);
7303
7392
  rb_define_method(cTGGeometrySegment, "a", rb_tg_geometry_segment_a, 0);
@@ -7305,7 +7394,9 @@ RUBY_FUNC_EXPORTED void Init_tg_geometry_ext_geometry_ext(void) {
7305
7394
  rb_define_method(cTGGeometrySegment, "points", rb_tg_geometry_segment_points, 0);
7306
7395
  rb_define_method(cTGGeometrySegment, "bbox", rb_tg_geometry_segment_bbox, 0);
7307
7396
  rb_define_method(cTGGeometrySegment, "intersects?", rb_tg_geometry_segment_intersects_p, 1);
7397
+ }
7308
7398
 
7399
+ static void tg_geometry_init_nearest(void) {
7309
7400
  cTGGeometryNearestSegment = rb_define_class_under(mTGGeometry, "NearestSegment", rb_cObject);
7310
7401
  rb_undef_alloc_func(cTGGeometryNearestSegment);
7311
7402
  rb_define_method(cTGGeometryNearestSegment, "segment", rb_tg_geometry_nearest_segment_segment,
@@ -7314,7 +7405,9 @@ RUBY_FUNC_EXPORTED void Init_tg_geometry_ext_geometry_ext(void) {
7314
7405
  rb_define_method(cTGGeometryNearestSegment, "distance", rb_tg_geometry_nearest_segment_distance,
7315
7406
  0);
7316
7407
  rb_define_method(cTGGeometryNearestSegment, "point", rb_tg_geometry_nearest_segment_point, 0);
7408
+ }
7317
7409
 
7410
+ static void tg_geometry_init_rect(void) {
7318
7411
  cTGGeometryRect = rb_define_class_under(mTGGeometry, "Rect", rb_cObject);
7319
7412
  rb_define_alloc_func(cTGGeometryRect, rb_tg_geometry_rect_alloc);
7320
7413
  rb_define_method(cTGGeometryRect, "initialize", rb_tg_geometry_rect_initialize, -1);
@@ -7329,7 +7422,9 @@ RUBY_FUNC_EXPORTED void Init_tg_geometry_ext_geometry_ext(void) {
7329
7422
  1);
7330
7423
  rb_define_method(cTGGeometryRect, "expand_to_include_point",
7331
7424
  rb_tg_geometry_rect_expand_to_include_point, 2);
7425
+ }
7332
7426
 
7427
+ static void tg_geometry_init_feature_source(void) {
7333
7428
  mTGGeometryFeatureSource = rb_define_module_under(mTGGeometry, "FeatureSource");
7334
7429
  rb_define_singleton_method(mTGGeometryFeatureSource, "read_entries_file",
7335
7430
  rb_tg_feature_source_read_entries_file, -1);
@@ -7349,7 +7444,9 @@ RUBY_FUNC_EXPORTED void Init_tg_geometry_ext_geometry_ext(void) {
7349
7444
  rb_tg_feature_source_build_index_json, -1);
7350
7445
  rb_define_singleton_method(mTGGeometryFeatureSource, "build_index_io",
7351
7446
  rb_tg_feature_source_build_index_io, -1);
7447
+ }
7352
7448
 
7449
+ static void tg_geometry_init_index(void) {
7353
7450
  cTGGeometryIndex = rb_define_class_under(mTGGeometry, "Index", rb_cObject);
7354
7451
  rb_undef_alloc_func(cTGGeometryIndex);
7355
7452
  rb_define_singleton_method(cTGGeometryIndex, "build", rb_tg_geometry_index_build, -1);
@@ -7377,7 +7474,9 @@ RUBY_FUNC_EXPORTED void Init_tg_geometry_ext_geometry_ext(void) {
7377
7474
  rb_define_method(cTGGeometryIndex, "strategy", rb_tg_geometry_index_strategy, 0);
7378
7475
  rb_define_method(cTGGeometryIndex, "predicate", rb_tg_geometry_index_predicate, 0);
7379
7476
  rb_define_method(cTGGeometryIndex, "bbox", rb_tg_geometry_index_bbox, 0);
7477
+ }
7380
7478
 
7479
+ static void tg_geometry_init_debug(void) {
7381
7480
  #ifdef TG_DEBUG_TEST
7382
7481
  rb_define_singleton_method(mTGGeometry, "_debug_reset_test_hooks!",
7383
7482
  rb_tg_geometry_debug_reset_test_hooks, 0);
@@ -7401,3 +7500,19 @@ RUBY_FUNC_EXPORTED void Init_tg_geometry_ext_geometry_ext(void) {
7401
7500
  rb_tg_geometry_index_force_dispose_for_test, 0);
7402
7501
  #endif
7403
7502
  }
7503
+
7504
+ RUBY_FUNC_EXPORTED void Init_tg_geometry_ext_geometry_ext(void) {
7505
+ tg_geometry_vendor_header_sanity();
7506
+ tg_geometry_init_ids();
7507
+ tg_geometry_init_core();
7508
+ tg_geometry_init_geom();
7509
+ tg_geometry_init_line();
7510
+ tg_geometry_init_ring();
7511
+ tg_geometry_init_polygon();
7512
+ tg_geometry_init_segment();
7513
+ tg_geometry_init_nearest();
7514
+ tg_geometry_init_rect();
7515
+ tg_geometry_init_feature_source();
7516
+ tg_geometry_init_index();
7517
+ tg_geometry_init_debug();
7518
+ }
@@ -2,6 +2,6 @@
2
2
 
3
3
  module TG
4
4
  module Geometry
5
- VERSION = "0.3.3"
5
+ VERSION = "0.3.4"
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tg_geometry
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.3
4
+ version: 0.3.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Roman Haydarov