cobolx-2 1.2.3 → 1.2.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.
- package/examples/math-calculations.cbx +128 -0
- package/examples/string-processing.cbx +105 -0
- package/package.json +1 -1
- package/runtime/src/date_utils.ts +400 -0
- package/runtime/src/file_utils.ts +414 -0
- package/runtime/src/index.ts +19 -0
- package/runtime/src/math_utils.ts +316 -0
- package/runtime/src/string_utils.ts +307 -0
|
@@ -0,0 +1,316 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* COBOL-X Standard Library — Math Built-in Functions
|
|
3
|
+
*
|
|
4
|
+
* Provides COBOL-style mathematical operations that extend the standard
|
|
5
|
+
* COMPUTE verb with advanced numerical functions. All functions operate
|
|
6
|
+
* on numeric (PIC 9 / PIC S9V9) values and return numbers.
|
|
7
|
+
*
|
|
8
|
+
* COBOL traditionally provides FUNCTION SQRT, FUNCTION ABS, etc.
|
|
9
|
+
* This module provides a comprehensive set with consistent error handling.
|
|
10
|
+
*
|
|
11
|
+
* @module math_utils
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* COMPUTE-POWER — Raises a base number to a specified exponent.
|
|
16
|
+
*
|
|
17
|
+
* COBOL equivalent: base ** exponent (COBOL 2002+), or manual multiplication.
|
|
18
|
+
*
|
|
19
|
+
* @param base - The base number.
|
|
20
|
+
* @param exponent - The exponent (must be non-negative for integer bases).
|
|
21
|
+
* @returns The result of base raised to the power of exponent.
|
|
22
|
+
* @throws {Error} If base is negative and exponent is not an integer.
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* COMPUTE_POWER(2, 10) // => 1024
|
|
26
|
+
* COMPUTE_POWER(3, 3) // => 27
|
|
27
|
+
* COMPUTE_POWER(9, 0.5) // => 3
|
|
28
|
+
*/
|
|
29
|
+
export function COMPUTE_POWER(base: number, exponent: number): number {
|
|
30
|
+
if (typeof base !== "number" || typeof exponent !== "number") {
|
|
31
|
+
throw new Error(
|
|
32
|
+
`COMPUTE-POWER: expected PIC 9 for both arguments, received ${typeof base} and ${typeof exponent}`
|
|
33
|
+
);
|
|
34
|
+
}
|
|
35
|
+
if (base < 0 && !Number.isInteger(exponent)) {
|
|
36
|
+
throw new Error(
|
|
37
|
+
`COMPUTE-POWER: negative base ${base} with non-integer exponent ${exponent} produces NaN`
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
return Math.pow(base, exponent);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* COMPUTE-SQRT — Computes the square root of a number.
|
|
45
|
+
*
|
|
46
|
+
* COBOL equivalent: FUNCTION SQRT.
|
|
47
|
+
*
|
|
48
|
+
* @param value - The numeric value (must be non-negative).
|
|
49
|
+
* @returns The square root of the value.
|
|
50
|
+
* @throws {Error} If the value is negative or not a number.
|
|
51
|
+
*
|
|
52
|
+
* @example
|
|
53
|
+
* COMPUTE_SQRT(144) // => 12
|
|
54
|
+
* COMPUTE_SQRT(2) // => 1.4142135623730951
|
|
55
|
+
*/
|
|
56
|
+
export function COMPUTE_SQRT(value: number): number {
|
|
57
|
+
if (typeof value !== "number") {
|
|
58
|
+
throw new Error(`COMPUTE-SQRT: expected PIC 9, received ${typeof value}`);
|
|
59
|
+
}
|
|
60
|
+
if (value < 0) {
|
|
61
|
+
throw new Error(`COMPUTE-SQRT: argument must be non-negative, received ${value}`);
|
|
62
|
+
}
|
|
63
|
+
return Math.sqrt(value);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* COMPUTE-ABS — Returns the absolute value of a number.
|
|
68
|
+
*
|
|
69
|
+
* COBOL equivalent: FUNCTION ABS.
|
|
70
|
+
*
|
|
71
|
+
* @param value - The numeric value.
|
|
72
|
+
* @returns The absolute (non-negative) value.
|
|
73
|
+
* @throws {Error} If the value is not a number.
|
|
74
|
+
*
|
|
75
|
+
* @example
|
|
76
|
+
* COMPUTE_ABS(-42) // => 42
|
|
77
|
+
* COMPUTE_ABS(42) // => 42
|
|
78
|
+
* COMPUTE_ABS(0) // => 0
|
|
79
|
+
*/
|
|
80
|
+
export function COMPUTE_ABS(value: number): number {
|
|
81
|
+
if (typeof value !== "number") {
|
|
82
|
+
throw new Error(`COMPUTE-ABS: expected PIC 9, received ${typeof value}`);
|
|
83
|
+
}
|
|
84
|
+
return Math.abs(value);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* COMPUTE-MOD — Computes the remainder of division (modulo operation).
|
|
89
|
+
*
|
|
90
|
+
* COBOL equivalent: result = dividend / divisor with REMAINDER.
|
|
91
|
+
* Unlike JavaScript's % operator, this always returns a non-negative
|
|
92
|
+
* result when the divisor is positive, matching COBOL's REM behavior.
|
|
93
|
+
*
|
|
94
|
+
* @param dividend - The number to be divided.
|
|
95
|
+
* @param divisor - The number to divide by (must not be zero).
|
|
96
|
+
* @returns The remainder of the division.
|
|
97
|
+
* @throws {Error} If either argument is not a number, or divisor is zero.
|
|
98
|
+
*
|
|
99
|
+
* @example
|
|
100
|
+
* COMPUTE_MOD(17, 5) // => 2
|
|
101
|
+
* COMPUTE_MOD(20, 4) // => 0
|
|
102
|
+
* COMPUTE_MOD(-7, 3) // => 2 (COBOL-style, always non-negative)
|
|
103
|
+
*/
|
|
104
|
+
export function COMPUTE_MOD(dividend: number, divisor: number): number {
|
|
105
|
+
if (typeof dividend !== "number" || typeof divisor !== "number") {
|
|
106
|
+
throw new Error(
|
|
107
|
+
`COMPUTE-MOD: expected PIC 9 for both arguments, received ${typeof dividend} and ${typeof divisor}`
|
|
108
|
+
);
|
|
109
|
+
}
|
|
110
|
+
if (divisor === 0) {
|
|
111
|
+
throw new Error("COMPUTE-MOD: division by zero — divisor must not be zero");
|
|
112
|
+
}
|
|
113
|
+
// COBOL-style: remainder is always non-negative when divisor is positive
|
|
114
|
+
const remainder = dividend % divisor;
|
|
115
|
+
return remainder < 0 ? remainder + Math.abs(divisor) : remainder;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* COMPUTE-MIN — Returns the smallest of the given numeric values.
|
|
120
|
+
*
|
|
121
|
+
* COBOL equivalent: FUNCTION MIN.
|
|
122
|
+
*
|
|
123
|
+
* @param values - Array of numeric values to compare.
|
|
124
|
+
* @returns The smallest value.
|
|
125
|
+
* @throws {Error} If values array is empty or contains non-numeric elements.
|
|
126
|
+
*
|
|
127
|
+
* @example
|
|
128
|
+
* COMPUTE_MIN([3, 1, 4, 1, 5]) // => 1
|
|
129
|
+
* COMPUTE_MIN([-10, 0, 10]) // => -10
|
|
130
|
+
*/
|
|
131
|
+
export function COMPUTE_MIN(values: number[]): number {
|
|
132
|
+
if (!Array.isArray(values) || values.length === 0) {
|
|
133
|
+
throw new Error("COMPUTE-MIN: values array must not be empty");
|
|
134
|
+
}
|
|
135
|
+
for (let i = 0; i < values.length; i++) {
|
|
136
|
+
if (typeof values[i] !== "number" || Number.isNaN(values[i])) {
|
|
137
|
+
throw new Error(
|
|
138
|
+
`COMPUTE-MIN: element at index ${i} is not a valid PIC 9 (received ${values[i]})`
|
|
139
|
+
);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
return Math.min(...values);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* COMPUTE-MAX — Returns the largest of the given numeric values.
|
|
147
|
+
*
|
|
148
|
+
* COBOL equivalent: FUNCTION MAX.
|
|
149
|
+
*
|
|
150
|
+
* @param values - Array of numeric values to compare.
|
|
151
|
+
* @returns The largest value.
|
|
152
|
+
* @throws {Error} If values array is empty or contains non-numeric elements.
|
|
153
|
+
*
|
|
154
|
+
* @example
|
|
155
|
+
* COMPUTE_MAX([3, 1, 4, 1, 5]) // => 5
|
|
156
|
+
* COMPUTE_MAX([-10, 0, 10]) // => 10
|
|
157
|
+
*/
|
|
158
|
+
export function COMPUTE_MAX(values: number[]): number {
|
|
159
|
+
if (!Array.isArray(values) || values.length === 0) {
|
|
160
|
+
throw new Error("COMPUTE-MAX: values array must not be empty");
|
|
161
|
+
}
|
|
162
|
+
for (let i = 0; i < values.length; i++) {
|
|
163
|
+
if (typeof values[i] !== "number" || Number.isNaN(values[i])) {
|
|
164
|
+
throw new Error(
|
|
165
|
+
`COMPUTE-MAX: element at index ${i} is not a valid PIC 9 (received ${values[i]})`
|
|
166
|
+
);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
return Math.max(...values);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* COMPUTE-ROUND — Rounds a number to a specified number of decimal places.
|
|
174
|
+
*
|
|
175
|
+
* COBOL equivalent: ROUNDED MODE IS NEAREST-AWAY-FROM-ZERO on COMPUTE.
|
|
176
|
+
* Uses "round half away from zero" (banker's rounding), which is the
|
|
177
|
+
* standard COBOL ROUNDED behavior.
|
|
178
|
+
*
|
|
179
|
+
* @param value - The numeric value to round.
|
|
180
|
+
* @param decimalPlaces - The number of decimal places (default: 0).
|
|
181
|
+
* @returns The rounded number.
|
|
182
|
+
* @throws {Error} If arguments are invalid.
|
|
183
|
+
*
|
|
184
|
+
* @example
|
|
185
|
+
* COMPUTE_ROUND(3.456, 2) // => 3.46
|
|
186
|
+
* COMPUTE_ROUND(3.454, 2) // => 3.45
|
|
187
|
+
* COMPUTE_ROUND(2.5, 0) // => 3
|
|
188
|
+
* COMPUTE_ROUND(-2.5, 0) // => -3
|
|
189
|
+
*/
|
|
190
|
+
export function COMPUTE_ROUND(value: number, decimalPlaces: number = 0): number {
|
|
191
|
+
if (typeof value !== "number") {
|
|
192
|
+
throw new Error(`COMPUTE-ROUND: expected PIC 9 for value, received ${typeof value}`);
|
|
193
|
+
}
|
|
194
|
+
if (!Number.isInteger(decimalPlaces) || decimalPlaces < 0) {
|
|
195
|
+
throw new Error(
|
|
196
|
+
`COMPUTE-ROUND: decimalPlaces must be a non-negative integer, received ${decimalPlaces}`
|
|
197
|
+
);
|
|
198
|
+
}
|
|
199
|
+
// COBOL "round half away from zero" behavior
|
|
200
|
+
const factor = Math.pow(10, decimalPlaces);
|
|
201
|
+
const shifted = value * factor;
|
|
202
|
+
// Use Math.sign to handle negative numbers correctly (away from zero)
|
|
203
|
+
return (Math.sign(shifted) * Math.round(Math.abs(shifted))) / factor;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* COMPUTE-FLOOR — Returns the largest integer less than or equal to a number.
|
|
208
|
+
*
|
|
209
|
+
* COBOL equivalent: FUNCTION INTEGER when value is positive.
|
|
210
|
+
*
|
|
211
|
+
* @param value - The numeric value.
|
|
212
|
+
* @returns The floor of the value.
|
|
213
|
+
* @throws {Error} If the value is not a number.
|
|
214
|
+
*
|
|
215
|
+
* @example
|
|
216
|
+
* COMPUTE_FLOOR(3.7) // => 3
|
|
217
|
+
* COMPUTE_FLOOR(-3.2) // => -4
|
|
218
|
+
* COMPUTE_FLOOR(5) // => 5
|
|
219
|
+
*/
|
|
220
|
+
export function COMPUTE_FLOOR(value: number): number {
|
|
221
|
+
if (typeof value !== "number") {
|
|
222
|
+
throw new Error(`COMPUTE-FLOOR: expected PIC 9, received ${typeof value}`);
|
|
223
|
+
}
|
|
224
|
+
return Math.floor(value);
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
/**
|
|
228
|
+
* COMPUTE-CEIL — Returns the smallest integer greater than or equal to a number.
|
|
229
|
+
*
|
|
230
|
+
* COBOL equivalent: FUNCTION INTEGER-PART + 1 when value has a fraction.
|
|
231
|
+
*
|
|
232
|
+
* @param value - The numeric value.
|
|
233
|
+
* @returns The ceiling of the value.
|
|
234
|
+
* @throws {Error} If the value is not a number.
|
|
235
|
+
*
|
|
236
|
+
* @example
|
|
237
|
+
* COMPUTE_CEIL(3.2) // => 4
|
|
238
|
+
* COMPUTE_CEIL(-3.7) // => -3
|
|
239
|
+
* COMPUTE_CEIL(5) // => 5
|
|
240
|
+
*/
|
|
241
|
+
export function COMPUTE_CEIL(value: number): number {
|
|
242
|
+
if (typeof value !== "number") {
|
|
243
|
+
throw new Error(`COMPUTE-CEIL: expected PIC 9, received ${typeof value}`);
|
|
244
|
+
}
|
|
245
|
+
return Math.ceil(value);
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
/**
|
|
249
|
+
* COMPUTE-SIGN — Determines the sign of a number.
|
|
250
|
+
*
|
|
251
|
+
* Returns -1, 0, or 1 depending on whether the value is negative, zero, or positive.
|
|
252
|
+
*
|
|
253
|
+
* @param value - The numeric value to test.
|
|
254
|
+
* @returns -1 if negative, 0 if zero, 1 if positive.
|
|
255
|
+
* @throws {Error} If the value is not a number.
|
|
256
|
+
*
|
|
257
|
+
* @example
|
|
258
|
+
* COMPUTE_SIGN(-42) // => -1
|
|
259
|
+
* COMPUTE_SIGN(0) // => 0
|
|
260
|
+
* COMPUTE_SIGN(42) // => 1
|
|
261
|
+
*/
|
|
262
|
+
export function COMPUTE_SIGN(value: number): -1 | 0 | 1 {
|
|
263
|
+
if (typeof value !== "number") {
|
|
264
|
+
throw new Error(`COMPUTE-SIGN: expected PIC 9, received ${typeof value}`);
|
|
265
|
+
}
|
|
266
|
+
if (value < 0) return -1;
|
|
267
|
+
if (value > 0) return 1;
|
|
268
|
+
return 0;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
/**
|
|
272
|
+
* COMPUTE-CLAMP — Restricts a value to be within a specified range.
|
|
273
|
+
*
|
|
274
|
+
* Useful for ensuring values stay within COBOL PIC bounds.
|
|
275
|
+
*
|
|
276
|
+
* @param value - The numeric value to clamp.
|
|
277
|
+
* @param min - The minimum allowed value.
|
|
278
|
+
* @param max - The maximum allowed value.
|
|
279
|
+
* @returns The value clamped to [min, max].
|
|
280
|
+
* @throws {Error} If arguments are invalid or min > max.
|
|
281
|
+
*
|
|
282
|
+
* @example
|
|
283
|
+
* COMPUTE_CLAMP(15, 0, 10) // => 10
|
|
284
|
+
* COMPUTE_CLAMP(-5, 0, 10) // => 0
|
|
285
|
+
* COMPUTE_CLAMP(5, 0, 10) // => 5
|
|
286
|
+
*/
|
|
287
|
+
export function COMPUTE_CLAMP(value: number, min: number, max: number): number {
|
|
288
|
+
if (typeof value !== "number" || typeof min !== "number" || typeof max !== "number") {
|
|
289
|
+
throw new Error("COMPUTE-CLAMP: all arguments must be PIC 9");
|
|
290
|
+
}
|
|
291
|
+
if (min > max) {
|
|
292
|
+
throw new Error(`COMPUTE-CLAMP: min (${min}) must not exceed max (${max})`);
|
|
293
|
+
}
|
|
294
|
+
return Math.max(min, Math.min(max, value));
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
/**
|
|
298
|
+
* COMPUTE-PERCENTAGE — Calculates a percentage of a value.
|
|
299
|
+
*
|
|
300
|
+
* Common business computation in COBOL programs.
|
|
301
|
+
*
|
|
302
|
+
* @param value - The base value.
|
|
303
|
+
* @param percentage - The percentage (e.g., 25 for 25%).
|
|
304
|
+
* @returns The calculated percentage of the value.
|
|
305
|
+
* @throws {Error} If arguments are not numbers.
|
|
306
|
+
*
|
|
307
|
+
* @example
|
|
308
|
+
* COMPUTE_PERCENTAGE(200, 15) // => 30
|
|
309
|
+
* COMPUTE_PERCENTAGE(100, 0.5) // => 0.5
|
|
310
|
+
*/
|
|
311
|
+
export function COMPUTE_PERCENTAGE(value: number, percentage: number): number {
|
|
312
|
+
if (typeof value !== "number" || typeof percentage !== "number") {
|
|
313
|
+
throw new Error("COMPUTE-PERCENTAGE: all arguments must be PIC 9");
|
|
314
|
+
}
|
|
315
|
+
return (value * percentage) / 100;
|
|
316
|
+
}
|
|
@@ -0,0 +1,307 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* COBOL-X Standard Library — String Handling Built-in Functions
|
|
3
|
+
*
|
|
4
|
+
* Provides COBOL-style string manipulation utilities that mirror
|
|
5
|
+
* classic COBOL STRING/UNSTRING operations while offering modern
|
|
6
|
+
* conveniences. All functions accept and return PIC X (string) values
|
|
7
|
+
* and follow COBOL naming conventions.
|
|
8
|
+
*
|
|
9
|
+
* @module string_utils
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* STRING-REVERSE — Reverses the characters in the given string.
|
|
14
|
+
*
|
|
15
|
+
* COBOL equivalent: Manual INSPECT TALLYING/REPLACING loop.
|
|
16
|
+
*
|
|
17
|
+
* @param value - The alphanumeric string to reverse.
|
|
18
|
+
* @returns The reversed string.
|
|
19
|
+
* @throws {Error} If the input is not a string.
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* STRING_REVERSE("HELLO WORLD") // => "DLROW OLLEH"
|
|
23
|
+
*/
|
|
24
|
+
export function STRING_REVERSE(value: string): string {
|
|
25
|
+
if (typeof value !== "string") {
|
|
26
|
+
throw new Error(`STRING-REVERSE: expected PIC X, received ${typeof value}`);
|
|
27
|
+
}
|
|
28
|
+
return value.split("").reverse().join("");
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* STRING-UPPER — Converts all alphabetic characters in the string to uppercase.
|
|
33
|
+
*
|
|
34
|
+
* COBOL equivalent: FUNCTION UPPER-CASE.
|
|
35
|
+
*
|
|
36
|
+
* @param value - The alphanumeric string to convert.
|
|
37
|
+
* @returns The uppercase version of the string.
|
|
38
|
+
* @throws {Error} If the input is not a string.
|
|
39
|
+
*
|
|
40
|
+
* @example
|
|
41
|
+
* STRING_UPPER("Hello World") // => "HELLO WORLD"
|
|
42
|
+
*/
|
|
43
|
+
export function STRING_UPPER(value: string): string {
|
|
44
|
+
if (typeof value !== "string") {
|
|
45
|
+
throw new Error(`STRING-UPPER: expected PIC X, received ${typeof value}`);
|
|
46
|
+
}
|
|
47
|
+
return value.toUpperCase();
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* STRING-LOWER — Converts all alphabetic characters in the string to lowercase.
|
|
52
|
+
*
|
|
53
|
+
* COBOL equivalent: FUNCTION LOWER-CASE.
|
|
54
|
+
*
|
|
55
|
+
* @param value - The alphanumeric string to convert.
|
|
56
|
+
* @returns The lowercase version of the string.
|
|
57
|
+
* @throws {Error} If the input is not a string.
|
|
58
|
+
*
|
|
59
|
+
* @example
|
|
60
|
+
* STRING_LOWER("Hello World") // => "hello world"
|
|
61
|
+
*/
|
|
62
|
+
export function STRING_LOWER(value: string): string {
|
|
63
|
+
if (typeof value !== "string") {
|
|
64
|
+
throw new Error(`STRING-LOWER: expected PIC X, received ${typeof value}`);
|
|
65
|
+
}
|
|
66
|
+
return value.toLowerCase();
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* STRING-TRIM — Removes leading and trailing whitespace from the string.
|
|
71
|
+
*
|
|
72
|
+
* In COBOL, fields are fixed-width so trailing spaces are normal.
|
|
73
|
+
* This utility trims both leading and trailing spaces, which is useful
|
|
74
|
+
* when interfacing with non-COBOL systems.
|
|
75
|
+
*
|
|
76
|
+
* @param value - The alphanumeric string to trim.
|
|
77
|
+
* @param mode - Trim mode: "BOTH" (default), "LEADING", or "TRAILING".
|
|
78
|
+
* @returns The trimmed string.
|
|
79
|
+
* @throws {Error} If the input is not a string or mode is invalid.
|
|
80
|
+
*
|
|
81
|
+
* @example
|
|
82
|
+
* STRING_TRIM(" HELLO ") // => "HELLO"
|
|
83
|
+
* STRING_TRIM(" HELLO ", "LEADING") // => "HELLO "
|
|
84
|
+
* STRING_TRIM(" HELLO ", "TRAILING") // => " HELLO"
|
|
85
|
+
*/
|
|
86
|
+
export function STRING_TRIM(value: string, mode: "BOTH" | "LEADING" | "TRAILING" = "BOTH"): string {
|
|
87
|
+
if (typeof value !== "string") {
|
|
88
|
+
throw new Error(`STRING-TRIM: expected PIC X, received ${typeof value}`);
|
|
89
|
+
}
|
|
90
|
+
const validModes = ["BOTH", "LEADING", "TRAILING"];
|
|
91
|
+
if (!validModes.includes(mode)) {
|
|
92
|
+
throw new Error(`STRING-TRIM: invalid mode '${mode}', expected one of ${validModes.join(", ")}`);
|
|
93
|
+
}
|
|
94
|
+
switch (mode) {
|
|
95
|
+
case "LEADING":
|
|
96
|
+
return value.replace(/^\s+/, "");
|
|
97
|
+
case "TRAILING":
|
|
98
|
+
return value.replace(/\s+$/, "");
|
|
99
|
+
case "BOTH":
|
|
100
|
+
default:
|
|
101
|
+
return value.trim();
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* STRING-SPLIT — Splits a string into an array of substrings using a delimiter.
|
|
107
|
+
*
|
|
108
|
+
* COBOL equivalent: UNSTRING ... DELIMITED BY ...
|
|
109
|
+
*
|
|
110
|
+
* @param value - The alphanumeric string to split.
|
|
111
|
+
* @param delimiter - The delimiter character or string.
|
|
112
|
+
* @returns An array of substrings.
|
|
113
|
+
* @throws {Error} If the input is not a string or delimiter is not a string.
|
|
114
|
+
*
|
|
115
|
+
* @example
|
|
116
|
+
* STRING_SPLIT("A,B,C", ",") // => ["A", "B", "C"]
|
|
117
|
+
* STRING_SPLIT("KEY=VALUE", "=") // => ["KEY", "VALUE"]
|
|
118
|
+
*/
|
|
119
|
+
export function STRING_SPLIT(value: string, delimiter: string): string[] {
|
|
120
|
+
if (typeof value !== "string") {
|
|
121
|
+
throw new Error(`STRING-SPLIT: expected PIC X for value, received ${typeof value}`);
|
|
122
|
+
}
|
|
123
|
+
if (typeof delimiter !== "string") {
|
|
124
|
+
throw new Error(`STRING-SPLIT: expected PIC X for delimiter, received ${typeof delimiter}`);
|
|
125
|
+
}
|
|
126
|
+
if (delimiter === "") {
|
|
127
|
+
throw new Error("STRING-SPLIT: delimiter must not be empty");
|
|
128
|
+
}
|
|
129
|
+
return value.split(delimiter);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* STRING-JOIN — Joins an array of strings into a single string using a separator.
|
|
134
|
+
*
|
|
135
|
+
* COBOL equivalent: STRING ... DELIMITED BY ... INTO ...
|
|
136
|
+
*
|
|
137
|
+
* @param items - Array of strings to join.
|
|
138
|
+
* @param separator - The separator string to insert between items.
|
|
139
|
+
* @returns The joined string.
|
|
140
|
+
* @throws {Error} If items is not an array or contains non-string elements.
|
|
141
|
+
*
|
|
142
|
+
* @example
|
|
143
|
+
* STRING_JOIN(["A", "B", "C"], ", ") // => "A, B, C"
|
|
144
|
+
* STRING_JOIN(["LINE1", "LINE2"], "\n") // => "LINE1\nLINE2"
|
|
145
|
+
*/
|
|
146
|
+
export function STRING_JOIN(items: string[], separator: string): string {
|
|
147
|
+
if (!Array.isArray(items)) {
|
|
148
|
+
throw new Error(`STRING-JOIN: expected array of PIC X, received ${typeof items}`);
|
|
149
|
+
}
|
|
150
|
+
if (typeof separator !== "string") {
|
|
151
|
+
throw new Error(`STRING-JOIN: expected PIC X for separator, received ${typeof separator}`);
|
|
152
|
+
}
|
|
153
|
+
for (let i = 0; i < items.length; i++) {
|
|
154
|
+
if (typeof items[i] !== "string") {
|
|
155
|
+
throw new Error(
|
|
156
|
+
`STRING-JOIN: element at index ${i} is not PIC X (received ${typeof items[i]})`
|
|
157
|
+
);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
return items.join(separator);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* STRING-REPLACE — Replaces all occurrences of a search string within the target.
|
|
165
|
+
*
|
|
166
|
+
* COBOL equivalent: INSPECT ... REPLACING ALL ...
|
|
167
|
+
*
|
|
168
|
+
* @param value - The original string.
|
|
169
|
+
* @param search - The substring to search for.
|
|
170
|
+
* @param replacement - The replacement string.
|
|
171
|
+
* @returns The string with all occurrences replaced.
|
|
172
|
+
* @throws {Error} If any argument is not a string, or if search is empty.
|
|
173
|
+
*
|
|
174
|
+
* @example
|
|
175
|
+
* STRING_REPLACE("Hello World", "World", "COBOL-X") // => "Hello COBOL-X"
|
|
176
|
+
* STRING_REPLACE("aaa", "a", "bb") // => "bbbbbb"
|
|
177
|
+
*/
|
|
178
|
+
export function STRING_REPLACE(value: string, search: string, replacement: string): string {
|
|
179
|
+
if (typeof value !== "string") {
|
|
180
|
+
throw new Error(`STRING-REPLACE: expected PIC X for value, received ${typeof value}`);
|
|
181
|
+
}
|
|
182
|
+
if (typeof search !== "string") {
|
|
183
|
+
throw new Error(`STRING-REPLACE: expected PIC X for search, received ${typeof search}`);
|
|
184
|
+
}
|
|
185
|
+
if (typeof replacement !== "string") {
|
|
186
|
+
throw new Error(`STRING-REPLACE: expected PIC X for replacement, received ${typeof replacement}`);
|
|
187
|
+
}
|
|
188
|
+
if (search === "") {
|
|
189
|
+
throw new Error("STRING-REPLACE: search string must not be empty");
|
|
190
|
+
}
|
|
191
|
+
return value.split(search).join(replacement);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
/**
|
|
195
|
+
* STRING-CONTAINS — Checks whether the target string contains the specified substring.
|
|
196
|
+
*
|
|
197
|
+
* COBOL equivalent: INSPECT ... TALLYING ... FOR LEADING/ALL ...
|
|
198
|
+
*
|
|
199
|
+
* @param value - The string to search within.
|
|
200
|
+
* @param search - The substring to look for.
|
|
201
|
+
* @returns 1 (true) if found, 0 (false) otherwise. Returns COBOL-style boolean.
|
|
202
|
+
* @throws {Error} If any argument is not a string.
|
|
203
|
+
*
|
|
204
|
+
* @example
|
|
205
|
+
* STRING_CONTAINS("Hello World", "World") // => 1
|
|
206
|
+
* STRING_CONTAINS("Hello World", "xyz") // => 0
|
|
207
|
+
*/
|
|
208
|
+
export function STRING_CONTAINS(value: string, search: string): 0 | 1 {
|
|
209
|
+
if (typeof value !== "string") {
|
|
210
|
+
throw new Error(`STRING-CONTAINS: expected PIC X for value, received ${typeof value}`);
|
|
211
|
+
}
|
|
212
|
+
if (typeof search !== "string") {
|
|
213
|
+
throw new Error(`STRING-CONTAINS: expected PIC X for search, received ${typeof search}`);
|
|
214
|
+
}
|
|
215
|
+
return value.includes(search) ? 1 : 0;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* STRING-LENGTH — Returns the length of the given string.
|
|
220
|
+
*
|
|
221
|
+
* COBOL equivalent: FUNCTION LENGTH.
|
|
222
|
+
*
|
|
223
|
+
* @param value - The string whose length is to be determined.
|
|
224
|
+
* @returns The number of characters in the string.
|
|
225
|
+
* @throws {Error} If the input is not a string.
|
|
226
|
+
*
|
|
227
|
+
* @example
|
|
228
|
+
* STRING_LENGTH("HELLO") // => 5
|
|
229
|
+
* STRING_LENGTH("") // => 0
|
|
230
|
+
*/
|
|
231
|
+
export function STRING_LENGTH(value: string): number {
|
|
232
|
+
if (typeof value !== "string") {
|
|
233
|
+
throw new Error(`STRING-LENGTH: expected PIC X, received ${typeof value}`);
|
|
234
|
+
}
|
|
235
|
+
return value.length;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
/**
|
|
239
|
+
* STRING-SUBSTRING — Extracts a portion of the string.
|
|
240
|
+
*
|
|
241
|
+
* COBOL equivalent: reference-modification (e.g., STRING(1:5)).
|
|
242
|
+
*
|
|
243
|
+
* @param value - The source string.
|
|
244
|
+
* @param start - The 1-based starting position.
|
|
245
|
+
* @param length - The number of characters to extract.
|
|
246
|
+
* @returns The extracted substring.
|
|
247
|
+
* @throws {Error} If arguments are invalid or out of range.
|
|
248
|
+
*
|
|
249
|
+
* @example
|
|
250
|
+
* STRING_SUBSTRING("HELLO WORLD", 1, 5) // => "HELLO"
|
|
251
|
+
* STRING_SUBSTRING("HELLO WORLD", 7, 5) // => "WORLD"
|
|
252
|
+
*/
|
|
253
|
+
export function STRING_SUBSTRING(value: string, start: number, length: number): string {
|
|
254
|
+
if (typeof value !== "string") {
|
|
255
|
+
throw new Error(`STRING-SUBSTRING: expected PIC X, received ${typeof value}`);
|
|
256
|
+
}
|
|
257
|
+
if (!Number.isInteger(start) || start < 1) {
|
|
258
|
+
throw new Error(`STRING-SUBSTRING: start position must be a positive integer, received ${start}`);
|
|
259
|
+
}
|
|
260
|
+
if (!Number.isInteger(length) || length < 0) {
|
|
261
|
+
throw new Error(`STRING-SUBSTRING: length must be a non-negative integer, received ${length}`);
|
|
262
|
+
}
|
|
263
|
+
if (start - 1 >= value.length) {
|
|
264
|
+
throw new Error(
|
|
265
|
+
`STRING-SUBSTRING: start position ${start} exceeds string length ${value.length}`
|
|
266
|
+
);
|
|
267
|
+
}
|
|
268
|
+
return value.substring(start - 1, start - 1 + length);
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
/**
|
|
272
|
+
* STRING-PAD — Pads a string to a target length.
|
|
273
|
+
*
|
|
274
|
+
* COBOL equivalent: MOVE SPACES TO or manual padding with STRING.
|
|
275
|
+
*
|
|
276
|
+
* @param value - The source string.
|
|
277
|
+
* @param targetLength - The desired total length.
|
|
278
|
+
* @param padChar - The character to pad with (default: space).
|
|
279
|
+
* @param mode - "RIGHT" (default) or "LEFT".
|
|
280
|
+
* @returns The padded string.
|
|
281
|
+
* @throws {Error} If arguments are invalid.
|
|
282
|
+
*
|
|
283
|
+
* @example
|
|
284
|
+
* STRING_PAD("ABC", 10) // => "ABC "
|
|
285
|
+
* STRING_PAD("123", 8, "0", "LEFT") // => "00000123"
|
|
286
|
+
*/
|
|
287
|
+
export function STRING_PAD(
|
|
288
|
+
value: string,
|
|
289
|
+
targetLength: number,
|
|
290
|
+
padChar: string = " ",
|
|
291
|
+
mode: "RIGHT" | "LEFT" = "RIGHT"
|
|
292
|
+
): string {
|
|
293
|
+
if (typeof value !== "string") {
|
|
294
|
+
throw new Error(`STRING-PAD: expected PIC X for value, received ${typeof value}`);
|
|
295
|
+
}
|
|
296
|
+
if (typeof padChar !== "string" || padChar.length !== 1) {
|
|
297
|
+
throw new Error(`STRING-PAD: padChar must be a single character, received '${padChar}'`);
|
|
298
|
+
}
|
|
299
|
+
if (!Number.isInteger(targetLength) || targetLength < 0) {
|
|
300
|
+
throw new Error(`STRING-PAD: targetLength must be a non-negative integer, received ${targetLength}`);
|
|
301
|
+
}
|
|
302
|
+
if (value.length >= targetLength) {
|
|
303
|
+
return value.substring(0, targetLength);
|
|
304
|
+
}
|
|
305
|
+
const padding = padChar.repeat(targetLength - value.length);
|
|
306
|
+
return mode === "LEFT" ? padding + value : value + padding;
|
|
307
|
+
}
|