lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]



On 27-Jun-05, at 1:57 PM, Alexander Marinov wrote:

LuaCURL is CURL 7.14.0 binding to Lua 5.x
Home Page: http://luacurl.luaforge.net
Download: http://luaforge.net/projects/luacurl/


Cool!

Here is an example how it works:

require("luacurl")

c=curl.new()

c:setopt(curl.OPT_WRITEFUNCTION, function (stream, buffer)
	if stream:write(buffer) then
		return string.len(buffer);
	end
end);


Just off the top of my head, and without even having looked at your
implementation, I would personally recommend a slightly simpler API:

c:setopt("writefunction", function...
c:setopt("writedata", ..

There is no real point introducing option objects (which I'll
bet end up being integers); you could implement this with a
simple internal table which used the option names as keys
(and I would be tempted to use some sort of functional as
a value, presumably wrapped in a static structure
wrapped in a lightuserdata, since function pointers are
not coercible to void*'s); the functional would then
do whatever argument coercion was necessary, and then
issue the internal setopt.)

Actually, though, there is a good argument for a different type
of binding for the writefunction/writedata options. A more
Lua-like binding would be similar to LuaLDAP, where the perform
function returns a generator (a "future", if you prefer), and
the caller can do whatever they want with the resulting strings.

Consider an API something like this:

function geturl(url)
  local c = curl.new():setopt("url", url)
                      :setopt("connecttimeout", 15)

  local chunks = {}
  for chunk in c:perform() do
    table.insert(chunks, chunk)
  end
  if c:error() then
    -- handle the error
   else
    c:close()
    return table.concat(chunks)
  end
end

or

function saveurl(url, filename, progfn)
  local c = curl.new():setopt("url", url)
                      :setopt("connecttimeout", 15)
  if progfn then
    c:setopt("progressfunction", progfn)
  end
  c:setopt("noprogress", not progfn)

  local f = io.open(filename, "w")
  for chunk in c:perform() do
    f:write(chunk)
  end
  if c:error() then
    -- handle the error
    -- somehow delete the file
   else
    f:close()
  end
  c:close()
end

(The : trick only requires setopt to return self. I personally
like the style but others may disagree. Another approach to
the multitude of options would be to model them as a pseudo-table,
allowing both read and write access.)

c:perform();
c:close();

I presume the garbage collector would take care of closing?

Please send me feedback with suggestions how to improve it, bug reports etc.

Thanks, again. Looks like it will be very useful.