@yuneta/gobj-js 7.25.3 → 7.25.5

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.
@@ -3033,7 +3033,7 @@ var gobjJs = (function(exports) {
3033
3033
  *
3034
3034
  * Licence: MIT (http://www.opensource.org/licenses/mit-license)
3035
3035
  * Copyright (c) 2014,2024 Niyamaka.
3036
- * Copyright (c) 2025, ArtGins.
3036
+ * Copyright (c) 2025-2026, ArtGins.
3037
3037
  *********************************************************************************/
3038
3038
  var kw_flag_t = Object.freeze({
3039
3039
  KW_REQUIRED: 1,
@@ -3609,10 +3609,13 @@ var gobjJs = (function(exports) {
3609
3609
  * anything else gives the default back, LOGGED ("path MUST BE a
3610
3610
  * json boolean", required or not) -- unless KW_WILD_NUMBER asks
3611
3611
  * to read a number (0 is false), a string ("true"/"false" in any
3612
- * case, else its integer) or null (false); a list or a dict is
3613
- * then false, logged too. Before gobj-js 7.25.2 the value went
3614
- * through Boolean(), so "false" was TRUE; before 7.25.3 a value
3615
- * of the wrong type gave the default back in silence.
3612
+ * case, else its decimal integer as atoi() reads it: "0x1F" is 0,
3613
+ * so false) or null (false); a list or a dict is then false,
3614
+ * logged too. Before gobj-js 7.25.2 the value went through
3615
+ * Boolean(), so "false" was TRUE; before 7.25.3 a value of the
3616
+ * wrong type gave the default back in silence; before 7.25.5 the
3617
+ * string went through parseInt() with no base, which reads hex:
3618
+ * "0x1F" was TRUE.
3616
3619
  ************************************************************/
3617
3620
  function kw_get_bool(gobj, kw, path, default_value, flag) {
3618
3621
  if (gobj && !is_gobj(gobj)) log_error(`GObj bad instanceof`);
@@ -3638,7 +3641,7 @@ var gobjJs = (function(exports) {
3638
3641
  else if (wild && is_string(b)) {
3639
3642
  if (b.toLowerCase() === "true") value = true;
3640
3643
  else if (b.toLowerCase() === "false") value = false;
3641
- else value = (parseInt(b) || 0) !== 0;
3644
+ else value = (parseInt(b, 10) || 0) !== 0;
3642
3645
  } else if (wild && b === null) value = false;
3643
3646
  else if (wild) {
3644
3647
  log_error(`${gobj ? gobj_short_name(gobj) + ": " : ""}path MUST BE a simple json element: '${path}'`);
@@ -3653,7 +3656,34 @@ var gobjJs = (function(exports) {
3653
3656
  return value;
3654
3657
  }
3655
3658
  /************************************************************
3656
- *
3659
+ * The integer at the start of a string, as C's strtoll(s, 0, 0)
3660
+ * reads it: leading spaces, a sign, then "0x" for hex, "0" for
3661
+ * octal, else decimal, up to the first character that is not a
3662
+ * digit of that base. 0 when there is no digit.
3663
+ ************************************************************/
3664
+ function strtoll_base0(s) {
3665
+ const m = /^\s*([+-]?)(0[xX][0-9a-fA-F]+|0[0-7]*|[1-9][0-9]*)/.exec(s);
3666
+ if (!m) return 0;
3667
+ let digits = m[2];
3668
+ let value;
3669
+ if (digits.length > 1 && (digits[1] === "x" || digits[1] === "X")) value = parseInt(digits.substring(2), 16);
3670
+ else if (digits[0] === "0") value = parseInt(digits, 8);
3671
+ else value = parseInt(digits, 10);
3672
+ return m[1] === "-" ? -value : value;
3673
+ }
3674
+ /************************************************************
3675
+ * As the C kw_get_int(): a number found is the answer,
3676
+ * truncated toward zero as C casts a real, and anything else
3677
+ * gives the default back (as an integer), LOGGED ("path MUST BE
3678
+ * a json integer", required or not) -- unless KW_WILD_NUMBER
3679
+ * asks to read a boolean (1/0), a string (as strtoll() with base
3680
+ * 0: "0x1F" is 31, "017" is 15, "12abc" is 12, "abc" is 0) or
3681
+ * null (0); a list or a dict is then 0, logged too. KW_EXTRACT
3682
+ * takes out only a value the reader answers with.
3683
+ * Before gobj-js 7.25.4 KW_EXTRACT deleted the value before its
3684
+ * type was looked at, a value of another type was logged only
3685
+ * with KW_REQUIRED, KW_WILD_NUMBER was ignored, and a number went
3686
+ * through parseInt(), which reads it as a string: 1e-7 gave 1.
3657
3687
  ************************************************************/
3658
3688
  function kw_get_int(gobj, kw, path, default_value, flag) {
3659
3689
  if (gobj && !is_gobj(gobj)) log_error(`GObj bad instanceof`);
@@ -3661,6 +3691,7 @@ var gobjJs = (function(exports) {
3661
3691
  const required = flag && flag & kw_flag_t.KW_REQUIRED;
3662
3692
  const create = flag && flag & kw_flag_t.KW_CREATE;
3663
3693
  const extract = flag && flag & kw_flag_t.KW_EXTRACT;
3694
+ const wild = flag && flag & kw_flag_t.KW_WILD_NUMBER;
3664
3695
  if (v === void 0) {
3665
3696
  if (create) {
3666
3697
  let v = parseInt(default_value);
@@ -3672,18 +3703,34 @@ var gobjJs = (function(exports) {
3672
3703
  }
3673
3704
  return parseInt(default_value);
3674
3705
  }
3675
- if (extract) kw_delete(gobj, kw, path);
3676
- if (!is_number(v)) {
3677
- if (required) {
3678
- log_error(`path value MUST BE a number: ${path}`);
3679
- trace_msg(kw);
3680
- }
3706
+ let value;
3707
+ if (is_number(v)) value = Math.trunc(v);
3708
+ else if (!wild) {
3709
+ log_error(`${gobj ? gobj_short_name(gobj) + ": " : ""}path MUST BE a json integer: '${path}'`);
3710
+ trace_json(kw);
3681
3711
  return parseInt(default_value);
3712
+ } else if (is_boolean(v)) value = v ? 1 : 0;
3713
+ else if (is_string(v)) value = strtoll_base0(v);
3714
+ else if (v === null) value = 0;
3715
+ else {
3716
+ log_error(`${gobj ? gobj_short_name(gobj) + ": " : ""}path MUST BE a simple json element: '${path}'`);
3717
+ trace_json(kw);
3718
+ return 0;
3682
3719
  }
3683
- return parseInt(v);
3720
+ if (extract) kw_delete(gobj, kw, path);
3721
+ return value;
3684
3722
  }
3685
3723
  /************************************************************
3686
- *
3724
+ * As the C kw_get_real(): a number found is the answer, and
3725
+ * anything else gives the default back (as a number), LOGGED
3726
+ * ("path MUST BE a json real", required or not) -- unless
3727
+ * KW_WILD_NUMBER asks to read a boolean (1/0), a string (as
3728
+ * parseFloat() reads it, 0 when it does not start with a number)
3729
+ * or null (0); a list or a dict is then 0, logged too.
3730
+ * KW_EXTRACT takes out only a value the reader answers with.
3731
+ * Before gobj-js 7.25.4 KW_EXTRACT deleted the value before its
3732
+ * type was looked at, a value of another type was logged only
3733
+ * with KW_REQUIRED, and KW_WILD_NUMBER was ignored.
3687
3734
  ************************************************************/
3688
3735
  function kw_get_real(gobj, kw, path, default_value, flag) {
3689
3736
  if (gobj && !is_gobj(gobj)) log_error(`GObj bad instanceof`);
@@ -3691,6 +3738,7 @@ var gobjJs = (function(exports) {
3691
3738
  const required = flag && flag & kw_flag_t.KW_REQUIRED;
3692
3739
  const create = flag && flag & kw_flag_t.KW_CREATE;
3693
3740
  const extract = flag && flag & kw_flag_t.KW_EXTRACT;
3741
+ const wild = flag && flag & kw_flag_t.KW_WILD_NUMBER;
3694
3742
  if (v === void 0) {
3695
3743
  if (create) {
3696
3744
  let v = Number(default_value);
@@ -3702,15 +3750,39 @@ var gobjJs = (function(exports) {
3702
3750
  }
3703
3751
  return Number(default_value);
3704
3752
  }
3705
- if (extract) kw_delete(gobj, kw, path);
3706
- if (!is_number(v)) {
3707
- if (required) {
3708
- log_error(`path value MUST BE a number: ${path}`);
3709
- trace_msg(kw);
3710
- }
3753
+ let value;
3754
+ if (is_number(v)) value = v;
3755
+ else if (!wild) {
3756
+ log_error(`${gobj ? gobj_short_name(gobj) + ": " : ""}path MUST BE a json real: '${path}'`);
3757
+ trace_json(kw);
3711
3758
  return Number(default_value);
3759
+ } else if (is_boolean(v)) value = v ? 1 : 0;
3760
+ else if (is_string(v)) {
3761
+ value = parseFloat(v);
3762
+ if (Number.isNaN(value)) value = 0;
3763
+ } else if (v === null) value = 0;
3764
+ else {
3765
+ log_error(`${gobj ? gobj_short_name(gobj) + ": " : ""}path MUST BE a simple json element: '${path}'`);
3766
+ trace_json(kw);
3767
+ return 0;
3768
+ }
3769
+ if (extract) kw_delete(gobj, kw, path);
3770
+ return value;
3771
+ }
3772
+ /************************************************************
3773
+ * TRUE when the last key of `path` is a key of its dict, whatever
3774
+ * its value: kw_find_path() answers undefined both for a key that
3775
+ * is not there and for one whose value is undefined.
3776
+ ************************************************************/
3777
+ function kw_path_holds_key(kw, path) {
3778
+ let ss = is_string(path) ? path.split("`") : [];
3779
+ let parent = kw;
3780
+ for (let i = 0; i < ss.length - 1; i++) {
3781
+ if (!(is_object(parent) || is_array(parent))) return false;
3782
+ parent = parent[ss[i]];
3712
3783
  }
3713
- return Number(v);
3784
+ if (!(is_object(parent) || is_array(parent)) || ss.length === 0) return false;
3785
+ return Object.prototype.hasOwnProperty.call(parent, ss[ss.length - 1]);
3714
3786
  }
3715
3787
  /************************************************************
3716
3788
  * The default comes back AS GIVEN, as in the C kw_get_str()
@@ -3719,6 +3791,17 @@ var gobjJs = (function(exports) {
3719
3791
  * TRUE: an `if(value)` on the answer took an absent key for a
3720
3792
  * present one. KW_CREATE stores a string default, and null for
3721
3793
  * any other, as C stores json_null() for a NULL default.
3794
+ * KW_EXTRACT takes out only a string (before gobj-js 7.25.4 it
3795
+ * deleted any value, and a value that was not a string was lost).
3796
+ * C refuses to extract a string at all ("Cannot extract a
3797
+ * string": its answer would point into the freed json); a JS
3798
+ * string outlives the kw, so here it is taken out.
3799
+ * A value that is there and is not a string gives the default
3800
+ * back, LOGGED ("path MUST BE a json str", required or not), as
3801
+ * C does; a null value is the key saying "no string" and is not
3802
+ * logged, and KW_REQUIRED logs only a path that is not there at
3803
+ * all. Before gobj-js 7.25.5 a value of another type was logged
3804
+ * only with KW_REQUIRED, and then a null one too.
3722
3805
  ************************************************************/
3723
3806
  function kw_get_str(gobj, kw, path, default_value, flag) {
3724
3807
  if (gobj && !is_gobj(gobj)) log_error(`GObj bad instanceof`);
@@ -3730,20 +3813,20 @@ var gobjJs = (function(exports) {
3730
3813
  if (create) {
3731
3814
  kw_set_dict_value(gobj, kw, path, is_string(default_value) ? default_value : null);
3732
3815
  return default_value;
3733
- } else if (required) {
3816
+ } else if (required && !kw_path_holds_key(kw, path)) {
3734
3817
  log_error(`path not found: '${path}'`);
3735
3818
  trace_json(kw);
3736
3819
  }
3737
3820
  return default_value;
3738
3821
  }
3739
- if (extract) kw_delete(gobj, kw, path);
3740
3822
  if (!is_string(v)) {
3741
- if (required) {
3742
- log_error(`${gobj_short_name(gobj)}: path value MUST BE a string: ${path}`);
3743
- trace_msg(kw);
3823
+ if (v !== null) {
3824
+ log_error(`${gobj ? gobj_short_name(gobj) + ": " : ""}path MUST BE a json str: '${path}'`);
3825
+ trace_json(kw);
3744
3826
  }
3745
3827
  return default_value;
3746
3828
  }
3829
+ if (extract) kw_delete(gobj, kw, path);
3747
3830
  return v;
3748
3831
  }
3749
3832
  /************************************************************
@@ -3795,8 +3878,8 @@ var gobjJs = (function(exports) {
3795
3878
  }
3796
3879
  if (!is_object(v)) {
3797
3880
  if (required) {
3798
- log_error(`${gobj_short_name(gobj)}: path value MUST BE a dict: ${path}`);
3799
- trace_msg(kw);
3881
+ log_error(`${gobj ? gobj_short_name(gobj) + ": " : ""}path MUST BE a json dict: '${path}'`);
3882
+ trace_json(kw);
3800
3883
  }
3801
3884
  return default_value;
3802
3885
  }
@@ -3853,8 +3936,8 @@ var gobjJs = (function(exports) {
3853
3936
  }
3854
3937
  if (!is_array(v)) {
3855
3938
  if (required) {
3856
- log_error(`${gobj_short_name(gobj)}: path value MUST BE an array: ${path}`);
3857
- trace_msg(kw);
3939
+ log_error(`${gobj ? gobj_short_name(gobj) + ": " : ""}path MUST BE a json list: '${path}'`);
3940
+ trace_json(kw);
3858
3941
  }
3859
3942
  return default_value;
3860
3943
  }