about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorKartik K. Agaram <vc@akkartik.com>2022-03-16 17:03:38 -0700
committerKartik K. Agaram <vc@akkartik.com>2022-03-16 17:03:38 -0700
commitb9c187d2594953267357ef37e352d425c7fbeafe (patch)
tree7c0ff7f3814475ac46c9af93d1b79d9e80f4bff6 /src
parentab89be1ed37351f4ff0a338b158d313e000751e3 (diff)
downloadteliva-b9c187d2594953267357ef37e352d425c7fbeafe.tar.gz
stop using tasks in start_reading/start_writing
We just need queues/streams for file I/O. No need to complect
concurrency concerns with them.
Diffstat (limited to 'src')
-rw-r--r--src/file.lua79
-rw-r--r--src/jsonf.lua28
2 files changed, 36 insertions, 71 deletions
diff --git a/src/file.lua b/src/file.lua
index 81fe68d..2ac840f 100644
--- a/src/file.lua
+++ b/src/file.lua
@@ -1,42 +1,43 @@
 -- primitive for reading files from a file system (or, later, network)
--- returns a channel or nil on error
--- read lines from the channel using :recv()
--- recv() on the channel will indicate end of file.
+-- returns an object or nil on error
+-- read lines from the object using .read() with args similar to file:read()
+-- read() will indicate end of file by returning nil.
 function start_reading(fs, filename)
-  local result = task.Channel:new()
   local infile = io.open(filename)
   if infile == nil then return nil end
-  task.spawn(reading_task, infile, result)
-  return result
-end
-
-function reading_task(infile, chanout)
-  for line in infile:lines() do
-    chanout:send(line)
-  end
-  chanout:send(nil)  -- eof
+  return {
+    read = coroutine.wrap(function(format)
+      while true do
+        if format == nil then format = '*l' end
+        format = coroutine.yield(infile:read(format))
+      end
+    end),
+  }
 end
 
 -- primitive for writing files to a file system (or, later, network)
--- returns a channel or nil on error
--- write to the channel using :send()
--- indicate you're done writing by calling :close()
--- file will not be externally visible until :close()
+-- returns an object or nil on error
+-- write to the object using .write()
+-- indicate you're done writing by calling .close()
+-- file will not be externally visible until .close()
 function start_writing(fs, filename)
   if filename == nil then
     error('start_writing requires two arguments: a file-system (nil for real disk) and a filename')
   end
-  local result = task.Channel:new()
   local initial_filename = temporary_filename_in_same_volume(filename)
   local outfile = io.open(initial_filename, 'w')
   if outfile == nil then return nil end
-  result.close = function()
-    result:send(nil)  -- end of file
-    outfile:close()
-    os.rename(initial_filename, filename)
-  end
-  task.spawn(writing_task, outfile, result)
-  return result
+  return {
+    write = coroutine.wrap(function(x)
+      while true do
+        x = coroutine.yield(outfile:write(x))
+      end
+    end),
+    close = function()
+      outfile:close()
+      os.rename(initial_filename, filename)
+    end,
+  }
 end
 
 function temporary_filename_in_same_volume(filename)
@@ -57,31 +58,3 @@ function temporary_filename_in_same_volume(filename)
     i = i+1
   end
 end
-
-function writing_task(outfile, chanin)
-  while true do
-    local line = chanin:recv()
-    if line == nil then break end  -- end of file
-    outfile:write(line)
-  end
-end
-
--- start_reading reads line by line by default
--- this helper permits character-by-character reading
-function character_by_character(chanin, buffer_size)
-  local chanout = task.Channel:new(buffer_size or 50)
-  task.spawn(character_splitting_task, chanin, chanout)
-  return chanout
-end
-
-function character_splitting_task(chanin, chanout)
-  while true do
-    local line = chanin:recv()
-    if line == nil then break end
-    local linesz = line:len()
-    for i=1,linesz do
-      chanout:send(line:sub(i, i))
-    end
-  end
-  chanout:send(nil)  -- end of file
-end
diff --git a/src/jsonf.lua b/src/jsonf.lua
index 25e0c6e..aec0e0a 100644
--- a/src/jsonf.lua
+++ b/src/jsonf.lua
@@ -67,7 +67,7 @@ local literal_map = {
 
 local function skip_spaces(infile)
   while true do
-    local c = infile:recv()
+    local c = infile.read(1)
     if c == nil then break end
     if space_chars[c] == nil then return c end
   end
@@ -79,7 +79,7 @@ local function next_chars(infile, set, firstc)
   local res = {firstc}
   local nextc
   while true do
-    nextc = infile:recv()
+    nextc = infile.read(1)
     if nextc == nil then break end
     if set[nextc] then break end
     table.insert(res, nextc)
@@ -121,27 +121,27 @@ local function parse_string(infile, firstc)
   local res = {}
 
   while true do
-    local chr = infile:recv()
+    local chr = infile.read(1)
     if chr == nil then break end
     local x = chr:byte()
 
     if x < 32 then
       error("control character in string")
     elseif chr == '\\' then
-      local c = infile:recv()
+      local c = infile.read(1)
       if c == nil then break end
       if c == "u" then
         local hex = ''
-        c = infile:recv()
+        c = infile.read(1)
         if c == nil then break end
         hex = hex..c
-        c = infile:recv()
+        c = infile.read(1)
         if c == nil then break end
         hex = hex..c
-        c = infile:recv()
+        c = infile.read(1)
         if c == nil then break end
         hex = hex..c
-        c = infile:recv()
+        c = infile.read(1)
         if c == nil then break end
         hex = hex..c
         if not hex:match('^%x%x%x%x') then
@@ -155,7 +155,7 @@ local function parse_string(infile, firstc)
         table.insert(res, escape_char_map_inv[c])
       end
     elseif chr == '"' then
-      return table.concat(res), infile:recv()
+      return table.concat(res), infile.read(1)
     else
       table.insert(res, chr)
     end
@@ -170,7 +170,7 @@ local function parse_number(infile, firstc)
   local res = {firstc}
   local nextc
   while true do
-    nextc = infile:recv()
+    nextc = infile.read(1)
     if nextc == nil then break end
     if delim_chars[nextc] then break end
     table.insert(res, nextc)
@@ -295,14 +295,6 @@ end
 
 
 function jsonf.decode(infile)
-  return decode2(character_by_character(infile))
-end
-
-
-function decode2(infile)
-  if not ischannel(infile) then
-    error("expected channel, got " .. type(f))
-  end
   local firstc = skip_spaces(infile)
   local res, nextc = parse(infile, firstc)
   if nextc then