Created
October 12, 2016 06:31
-
-
Save treelite/951b2573574d7fe465ce4127f9ee8d63 to your computer and use it in GitHub Desktop.
Validator for custom data
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* @file Validator for custom data | |
* @author treelite(c.xinle@gmail.com) | |
*/ | |
const STATE_IDLE = 0; | |
const STATE_SPLIT = 1; | |
const STATE_TOKEN = 2; | |
const STATE_NEWLINE = 3; | |
class Validator { | |
constructor(str) { | |
this.str = str; | |
// current token | |
this.token = ''; | |
// defined fields | |
this.fields = []; | |
// extraf fiels | |
this.extraFields = []; | |
// line count | |
this.lines = 0; | |
this.error = false; | |
// count of empty data | |
this.emptyValues = 0; | |
this.state = STATE_IDLE; | |
// all names | |
this.names = []; | |
// data for current line | |
this.values = []; | |
this.validate(); | |
} | |
get fieldCount() { | |
return this.fields.length + this.extraFields.length; | |
} | |
getResult() { | |
if (this.error) { | |
return '0:0:0:format_error'; | |
} | |
let lastFieldName = this.extraFields.length | |
? this.extraFields[this.extraFields.length - 1] | |
: this.fields[this.fields.length - 1]; | |
return (this.lines - 1) + ':' + this.fieldCount + ':' + this.emptyValues + ':' + lastFieldName; | |
} | |
validate() { | |
let str = this.str; | |
let len = str.length; | |
let c; | |
let steps; | |
let i = 0; | |
while (i < len) { | |
steps = 1; | |
c = str.charAt(i); | |
if (c === '|') { | |
steps = this.split(); | |
} | |
else if (c === '~') { | |
steps = this.escape(c + str.charAt(i + 1)); | |
} | |
else { | |
steps = this.eatToken(c); | |
} | |
if (this.error) { | |
break; | |
} | |
i += steps; | |
} | |
} | |
eatToken(c) { | |
if (this.state === STATE_TOKEN || this.state === STATE_SPLIT) { | |
this.state = STATE_TOKEN; | |
this.token += c; | |
} | |
else { | |
this.error = true; | |
} | |
return 1; | |
} | |
checkName(name) { | |
return name && (this.names.indexOf(name) < 0); | |
} | |
split() { | |
if (this.state === STATE_TOKEN || this.state === STATE_SPLIT) { | |
// collect name | |
if (this.values.length === 0 && !this.lines) { | |
if (this.checkName(this.token)) { | |
this.names.push(this.token); | |
} | |
else { | |
// name is empty | |
// or not unique | |
this.error = true; | |
} | |
} | |
this.values.push(this.token); | |
// handle empty value | |
if (!this.token) { | |
if (!this.lines) { | |
// field name can't be empty; | |
this.error = true; | |
} | |
else { | |
this.emptyValues++; | |
} | |
} | |
// handle extra fields | |
if (this.lines && this.values.length > this.fieldCount) { | |
this.extendField(); | |
} | |
this.token = ''; | |
} | |
this.state = STATE_SPLIT; | |
return 1; | |
} | |
extendField() { | |
let count = this.extraFields.length + 1; | |
let text = this.fields[this.fields.length - 1]; | |
this.extraFields.push(text + '_' + count); | |
} | |
newLine() { | |
if (this.state !== STATE_SPLIT) { | |
this.error = true; | |
} | |
else { | |
this.state = STATE_NEWLINE; | |
if (!this.lines) { | |
this.fields = this.values; | |
} | |
this.values = []; | |
this.lines++; | |
} | |
} | |
escape(token) { | |
let steps = 1; | |
if (token === '~n') { | |
this.newLine(); | |
steps++; | |
} | |
else if (token === '~|' || token === '~~') { | |
this.eatToken(token.charAt(1)); | |
steps++; | |
} | |
else { | |
this.eatToken(token.charAt(0)); | |
} | |
return steps; | |
} | |
} | |
function validate(str) { | |
let validator = new Validator(str); | |
return validator.getResult(); | |
} | |
console.log(validate('~~~')); | |
console.log(validate('|name|addr~~ness|~n|Patrick|partick@test.com|pat@test.com|~n|Annie||annie@test.com|~n')); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment