summaryrefslogtreecommitdiff
path: root/data/extensions/uBlock0@raymondhill.net/js/arglist-parser.js
diff options
context:
space:
mode:
Diffstat (limited to 'data/extensions/uBlock0@raymondhill.net/js/arglist-parser.js')
-rw-r--r--data/extensions/uBlock0@raymondhill.net/js/arglist-parser.js116
1 files changed, 116 insertions, 0 deletions
diff --git a/data/extensions/uBlock0@raymondhill.net/js/arglist-parser.js b/data/extensions/uBlock0@raymondhill.net/js/arglist-parser.js
new file mode 100644
index 0000000..708029e
--- /dev/null
+++ b/data/extensions/uBlock0@raymondhill.net/js/arglist-parser.js
@@ -0,0 +1,116 @@
+/*******************************************************************************
+
+ uBlock Origin - a comprehensive, efficient content blocker
+ Copyright (C) 2020-present Raymond Hill
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see {http://www.gnu.org/licenses/}.
+
+ Home: https://github.com/gorhill/uBlock
+*/
+
+/******************************************************************************/
+
+export class ArglistParser {
+ constructor(separatorChar = ',', mustQuote = false) {
+ this.separatorChar = this.actualSeparatorChar = separatorChar;
+ this.separatorCode = this.actualSeparatorCode = separatorChar.charCodeAt(0);
+ this.mustQuote = mustQuote;
+ this.quoteBeg = 0; this.quoteEnd = 0;
+ this.argBeg = 0; this.argEnd = 0;
+ this.separatorBeg = 0; this.separatorEnd = 0;
+ this.transform = false;
+ this.failed = false;
+ this.reWhitespaceStart = /^\s+/;
+ this.reWhitespaceEnd = /(?:^|\S)(\s+)$/;
+ this.reOddTrailingEscape = /(?:^|[^\\])(?:\\\\)*\\$/;
+ this.reTrailingEscapeChars = /\\+$/;
+ }
+ nextArg(pattern, beg = 0) {
+ const len = pattern.length;
+ this.quoteBeg = beg + this.leftWhitespaceCount(pattern.slice(beg));
+ this.failed = false;
+ const qc = pattern.charCodeAt(this.quoteBeg);
+ if ( qc === 0x22 /* " */ || qc === 0x27 /* ' */ || qc === 0x60 /* ` */ ) {
+ this.indexOfNextArgSeparator(pattern, qc);
+ if ( this.argEnd !== len ) {
+ this.quoteEnd = this.argEnd + 1;
+ this.separatorBeg = this.separatorEnd = this.quoteEnd;
+ this.separatorEnd += this.leftWhitespaceCount(pattern.slice(this.quoteEnd));
+ if ( this.separatorEnd === len ) { return this; }
+ if ( pattern.charCodeAt(this.separatorEnd) === this.separatorCode ) {
+ this.separatorEnd += 1;
+ return this;
+ }
+ }
+ }
+ this.indexOfNextArgSeparator(pattern, this.separatorCode);
+ this.separatorBeg = this.separatorEnd = this.argEnd;
+ if ( this.separatorBeg < len ) {
+ this.separatorEnd += 1;
+ }
+ this.argEnd -= this.rightWhitespaceCount(pattern.slice(0, this.separatorBeg));
+ this.quoteEnd = this.argEnd;
+ if ( this.mustQuote ) {
+ this.failed = true;
+ }
+ return this;
+ }
+ normalizeArg(s, char = '') {
+ if ( char === '' ) { char = this.actualSeparatorChar; }
+ let out = '';
+ let pos = 0;
+ while ( (pos = s.lastIndexOf(char)) !== -1 ) {
+ out = s.slice(pos) + out;
+ s = s.slice(0, pos);
+ const match = this.reTrailingEscapeChars.exec(s);
+ if ( match === null ) { continue; }
+ const tail = (match[0].length & 1) !== 0
+ ? match[0].slice(0, -1)
+ : match[0];
+ out = tail + out;
+ s = s.slice(0, -match[0].length);
+ }
+ if ( out === '' ) { return s; }
+ return s + out;
+ }
+ leftWhitespaceCount(s) {
+ const match = this.reWhitespaceStart.exec(s);
+ return match === null ? 0 : match[0].length;
+ }
+ rightWhitespaceCount(s) {
+ const match = this.reWhitespaceEnd.exec(s);
+ return match === null ? 0 : match[1].length;
+ }
+ indexOfNextArgSeparator(pattern, separatorCode) {
+ this.argBeg = this.argEnd = separatorCode !== this.separatorCode
+ ? this.quoteBeg + 1
+ : this.quoteBeg;
+ this.transform = false;
+ if ( separatorCode !== this.actualSeparatorCode ) {
+ this.actualSeparatorCode = separatorCode;
+ this.actualSeparatorChar = String.fromCharCode(separatorCode);
+ }
+ while ( this.argEnd < pattern.length ) {
+ const pos = pattern.indexOf(this.actualSeparatorChar, this.argEnd);
+ if ( pos === -1 ) {
+ return (this.argEnd = pattern.length);
+ }
+ if ( this.reOddTrailingEscape.test(pattern.slice(0, pos)) === false ) {
+ return (this.argEnd = pos);
+ }
+ this.transform = true;
+ this.argEnd = pos + 1;
+ }
+ }
+}