Skip to content

Commit 99b60f8

Browse files
committed
All unit tests are once again passing
Some unit tests had to be removed, because they were only relevant when integers had bounded size. I still haven't decided whether to merge this into main, because parsing of integers is considerably slower than it was before.
1 parent cc84249 commit 99b60f8

10 files changed

Lines changed: 138 additions & 102 deletions

File tree

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,12 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
4949
- Since v7.0, holding down `Enter` in a multiline textbox (like the [tree viewer query box](/docs/README.md#remespath)) only adds one newline when the key is lifted.
5050
- Maybe use pre-7.1 (dictionary-based rather than indicator-based) [selection remembering](/docs/README.md#working-with-selections) for Notepad++ 8.5.5 and earlier? Indicators are risky with those older NPP's because of the lack of `NPPM_ALLOCATEINDICATOR`.
5151

52+
## [9.0.0] - (UNRELEASED) YYYY-MM-DD
53+
54+
### Changed
55+
56+
1. Internally represent integers as BigIntegers instead of 64-bit integers, __meaning that JsonTools can correctly parse integers of unlimited size.__
57+
5258
## [8.4.0] - 2025-05-04
5359

5460
### Added

JsonToolsNppPlugin/Forms/TreeViewer.cs

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1235,10 +1235,11 @@ public string KeyOfTreeNode(TreeNode node, KeyStyle style, char separator = JNod
12351235
}
12361236

12371237
/// <summary>
1238-
/// how long we think the UTF8-encoded representations of a list of JNodes is in regex mode.<br></br>
1238+
/// <paramref name="utf8Lengths"/> is populated with a list of how long we think the UTF8-encoded representations of a list of JNodes is in regex mode.<br></br>
12391239
/// if delim is '\x00' (not in CSV mode) and nodes are all strings, these are just the lengths of their UTF8 reprs.<br></br>
12401240
/// Otherwise, we do some special casing.<br></br>
1241-
/// returns true unless there was some error (e.g., probably b/c of nodes was a JObject or JArray)
1241+
/// Returns true unless there was some error (e.g., probably b/c of nodes was a JObject or JArray)<br></br>
1242+
/// If false was returned, the utf8Lengths array is useless.
12421243
/// </summary>
12431244
/// <param name="nodes">THESE MUST BE ORDERED BY POSITION ASCENDING</param>
12441245
/// <param name="delim"></param>
@@ -1260,13 +1261,20 @@ public static bool LengthOfStringInRegexMode(JNode[] nodes, char delim, char quo
12601261
return false;
12611262
}
12621263
IComparable value = jnode.value;
1264+
1265+
bool isNum = value is double;
1266+
double d = isNum ? (double)value : 0;
1267+
if (value is BigInteger bi)
1268+
{
1269+
isNum = true;
1270+
d = (double)bi;
1271+
}
12631272

1264-
if (value is BigInteger || value is double)
1273+
if (isNum)
12651274
{
12661275
// two equal numbers may have several valid representations
12671276
// we will try to find the length of the representation used in the document,
12681277
// but we will quit and use the JSON string length if our first attempt fails to find the length
1269-
double d = (double)value;
12701278
int nodepos = jnode.position;
12711279
if (documentText is null)
12721280
documentText = selectionEnd < 0

JsonToolsNppPlugin/JSONTools/Dson.cs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -42,13 +42,13 @@ private static string FormatInteger(BigInteger val)
4242
val = BigInteger.DivRem(val, 8, out BigInteger rem);
4343
sb.Append((int)rem);
4444
}
45-
int sblenM1 = sb.Length - 1;
45+
int sblen = sb.Length;
4646
string s;
47-
if (sblenM1 > 0)
47+
if (sblen > 1)
4848
{
49-
var chars = new char[sblenM1 + 1];
50-
for (int ii = 0; ii <= sblenM1; ii--)
51-
chars[ii] = sb[sblenM1 - ii];
49+
var chars = new char[sblen];
50+
for (int ii = 0; ii < sblen; ii++)
51+
chars[ii] = sb[sblen - 1 - ii];
5252
s = new string(chars);
5353
}
5454
else

JsonToolsNppPlugin/JSONTools/JNode.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -490,14 +490,18 @@ public bool TryGetValueAsBigInteger(out BigInteger bi)
490490
public bool TryGetValueAsInt32(out int i)
491491
{
492492
i = 0;
493-
if (value is BigInteger bi && bi >= int.MinValue && bi <= int.MaxValue)
493+
if (value is BigInteger bi && bi >= Int32MinValueAsBigInt && bi <= Int32MaxValueAsBigInt)
494494
{
495495
i = (int)bi;
496496
return true;
497497
}
498498
return false;
499499
}
500500

501+
public static readonly BigInteger Int32MaxValueAsBigInt = (BigInteger)int.MaxValue;
502+
503+
public static readonly BigInteger Int32MinValueAsBigInt = (BigInteger)int.MinValue;
504+
501505
public static readonly BigInteger DoubleMaxValueAsBigInt = (BigInteger)double.MaxValue;
502506

503507
public static readonly BigInteger DoubleMinValueAsBigInt = (BigInteger)double.MinValue;

JsonToolsNppPlugin/JSONTools/JsonTabularize.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ Uses an algorithm to flatten nested JSON.
66
*/
77
using System;
88
using System.Collections.Generic;
9+
using System.Numerics;
910
using System.Text;
1011

1112
namespace JSON_Tools.JSON_Tools
@@ -307,7 +308,7 @@ private void FindTabsInSchemaHelper(Dictionary<string, object> schema, List<obje
307308
{
308309
if (node is int && (int)node == 0)
309310
{
310-
patharr.children.Add(new JNode(0L, Dtype.INT, 0));
311+
patharr.children.Add(new JNode(BigInteger.Zero, Dtype.INT, 0));
311312
}
312313
else
313314
{

JsonToolsNppPlugin/JSONTools/RemesPathFunctions.cs

Lines changed: 37 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,8 @@ public static JNode Mul(JNode a, JNode b)
233233
}
234234
if (!JNode.BothTypesIntersect(atype, btype, Dtype.NUM))
235235
throw new RemesPathException($"Can't multiply objects of type {JNode.FormatDtype(atype)} and {JNode.FormatDtype(btype)}");
236+
if (aval is BigInteger abi && bval is BigInteger bbi_)
237+
return new JNode(abi * bbi_);
236238
return new JNode(JNode.ConvertJNodeValueToDouble(aval) * JNode.ConvertJNodeValueToDouble(bval));
237239
}
238240

@@ -1202,9 +1204,9 @@ private static (JNode elt, char printStyle, bool sortKeys, int indent, char inde
12021204
char printStyle = args[1].type == Dtype.NULL ? 'm' : ((string)args[1].value)[0];
12031205
bool sortKeys = args[2].type == Dtype.NULL || (bool)args[2].value;
12041206
JNode arg3 = args[3];
1205-
int indent = 4;
1207+
int indent = arg3.TryGetValueAsInt32(out int i) ? i : 4;
12061208
char indentChar = ' ';
1207-
if (!arg3.TryGetValueAsInt32(out indent) && arg3.value is string s && s[0] is char c && c == '\t')
1209+
if (arg3.value is string s && s[0] is char c && c == '\t')
12081210
{
12091211
indent = 1;
12101212
indentChar = c;
@@ -1601,7 +1603,7 @@ public static JNode MinBy(List<JNode> args)
16011603
}
16021604
else if (key is BigInteger kbi)
16031605
{
1604-
int kint = (int)key;
1606+
int kint = (int)kbi;
16051607
for (int ii = 0; ii < itbl.Count; ii++)
16061608
{
16071609
var x = (JArray)itbl[ii];
@@ -1629,8 +1631,8 @@ public static JNode RandomFrom0To1(List<JNode> args)
16291631
public static JNode RandomFromSchema(List<JNode> args)
16301632
{
16311633
JNode node = args[0];
1632-
int minArrayLength = args.Count >= 2 && args[1].value is BigInteger l && l < int.MaxValue && l >= 0 ? (int)l : 0;
1633-
int maxArrayLength = args.Count >= 3 && args[2].value is BigInteger l2 && l2 < int.MaxValue && l2 >= 0 ? (int)l2 : 10;
1634+
int minArrayLength = args.Count > 1 && args[1].TryGetValueAsInt32(out int minArrLen) ? minArrLen : 0;
1635+
int maxArrayLength = args.Count > 2 && args[2].TryGetValueAsInt32(out int maxArrLen) ? maxArrLen : 10;
16341636
bool extendedAsciiStrings = args.Count >= 4 && args[3].value is bool b && b;
16351637
bool usePatterns = args.Count >= 5 && args[4].value is bool b2 && b2;
16361638
return RandomJsonFromSchema.RandomJson(node, minArrayLength, maxArrayLength, extendedAsciiStrings, usePatterns);
@@ -1694,49 +1696,53 @@ public static JNode LoopCount(List<JNode> args)
16941696
/// </summary>
16951697
public static JNode Range(List<JNode> args)
16961698
{
1697-
var start = (BigInteger?)args[0].value;
1698-
var end = (BigInteger?)args[1].value;
1699-
var step = (BigInteger?)args[2].value;
1700-
var nums = new JArray();
1701-
if (start == null)
1699+
if (!args[0].TryGetValueAsBigInteger(out BigInteger start))
17021700
{
17031701
throw new RemesPathException("First argument for 'range' function cannot be null.");
17041702
}
1703+
var stepNode = args[2];
1704+
int step = stepNode.TryGetValueAsInt32(out int step_) ? step_ : -1;
17051705
if (step == 0)
17061706
{
17071707
throw new RemesPathException("Can't have a step size of 0 for the 'range' function");
17081708
}
1709-
if (end == null && start > 0)
1710-
{
1711-
for (BigInteger ii = 0; ii < start; ii++)
1712-
{
1713-
nums.children.Add(new JNode(ii, Dtype.INT, 0));
1714-
}
1715-
}
1716-
else if (step == null && start < end)
1717-
{
1718-
for (BigInteger ii = start.Value; ii < end; ii++)
1719-
{
1720-
nums.children.Add(new JNode(ii, Dtype.INT, 0));
1721-
}
1722-
}
1723-
else
1709+
var nums = new JArray();
1710+
if (args[1].TryGetValueAsBigInteger(out BigInteger end))
17241711
{
1725-
if (start > end && step < 0)
1712+
if (stepNode.type == Dtype.NULL)
17261713
{
1727-
for (BigInteger ii = start.Value; ii > end; ii += step.Value)
1714+
// step is unspecified, so default to step size 1
1715+
for (BigInteger ii = start; ii < end; ii++)
17281716
{
17291717
nums.children.Add(new JNode(ii, Dtype.INT, 0));
17301718
}
17311719
}
1732-
else if (start < end && step > 0)
1720+
else
17331721
{
1734-
for (BigInteger ii = start.Value; ii < end; ii += step.Value)
1722+
if (start > end && step < 0)
17351723
{
1736-
nums.children.Add(new JNode(ii, Dtype.INT, 0));
1724+
for (BigInteger ii = start; ii > end; ii += step)
1725+
{
1726+
nums.children.Add(new JNode(ii, Dtype.INT, 0));
1727+
}
1728+
}
1729+
else if (start < end && step > 0)
1730+
{
1731+
for (BigInteger ii = start; ii < end; ii += step)
1732+
{
1733+
nums.children.Add(new JNode(ii, Dtype.INT, 0));
1734+
}
17371735
}
17381736
}
17391737
}
1738+
else if (start > 0)
1739+
{
1740+
// end is unspecified, so just list all integers in range [0, start)
1741+
for (BigInteger ii = 0; ii < start; ii++)
1742+
{
1743+
nums.children.Add(new JNode(ii, Dtype.INT, 0));
1744+
}
1745+
}
17401746
return nums;
17411747
}
17421748

@@ -3523,7 +3529,7 @@ public static JNode ToStr(List<JNode> args)
35233529
/// <summary>
35243530
/// float(x: anything) -> float<br></br>
35253531
/// converts all numeric JNodes to an equal double.<br></br>
3526-
/// Converts all decimal string representations of floating point numbers to the corresponding double.
3532+
/// Converts all base 10 string representations of floating point numbers to the corresponding double.
35273533
/// </summary>
35283534
public static JNode ToFloat(List<JNode> args)
35293535
{

JsonToolsNppPlugin/Tests/DsonTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ public static bool TestDump()
2424
("{\"aჿ\":[true,false,{\"c\": 3},\"оa\",[1, -2]], \"b\\\"\": \"z\", \"c\": {\"d\": 1.13}, \"d\": 50, \"e\": 0.76, \"f\": null}",
2525
"such \"aჿ\" is so yes and no also such \"c\" is 3 wow and \"оa\" also so 1 and -2 many many, \"b\\\"\" is \"z\". " +
2626
"\"c\" is such \"d\" is 1.15 wow! \"d\" is 62? \"e\" is 0.114, \"f\" is empty wow"),
27-
("[-9223372036854775808, 9223372036854775807]", "so 1000000000000000000000 and 777777777777777777777 many"),
27+
("[-9223372036854775808, 9223372036854775807]", "so -1000000000000000000000 and 777777777777777777777 many"),
2828
};
2929
int testsFailed = 0;
3030
int ii = 0;

JsonToolsNppPlugin/Tests/JsonGrepperTests.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ public static async Task<bool> TestApiRequester()
147147
int testsFailed = 0;
148148

149149
string[] urls = new string[] {
150-
"https://api.weather.gov",
150+
"https://api.weather.gov/stations/KCCR",
151151
"https://api.weather.gov/points/37.68333333333334,-121.92500000000001", // Alameda
152152
"https://api.weather.gov/points/37.75833333333334,-122.43333333333334", // San Francisco
153153
};
@@ -156,7 +156,7 @@ public static async Task<bool> TestApiRequester()
156156
ii = testResult[0];
157157
testsFailed = testResult[1];
158158
// test when requesting from only one url
159-
string[] firstUrl = new string[] { "https://api.weather.gov" };
159+
string[] firstUrl = new string[] { "https://api.weather.gov/stations/KCCR" };
160160
testResult = await TestApiRequesterHelper(firstUrl, ii, testsFailed, grepper);
161161
ii = testResult[0];
162162
testsFailed = testResult[1];

JsonToolsNppPlugin/Tests/YamlDumperTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ public static bool Test()
5656
new string[] { "\"a \"", "\"a \"\n", "scalar string" },
5757
new string[] { "9", "9\n", "scalar int" },
5858
new string[] { "-940.3", "-940.3\n", "scalar float" },
59-
new string[] { "[true, false]", "- True\n- False\n", "scalar bools" },
59+
new string[] { "[true, false]", "- true\n- false\n", "scalar bools" },
6060
new string[] { "[null, Infinity, -Infinity, NaN]", "- null\n- .inf\n- -.inf\n- .nan\n", "null, +/-infinity, NaN" },
6161
// in the below case, there's actually a bit of an error;
6262
// it is better to dump the float 2.0 as '2.0', but this algorithm dumps it

0 commit comments

Comments
 (0)