Skip to content
This repository has been archived by the owner on Jun 28, 2021. It is now read-only.

Commit

Permalink
options: accept camelize and underscore forms
Browse files Browse the repository at this point in the history
  • Loading branch information
wdavidw committed Nov 20, 2018
1 parent 3ce496d commit 0cb72e3
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 47 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
@@ -1,6 +1,12 @@

# Changelog

## Trunk

New features:

* options: accept camelize and underscore forms

## Version 4.0.1

Fix:
Expand Down
100 changes: 53 additions & 47 deletions lib/index.js
Expand Up @@ -4,24 +4,24 @@ const ResizeableBuffer = require('./ResizeableBuffer')

const default_options = {
// cast: false,
// cast_date: false,
// castDate: false,
columns: null,
delimiter: Buffer.from(','),
escape: Buffer.from('"'),
from: 1,
from_line: 1,
fromLine: 1,
objname: undefined,
// ltrim: false,
// quote: Buffer.from('"'),
// TODO create a max_comment_size
max_record_size: 0,
maxRecordSize: 0,
relax: false,
relax_column_count: false,
relaxColumnCount: false,
// rtrim: false,
skip_empty_lines: false,
skip_lines_with_empty_values: false,
skip_lines_with_error: false,
to_line: -1,
skipEmptyLines: false,
skipLinesWithEmptyValues: false,
skipLinesWithError: false,
toLine: -1,
to: -1,
trim: false
}
Expand All @@ -33,8 +33,8 @@ const space = 32
class Parser extends Transform {
constructor(opts = {}){
const options = {}
for(let i in opts){
options[i] = opts[i]
for(let opt in opts){
options[camelize(opt)] = opts[opt]
}
options.readableObjectMode = true
super(options)
Expand All @@ -55,14 +55,14 @@ class Parser extends Transform {
throw new Error('Invalid Option: cast must be true or a function')
}
// Normize option `cast_date`
if(options.cast_date === undefined || options.cast_date === null || options.cast_date === false || options.cast_date === ''){
options.cast_date = false
}else if(options.cast_date === true){
options.cast_date = function(value){
if(options.castDate === undefined || options.castDate === null || options.castDate === false || options.castDate === ''){
options.castDate = false
}else if(options.castDate === true){
options.castDate = function(value){
const date = Date.parse(value)
return !isNaN(date) ? new Date(date) : value
}
}else if(typeof options.cast_date !== 'function'){
}else if(typeof options.castDate !== 'function'){
throw new Error('Invalid Option: cast_date must be true or a function')
}
// Normalize option `comment`
Expand Down Expand Up @@ -135,12 +135,12 @@ class Parser extends Transform {
throw new Error(`Invalid Option: raw must be true, got ${JSON.stringify(options.raw)}`)
}
// Normalize option `record_delimiter`
if(!options.record_delimiter){
options.record_delimiter = []
}else if(!Array.isArray(options.record_delimiter)){
options.record_delimiter = [options.record_delimiter]
if(!options.recordDelimiter){
options.recordDelimiter = []
}else if(!Array.isArray(options.recordDelimiter)){
options.recordDelimiter = [options.recordDelimiter]
}
options.record_delimiter = options.record_delimiter.map( function(rd){
options.recordDelimiter = options.recordDelimiter.map( function(rd){
if(typeof rd === 'string'){
rd = Buffer.from(rd)
}
Expand Down Expand Up @@ -168,7 +168,7 @@ class Parser extends Transform {
this.state = {
castField: fnCastField,
commenting: false,
enabled: options.from_line === 1,
enabled: options.fromLine === 1,
escaping: false,
escapeIsQuote: options.escape === options.quote,
expectedRecordLength: options.columns === null ? 0 : options.columns.length,
Expand All @@ -182,7 +182,7 @@ class Parser extends Transform {
record: [],
recordHasError: false,
record_length: 0,
recordDelimiterMaxLength: options.record_delimiter.length === 0 ? 2 : Math.max(...options.record_delimiter.map( (v) => v.length)),
recordDelimiterMaxLength: options.recordDelimiter.length === 0 ? 2 : Math.max(...options.recordDelimiter.map( (v) => v.length)),
trimChars: [Buffer.from(' ')[0], Buffer.from('\t')[0]],
wasQuoting: false,
wasRowDelimiter: false
Expand All @@ -206,8 +206,8 @@ class Parser extends Transform {
callback(err)
}
__parse(nextBuf, end){
const {comment, escape, from, from_line, info, ltrim, max_record_size, quote, raw, relax, rtrim, skip_empty_lines, to, to_line} = this.options
let {record_delimiter} = this.options
const {comment, escape, from, fromLine, info, ltrim, maxRecordSize, quote, raw, relax, rtrim, skipEmptyLines, to, toLine} = this.options
let {recordDelimiter} = this.options
const {previousBuf, rawBuffer, escapeIsQuote, trimChars} = this.state
let buf
if(previousBuf === undefined && nextBuf !== undefined){
Expand All @@ -233,16 +233,16 @@ class Parser extends Transform {
}
this.state.wasRowDelimiter = false
}
if(to_line !== -1 && this.info.lines > to_line){
if(toLine !== -1 && this.info.lines > toLine){
this.state.stop = true
this.push(null)
return
}
// Auto discovery of record_delimiter, unix, mac and windows supported
if(this.state.quoting === false && record_delimiter.length === 0){
if(this.state.quoting === false && recordDelimiter.length === 0){
const recordDelimiterCount = this.__autoDiscoverRowDelimiter(buf, pos)
if(recordDelimiterCount){
record_delimiter = this.options.record_delimiter
recordDelimiter = this.options.recordDelimiter
}
}
const chr = buf[pos]
Expand Down Expand Up @@ -279,7 +279,7 @@ class Parser extends Transform {
// const isNextChrComment = nextChr === comment
const isNextChrComment = comment !== null && this.__compareBytes(comment, buf, pos+1, nextChr)
const isNextChrDelimiter = this.__isDelimiter(nextChr, buf, pos+1)
const isNextChrRowDelimiter = record_delimiter.length === 0 ? this.__autoDiscoverRowDelimiter(buf, pos+1) : this.__isRecordDelimiter(nextChr, buf, pos+1)
const isNextChrRowDelimiter = recordDelimiter.length === 0 ? this.__autoDiscoverRowDelimiter(buf, pos+1) : this.__isRecordDelimiter(nextChr, buf, pos+1)
// Escape a quote
// Treat next char as a regular character
// TODO: need to compare bytes instead of single char
Expand Down Expand Up @@ -320,13 +320,13 @@ class Parser extends Transform {
this.info.comment_lines++
// Skip full comment line
}else{
// Skip if line is empty and skip_empty_lines activated
if(skip_empty_lines === true && this.state.wasQuoting === false && this.state.record.length === 0 && this.state.field.length === 0){
// Skip if line is empty and skipEmptyLines activated
if(skipEmptyLines === true && this.state.wasQuoting === false && this.state.record.length === 0 && this.state.field.length === 0){
this.info.empty_lines++
continue
}
// Activate records emition if above from_line
if(this.state.enabled === false && this.info.lines + (this.state.wasRowDelimiter === true ? 1: 0 ) >= from_line){
// Activate records emition if above fromLine
if(this.state.enabled === false && this.info.lines + (this.state.wasRowDelimiter === true ? 1: 0 ) >= fromLine){
this.state.enabled = true
this.__resetField()
this.__resetRow()
Expand Down Expand Up @@ -365,8 +365,8 @@ class Parser extends Transform {
}
}
if(this.state.commenting === false){
if(max_record_size !== 0 && this.state.record_length + this.state.field.length > max_record_size){
const err = this.__error(`Max Record Size: record exceed the maximum number of tolerated bytes of ${max_record_size} on line ${this.info.lines}`)
if(maxRecordSize !== 0 && this.state.record_length + this.state.field.length > maxRecordSize){
const err = this.__error(`Max Record Size: record exceed the maximum number of tolerated bytes of ${maxRecordSize} on line ${this.info.lines}`)
if(err !== undefined) return err
}
}
Expand Down Expand Up @@ -410,7 +410,7 @@ class Parser extends Transform {
return chr === space || chr === cr || chr === nl
}
__onRow(){
const {columns, info, from, relax_column_count, raw, skip_lines_with_empty_values} = this.options
const {columns, info, from, relaxColumnCount, raw, skipLinesWithEmptyValues} = this.options
const {enabled, record} = this.state
// Validate column length
if(columns === true && this.state.firstLineToHeaders){
Expand All @@ -421,7 +421,7 @@ class Parser extends Transform {
this.state.expectedRecordLength = recordLength
}else if(enabled === true){
if(recordLength !== this.state.expectedRecordLength){
if(relax_column_count === true){
if(relaxColumnCount === true){
this.info.invalid_field_length++
}else{
if(columns === false){
Expand All @@ -437,7 +437,7 @@ class Parser extends Transform {
if(enabled === false){
return this.__resetRow()
}
if( skip_lines_with_empty_values === true){
if( skipLinesWithEmptyValues === true){
if(record.map( (field) => field.trim() ).join('') === ''){
this.__resetRow()
return
Expand Down Expand Up @@ -562,8 +562,8 @@ class Parser extends Transform {
return [undefined, parseInt(field)]
}else if(this.__isFloat(field)){
return [undefined, parseFloat(field)]
}else if(this.options.cast_date !== false){
return [undefined, this.options.cast_date.call(null, field, context)]
}else if(this.options.castDate !== false){
return [undefined, this.options.castDate.call(null, field, context)]
}
return [undefined, field]
}
Expand Down Expand Up @@ -614,10 +614,10 @@ class Parser extends Transform {
return delimiter.length
}
__isRecordDelimiter(chr, buf, pos){
const {record_delimiter} = this.options
const recordDelimiterLength = record_delimiter.length
const {recordDelimiter} = this.options
const recordDelimiterLength = recordDelimiter.length
loop1: for(let i = 0; i < recordDelimiterLength; i++){
const rd = record_delimiter[i]
const rd = recordDelimiter[i]
const rdLength = rd.length
if(rd[0] !== chr){
continue
Expand All @@ -635,25 +635,25 @@ class Parser extends Transform {
const chr = buf[pos]
if(chr === cr){
if(buf[pos+1] === nl){
this.options.record_delimiter.push(Buffer.from('\r\n'))
this.options.recordDelimiter.push(Buffer.from('\r\n'))
this.state.recordDelimiterMaxLength = 2
return 2
}else{
this.options.record_delimiter.push(Buffer.from('\r'))
this.options.recordDelimiter.push(Buffer.from('\r'))
this.state.recordDelimiterMaxLength = 1
return 1
}
}else if(chr === nl){
this.options.record_delimiter.push(Buffer.from('\n'))
this.options.recordDelimiter.push(Buffer.from('\n'))
this.state.recordDelimiterMaxLength = 1
return 1
}
return 0
}
__error(msg){
const {skip_lines_with_error} = this.options
const {skipLinesWithError} = this.options
const err = new Error(msg)
if(skip_lines_with_error){
if(skipLinesWithError){
this.state.recordHasError = true
this.emit('skip', err)
return undefined
Expand Down Expand Up @@ -709,6 +709,12 @@ parse.Parser = Parser

module.exports = parse

const camelize = function(str){
return str.replace(/_([a-z])/gi, function(_, match, index){
return match.toUpperCase()
})
}

const isObject = function(obj){
return (typeof obj === 'object' && obj !== null && !Array.isArray(obj))
}
Expand Down
5 changes: 5 additions & 0 deletions test/options.coffee
Expand Up @@ -13,3 +13,8 @@ describe 'Options', ->
return next err if err
(options.quote is false).should.be.true()
next()

it 'camelize options', ->
parser = parse record_delimiter: ':'
parser.options.recordDelimiter.toString().should.eql ':'
(parser.options.record_delimiter is undefined).should.be.true()

0 comments on commit 0cb72e3

Please sign in to comment.