diff --git a/AUTHORS b/AUTHORS index bf6696b..84961bd 100644 --- a/AUTHORS +++ b/AUTHORS @@ -1 +1,2 @@ -Leyland, Geoff \ No newline at end of file +Leyland, Geoff +Martin, Kevin diff --git a/LICENSE b/LICENSE index 730151d..020becc 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,5 @@ Copyright (c) 2013 Incremental IP Limited +Copyright (c) 2014 Kevin Martin Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index a6ee15d..86a0405 100644 --- a/README.md +++ b/README.md @@ -54,6 +54,9 @@ controlling how the file is read: + `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. +`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 diff --git a/lua/csv.lua b/lua/csv.lua index 36b57cf..93daf03 100644 --- a/lua/csv.lua +++ b/lua/csv.lua @@ -11,9 +11,10 @@ -- likely gets something wrong. -- (c) Copyright 2013 Incremental IP Limited. +-- (c) Copyright 2014 Kevin Martin -- 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) t.file:close() end, + name = function(t) + return t.parameters.filename + end, } 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 } ------------------------------------------------------------------------------ diff --git a/lua/test.lua b/lua/test.lua index fc0eac2..4bee710 100644 --- a/lua/test.lua +++ b/lua/test.lua @@ -3,10 +3,9 @@ local csv = require"csv" local errors = 0 -local function test(filename, correct_result, parameters) +local function testhandle(handle, correct_result) local result = {} - local f = csv.open(filename, parameters) - for r in f:lines() do + for r in handle:lines() do if not r[1] then local r2 = {} 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 result[#result+1] = table.concat(r, ",") end + + handle:close() + result = table.concat(result, "\n") if result ~= correct_result then io.stderr:write( ("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 + return false end + return true 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", [[ embedded @@ -62,4 +79,4 @@ else io.stdout:write(("%d errors\n"):format(errors)) end -os.exit(errors) \ No newline at end of file +os.exit(errors) diff --git a/test-data/blank-line.csv b/test-data/blank-line.csv index d04ca0d..63fc515 100644 --- a/test-data/blank-line.csv +++ b/test-data/blank-line.csv @@ -1 +1,2 @@ this,file,ends,with,a,blank,line +