From f28dfe07206824bf350fa406212baa4ff97ad236 Mon Sep 17 00:00:00 2001 From: Kevin Martin Date: Sun, 18 May 2014 18:52:16 +0100 Subject: [PATCH] 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 --- AUTHORS | 3 ++- LICENSE | 1 + README.md | 3 +++ lua/csv.lua | 54 ++++++++++++++++++++++++++++++++++++++-- lua/test.lua | 27 ++++++++++++++++---- test-data/blank-line.csv | 1 + 6 files changed, 81 insertions(+), 8 deletions(-) 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 +