Skip to content

Commit e34c08b

Browse files
major vanilla lua speedups
1 parent c58bd79 commit e34c08b

File tree

2 files changed

+58
-27
lines changed

2 files changed

+58
-27
lines changed

ftcsv.lua

+57-27
Original file line numberDiff line numberDiff line change
@@ -27,14 +27,69 @@ local ftcsv = {
2727
]]
2828
}
2929

30-
-- lua 5.1 compat
30+
-- lua 5.1 load compat
3131
local M = {}
3232
if type(jit) == 'table' or _ENV then
3333
M.load = _G.load
3434
else
3535
M.load = loadstring
3636
end
3737

38+
-- luajit specific speedups
39+
-- luajit performs faster with iterating over string.byte,
40+
-- whereas vanilla lua performs faster with string.find
41+
if type(jit) == 'table' then
42+
-- finds the end of an escape sequence
43+
function M.findClosingQuote(i, inputLength, inputString, quote, doubleQuoteEscape)
44+
-- local doubleQuoteEscape = doubleQuoteEscape
45+
local currentChar, nextChar = string.byte(inputString, i), nil
46+
while i <= inputLength do
47+
-- print(i)
48+
nextChar = string.byte(inputString, i+1)
49+
50+
-- this one deals with " double quotes that are escaped "" within single quotes "
51+
-- these should be turned into a single quote at the end of the field
52+
if currentChar == quote and nextChar == quote then
53+
doubleQuoteEscape = true
54+
i = i + 2
55+
currentChar = string.byte(inputString, i)
56+
57+
-- identifies the escape toggle
58+
elseif currentChar == quote and nextChar ~= quote then
59+
-- print("exiting", i-1)
60+
return i-1, doubleQuoteEscape
61+
else
62+
i = i + 1
63+
currentChar = nextChar
64+
end
65+
end
66+
end
67+
68+
else
69+
-- vanilla lua closing quote finder
70+
function M.findClosingQuote(i, inputLength, inputString, quote, doubleQuoteEscape)
71+
local firstCharIndex = 1
72+
local firstChar, iChar = nil, nil
73+
repeat
74+
firstCharIndex, i = inputString:find('".?', i+1)
75+
firstChar = string.byte(inputString, firstCharIndex)
76+
iChar = string.byte(inputString, i)
77+
-- nextChar = string.byte(inputString, i+1)
78+
-- print("HI", offset, i)
79+
-- print(firstChar, iChar)
80+
if firstChar == quote and iChar == quote then
81+
doubleQuoteEscape = true
82+
end
83+
until iChar ~= quote
84+
if i == nil then
85+
return inputLength-1, doubleQuoteEscape
86+
end
87+
-- print("exiting", i-2)
88+
return i-2, doubleQuoteEscape
89+
end
90+
91+
end
92+
3893
-- load an entire file into memory
3994
local function loadFile(textFile)
4095
local file = io.open(textFile, "r")
@@ -44,31 +99,6 @@ local function loadFile(textFile)
4499
return allLines
45100
end
46101

47-
-- finds the end of an escape sequence
48-
local function findClosingQuote(i, inputLength, inputString, quote, doubleQuoteEscape)
49-
-- local doubleQuoteEscape = doubleQuoteEscape
50-
local currentChar, nextChar = string.byte(inputString, i), nil
51-
while i <= inputLength do
52-
-- print(i)
53-
nextChar = string.byte(inputString, i+1)
54-
55-
-- this one deals with " double quotes that are escaped "" within single quotes "
56-
-- these should be turned into a single quote at the end of the field
57-
if currentChar == quote and nextChar == quote then
58-
doubleQuoteEscape = true
59-
i = i + 2
60-
currentChar = string.byte(inputString, i)
61-
62-
-- identifies the escape toggle
63-
elseif currentChar == quote and nextChar ~= quote then
64-
return i-1, doubleQuoteEscape
65-
else
66-
i = i + 1
67-
currentChar = nextChar
68-
end
69-
end
70-
end
71-
72102
-- creates a new field and adds it to the main table
73103
local function createNewField(inputString, quote, fieldStart, i, line, fieldNum, doubleQuoteEscape, fieldsToKeep)
74104
-- print(lineNum, fieldNum, fieldStart, i-1)
@@ -193,7 +223,7 @@ function ftcsv.parse(inputFile, delimiter, options)
193223
elseif currentChar == quote and nextChar ~= quote then
194224
-- print("ESCAPE TOGGLE")
195225
fieldStart = i + 1
196-
i, doubleQuoteEscape = findClosingQuote(i+1, inputLength, inputString, quote, doubleQuoteEscape)
226+
i, doubleQuoteEscape = M.findClosingQuote(i+1, inputLength, inputString, quote, doubleQuoteEscape)
197227
-- print("I VALUE", i, doubleQuoteEscape)
198228
skipChar = 1
199229
-- end

spec/parse_encode_spec.lua

+1
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ describe("csv decode", function()
3434
local json = loadFile("spec/json/" .. value .. ".json")
3535
json = cjson.decode(json)
3636
local parse = ftcsv.parse("spec/csvs/" .. value .. ".csv", ",")
37+
assert.are.same(#json, #parse)
3738
assert.are.same(json, parse)
3839
end)
3940
end

0 commit comments

Comments
 (0)