Skip to content

Instantly share code, notes, and snippets.

@friendlyanon
Last active February 27, 2022 03:38
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save friendlyanon/1444a3fe190e909a8531d90e51163dde to your computer and use it in GitHub Desktop.
Save friendlyanon/1444a3fe190e909a8531d90e51163dde to your computer and use it in GitHub Desktop.
PHP's explode function implemented in JavaScript
/**
* Explode implementation. The inputs to this function are not validated, use
* {@link explode} for inputs that might not meet the requirements.
*
* @param delimiter Non-empty string
* @param string
* @param limit Integer in the range of [2 - 4294967295]
*/
export function explodeUnchecked(
delimiter: string,
string: string,
limit: number,
): string[] {
let index = string.indexOf(delimiter);
if (index === -1) {
return [string];
}
const { length } = delimiter;
if (limit === 2) {
return [string.slice(0, index), string.slice(index + length)];
}
const result: string[] = [];
let previous = 0;
do {
const slice = string.slice(previous, index);
const count = result.push(slice);
previous += slice.length + length;
if (count + 1 === limit) {
break;
}
index = string.indexOf(delimiter, previous);
} while (index !== -1);
result.push(string.slice(previous));
return result;
}
const parseLimit = (limit: number): [boolean, number] =>
limit === 0 ? [false, 1] : [limit < 0, Math.abs(Math.trunc(limit))];
const maxLimit = -1 >>> 0;
/**
* This function validates its inputs and delegates to
* {@link explodeUnchecked}, then if `limit` was a negative number,
* removes that many slices from the end of the result.
*
* @see https://www.php.net/manual/en/function.explode.php
*
* @param delimiter
* @param string
* @param limit
*
* @throws {TypeError} if limit is NaN
* @throws {Error} if delimiter is an empty string
* @throws {RangeError} if the validated limit is bigger than the maximum array
* capacity
*/
export function explode(
delimiter: string,
string: string,
limit: number = maxLimit,
): string[] {
if (isNaN(limit)) {
throw new TypeError("limit is not a number");
}
if (!delimiter) {
throw new Error("Empty delimiter");
}
const [isNegative, max] = parseLimit(limit);
if (max > maxLimit) {
throw new RangeError(
`limit (${max}) is out of range (-${maxLimit} - ${maxLimit})`,
);
}
const slices = string === "" || max === 1
? [string]
: explodeUnchecked(delimiter, string, max);
if (isNegative) {
return max < slices.length
? slices.slice(0, slices.length - max)
: [];
}
return slices;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment