ya-kansuji 0.1.0 → 1.0.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.
- package/CHANGELOG.md +15 -1
- package/README.md +14 -2
- package/dist/index.cjs +9 -1
- package/dist/index.d.cts +6 -1
- package/dist/index.d.ts +6 -1
- package/dist/index.iife.min.js +1 -1
- package/dist/index.js +9 -2
- package/package.json +1 -1
- package/src/index.ts +1 -1
- package/src/parse.ts +10 -1
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,19 @@
|
|
|
4
4
|
|
|
5
5
|
## [Unreleased]
|
|
6
6
|
|
|
7
|
+
## [1.0.0] - 2026-07-14
|
|
8
|
+
|
|
9
|
+
### Security
|
|
10
|
+
|
|
11
|
+
- `toBigInt` / `toNumber` に入力長の上限 `MAX_INPUT_LENGTH`(16384 コードユニット)を導入。
|
|
12
|
+
過大な入力によるリソース枯渇(DoS)を防ぐため、上限超過時は `RangeError` を投げる。
|
|
13
|
+
値そのものに上限はなく、上限が掛かるのは入力の長さのみ。
|
|
14
|
+
従来 `toBigInt` は例外を投げなかったが、過長入力に対しては投げるようになった(破壊的変更)。
|
|
15
|
+
|
|
16
|
+
### Added
|
|
17
|
+
|
|
18
|
+
- `MAX_INPUT_LENGTH` を公開エクスポートに追加。
|
|
19
|
+
|
|
7
20
|
## [0.1.0] - 2026-07-14
|
|
8
21
|
|
|
9
22
|
初回リリース。Ruby gem [ya_kansuji](https://github.com/sugi/ya_kansuji) 1.1.0 の TypeScript/JavaScript 移植版。
|
|
@@ -15,5 +28,6 @@
|
|
|
15
28
|
- `registerFormatter` / `getFormatter` によるフォーマッタプラグイン機構。
|
|
16
29
|
- ESM・CommonJS・IIFE(CDN 用)ビルドと型定義を同梱。
|
|
17
30
|
|
|
18
|
-
[Unreleased]: https://github.com/sugi/ya-kansuji-js/compare/
|
|
31
|
+
[Unreleased]: https://github.com/sugi/ya-kansuji-js/compare/v1.0.0...HEAD
|
|
32
|
+
[1.0.0]: https://github.com/sugi/ya-kansuji-js/compare/v0.1.0...v1.0.0
|
|
19
33
|
[0.1.0]: https://github.com/sugi/ya-kansuji-js/releases/tag/v0.1.0
|
package/README.md
CHANGED
|
@@ -48,6 +48,18 @@ toBigInt('一無量大数') // => 1000000000000000000000000000000000000000000000
|
|
|
48
48
|
toNumber('一無量大数') // throws RangeError
|
|
49
49
|
```
|
|
50
50
|
|
|
51
|
+
#### 入力長の上限
|
|
52
|
+
|
|
53
|
+
`toBigInt` / `toNumber` が受け付ける入力は最大 `MAX_INPUT_LENGTH`(16384 コードユニット)です。これを超える入力には `RangeError` を投げます。上限は入力文字列の**長さ**に対するもので、変換後の**値**に上限はありません(無量大数を超える大きさも扱えます)。この上限により、任意長テキストを渡してもパースの最悪計算コストが有界になります。
|
|
54
|
+
|
|
55
|
+
```ts
|
|
56
|
+
import { MAX_INPUT_LENGTH, toBigInt } from 'ya-kansuji'
|
|
57
|
+
|
|
58
|
+
MAX_INPUT_LENGTH // => 16384
|
|
59
|
+
toBigInt('一'.repeat(MAX_INPUT_LENGTH)) // OK
|
|
60
|
+
toBigInt('一'.repeat(MAX_INPUT_LENGTH + 1)) // throws RangeError
|
|
61
|
+
```
|
|
62
|
+
|
|
51
63
|
先頭の「マイナス」は負の符号として解釈します。ASCII の `-` や Unicode の `−` (U+2212) は符号として扱いません。
|
|
52
64
|
|
|
53
65
|
```ts
|
|
@@ -134,14 +146,14 @@ npm 経由のインストールなしに、CDN から直接読み込むことも
|
|
|
134
146
|
|
|
135
147
|
```html
|
|
136
148
|
<!-- script タグ (グローバル YaKansuji) -->
|
|
137
|
-
<script src="https://cdn.jsdelivr.net/npm/ya-kansuji@
|
|
149
|
+
<script src="https://cdn.jsdelivr.net/npm/ya-kansuji@1.0.0/dist/index.iife.min.js"></script>
|
|
138
150
|
<script>
|
|
139
151
|
console.log(YaKansuji.toKan(1234)); // => 千二百三十四
|
|
140
152
|
</script>
|
|
141
153
|
|
|
142
154
|
<!-- ES Modules -->
|
|
143
155
|
<script type="module">
|
|
144
|
-
import { toNumber } from 'https://cdn.jsdelivr.net/npm/ya-kansuji@
|
|
156
|
+
import { toNumber } from 'https://cdn.jsdelivr.net/npm/ya-kansuji@1.0.0/+esm';
|
|
145
157
|
console.log(toNumber('九億6千万卌一')); // => 960000041
|
|
146
158
|
</script>
|
|
147
159
|
```
|
package/dist/index.cjs
CHANGED
|
@@ -106,6 +106,8 @@ function createUnitValues(units, base) {
|
|
|
106
106
|
const UNIT_EXP3_VALUES = createUnitValues(UNIT_EXP3, 10n);
|
|
107
107
|
const UNIT_EXP4_VALUES = createUnitValues(UNIT_EXP4, 10000n);
|
|
108
108
|
const MAX_SAFE_BIGINT = BigInt(Number.MAX_SAFE_INTEGER);
|
|
109
|
+
/** toBigInt / toNumber が受け付ける入力の最大長(UTF-16 コードユニット数)。 */
|
|
110
|
+
const MAX_INPUT_LENGTH = 16384;
|
|
109
111
|
function clean(str) {
|
|
110
112
|
let result = "";
|
|
111
113
|
for (const c of str) {
|
|
@@ -121,16 +123,20 @@ function clean(str) {
|
|
|
121
123
|
* 数値表現だけを読み取る(例: `toBigInt('五x六')` は `5n`)。マッチしなければ `0n` を返す。
|
|
122
124
|
* 先頭の「マイナス」は負号として扱うが、ASCII の `-` や U+2212(−)は負号として扱わない。
|
|
123
125
|
* 値の上限はなく、無量大数(10^68)を超える大きさもそのまま扱える。
|
|
126
|
+
* 入力長が {@link MAX_INPUT_LENGTH} を超える場合は `RangeError` を投げる。
|
|
124
127
|
*
|
|
125
128
|
* @param str 変換対象の文字列
|
|
126
129
|
* @returns テキストが表す整数値
|
|
130
|
+
* @throws {RangeError} 入力長が {@link MAX_INPUT_LENGTH} を超える場合
|
|
127
131
|
* @example
|
|
128
132
|
* toBigInt('一〇二四') // => 1024n
|
|
129
133
|
* toBigInt('マイナス千二百') // => -1200n
|
|
130
134
|
* toBigInt('一無量大数') // => 10n ** 68n
|
|
131
135
|
*/
|
|
132
136
|
function toBigInt(str) {
|
|
133
|
-
const
|
|
137
|
+
const s = String(str);
|
|
138
|
+
if (s.length > 16384) throw new RangeError(`kansuji input exceeds maximum length of ${MAX_INPUT_LENGTH} UTF-16 code units`);
|
|
139
|
+
const cleaned = clean(s);
|
|
134
140
|
const matched = KANSUJI_REGEXP.exec(cleaned);
|
|
135
141
|
if (!matched) return 0n;
|
|
136
142
|
const matchedText = matched[0];
|
|
@@ -181,6 +187,7 @@ function toBigInt(str) {
|
|
|
181
187
|
* @param str 変換対象の文字列
|
|
182
188
|
* @returns テキストが表す数値
|
|
183
189
|
* @throws {RangeError} 値が安全整数の範囲を超える場合
|
|
190
|
+
* @throws {RangeError} 入力長が {@link MAX_INPUT_LENGTH} を超える場合
|
|
184
191
|
* @example
|
|
185
192
|
* toNumber('一〇二四') // => 1024
|
|
186
193
|
* toNumber('一無量大数') // throws RangeError
|
|
@@ -387,6 +394,7 @@ function toKan(num, formatter = "simple", options = {}) {
|
|
|
387
394
|
return fn(value, options);
|
|
388
395
|
}
|
|
389
396
|
//#endregion
|
|
397
|
+
exports.MAX_INPUT_LENGTH = MAX_INPUT_LENGTH;
|
|
390
398
|
exports.UNIT_EXP3 = UNIT_EXP3;
|
|
391
399
|
exports.UNIT_EXP4 = UNIT_EXP4;
|
|
392
400
|
exports.getFormatter = getFormatter;
|
package/dist/index.d.cts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
//#region src/parse.d.ts
|
|
2
|
+
/** toBigInt / toNumber が受け付ける入力の最大長(UTF-16 コードユニット数)。 */
|
|
3
|
+
declare const MAX_INPUT_LENGTH = 16384;
|
|
2
4
|
/**
|
|
3
5
|
* 漢数字・大字・全角数字が混じったテキストを bigint に変換する。
|
|
4
6
|
*
|
|
@@ -6,9 +8,11 @@
|
|
|
6
8
|
* 数値表現だけを読み取る(例: `toBigInt('五x六')` は `5n`)。マッチしなければ `0n` を返す。
|
|
7
9
|
* 先頭の「マイナス」は負号として扱うが、ASCII の `-` や U+2212(−)は負号として扱わない。
|
|
8
10
|
* 値の上限はなく、無量大数(10^68)を超える大きさもそのまま扱える。
|
|
11
|
+
* 入力長が {@link MAX_INPUT_LENGTH} を超える場合は `RangeError` を投げる。
|
|
9
12
|
*
|
|
10
13
|
* @param str 変換対象の文字列
|
|
11
14
|
* @returns テキストが表す整数値
|
|
15
|
+
* @throws {RangeError} 入力長が {@link MAX_INPUT_LENGTH} を超える場合
|
|
12
16
|
* @example
|
|
13
17
|
* toBigInt('一〇二四') // => 1024n
|
|
14
18
|
* toBigInt('マイナス千二百') // => -1200n
|
|
@@ -24,6 +28,7 @@ declare function toBigInt(str: string): bigint;
|
|
|
24
28
|
* @param str 変換対象の文字列
|
|
25
29
|
* @returns テキストが表す数値
|
|
26
30
|
* @throws {RangeError} 値が安全整数の範囲を超える場合
|
|
31
|
+
* @throws {RangeError} 入力長が {@link MAX_INPUT_LENGTH} を超える場合
|
|
27
32
|
* @example
|
|
28
33
|
* toNumber('一〇二四') // => 1024
|
|
29
34
|
* toNumber('一無量大数') // throws RangeError
|
|
@@ -145,4 +150,4 @@ declare function judicV(num: bigint): string;
|
|
|
145
150
|
*/
|
|
146
151
|
declare function judicH(num: bigint): string;
|
|
147
152
|
//#endregion
|
|
148
|
-
export { type KansujiFormatter, type KansujiFormatterOptions, UNIT_EXP3, UNIT_EXP4, getFormatter, gov, judicH, judicV, lawyer, registerFormatter, simple, toBigInt, toKan, toNumber };
|
|
153
|
+
export { type KansujiFormatter, type KansujiFormatterOptions, MAX_INPUT_LENGTH, UNIT_EXP3, UNIT_EXP4, getFormatter, gov, judicH, judicV, lawyer, registerFormatter, simple, toBigInt, toKan, toNumber };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
//#region src/parse.d.ts
|
|
2
|
+
/** toBigInt / toNumber が受け付ける入力の最大長(UTF-16 コードユニット数)。 */
|
|
3
|
+
declare const MAX_INPUT_LENGTH = 16384;
|
|
2
4
|
/**
|
|
3
5
|
* 漢数字・大字・全角数字が混じったテキストを bigint に変換する。
|
|
4
6
|
*
|
|
@@ -6,9 +8,11 @@
|
|
|
6
8
|
* 数値表現だけを読み取る(例: `toBigInt('五x六')` は `5n`)。マッチしなければ `0n` を返す。
|
|
7
9
|
* 先頭の「マイナス」は負号として扱うが、ASCII の `-` や U+2212(−)は負号として扱わない。
|
|
8
10
|
* 値の上限はなく、無量大数(10^68)を超える大きさもそのまま扱える。
|
|
11
|
+
* 入力長が {@link MAX_INPUT_LENGTH} を超える場合は `RangeError` を投げる。
|
|
9
12
|
*
|
|
10
13
|
* @param str 変換対象の文字列
|
|
11
14
|
* @returns テキストが表す整数値
|
|
15
|
+
* @throws {RangeError} 入力長が {@link MAX_INPUT_LENGTH} を超える場合
|
|
12
16
|
* @example
|
|
13
17
|
* toBigInt('一〇二四') // => 1024n
|
|
14
18
|
* toBigInt('マイナス千二百') // => -1200n
|
|
@@ -24,6 +28,7 @@ declare function toBigInt(str: string): bigint;
|
|
|
24
28
|
* @param str 変換対象の文字列
|
|
25
29
|
* @returns テキストが表す数値
|
|
26
30
|
* @throws {RangeError} 値が安全整数の範囲を超える場合
|
|
31
|
+
* @throws {RangeError} 入力長が {@link MAX_INPUT_LENGTH} を超える場合
|
|
27
32
|
* @example
|
|
28
33
|
* toNumber('一〇二四') // => 1024
|
|
29
34
|
* toNumber('一無量大数') // throws RangeError
|
|
@@ -145,4 +150,4 @@ declare function judicV(num: bigint): string;
|
|
|
145
150
|
*/
|
|
146
151
|
declare function judicH(num: bigint): string;
|
|
147
152
|
//#endregion
|
|
148
|
-
export { type KansujiFormatter, type KansujiFormatterOptions, UNIT_EXP3, UNIT_EXP4, getFormatter, gov, judicH, judicV, lawyer, registerFormatter, simple, toBigInt, toKan, toNumber };
|
|
153
|
+
export { type KansujiFormatter, type KansujiFormatterOptions, MAX_INPUT_LENGTH, UNIT_EXP3, UNIT_EXP4, getFormatter, gov, judicH, judicV, lawyer, registerFormatter, simple, toBigInt, toKan, toNumber };
|
package/dist/index.iife.min.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
var YaKansuji=(function(e){Object.defineProperty(e,Symbol.toStringTag,{value:`Module`});let t=[`十`,`百`,`千`],n=[`万`,`億`,`兆`,`京`,`垓`,`𥝱`,`穣`,`溝`,`澗`,`正`,`載`,`極`,`恒河沙`,`阿僧祇`,`那由他`,`不可思議`,`無量大数`],r=`〇一二三四五六七八九`,i=`${r}0123456789零壱壹弌弐貳貮参參弎肆伍陸漆質柒捌玖拾什陌佰阡仟萬秭`,a=Array.from(i),o=Array.from(`01234567890123456789011122233345677789十十百百千千万𥝱`),s=new Map(a.map((e,t)=>[e,o[t]])),c=new Set(`,.,.、. .
|
|
2
|
-
.\v.\f.\r. .\xA0. . . . . . . . . . . . .\u2028.\u2029. . . .`.split(`.`)),l=[0n,1n,2n,3n,4n,5n,6n,7n,8n,9n],u=new Map([[`卄`,20n],[`廿`,20n],[`卅`,30n],[`丗`,30n],[`卌`,40n],[`皕`,200n]]),d=[...t,...n.filter(e=>Array.from(e).length===1)],f=n.filter(e=>Array.from(e).length>1),p=[...new Set([...a,...o,...d,...u.keys()])].join(``),m=`${f.join(`|`)}|[${p}]`,h=RegExp(`(?:マイナス)?(?:${m})+`,`u`),g=new RegExp(m,`gu`);function _(e,t){let n=t;return new Map(e.map(e=>{let r=[e,n];return n*=t,r}))}let v=_(t,10n),y=_(n,10000n),b=BigInt(2**53-1);function
|
|
2
|
+
.\v.\f.\r. .\xA0. . . . . . . . . . . . .\u2028.\u2029. . . .`.split(`.`)),l=[0n,1n,2n,3n,4n,5n,6n,7n,8n,9n],u=new Map([[`卄`,20n],[`廿`,20n],[`卅`,30n],[`丗`,30n],[`卌`,40n],[`皕`,200n]]),d=[...t,...n.filter(e=>Array.from(e).length===1)],f=n.filter(e=>Array.from(e).length>1),p=[...new Set([...a,...o,...d,...u.keys()])].join(``),m=`${f.join(`|`)}|[${p}]`,h=RegExp(`(?:マイナス)?(?:${m})+`,`u`),g=new RegExp(m,`gu`);function _(e,t){let n=t;return new Map(e.map(e=>{let r=[e,n];return n*=t,r}))}let v=_(t,10n),y=_(n,10000n),b=BigInt(2**53-1),x=16384;function S(e){let t=``;for(let n of e){let e=s.get(n)??n;c.has(e)||(t+=e)}return t}function C(e){let t=String(e);if(t.length>16384)throw RangeError(`kansuji input exceeds maximum length of ${x} UTF-16 code units`);let n=S(t),r=h.exec(n);if(!r)return 0n;let i=r[0];if(i===void 0)return 0n;let a=0n,o=0n,s=null;for(let e of i.match(g)??[])if(e>=`1`&&e<=`9`){let t=l[e.charCodeAt(0)-48];s=(s??0n)*10n+t}else if(e===`0`)s!==null&&(s*=10n);else{let t=u.get(e);if(t!==void 0)a+=t,s=null;else{let t=y.get(e);if(t!==void 0)s!==null&&(a+=s,s=null),a===0n&&(a=1n),o+=a*t,a=0n;else{let t=v.get(e);t!==void 0&&(s??=1n,a+=s*t,s=null)}}}s!==null&&(a+=s);let c=o+a;return i.startsWith(`マイナス`)?-c:c}function w(e){let t=C(e);if(t>b||t<-b)throw RangeError(`kansuji value exceeds Number.MAX_SAFE_INTEGER: ${e}`);return Number(t)}let T=10000n,E=[``,...n],D=E.length,O=T**BigInt(D),k=D*4;function A(e){if(e<0n||e>=O)throw RangeError(`Kansuji formatters require a bigint between 0 and 10^${k} - 1`);let t=[],n=e,r=0;do{let e=E[r];if(e===void 0)throw RangeError(`Kansuji formatters require a bigint between 0 and 10^${k} - 1`);t.push([Number(n%T),e]),n/=T,r++}while(n>0n);return t.reverse()}function j(e){if(e===0n)return`0`;let t=[];for(let[n,r]of A(e))n!==0&&t.push(`${n}${r}`);return t.join(`, `)}function M(e,t,n){if(e===0n)return t;let r=``,i=!0;for(let[t,n]of A(e))t!==0&&(r+=(i?String(t):String(t).padStart(4,`0`))+n,i=!1);return n(r)}function N(e){return M(e,`〇`,e=>e.replace(/[0-9]/g,e=>r.charAt(Number(e))))}function P(e){return M(e,`0`,e=>e.replace(/[0-9]/g,e=>String.fromCharCode(e.charCodeAt(0)+65248)))}function F(e){if(e===0n)return`0`;let t=``;for(let[n,r]of A(e)){if(n===0)continue;let e=String(n);t+=(n>=1e3?`${e[0]},${e.slice(1)}`:e)+r}return t}let I=[1,10,100,1e3];function L(e){if(e===0n)return`零`;let n=``;for(let[i,a]of A(e))if(i!==0){for(let e=t.length;e>=0;e--){let a=t[e-1]??``,o=Math.floor(i/(I[e]??1))%10;o!==0&&(n+=o===1&&a!==``?a:r.charAt(o)+a)}n+=a}return n}let R=new Map([[`simple`,L],[`gov`,j],[`lawyer`,F],[`judic_v`,N],[`judic_h`,P]]);function z(e,t){if(typeof t!=`function`)throw TypeError(`Registering invalid formatter.`);R.set(e,t)}function B(e){return R.get(e)}function V(e,t=`simple`,n={}){let r;if(typeof e==`bigint`)r=e;else if(Number.isSafeInteger(e))r=BigInt(e);else throw RangeError(`toKan requires a safe integer or bigint: ${e}`);if(r<0n)return`マイナス${V(-r,t,n)}`;let i=typeof t==`function`?t:R.get(t);if(!i)throw TypeError(`Unable to find formatter ${String(t)}`);return i(r,n)}return e.MAX_INPUT_LENGTH=x,e.UNIT_EXP3=t,e.UNIT_EXP4=n,e.getFormatter=B,e.gov=j,e.judicH=P,e.judicV=N,e.lawyer=F,e.registerFormatter=z,e.simple=L,e.toBigInt=C,e.toKan=V,e.toNumber=w,e})({});
|
|
3
3
|
globalThis.YaKansuji = YaKansuji;
|
package/dist/index.js
CHANGED
|
@@ -105,6 +105,8 @@ function createUnitValues(units, base) {
|
|
|
105
105
|
const UNIT_EXP3_VALUES = createUnitValues(UNIT_EXP3, 10n);
|
|
106
106
|
const UNIT_EXP4_VALUES = createUnitValues(UNIT_EXP4, 10000n);
|
|
107
107
|
const MAX_SAFE_BIGINT = BigInt(Number.MAX_SAFE_INTEGER);
|
|
108
|
+
/** toBigInt / toNumber が受け付ける入力の最大長(UTF-16 コードユニット数)。 */
|
|
109
|
+
const MAX_INPUT_LENGTH = 16384;
|
|
108
110
|
function clean(str) {
|
|
109
111
|
let result = "";
|
|
110
112
|
for (const c of str) {
|
|
@@ -120,16 +122,20 @@ function clean(str) {
|
|
|
120
122
|
* 数値表現だけを読み取る(例: `toBigInt('五x六')` は `5n`)。マッチしなければ `0n` を返す。
|
|
121
123
|
* 先頭の「マイナス」は負号として扱うが、ASCII の `-` や U+2212(−)は負号として扱わない。
|
|
122
124
|
* 値の上限はなく、無量大数(10^68)を超える大きさもそのまま扱える。
|
|
125
|
+
* 入力長が {@link MAX_INPUT_LENGTH} を超える場合は `RangeError` を投げる。
|
|
123
126
|
*
|
|
124
127
|
* @param str 変換対象の文字列
|
|
125
128
|
* @returns テキストが表す整数値
|
|
129
|
+
* @throws {RangeError} 入力長が {@link MAX_INPUT_LENGTH} を超える場合
|
|
126
130
|
* @example
|
|
127
131
|
* toBigInt('一〇二四') // => 1024n
|
|
128
132
|
* toBigInt('マイナス千二百') // => -1200n
|
|
129
133
|
* toBigInt('一無量大数') // => 10n ** 68n
|
|
130
134
|
*/
|
|
131
135
|
function toBigInt(str) {
|
|
132
|
-
const
|
|
136
|
+
const s = String(str);
|
|
137
|
+
if (s.length > 16384) throw new RangeError(`kansuji input exceeds maximum length of ${MAX_INPUT_LENGTH} UTF-16 code units`);
|
|
138
|
+
const cleaned = clean(s);
|
|
133
139
|
const matched = KANSUJI_REGEXP.exec(cleaned);
|
|
134
140
|
if (!matched) return 0n;
|
|
135
141
|
const matchedText = matched[0];
|
|
@@ -180,6 +186,7 @@ function toBigInt(str) {
|
|
|
180
186
|
* @param str 変換対象の文字列
|
|
181
187
|
* @returns テキストが表す数値
|
|
182
188
|
* @throws {RangeError} 値が安全整数の範囲を超える場合
|
|
189
|
+
* @throws {RangeError} 入力長が {@link MAX_INPUT_LENGTH} を超える場合
|
|
183
190
|
* @example
|
|
184
191
|
* toNumber('一〇二四') // => 1024
|
|
185
192
|
* toNumber('一無量大数') // throws RangeError
|
|
@@ -386,4 +393,4 @@ function toKan(num, formatter = "simple", options = {}) {
|
|
|
386
393
|
return fn(value, options);
|
|
387
394
|
}
|
|
388
395
|
//#endregion
|
|
389
|
-
export { UNIT_EXP3, UNIT_EXP4, getFormatter, gov, judicH, judicV, lawyer, registerFormatter, simple, toBigInt, toKan, toNumber };
|
|
396
|
+
export { MAX_INPUT_LENGTH, UNIT_EXP3, UNIT_EXP4, getFormatter, gov, judicH, judicV, lawyer, registerFormatter, simple, toBigInt, toKan, toNumber };
|
package/package.json
CHANGED
package/src/index.ts
CHANGED
package/src/parse.ts
CHANGED
|
@@ -42,6 +42,8 @@ function createUnitValues(units: readonly string[], base: bigint): Map<string, b
|
|
|
42
42
|
const UNIT_EXP3_VALUES = createUnitValues(UNIT_EXP3, 10n)
|
|
43
43
|
const UNIT_EXP4_VALUES = createUnitValues(UNIT_EXP4, 10_000n)
|
|
44
44
|
const MAX_SAFE_BIGINT = BigInt(Number.MAX_SAFE_INTEGER)
|
|
45
|
+
/** toBigInt / toNumber が受け付ける入力の最大長(UTF-16 コードユニット数)。 */
|
|
46
|
+
export const MAX_INPUT_LENGTH = 16384
|
|
45
47
|
|
|
46
48
|
function clean(str: string): string {
|
|
47
49
|
let result = ''
|
|
@@ -59,16 +61,22 @@ function clean(str: string): string {
|
|
|
59
61
|
* 数値表現だけを読み取る(例: `toBigInt('五x六')` は `5n`)。マッチしなければ `0n` を返す。
|
|
60
62
|
* 先頭の「マイナス」は負号として扱うが、ASCII の `-` や U+2212(−)は負号として扱わない。
|
|
61
63
|
* 値の上限はなく、無量大数(10^68)を超える大きさもそのまま扱える。
|
|
64
|
+
* 入力長が {@link MAX_INPUT_LENGTH} を超える場合は `RangeError` を投げる。
|
|
62
65
|
*
|
|
63
66
|
* @param str 変換対象の文字列
|
|
64
67
|
* @returns テキストが表す整数値
|
|
68
|
+
* @throws {RangeError} 入力長が {@link MAX_INPUT_LENGTH} を超える場合
|
|
65
69
|
* @example
|
|
66
70
|
* toBigInt('一〇二四') // => 1024n
|
|
67
71
|
* toBigInt('マイナス千二百') // => -1200n
|
|
68
72
|
* toBigInt('一無量大数') // => 10n ** 68n
|
|
69
73
|
*/
|
|
70
74
|
export function toBigInt(str: string): bigint {
|
|
71
|
-
const
|
|
75
|
+
const s = String(str)
|
|
76
|
+
if (s.length > MAX_INPUT_LENGTH) {
|
|
77
|
+
throw new RangeError(`kansuji input exceeds maximum length of ${MAX_INPUT_LENGTH} UTF-16 code units`)
|
|
78
|
+
}
|
|
79
|
+
const cleaned = clean(s)
|
|
72
80
|
const matched = KANSUJI_REGEXP.exec(cleaned)
|
|
73
81
|
if (!matched) return 0n
|
|
74
82
|
const matchedText = matched[0]
|
|
@@ -123,6 +131,7 @@ export function toBigInt(str: string): bigint {
|
|
|
123
131
|
* @param str 変換対象の文字列
|
|
124
132
|
* @returns テキストが表す数値
|
|
125
133
|
* @throws {RangeError} 値が安全整数の範囲を超える場合
|
|
134
|
+
* @throws {RangeError} 入力長が {@link MAX_INPUT_LENGTH} を超える場合
|
|
126
135
|
* @example
|
|
127
136
|
* toNumber('一〇二四') // => 1024
|
|
128
137
|
* toNumber('一無量大数') // throws RangeError
|