Socket
Socket
Sign inDemoInstall

randexp

Package Overview
Dependencies
Maintainers
1
Versions
20
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

randexp - npm Package Compare versions

Comparing version 0.3.4 to 0.4.0

349

lib/randexp.js
var ret = require('ret');
var DRange = require('discontinuous-range');
var types = ret.types;

@@ -6,14 +7,2 @@

/**
* Returns random number in the range [a, b].
*
* @param {Number} a
* @param {Number} b
* @return {Number}
*/
function randInt(a, b) {
return a + Math.floor(Math.random() * (1 + b - a));
}
/**
* If code is alphabetic, converts to other case.

@@ -32,132 +21,153 @@ * If not alphabetic, returns back code.

/**
* Returns subset of [a, b] if [from, to] is in it.
* Randomly returns a true or false value.
*
* @param {Number} a
* @param {Number} b
* @param {Number} from
* @param {Number} to
* @return {Object|Boolean}
* {Number} from
* {Number} to
* @return {Boolean}
*/
function range(a, b, from, to) {
return a <= from && from <= b ? { from: from, to: Math.min(b, to) } :
a <= to && to <= b ? { from: Math.max(a, from), to: to } :
false;
}
function randBool() {
return !this.randInt(0, 1);
};
/**
* Returns true if all properties of a are equal to b.
* a and b are arrays of objects.
*
* @param {Number} a
* @param {Number} b
* Randomly selects and returns a value from the array.
*
* @param {Array.<Object>} arr
* @return {Object}
*/
function deepEqual(a, b) {
var i, l, key, obj;
if ((l = a.length) !== b.length) return false;
for (i = 0; i < l; i++) {
obj = a[i];
for (key in obj) {
if (obj.hasOwnProperty(key) && obj[key] !== b[i][key]) {
return false;
}
}
function randSelect(arr) {
if (arr instanceof DRange) {
return arr.index(this.randInt(0, arr.length - 1));
}
return arr[this.randInt(0, arr.length - 1)];
};
return true;
}
/**
* Determines if a character code is alphabetic and decide
* to switch case randomly.
*
* @param {Number} code
* @param {Boolean} ignoreCase
* @return {String}
*/
function char(code, ignoreCase) {
code = ignoreCase && randBool.call(this) ? toOtherCase(code) : code;
return String.fromCharCode(code);
};
/**
* Returns true if negated needle set is inside of sets array.
* Using deepEqual as comparator.
* expands a token to a DiscontinuousRange of characters which has a
* length and an index function (for random selecting)
*
* @param {Array.<Object>} sets
* @param {String} needle
* @param {Boolean}
* @param {Object} token
* @return {DiscontinuousRange}
*/
function findNotSet(sets, needle) {
for (var i = 0, l = sets.length; i < l; i++) {
var cset = sets[i];
if (cset.not !== needle.not && deepEqual(cset.set, needle.set)) {
return true;
function expand(token) {
if (token.type === ret.types.CHAR) return new DRange(token.value);
if (token.type === ret.types.RANGE) return new DRange(token.from, token.to);
if (token.type === ret.types.SET) {
var drange = new DRange();
for (var i = 0; i < token.set.length; i++) {
drange.add(expand.call(this, token.set[i]));
}
if (token.not) {
return this.defaultRange.clone().subtract(drange);
} else {
return drange;
}
}
throw new Error('unexpandable token type: ' + token.type);
};
return false;
}
/**
* Returns true if character is in class set.
*
* @param {Object} set
* @param {Number} code
* @param {Boolean} ignoreCase
* @return {Boolean}
* @constructor
* @param {RegExp|String} regexp
* @param {String} m
*/
function inClass(set, code, ignoreCase) {
var token;
var v;
var sets = [];
var infLoop = false;
var RandExp = module.exports = function(regexp, m) {
this.defaultRange = this.defaultRange.clone();
if (regexp instanceof RegExp) {
this.ignoreCase = regexp.ignoreCase;
this.multiline = regexp.multiline;
if (typeof regexp.max === 'number') {
this.max = regexp.max;
}
regexp = regexp.source;
for (var i = 0, l = set.length; i < l; i++) {
token = set[i];
} else if (typeof regexp === 'string') {
this.ignoreCase = m && m.indexOf('i') !== -1;
this.multiline = m && m.indexOf('m') !== -1;
} else {
throw new Error('Expected a regexp or string');
}
switch (token.type) {
case types.CHAR:
v = token.value;
if (v === code || (ignoreCase && toOtherCase(v) === code)) {
return true;
}
break;
this.tokens = ret(regexp);
};
case types.RANGE:
// If ignoreCase is on, and alphabetic character ranges fall
// inside this range, check against both cases.
if (token.from <= code && code <= token.to || (ignoreCase &&
(((v = range(97, 122, token.from, token.to)) !== false &&
v.from <= code && code <= v.to) ||
((v = range(65, 90, token.from, token.to)) !== false &&
v.from <= code && code <= v.to)))) {
return true;
}
break;
case types.SET:
// Use these to detect an infinite loop with 2 sets
// that cancel out each other.
if (sets.length > 0 && findNotSet(sets, token)) {
infLoop = true;
} else {
sets.push(token);
}
// When a repetitional token has its max set to Infinite,
// randexp won't actually generate a random amount between min and Infinite
// instead it will see Infinite as min + 100.
RandExp.prototype.max = 100;
if (!infLoop &&
inClass(token.set, code, ignoreCase) !== token.not) {
return true;
}
// Generates the random string.
RandExp.prototype.gen = function() {
return gen.call(this, this.tokens, []);
};
// Enables use of randexp with a shorter call.
RandExp.randexp = function(regexp, m) {
var randexp;
if (regexp._randexp === undefined) {
randexp = new RandExp(regexp, m);
regexp._randexp = randexp;
} else {
randexp = regexp._randexp;
if (typeof regexp.max === 'number') {
randexp.max = regexp.max;
}
if (regexp.defaultRange instanceof DRange) {
randexp.defaultRange = regexp.defaultRange;
}
if (typeof regexp.randInt === 'function') {
randexp.randInt = regexp.randInt;
}
}
return false;
}
return randexp.gen();
};
// This enables sugary /regexp/.gen syntax.
RandExp.sugar = function() {
/* jshint freeze:false */
RegExp.prototype.gen = function() {
return RandExp.randexp(this);
};
};
// This allows expanding to include additional characters
// for instance: RandExp.defaultRange.add(0, 65535);
RandExp.prototype.defaultRange = new DRange(32, 126);
/**
* Determines if a character code is alphabetic and decide
* to switch case randomly.
* Randomly generates and returns a number between a and b (inclusive).
*
* @param {Number} code
* @param {Boolean} ignoreCase
* @return {String}
* @param {Number} a
* @param {Number} b
* @return {Number}
*/
function char(code, ignoreCase) {
return String.fromCharCode(ignoreCase && Math.random() > 0.5 ?
toOtherCase(code) : code);
}
RandExp.prototype.randInt = function(a, b) {
return a + Math.floor(Math.random() * (1 + b - a));
};

@@ -170,7 +180,6 @@

* @param {Array.<String>} groups
* @param {Boolean} negate
* @return {String}
*/
function gen(token, groups, negate) {
var stack, str, n, i, l, not;
function gen(token, groups) {
var stack, str, n, i, l;

@@ -189,5 +198,3 @@ switch (token.type) {

stack = token.options ?
token.options[Math.floor(Math.random() * token.options.length)] :
token.stack;
stack = token.options ? randSelect.call(this, token.options) : token.stack;

@@ -212,31 +219,8 @@ str = '';

// If this class is an except class, i.e. [^abc],
// generate a random character until one that isnt in this class
// is found.
negate = !!negate;
not = negate !== token.not;
if (not) {
while (true) {
var c = this.anyRandChar();
var code = c.charCodeAt(0);
var expanded_set = expand.call(this, token);
if (!expanded_set.length) return '';
return char.call(this, randSelect.call(this, expanded_set), this.ignoreCase);
if (inClass(token.set, code, this.ignoreCase)) { continue; }
return c;
}
// Otherwise, pick a random token in the class set.
} else {
if (token.set.length) {
return gen.call(this,
token.set[Math.floor(Math.random() * token.set.length)],
groups, not);
} else {
return '';
}
}
break;
case types.RANGE:
return char(randInt(token.from, token.to), this.ignoreCase);
return char.call(this, this.randInt(token.from, token.to), this.ignoreCase);

@@ -246,3 +230,3 @@

// Randomly generate number between min and max.
n = randInt(token.min,
n = this.randInt(token.min,
token.max === Infinity ? token.min + this.max : token.max);

@@ -263,3 +247,3 @@

case types.CHAR:
return char(token.value, this.ignoreCase);
return char.call(this, token.value, this.ignoreCase);
}

@@ -269,76 +253,1 @@ }

/**
* @constructor
* @param {RegExp|String} regexp
* @param {String} m
*/
var RandExp = module.exports = function(regexp, m) {
if (regexp instanceof RegExp) {
this.ignoreCase = regexp.ignoreCase;
this.multiline = regexp.multiline;
if (typeof regexp.max === 'number') {
this.max = regexp.max;
}
if (typeof regexp.anyRandChar === 'function') {
this.anyRandChar = regexp.anyRandChar;
}
regexp = regexp.source;
} else if (typeof regexp === 'string') {
this.ignoreCase = m && m.indexOf('i') !== -1;
this.multiline = m && m.indexOf('m') !== -1;
} else {
throw new Error('Expected a regexp or string');
}
this.tokens = ret(regexp);
};
// When a repetitional token has its max set to Infinite,
// randexp won't actually generate a random amount between min and Infinite
// instead it will see Infinite as min + 100.
RandExp.prototype.max = 100;
// Returns any random character.
RandExp.prototype.anyRandChar = function() {
return String.fromCharCode(randInt(0, 65535));
};
// Generates the random string.
RandExp.prototype.gen = function() {
return gen.call(this, this.tokens, []);
};
// Enables use of randexp with a shorter call.
// Saves the RandExp object into the regex.
var randexp = RandExp.randexp = function(regexp, m) {
var randexp;
if (regexp._randexp === undefined) {
randexp = new RandExp(regexp, m);
regexp._randexp = randexp;
} else {
randexp = regexp._randexp;
if (typeof regexp.max === 'number') {
randexp.max = regexp.max;
}
if (typeof regexp.anyRandChar === 'function') {
randexp.anyRandChar = regexp.anyRandChar;
}
}
return randexp.gen();
};
// This enables sugary /regexp/.gen syntax.
RandExp.sugar = function() {
/* jshint freeze:false */
RegExp.prototype.gen = function() {
return randexp(this);
};
};

@@ -5,3 +5,3 @@ {

"keywords": ["regex", "regexp", "regular expression", "random", "test"],
"version": "0.3.4",
"version": "0.4.0",
"homepage": "http://fent.github.io/randexp.js/",

@@ -21,3 +21,4 @@ "repository": {

"dependencies": {
"ret": "0.1.x"
"discontinuous-range": "1.0.0",
"ret": "0.1.10"
},

@@ -24,0 +25,0 @@ "devDependencies": {

@@ -20,3 +20,3 @@ # randexp.js [![Build Status](https://secure.travis-ci.org/fent/randexp.js.png)](http://travis-ci.org/fent/randexp.js)

new RandExp(/random stuff: .+/).gen();
// => random stuff: 湐箻ໜ䫴␩⶛㳸長���邓蕲뤀쑡篷皇硬剈궦佔칗븛뀃匫鴔事좍ﯣ⭼ꝏ䭍詳蒂䥂뽭
// => random stuff: l3m;Hf9XYbI [YPaxV>U*4-_F!WXQh9>;rH3i l!8.zoh?[utt1OWFQrE ^~8zEQm]~tK

@@ -57,20 +57,18 @@ // ignore case

# Negated Character Sets
Sets like the `.` character will match anything except a new line. In this case, a character with a random char code between 0 and 65535 will be generated. If you want to overwrite this function you can change the `anyRandChar` function in the randexp object.
# Default Range
The default generated character range includes printable ASCII. In order to add or remove characters,
a `defaultRange` attribute is exposed. you can `subtract(from, to)` and `add(from, to)`
```js
var randexp = new RandExp(/./);
randexp.anyRandChar = function() {
return 'c';
};
var randexp = new RandExp(/random stuff: .+/);
randexp.defaultRange.subtract(32, 126);
randexp.defaultRange.add(0, 65535);
randexp.gen();
// => random stuff: 湐箻ໜ䫴␩⶛㳸長���邓蕲뤀쑡篷皇硬剈궦佔칗븛뀃匫鴔事좍ﯣ⭼ꝏ䭍詳蒂䥂뽭
```
If using `RandExp.sugar()`
# Custom PRNG
The default randomness is provided by `Math.random()`. If you need to use a seedable or cryptographic PRNG you
can override `RandExp.prototype.randInt` or `randexp.randInt` (where `randexp` is an instance of `RandExp`. `randInt(from, to)` accepts an inclusive range and returns a randomly selected
number within that range.
```js
var regexp = /./;
regexp.anyRandChar = function() {
return 'c';
};
```

@@ -102,5 +100,3 @@ # Infinite Repetitionals

Other cancelling out character sets like `/[^\D]/` are bad too. These are the same as `/[\d]/`. Except it will be slow in generating a matching string because it will first generate a random character and then check if it's in the set inside. It will take a while to randomly generate an integer out of 65535 characters.
# Install

@@ -107,0 +103,0 @@ ### Node.js

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc