@carbonenginejs/runtime-utils 0.1.0

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.
Files changed (101) hide show
  1. package/LICENSE +21 -0
  2. package/NOTICE +23 -0
  3. package/README.md +56 -0
  4. package/THIRD-PARTY-NOTICES.md +38 -0
  5. package/docs/README.md +81 -0
  6. package/docs/architecture.md +101 -0
  7. package/docs/concepts/foundation-consolidation.md +86 -0
  8. package/docs/const-kb.md +92 -0
  9. package/docs/core-types/DECORATOR-TODOS.md +25 -0
  10. package/docs/core-types/README.md +203 -0
  11. package/docs/reference/api.md +70 -0
  12. package/docs/reference/classes/README.md +115 -0
  13. package/package.json +132 -0
  14. package/src/arrays.js +5 -0
  15. package/src/audio/audioFormats.js +34 -0
  16. package/src/audio/index.js +1 -0
  17. package/src/box3.js +1385 -0
  18. package/src/bytes.js +56 -0
  19. package/src/compression.js +56 -0
  20. package/src/constants/index.js +6 -0
  21. package/src/constants.js +15 -0
  22. package/src/curve.js +419 -0
  23. package/src/d3d/dxgiFormats.js +46 -0
  24. package/src/d3d/index.js +2 -0
  25. package/src/d3d/primitiveTopology.js +11 -0
  26. package/src/document/CjsCarbonDocument.js +212 -0
  27. package/src/document/CjsClassRegistry.js +373 -0
  28. package/src/document/CjsDocumentDehydrator.js +142 -0
  29. package/src/document/CjsDocumentHydrator.js +156 -0
  30. package/src/document/CjsStructRegistry.js +348 -0
  31. package/src/document/hydrationAdapter.js +129 -0
  32. package/src/document/index.js +6 -0
  33. package/src/geometry/box.js +137 -0
  34. package/src/geometry/cylinder.js +244 -0
  35. package/src/geometry/helpers/LICENSE +15 -0
  36. package/src/geometry/helpers/earcut.js +766 -0
  37. package/src/geometry/helpers/misc.js +103 -0
  38. package/src/geometry/index.js +8 -0
  39. package/src/geometry/json.js +165 -0
  40. package/src/geometry/lathe.js +172 -0
  41. package/src/geometry/octahedron.js +0 -0
  42. package/src/geometry/plane.js +81 -0
  43. package/src/geometry/shape.js +95 -0
  44. package/src/geometry/sphere.js +123 -0
  45. package/src/geometry/torus.js +96 -0
  46. package/src/graphics/colorSpaces.js +22 -0
  47. package/src/graphics/index.js +4 -0
  48. package/src/graphics/pixelFormats.js +158 -0
  49. package/src/graphics/textureDimensions.js +22 -0
  50. package/src/graphics/trinityEnums.js +87 -0
  51. package/src/index.js +58 -0
  52. package/src/is.js +524 -0
  53. package/src/json.js +23 -0
  54. package/src/lifecycle/CjsLifecycleState.js +77 -0
  55. package/src/lifecycle/index.js +1 -0
  56. package/src/lne3.js +497 -0
  57. package/src/lookup.js +48 -0
  58. package/src/mat3.js +131 -0
  59. package/src/mat4.js +699 -0
  60. package/src/math/index.js +25 -0
  61. package/src/math/scalar.js +63 -0
  62. package/src/media/index.js +1 -0
  63. package/src/media/mediaTypes.js +50 -0
  64. package/src/mesh.js +394 -0
  65. package/src/model/CjsEventEmitter.js +333 -0
  66. package/src/model/CjsModel.js +1544 -0
  67. package/src/model/CjsModelState.js +72 -0
  68. package/src/model/index.js +4 -0
  69. package/src/model/sourceRecordUtils.js +54 -0
  70. package/src/noise.js +310 -0
  71. package/src/num.js +827 -0
  72. package/src/path.js +21 -0
  73. package/src/pln.js +762 -0
  74. package/src/pool.js +160 -0
  75. package/src/quat.js +144 -0
  76. package/src/ray3.js +1085 -0
  77. package/src/renderContext/formats.js +145 -0
  78. package/src/renderContext/index.js +5 -0
  79. package/src/renderContext/presentation.js +125 -0
  80. package/src/renderContext/resources.js +27 -0
  81. package/src/renderContext/upscaling.js +22 -0
  82. package/src/renderContext/window.js +20 -0
  83. package/src/runtime/CjsRuntimeState.js +50 -0
  84. package/src/schema/CjsSchema.js +1009 -0
  85. package/src/schema/index.js +17 -0
  86. package/src/shader/index.js +1 -0
  87. package/src/shader/shaderStages.js +37 -0
  88. package/src/sph3.js +754 -0
  89. package/src/tangent.js +288 -0
  90. package/src/text.js +40 -0
  91. package/src/tri3.js +650 -0
  92. package/src/types/carbonTypes.js +635 -0
  93. package/src/types/index.js +2 -0
  94. package/src/utils.js +58 -0
  95. package/src/validation.js +46 -0
  96. package/src/vec2.js +229 -0
  97. package/src/vec3.js +1172 -0
  98. package/src/vec4.js +347 -0
  99. package/src/vertex.js +108 -0
  100. package/src/webgpu/index.js +1 -0
  101. package/src/webgpu/textureFormats.js +121 -0
