diff --git a/lib/functions.js b/lib/functions.js index e957c8c..cbeaea4 100644 --- a/lib/functions.js +++ b/lib/functions.js @@ -401,6 +401,94 @@ registerFunction({ } }) +registerFunction({ + name: 'indexOf', + instances: ['String'], + returns: ['Integer'], + minArgs: 2, + maxArgs: 3, + handler(string, search, fromIndex) { + if (typeof search !== 'string') { + throw new EvaluationError('string.indexOf(search, fromIndex): search must be a string') + } + + if (fromIndex === undefined) return BigInt(string.indexOf(search)) + + if (typeof fromIndex !== 'bigint') { + throw new EvaluationError('string.indexOf(search, fromIndex): fromIndex must be an integer') + } + + if (search === '') return fromIndex + + fromIndex = Number(fromIndex) + if (fromIndex < 0 || fromIndex >= string.length) { + throw new EvaluationError('string.indexOf(search, fromIndex): fromIndex out of range') + } + + return BigInt(string.indexOf(search, fromIndex)) + } +}) + +registerFunction({ + name: 'lastIndexOf', + instances: ['String'], + returns: ['Integer'], + minArgs: 2, + maxArgs: 3, + handler(string, search, fromIndex) { + if (typeof search !== 'string') { + throw new EvaluationError('string.lastIndexOf(search, fromIndex): search must be a string') + } + + if (fromIndex === undefined) return BigInt(string.lastIndexOf(search)) + + if (typeof fromIndex !== 'bigint') { + throw new EvaluationError( + 'string.lastIndexOf(search, fromIndex): fromIndex must be an integer' + ) + } + + if (search === '') return fromIndex + + fromIndex = Number(fromIndex) + if (fromIndex < 0 || fromIndex >= string.length) { + throw new EvaluationError('string.lastIndexOf(search, fromIndex): fromIndex out of range') + } + + return BigInt(string.lastIndexOf(search, fromIndex)) + } +}) + +registerFunction({ + name: 'substring', + instances: ['String'], + returns: ['String'], + minArgs: 2, + maxArgs: 3, + handler(string, start, end) { + if (typeof start === 'bigint') start = Number(start) + + if (typeof start !== 'number') { + throw new EvaluationError('string.substring(start, end): start index must be an integer') + } + + if (start < 0 || start > string.length) { + throw new EvaluationError('string.substring(start, end): start index out of range') + } + + if (end === undefined) return string.substring(start) + + if (typeof end === 'bigint') end = Number(end) + if (typeof end !== 'number') { + throw new EvaluationError('string.substring(start, end): end index must be an integer') + } else if (end < start || end > string.length) { + throw new EvaluationError('string.substring(start, end): end index out of range') + } + + return string.substring(start, end) + } +}) + registerFunction({ name: 'matches', instances: ['String'], @@ -419,6 +507,46 @@ registerFunction({ } }) +registerFunction({ + name: 'split', + instances: ['String'], + returns: ['List'], + minArgs: 2, + maxArgs: 3, + handler(string, separator, limit) { + if (limit !== undefined && !(typeof limit === 'bigint' || typeof limit === 'number')) { + throw new EvaluationError('string.split(separator, limit): limit must be an integer') + } + + if (typeof separator !== 'string') { + throw new EvaluationError('string.split(separator, limit): separator must be a string') + } + + return string.split(separator, limit) + } +}) + +registerFunction({ + name: 'join', + instances: ['List'], + returns: ['String'], + minArgs: 1, + maxArgs: 2, + handler(list, separator = '') { + if (typeof separator !== 'string') { + throw new EvaluationError('string.join(separator): separator must be a string') + } + + for (let i = 0; i < list.length; i++) { + if (typeof list[i] !== 'string') { + throw new EvaluationError('string.join(separator): list must contain only strings') + } + } + + return list.join(separator) + } +}) + const ByteOpts = typeof Buffer !== 'undefined' ? {