Added an openstring function, by wrapping the string in an object

that supports read(bytes) and passing the object to the underlying
code. Modified all the tests to run with both open and openstring.

Changed the default buffer size in csv.lua to match the value in the
README, and added the crucial blank line to test-data/blankline.csv
This commit is contained in:
Kevin Martin 2014-05-18 18:52:16 +01:00
parent 1ed256e9f5
commit f28dfe0720
6 changed files with 81 additions and 8 deletions

View File

@ -1 +1,2 @@
Leyland, Geoff Leyland, Geoff
Martin, Kevin

View File

@ -1,4 +1,5 @@
Copyright (c) 2013 Incremental IP Limited Copyright (c) 2013 Incremental IP Limited
Copyright (c) 2014 Kevin Martin
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal

View File

@ -54,6 +54,9 @@ controlling how the file is read:
+ `buffer_size` controls the size of the blocks the file is read in. The + `buffer_size` controls the size of the blocks the file is read in. The
default is 4096, which is what `pagesize` says on my system. default is 4096, which is what `pagesize` says on my system.
`csv.openstring` works exactly like `csv.open` except the first argument
is the contents of the csv file. In this case `buffer_size` is set to
the length of the string.
## 3. Requirements ## 3. Requirements

View File

@ -11,9 +11,10 @@
-- likely gets something wrong. -- likely gets something wrong.
-- (c) Copyright 2013 Incremental IP Limited. -- (c) Copyright 2013 Incremental IP Limited.
-- (c) Copyright 2014 Kevin Martin
-- Available under the MIT licence. See LICENSE for more information. -- Available under the MIT licence. See LICENSE for more information.
local DEFAULT_BUFFER_SIZE = 1024 local DEFAULT_BUFFER_SIZE = 4096
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
@ -322,6 +323,9 @@ local file_mt =
close = function(t) close = function(t)
t.file:close() t.file:close()
end, end,
name = function(t)
return t.parameters.filename
end,
} }
file_mt.__index = file_mt file_mt.__index = file_mt
@ -349,6 +353,52 @@ end
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
return { open = open, use = use } local stringfh_mt =
{
read = function(self, bytes)
if not self._string then return nil end
local read_rv
read_rv, self._string =
self._string:sub(1, bytes), self._string:sub(bytes+1)
if #self._string == 0 then
self._string = nil
end
return read_rv
end,
close = function()
end
}
stringfh_mt.__index = stringfh_mt
--- Open a string for reading as a delimited file
-- @return a file object
local function openstring(
filecontents, -- string: The contents of the delimited file
parameters) -- ?table: parameters controlling reading the file.
-- See README.md
parameters = parameters or {}
local function makename()
local t = {}
t[#t+1] = "<(String) "
t[#t+1] = (filecontents:gmatch("[^\n]+")() or ""):sub(1,15)
if #t[#t] > 14 then t[#t+1] = "..." end
t[#t+1] = " >"
return table.concat(t)
end
parameters.filename = parameters.filename or makename()
parameters.buffer_size = parameters.buffer_size or #filecontents
local fileh = setmetatable({_string = filecontents}, stringfh_mt)
return use(fileh, parameters)
end
------------------------------------------------------------------------------
return { open = open, openstring = openstring, use = use }
------------------------------------------------------------------------------ ------------------------------------------------------------------------------

View File

@ -3,10 +3,9 @@ local csv = require"csv"
local errors = 0 local errors = 0
local function test(filename, correct_result, parameters) local function testhandle(handle, correct_result)
local result = {} local result = {}
local f = csv.open(filename, parameters) for r in handle:lines() do
for r in f:lines() do
if not r[1] then if not r[1] then
local r2 = {} local r2 = {}
for k, v in pairs(r) do r2[#r2+1] = k..":"..tostring(v) end for k, v in pairs(r) do r2[#r2+1] = k..":"..tostring(v) end
@ -15,15 +14,33 @@ local function test(filename, correct_result, parameters)
end end
result[#result+1] = table.concat(r, ",") result[#result+1] = table.concat(r, ",")
end end
handle:close()
result = table.concat(result, "\n") result = table.concat(result, "\n")
if result ~= correct_result then if result ~= correct_result then
io.stderr:write( io.stderr:write(
("Error reading '%s':\nExpected output:\n%s\n\nActual output:\n%s\n\n"): ("Error reading '%s':\nExpected output:\n%s\n\nActual output:\n%s\n\n"):
format(filename, correct_result, result)) format(handle:name(), correct_result, result))
errors = errors + 1 errors = errors + 1
return false
end end
return true
end end
local function test(filename, correct_result, parameters)
local f = csv.open(filename, parameters)
local fileok = testhandle(f, correct_result)
if fileok then
f = io.open(filename, "r")
local data = f:read("*a")
f:close()
f = csv.openstring(data, parameters)
testhandle(f, correct_result)
end
end
test("../test-data/embedded-newlines.csv", [[ test("../test-data/embedded-newlines.csv", [[
embedded embedded
@ -62,4 +79,4 @@ else
io.stdout:write(("%d errors\n"):format(errors)) io.stdout:write(("%d errors\n"):format(errors))
end end
os.exit(errors) os.exit(errors)

View File

@ -1 +1,2 @@
this,file,ends,with,a,blank,line this,file,ends,with,a,blank,line

1 this file ends with a blank line
2