@@ -0,0 +1,129 @@
1
+ import { CjsSchema } from "../schema/index.js";
2
+
3
+ /**
4
+ * Hydration adapter seam.
5
+ *
6
+ * runtime-utils deliberately does NOT impose a runtime lifecycle
7
+ * (SetValues / OnValueChanged / Initialize / etc. are one project's rules,
8
+ * not a contract). The only thing the library guarantees is ORDERING:
9
+ *
10
+ * 1. construct - build every instance (register refs before values, so
11
+ * cycles/back-references resolve)
12
+ * 2. applyValues - apply each node's field values
13
+ * 3. finalize - run once per instance AFTER the whole graph is built,
14
+ * so references are already resolved
15
+ *
16
+ * Callers inject HOW their own classes are constructed, populated, and
17
+ * finalized. Every hook is optional; when absent the built-in default is used
18
+ * so plain objects / `class {}` need zero configuration.
19
+ *
20
+ * Adapter shape (all methods optional):
21
+ * construct(kind, ctx) -> instance | undefined
22
+ * Return an instance, or `undefined` to fall back to the caller's
23
+ * built-in default construction (registry/class lookup).
24
+ * applyValues(instance, values, ctx) -> instance
25
+ * Apply `values` ({ fieldName: value }) to the instance. MUST mutate
26
+ * the given instance in place (returning a replacement would strip
27
+ * already-resolved references in cyclic graphs). Default: Object.assign.
28
+ * finalize(instance, ctx) -> void
29
+ * Post-graph initialization. Default: no-op.
30
+ *
31
+ * ctx: { kind, shape?, node?, options }
32
+ *
33
+ * Options consumed:
34
+ * options.adapter / options.hydrationAdapter : a single adapter object
35
+ * options.adapters : { [kind]: adapter } | Map per-kind override (wins over
36
+ * the single adapter)
37
+ */
38
+
39
+ function adapterOwning(perKind, global, kind, name)
40
+ {
41
+ if (perKind)
42
+ {
43
+ const specific = perKind instanceof Map ? perKind.get(kind) : perKind[kind];
44
+ if (specific && typeof specific[name] === "function") return specific;
45
+ }
46
+ if (global && typeof global[name] === "function") return global;
47
+ return null;
48
+ }
49
+
50
+ /**
51
+ * Resolves a normalized adapter from hydration options. The returned object
52
+ * always exposes construct/applyValues/finalize with the documented defaults.
53
+ * @param {Object} [options]
54
+ * @returns {{ construct: Function, applyValues: Function, finalize: Function }}
55
+ */
56
+ export function resolveHydrationAdapter(options = {})
57
+ {
58
+ const global = options.adapter || options.hydrationAdapter || null;
59
+ const perKind = options.adapters || null;
60
+
61
+ return {
62
+ construct(kind, ctx)
63
+ {
64
+ const owner = adapterOwning(perKind, global, kind, "construct");
65
+ return owner ? owner.construct(kind, ctx) : undefined;
66
+ },
67
+ applyValues(instance, values, ctx)
68
+ {
69
+ const owner = adapterOwning(perKind, global, ctx?.kind, "applyValues");
70
+ if (owner) return owner.applyValues(instance, values, ctx);
71
+ return Object.assign(instance, values);
72
+ },
73
+ finalize(instance, ctx)
74
+ {
75
+ const owner = adapterOwning(perKind, global, ctx?.kind, "finalize");
76
+ if (owner) owner.finalize(instance, ctx);
77
+ }
78
+ };
79
+ }
80
+
81
+ /**
82
+ * Optional convenience adapter for callers whose classes follow a
83
+ * "SetValues + Initialize" convention (Carbon / ccpwgl / CjsModel style).
84
+ *
85
+ * This is NOT a default - opt in by passing it as `options.adapter`. Method
86
+ * names are configurable; pass `false`/`null` to disable a phase. When
87
+ * SetValues is enabled, applyValues throws if the populated instance does not
88
+ * implement it; this keeps class population from silently bypassing runtime
89
+ * validation. Finalize is skipped when the named initialize method is missing.
90
+ *
91
+ * @param {Object} [config]
92
+ * @param {String|false|null} [config.setValues="SetValues"]
93
+ * @param {String|false|null} [config.initialize="Initialize"]
94
+ * @param {Function} [config.construct] optional construct hook
95
+ * @returns {{ construct?: Function, applyValues: Function, finalize: Function }}
96
+ */
97
+ export function createLifecycleAdapter(config = {})
98
+ {
99
+ const setValuesName = config.setValues === undefined ? "SetValues" : config.setValues;
100
+ const initializeName = config.initialize === undefined ? "Initialize" : config.initialize;
101
+ const construct = typeof config.construct === "function" ? config.construct : null;
102
+
103
+ const adapter = {
104
+ applyValues(instance, values, ctx)
105
+ {
106
+ if (setValuesName && instance && typeof instance[setValuesName] === "function")
107
+ {
108
+ instance[setValuesName](values, ctx?.options);
109
+ return instance;
110
+ }
111
+ if (setValuesName && instance && typeof instance === "object")
112
+ {
113
+ const kind = ctx?.kind ?? CjsSchema.getClassName(instance.constructor) ?? "unknown";
114
+ throw new TypeError(`${kind} cannot be populated by createLifecycleAdapter: missing ${setValuesName}().`);
115
+ }
116
+ return Object.assign(instance, values);
117
+ },
118
+ finalize(instance, ctx)
119
+ {
120
+ if (initializeName && instance && typeof instance[initializeName] === "function")
121
+ {
122
+ instance[initializeName](ctx?.options);
123
+ }
124
+ }
125
+ };
126
+
127
+ if (construct) adapter.construct = construct;
128
+ return adapter;
129
+ }
@@ -0,0 +1,6 @@
1
+ export * from "./CjsCarbonDocument.js";
2
+ export * from "./CjsClassRegistry.js";
3
+ export * from "./CjsDocumentDehydrator.js";
4
+ export * from "./CjsDocumentHydrator.js";
5
+ export * from "./CjsStructRegistry.js";
6
+ export * from "./hydrationAdapter.js";
@@ -0,0 +1,137 @@
1
+ import { vec3 } from "../vec3.js";
2
+ import { toJSON } from "./json.js";
3
+
4
+
5
+ /**
6
+ * Creates a box
7
+ * @author Three.js converted
8
+ * @param {Object} [options={}]
9
+ * @param {Number} [options.width=1]
10
+ * @param {Number} [options.height=1]
11
+ * @param {Number} [options.depth=1]
12
+ * @param {Number} [widthSegments=1]
13
+ * @param {Number} [heightSegments=1]
14
+ * @param {Number} [depthSegments=1]
15
+ * @returns {Object}
16
+ */
17
+ export function createBox(options = {})
18
+ {
19
+ let {
20
+ width = 1,
21
+ height = 1,
22
+ depth = 1,
23
+ widthSegments = 1,
24
+ heightSegments = 1,
25
+ depthSegments = 1
26
+ } = options;
27
+
28
+ if (![ width, height, depth ].every(Number.isFinite) ||
29
+ width === 0 || height === 0 || depth === 0)
30
+ {
31
+ throw new Error("Box dimensions must be finite and non-zero");
32
+ }
33
+
34
+ widthSegments = Math.max(1, Math.floor(Number.isFinite(widthSegments) ? widthSegments : 1));
35
+ heightSegments = Math.max(1, Math.floor(Number.isFinite(heightSegments) ? heightSegments : 1));
36
+ depthSegments = Math.max(1, Math.floor(Number.isFinite(depthSegments) ? depthSegments : 1));
37
+
38
+ const
39
+ indices = [],
40
+ positions = [],
41
+ normals = [],
42
+ uvs = [];
43
+
44
+ let numberOfVertices = 0;
45
+
46
+ function buildPlane(u, v, w, udir, vdir, width, height, depth, gridX, gridY)
47
+ {
48
+ const
49
+ segmentWidth = width / gridX,
50
+ segmentHeight = height / gridY,
51
+ widthHalf = width / 2,
52
+ heightHalf = height / 2,
53
+ depthHalf = depth / 2,
54
+ gridX1 = gridX + 1,
55
+ gridY1 = gridY + 1;
56
+
57
+ let vertexCounter = 0;
58
+
59
+ const vec3_0 = vec3.alloc();
60
+
61
+ // generate vertices, normals and uvs
62
+
63
+ for (let iy = 0; iy < gridY1; iy++)
64
+ {
65
+ const y = iy * segmentHeight - heightHalf;
66
+
67
+ for (let ix = 0; ix < gridX1; ix++)
68
+ {
69
+ const x = ix * segmentWidth - widthHalf;
70
+ // set values to correct vec3_0 component
71
+ vec3_0[u] = x * udir;
72
+ vec3_0[v] = y * vdir;
73
+ vec3_0[w] = depthHalf;
74
+ // now apply vec3_0 to vertex buffer
75
+ positions.push(vec3_0[0], vec3_0[1], vec3_0[2]);
76
+ // set values to correct vec3_0 component
77
+ vec3_0[u] = 0;
78
+ vec3_0[v] = 0;
79
+ vec3_0[w] = depth > 0 ? 1 : -1;
80
+ // now apply vec3_0 to normal buffer
81
+ normals.push(vec3_0[0], vec3_0[1], vec3_0[2]);
82
+ // uvs
83
+ uvs.push(ix / gridX);
84
+ uvs.push(1 - (iy / gridY));
85
+ // counters
86
+ vertexCounter += 1;
87
+ }
88
+ }
89
+
90
+ vec3.unalloc(vec3_0);
91
+
92
+ // indices
93
+ // 1. you need three indices to draw a single face
94
+ // 2. a single segment consists of two faces
95
+ // 3. so we need to generate six (2*3) indices per segment
96
+ for (let iy = 0; iy < gridY; iy++)
97
+ {
98
+ for (let ix = 0; ix < gridX; ix++)
99
+ {
100
+ const
101
+ a = numberOfVertices + ix + gridX1 * iy,
102
+ b = numberOfVertices + ix + gridX1 * (iy + 1),
103
+ c = numberOfVertices + (ix + 1) + gridX1 * (iy + 1),
104
+ d = numberOfVertices + (ix + 1) + gridX1 * iy;
105
+ // faces
106
+ indices.push(a, b, d);
107
+ indices.push(b, c, d);
108
+ }
109
+ }
110
+
111
+ // update total number of vertices
112
+ numberOfVertices += vertexCounter;
113
+ }
114
+
115
+ buildPlane(2, 1, 0, - 1, - 1, depth, height, width, depthSegments, heightSegments); // px
116
+ buildPlane(2, 1, 0, 1, - 1, depth, height, - width, depthSegments, heightSegments); // nx
117
+ buildPlane(0, 2, 1, 1, 1, width, depth, height, widthSegments, depthSegments); // py
118
+ buildPlane(0, 2, 1, 1, - 1, width, depth, - height, widthSegments, depthSegments); // ny
119
+ buildPlane(0, 1, 2, 1, - 1, width, height, depth, widthSegments, heightSegments); // pz
120
+ buildPlane(0, 1, 2, - 1, - 1, width, height, - depth, widthSegments, heightSegments); // nz
121
+
122
+ // Normalize
123
+ const result = toJSON(indices, positions, uvs, normals);
124
+ result.factory = createBox;
125
+ result.options = {
126
+ width,
127
+ height,
128
+ depth,
129
+ widthSegments,
130
+ heightSegments,
131
+ depthSegments
132
+ };
133
+ result.shape = { factory: result.factory, options: result.options };
134
+ return result;
135
+
136
+ }
137
+
@@ -0,0 +1,244 @@
1
+ import { vec3 } from "../vec3.js";
2
+ import { vec2 } from "../vec2.js";
3
+ import { toJSON } from "./json.js";
4
+
5
+ /**
6
+ * Creates a cylinder
7
+ * @author Three.js converted
8
+ **/
9
+ export function createCylinder(options = {})
10
+ {
11
+ let {
12
+ radiusTop = 1,
13
+ radiusBottom = 1,
14
+ height = 1,
15
+ radialSegments = 32,
16
+ heightSegments = 1,
17
+ openEnded = false,
18
+ thetaStart = 0,
19
+ thetaLength = Math.PI * 2
20
+ } = options;
21
+
22
+ if (![ radiusTop, radiusBottom, height, thetaStart, thetaLength ].every(Number.isFinite) ||
23
+ height === 0 ||
24
+ thetaLength === 0 ||
25
+ (radiusTop === 0 && radiusBottom === 0))
26
+ {
27
+ throw new Error("Invalid cylinder dimensions");
28
+ }
29
+
30
+ radialSegments = Math.max(3, Math.floor(Number.isFinite(radialSegments) ? radialSegments : 32));
31
+ heightSegments = Math.max(1, Math.floor(Number.isFinite(heightSegments) ? heightSegments : 1));
32
+
33
+ // buffers
34
+ const
35
+ indices = [],
36
+ positions = [],
37
+ normals = [],
38
+ uvs = [];
39
+
40
+ // helper variables
41
+ let index = 0;
42
+
43
+ const
44
+ indexArray = [],
45
+ halfHeight = height / 2;
46
+
47
+ // build geometry
48
+ function generateTorso()
49
+ {
50
+ const
51
+ normal = vec3.alloc(),
52
+ vertex = vec3.alloc();
53
+
54
+ // this will be used to calculate the normal
55
+ const slope = (radiusBottom - radiusTop) / height;
56
+
57
+ // generate positions, normals and uvs
58
+
59
+ for (let y = 0; y <= heightSegments; y++)
60
+ {
61
+ const
62
+ indexRow = [],
63
+ v = y / heightSegments;
64
+
65
+ // calculate the radius of the current row
66
+ const radius = v * (radiusBottom - radiusTop) + radiusTop;
67
+ for (let x = 0; x <= radialSegments; x++)
68
+ {
69
+ const
70
+ u = x / radialSegments,
71
+ theta = u * thetaLength + thetaStart,
72
+ sinTheta = Math.sin(theta),
73
+ cosTheta = Math.cos(theta);
74
+
75
+ // vertex
76
+ vertex[0] = radius * sinTheta;
77
+ vertex[1] = -v * height + halfHeight;
78
+ vertex[2] = radius * cosTheta;
79
+ positions.push(vertex[0], vertex[1], vertex[2]);
80
+
81
+ // normal
82
+ normal[0] = sinTheta;
83
+ normal[1] = slope;
84
+ normal[2] = cosTheta;
85
+ vec3.normalize(normal, normal);
86
+ normals.push(normal[0], normal[1], normal[2]);
87
+
88
+ // uv
89
+ uvs.push(u, 1 - v);
90
+
91
+ // save index of vertex in respective row
92
+ indexRow.push(index++);
93
+ }
94
+
95
+ // now save positions of the row in our index array
96
+ indexArray.push(indexRow);
97
+ }
98
+
99
+ vec3.unalloc(vertex);
100
+ vec3.unalloc(normal);
101
+
102
+ // generate indices
103
+ for (let x = 0; x < radialSegments; x++)
104
+ {
105
+ for (let y = 0; y < heightSegments; y++)
106
+ {
107
+ // we use the index array to access the correct indices
108
+ const
109
+ a = indexArray[y][x],
110
+ b = indexArray[y + 1][x],
111
+ c = indexArray[y + 1][x + 1],
112
+ d = indexArray[y][x + 1],
113
+ upperRadius = (y / heightSegments) * (radiusBottom - radiusTop) + radiusTop,
114
+ lowerRadius = ((y + 1) / heightSegments) * (radiusBottom - radiusTop) + radiusTop;
115
+
116
+ // faces
117
+ if (upperRadius !== 0) indices.push(a, b, d);
118
+ if (lowerRadius !== 0) indices.push(b, c, d);
119
+ }
120
+ }
121
+ }
122
+
123
+ function generateCap(top)
124
+ {
125
+
126
+ // save the index of the first center vertex
127
+ const centerIndexStart = index;
128
+
129
+ const
130
+ uv = vec2.alloc(),
131
+ vertex = vec3.alloc(),
132
+ radius = (top === true) ? radiusTop : radiusBottom,
133
+ sign = (top === true) ? 1 : -1;
134
+
135
+ // first we generate the center vertex data of the cap.
136
+ // because the geometry needs one set of uvs per face,
137
+ // we must generate a center vertex per face/segment
138
+
139
+ for (let x = 1; x <= radialSegments; x++)
140
+ {
141
+ // vertex
142
+ positions.push(0, halfHeight * sign, 0);
143
+
144
+ // normal
145
+ normals.push(0, sign, 0);
146
+
147
+ // uv
148
+ uvs.push(0.5, 0.5);
149
+
150
+ // increase index
151
+ index++;
152
+ }
153
+
154
+ // save the index of the last center vertex
155
+ const centerIndexEnd = index;
156
+
157
+ // now we generate the surrounding positions, normals and uvs
158
+
159
+ for (let x = 0; x <= radialSegments; x++)
160
+ {
161
+ const
162
+ u = x / radialSegments,
163
+ theta = u * thetaLength + thetaStart,
164
+ cosTheta = Math.cos(theta),
165
+ sinTheta = Math.sin(theta);
166
+
167
+ // vertex
168
+ vertex[0] = radius * sinTheta;
169
+ vertex[1] = halfHeight * sign;
170
+ vertex[2] = radius * cosTheta;
171
+ positions.push(vertex[0], vertex[1], vertex[2]);
172
+
173
+ // normal
174
+ normals.push(0, sign, 0);
175
+
176
+ // uv
177
+ uv[0] = (cosTheta * 0.5) + 0.5;
178
+ uv[1] = (sinTheta * 0.5 * sign) + 0.5;
179
+ uvs.push(uv[0], uv[1]);
180
+
181
+ // increase index
182
+ index++;
183
+ }
184
+
185
+ vec2.unalloc(uv);
186
+ vec3.unalloc(vertex);
187
+
188
+ // generate indices
189
+ for (let x = 0; x < radialSegments; x++)
190
+ {
191
+ const
192
+ c = centerIndexStart + x,
193
+ i = centerIndexEnd + x;
194
+
195
+ if (top === true)
196
+ {
197
+ // face top
198
+ indices.push(i, i + 1, c);
199
+ }
200
+ else
201
+ {
202
+ // face bottom
203
+ indices.push(i + 1, i, c);
204
+ }
205
+ }
206
+ }
207
+
208
+ // generate geometry
209
+ generateTorso();
210
+
211
+ if (openEnded === false)
212
+ {
213
+ if (radiusTop > 0) generateCap(true);
214
+ if (radiusBottom > 0) generateCap(false);
215
+ }
216
+
217
+ const result = toJSON(indices, positions, uvs, normals);
218
+ result.factory = createCylinder;
219
+ result.options = {
220
+ radiusTop,
221
+ radiusBottom,
222
+ height,
223
+ radialSegments,
224
+ heightSegments,
225
+ openEnded,
226
+ thetaStart,
227
+ thetaLength
228
+ };
229
+ return result;
230
+ }
231
+
232
+ export function createCone(options={})
233
+ {
234
+ const { radius = 1 } = options;
235
+ const result = createCylinder(Object.assign({}, options, {
236
+ radiusTop: 0,
237
+ radiusBottom: radius
238
+ }));
239
+ result.factory = createCone;
240
+ Reflect.deleteProperty(result.options, "radiusTop");
241
+ Reflect.deleteProperty(result.options, "radiusBottom");
242
+ result.options.radius = radius;
243
+ return result;
244
+ }
@@ -0,0 +1,15 @@
1
+ ISC License
2
+
3
+ Copyright (c) 2016, Mapbox
4
+
5
+ Permission to use, copy, modify, and/or distribute this software for any purpose
6
+ with or without fee is hereby granted, provided that the above copyright notice
7
+ and this permission notice appear in all copies.
8
+
9
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
10
+ REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
11
+ FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
12
+ INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
13
+ OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
14
+ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
15
+ THIS SOFTWARE.