smsmslib 1.0.70 → 1.0.72

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.
@@ -11,9 +11,15 @@
11
11
 
12
12
  import
13
13
  {
14
- sj_array_lengthen,
14
+ sj_new_lit,
15
15
  }
16
- from "./array.js";
16
+ from "./new.js";
17
+
18
+ import
19
+ {
20
+ sj_array_new,
21
+ }
22
+ from "./arraynew.js";
17
23
 
18
24
  import
19
25
  {
@@ -23,9 +29,16 @@ from "./arraypush.js";
23
29
 
24
30
  import
25
31
  {
26
- sj_array_new,
32
+ sj_array_lengthen,
27
33
  }
28
- from "./arraynew.js";
34
+ from "./array.js";
35
+
36
+ import
37
+ {
38
+ sj_tree_walk,
39
+ go_tree_walk_ret,
40
+ }
41
+ from "./tree.js";
29
42
 
30
43
 
31
44
  /** ---------------------------------------------------------------------------
@@ -35,41 +48,36 @@ from "./arraynew.js";
35
48
  /**
36
49
  * Creates a multi-dimensional array (matrix) with specified dimensions.
37
50
  * This function constructs a nested array structure based on the provided
38
- * dimension arguments.
51
+ * dimension array.
39
52
  *
40
- * @param {...number} ai_dim [in]
41
- * A variable number of arguments defining the size of each dimension.
42
- * For example, `sj_mat_new(2, 3)` creates a 2x3 matrix. All arguments
53
+ * @param {number[]} ai_dim [in]
54
+ * An array of integers defining the size of each dimension.
55
+ * For example, `sj_mat_new([2, 3], 0)` creates a 2x3 matrix. All elements
43
56
  * must be positive integers.
44
57
  *
58
+ * @param {any} initial [in]
59
+ * The value to fill the deepest level of the newly created array with.
60
+ *
45
61
  * @returns {Array | null}
46
- * A new multi-dimensional array initialized with 0 at the deepest level.
62
+ * A new multi-dimensional array initialized with the `initial` value.
47
63
  * Returns `null` if any dimension is invalid or if allocation fails.
48
64
  *
49
65
  * @see mat_new_init
50
- * @see mat_new_push
51
- * @see mat_new_pop
66
+ * @see mat_new_cb
52
67
  */
53
- export function sj_mat_new(...ai_dim)
68
+ function sj_mat_new(ai_dim, initial)
54
69
  {
55
- let a_mat = null;
56
- const aa_stack = sj_array_new(0);
70
+ let a_root = mat_new_init(ai_dim);
71
+ let a_mat = null;
72
+ const o_user = sj_new_lit(() => ({ai_dim, initial}));
57
73
 
58
- if (aa_stack)
74
+ if (a_root && o_user)
59
75
  {
60
- a_mat = mat_new_init(ai_dim);
61
- }
76
+ const i_ret = sj_tree_walk(mat_new_cb, a_root, o_user);
62
77
 
63
- while (a_mat && (a_mat.length < ai_dim[aa_stack.length]))
64
- {
65
- if (aa_stack.length < (ai_dim.length - 1))
78
+ if (i_ret === go_tree_walk_ret.i_ok)
66
79
  {
67
- a_mat = mat_new_push(aa_stack, a_mat);
68
- }
69
- else
70
- {
71
- sj_array_lengthen(a_mat, ai_dim[aa_stack.length], 0);
72
- a_mat = mat_new_pop(aa_stack, a_mat, ai_dim);
80
+ a_mat = a_root;
73
81
  }
74
82
  }
75
83
 
@@ -93,9 +101,10 @@ export function sj_mat_new(...ai_dim)
93
101
  */
94
102
  function mat_new_init(ai_dim)
95
103
  {
96
- let a_mat = null;
104
+ let a_mat = null;
105
+ const b_array = Array.isArray(ai_dim);
97
106
 
98
- if (0 < ai_dim.length)
107
+ if (b_array && (0 < ai_dim.length))
99
108
  {
100
109
  const b_every_ok =
101
110
  ai_dim.every(i_dim => Number.isInteger(i_dim) && (0 < i_dim));
@@ -111,74 +120,55 @@ function mat_new_init(ai_dim)
111
120
 
112
121
 
113
122
  /**
114
- * Creates a new empty array for a deeper dimension and pushes the current
115
- * array `a_mat` onto the stack.
123
+ * Callback to initialize a multi-dimensional array structure.
116
124
  *
117
- * @param {Array<Array>} aa_stack [in/out]
118
- * A stack used to store parent array references as the construction
119
- * moves to deeper dimensions.
125
+ * @param {array} ao_TreeStack [in, out]
126
+ * The current traversal path (stack of `TreeStack_t`).
127
+ * The callback processes the last element to manage the array's growth.
120
128
  *
121
- * @param {Array} a_mat [in]
122
- * The current array level that will now act as a parent to the
123
- * newly created array.
129
+ * @param {any} from_child [in]
130
+ * Data passed back from a child node to the parent.
124
131
  *
125
- * @returns {Array | null}
126
- * The newly created array instance (the new current level).
127
- * Returns `null` if array creation or pushing fails.
132
+ * @param {object} o_user [in, out]
133
+ * User-defined context containing:
134
+ * - ai_dim : Array of integers defining the size of each dimension.
135
+ * - initial: The initial value used to populate the leaf arrays.
136
+ *
137
+ * @returns {boolean}
138
+ * - true : Successfully processed and continues the traversal.
139
+ * - false: Failed to create a sub-array or lengthen the array.
128
140
  */
129
- function mat_new_push(aa_stack, a_mat)
141
+ function mat_new_cb(ao_TreeStack, from_child, o_user)
130
142
  {
131
- let a_push = sj_array_new(0, 0);
132
-
133
- if (a_push)
134
- {
135
- let i_len = sj_array_push(a_mat, a_push);
143
+ let i_ret;
144
+ let b_continue = true;
145
+ const o_TreeStack = ao_TreeStack.at(- 1);
146
+ const a_node = o_TreeStack.node;
147
+ const i_dim = o_user.ai_dim.at(ao_TreeStack.length - 1);
136
148
 
137
- if (0 < i_len)
138
- {
139
- i_len = sj_array_push(aa_stack, a_mat);
140
- }
149
+ o_TreeStack.child = null;
141
150
 
142
- if (i_len < 1)
151
+ if (ao_TreeStack.length < o_user.ai_dim.length) /* if not leaf */
152
+ {
153
+ if (o_TreeStack.i_child < i_dim)
143
154
  {
144
- a_push = null;
155
+ o_TreeStack.child = sj_array_new(0);
156
+ b_continue = !(!o_TreeStack.child);
157
+
158
+ if (b_continue)
159
+ {
160
+ i_ret = sj_array_push(a_node, o_TreeStack.child);
161
+ b_continue = (0 < i_ret);
162
+ }
145
163
  }
146
164
  }
147
-
148
- return a_push;
149
- }
150
-
151
-
152
- /**
153
- * Pops the stack to find the next available parent level after a_mat
154
- * has been fully populated.
155
- *
156
- * This function repeatedly executes `a_mat = aa_stack.pop()` until the
157
- * condition `a_mat.length < ai_dim[aa_stack.length]` is met, ensuring
158
- * the returned array has space for the next element at its specific depth.
159
- *
160
- * @param {Array<Array>} aa_stack [in/out]
161
- * A stack containing references to the parent arrays of `a_mat`.
162
- *
163
- * @param {Array} a_mat [in]
164
- * The current array level having been populated.
165
- *
166
- * @param {number[]} ai_dim [in]
167
- * An array where `ai_dim[n]` represents the size of the n-th order dimension.
168
- *
169
- * @returns {Array}
170
- * The parent array of `a_mat` that has available capacity.
171
- * Returns `a_mat` as is if no popping was necessary.
172
- */
173
- function mat_new_pop(aa_stack, a_mat, ai_dim)
174
- {
175
- let a_mat_now = a_mat;
176
-
177
- while ((0 < aa_stack.length) && (ai_dim[aa_stack.length] <= a_mat_now.length))
165
+ else /* if leaf */
178
166
  {
179
- a_mat_now = aa_stack.pop();
167
+ i_ret = sj_array_lengthen(a_node, i_dim, o_user.initial);
168
+ b_continue = (0 < i_ret);
180
169
  }
181
170
 
182
- return a_mat_now;
171
+ return b_continue;
183
172
  }
184
173
 
174
+
@@ -0,0 +1,56 @@
1
+ /**
2
+ * @file
3
+ * A collection of factory utilities providing **safe and controlled
4
+ * initialization** for objects, arrays, and other data structures.
5
+ *
6
+ * @module javascr/system/new
7
+ */
8
+
9
+ /** ---------------------------------------------------------------------------
10
+ * Imports.
11
+ * --------------------------------------------------------------------------- */
12
+
13
+ import
14
+ {
15
+ go_typeof,
16
+ }
17
+ from "./type.js";
18
+
19
+
20
+ /** ---------------------------------------------------------------------------
21
+ * Functions.
22
+ * --------------------------------------------------------------------------- */
23
+
24
+ /**
25
+ * Executes a provided initialization function to safely create and return
26
+ * an object (literal).
27
+ *
28
+ * @param {function} f_init [in]
29
+ * A callback function that returns the initial object or data.
30
+ * Must be of type 'function'.
31
+ *
32
+ * @returns {any|null}
33
+ * - The object returned by f_init.
34
+ * - null if f_init is not a function or
35
+ * if an exception was caught during its execution.
36
+ */
37
+ export function sj_new_lit(f_init)
38
+ {
39
+ let o_lit = null;
40
+
41
+ try
42
+ {
43
+ if (typeof(f_init) === go_typeof.s_function)
44
+ {
45
+ o_lit = f_init();
46
+ }
47
+ }
48
+ catch (o_err)
49
+ {
50
+ console.error(`${sj_new_lit.name}: ${o_err.message}`);
51
+ }
52
+
53
+ return o_lit;
54
+ }
55
+
56
+
@@ -0,0 +1,274 @@
1
+ /**
2
+ * @file
3
+ * Provides a non-recursive tree traversal engine.
4
+ *
5
+ * @module javascr/system/tree
6
+ */
7
+
8
+ /** ---------------------------------------------------------------------------
9
+ * Imports.
10
+ * --------------------------------------------------------------------------- */
11
+
12
+ import
13
+ {
14
+ go_typeof,
15
+ }
16
+ from "./type.js";
17
+
18
+ import
19
+ {
20
+ sj_array_push,
21
+ }
22
+ from "./arraypush.js";
23
+
24
+ import
25
+ {
26
+ sj_array_new,
27
+ }
28
+ from "./arraynew.js";
29
+
30
+ import
31
+ {
32
+ sj_new_lit,
33
+ }
34
+ from "./new.js";
35
+
36
+
37
+ /** ---------------------------------------------------------------------------
38
+ * Constants.
39
+ * --------------------------------------------------------------------------- */
40
+
41
+ /**
42
+ * Initial value for the data passed back from a child node to the parent.
43
+ */
44
+ const GI_FROM_CHILD_INI = 0;
45
+
46
+
47
+ /**
48
+ * Return status codes for the tree traversal process.
49
+ *
50
+ * This frozen object defines the possible outcomes and error states
51
+ * returned by the `sj_tree_walk` function and its internal components.
52
+ *
53
+ * @constant
54
+ * @readonly
55
+ * @enum {number}
56
+ */
57
+ export const go_tree_walk_ret = Object.freeze(
58
+ {
59
+ i_ok: 0,
60
+ i_nostack: 1,
61
+ i_stop: 2,
62
+ i_noncb: 3,
63
+ }
64
+ );
65
+
66
+
67
+ /** ---------------------------------------------------------------------------
68
+ * Functions.
69
+ * --------------------------------------------------------------------------- */
70
+
71
+ /**
72
+ * Performs a tree traversal using a stack-based approach.
73
+ *
74
+ * This function initiates a traversal of the tree starting from the `root` node.
75
+ * It manages the traversal state using a stack to avoid recursion depth issues
76
+ * and provides a controlled environment for the user callback.
77
+ *
78
+ * @param {function} f_cb [in]
79
+ * The traversal callback function.
80
+ * It will be called for each node with the following signature:
81
+ * `b_continue = f_cb(ao_TreeStack, from_child, user);`
82
+ * - ao_TreeStack: The current traversal path (stack of `TreeStack_t`).
83
+ * The callback typically processes the last element of this
84
+ * stack (the current node context).
85
+ * - from_child : Data passed back from a child node(initially `GI_FROM_CHILD_INI`).
86
+ * - user : User-defined data.
87
+ * - Returns : true to continue descending/traversing, false to stop.
88
+ *
89
+ * @param {any} root [in]
90
+ * The root node of the tree to start walking from.
91
+ *
92
+ * @param {any} user [in, out]
93
+ * User-defined data passed through to every callback invocation.
94
+ *
95
+ * @returns {number}
96
+ * - go_tree_walk_ret.i_ok : Traversal completed or processed as intended.
97
+ * - go_tree_walk_ret.i_noncb : Provided f_cb is not a function.
98
+ * - go_tree_walk_ret.i_stop : Traversal was explicitly stopped by the callback.
99
+ * - go_tree_walk_ret.i_nostack: Failed to allocate or push to the traversal stack.
100
+ */
101
+ export function sj_tree_walk(f_cb, root, user)
102
+ {
103
+ let i_result;
104
+
105
+ if (typeof(f_cb) === go_typeof.s_function)
106
+ {
107
+ i_result = tree_walk(f_cb, root, user);
108
+ }
109
+ else
110
+ {
111
+ i_result = go_tree_walk_ret.i_noncb;
112
+ }
113
+
114
+ return i_result;
115
+ }
116
+
117
+
118
+ /**
119
+ * The core iterative engine for tree traversal.
120
+ *
121
+ * This function implements a non-recursive tree walk using a stack-based
122
+ * approach to manage depth. It coordinates the descent into child nodes
123
+ * and the ascent back to parent nodes, invoking the user callback at
124
+ * each step.
125
+ *
126
+ * @param {function} f_cb [in]
127
+ * The traversal callback function.
128
+ * @see sj_tree_walk. For the detailed callback prototype and behavior.
129
+ *
130
+ * @param {any} root [in]
131
+ * The root node where the traversal begins.
132
+ *
133
+ * @param {any} user [in, out]
134
+ * User-defined data passed to the callback.
135
+ *
136
+ * @returns {number}
137
+ * - go_tree_walk_ret.i_ok : Traversal completed successfully.
138
+ * - go_tree_walk_ret.i_stop : Traversal was stopped by the callback.
139
+ * - go_tree_walk_ret.i_nostack: Failed to push a node onto the stack.
140
+ */
141
+ function tree_walk(f_cb, root, user)
142
+ {
143
+ let from_child = GI_FROM_CHILD_INI;
144
+ const ao_TreeStack = sj_array_new(0);
145
+ let i_result = ao_TreeStack_push(ao_TreeStack, root);
146
+
147
+ while ((i_result === go_tree_walk_ret.i_ok) && (0 < ao_TreeStack.length))
148
+ {
149
+ let o_TreeStackLast = ao_TreeStack.at(- 1);
150
+
151
+ i_result = tree_walk_cb(f_cb, ao_TreeStack, from_child, user);
152
+
153
+ while ((i_result === go_tree_walk_ret.i_ok) && o_TreeStackLast.child)
154
+ {
155
+ i_result = ao_TreeStack_push(ao_TreeStack, o_TreeStackLast.child); /* Descend */
156
+
157
+ if (i_result === go_tree_walk_ret.i_ok)
158
+ {
159
+ o_TreeStackLast = ao_TreeStack.at(- 1);
160
+ i_result = tree_walk_cb(f_cb, ao_TreeStack, GI_FROM_CHILD_INI, user);
161
+ }
162
+ }
163
+
164
+ from_child = o_TreeStackLast.to_parent;
165
+ ao_TreeStack.pop(); /* Ascend */
166
+ }
167
+
168
+ return i_result;
169
+ }
170
+
171
+
172
+ /**
173
+ * Creates a new stack frame and pushes it onto the traversal stack.
174
+ *
175
+ * @param {array} ao_TreeStack [in, out]
176
+ * The stack of TreeStack_t objects representing the current traversal path.
177
+ *
178
+ * @param {any} node [in]
179
+ * The tree node to be pushed onto the stack.
180
+ *
181
+ * @returns {number}
182
+ * - go_tree_walk_ret.i_ok : Successfully pushed the node onto the stack.
183
+ * - go_tree_walk_ret.i_nostack: Failed to create a stack frame or push it
184
+ */
185
+ function ao_TreeStack_push(ao_TreeStack, node)
186
+ {
187
+ let i_result = go_tree_walk_ret.i_nostack;
188
+ let o_TreeStack = TreeStack_t(node);
189
+
190
+ if (o_TreeStack)
191
+ {
192
+ const i_ret = sj_array_push(ao_TreeStack, o_TreeStack);
193
+
194
+ if (0 < i_ret)
195
+ {
196
+ i_result = go_tree_walk_ret.i_ok;
197
+ }
198
+ }
199
+
200
+ return i_result;
201
+ }
202
+
203
+
204
+ /**
205
+ * Invokes the traversal callback and updates the traversal state.
206
+ *
207
+ * @param {function} f_cb [in]
208
+ * The traversal callback function.
209
+ * @see sj_tree_walk. For the detailed callback prototype and behavior.
210
+ *
211
+ * @param {array} ao_TreeStack [in, out]
212
+ * The stack of TreeStack_t objects representing the current traversal path.
213
+ *
214
+ * @param {any} from_child [in]
215
+ * Information or state passed back from the child node that was just visited.
216
+ *
217
+ * @param {any} user [in, out]
218
+ * User-defined data passed to the callback.
219
+ *
220
+ * @returns {number}
221
+ * - go_tree_walk_ret.i_ok : Continue traversal.
222
+ * - go_tree_walk_ret.i_stop: Stop traversal.
223
+ */
224
+ function tree_walk_cb(f_cb, ao_TreeStack, from_child, user)
225
+ {
226
+ let i_result = go_tree_walk_ret.i_stop;
227
+ const b_continue = f_cb(ao_TreeStack, from_child, user);
228
+ const o_TreeStackLast = ao_TreeStack.at(- 1);
229
+
230
+ ++(o_TreeStackLast.i_child);
231
+
232
+ if (b_continue) /* If continue */
233
+ {
234
+ i_result = go_tree_walk_ret.i_ok;
235
+ }
236
+
237
+ return i_result;
238
+ }
239
+
240
+
241
+ /**
242
+ * Creates a new stack frame object for tree traversal.
243
+ *
244
+ * @param {any} node [in]
245
+ * The tree node to be contained in a new stack frame object.
246
+ *
247
+ * @returns {object|null}
248
+ * A literal object containing:
249
+ * - node : node.
250
+ * The tree node specified.
251
+ * Its child node, if any, will be assigned to `child`.
252
+ *
253
+ * - child : null.
254
+ * The i_child-th child node being visited.
255
+ *
256
+ * - i_child : 0.
257
+ * 0-based index of the child node.
258
+ *
259
+ * - to_parent: GI_FROM_CHILD_INI.
260
+ * Information or state to be passed back to the parent node.
261
+ *
262
+ * Returns null if object creation fails.
263
+ */
264
+ function TreeStack_t(node)
265
+ {
266
+ const child = null;
267
+ const i_child = 0;
268
+ const to_parent = GI_FROM_CHILD_INI;
269
+
270
+ const o_lit = sj_new_lit(() => ({node, child, i_child, to_parent}));
271
+ return o_lit;
272
+ }
273
+
274
+
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "smsmslib",
3
- "version": "1.0.70",
3
+ "version": "1.0.72",
4
4
  "description": "Reusable functions for me.",
5
5
  "files": [
6
6
  "javascr/**/*.js",
@@ -19,6 +19,6 @@
19
19
  "author": "",
20
20
  "license": "ISC",
21
21
  "dependencies": {
22
- "smsmslib": "^1.0.70"
22
+ "smsmslib": "^1.0.72"
23
23
  }
24
24
  }