diff --git a/examples/cURLv3/file.lua b/examples/cURLv3/file.lua new file mode 100644 index 0000000..4ddf256 --- /dev/null +++ b/examples/cURLv3/file.lua @@ -0,0 +1,16 @@ +local cURL = require "cURL" + +-- open output file +f = io.open("example_homepage", "w") + +cURL.easy{ + url = "http://www.example.com/", + writefunction = f +} +:perform() +:close() + +-- close output file +f:close() + +print("Done") \ No newline at end of file diff --git a/examples/cURLv3/multi.lua b/examples/cURLv3/multi.lua new file mode 100644 index 0000000..56d6be9 --- /dev/null +++ b/examples/cURLv3/multi.lua @@ -0,0 +1,17 @@ +local cURL = require("cURL") + +-- setup easy and url +c1 = cURL.easy{url = "http://www.lua.org/"} +c2 = cURL.easy{url = "http://luajit.org/"} + +m = cURL.multi() + :add_handle(c1) + :add_handle(c2) + +local f1 = io.open("lua.html", "w+b") +local f2 = io.open("luajit.html", "w+b") + +for data, type, easy in m:iperform() do + if type == "data" and c1 == easy then f1:write(data) end + if type == "data" and c2 == easy then f2:write(data) end +end diff --git a/examples/cURLv3/rss.lua b/examples/cURLv3/rss.lua new file mode 100644 index 0000000..f29d914 --- /dev/null +++ b/examples/cURLv3/rss.lua @@ -0,0 +1,47 @@ +-- use LuaExpat and Lua-CuRL together for On-The-Fly XML parsing +local lxp = require "lxp" +local cURL = require "cURL" + +-- create XML parser +items, tags = {}, {} +p = lxp.new{ + StartElement = function (parser, tagname) + tags[#tags + 1] = tagname + if (tagname == "item") then + items[#items + 1] = {} + end + end; + + CharacterData = function (parser, str) + if (tags[#tags -1] == "item") then + --we are parsing a item, get rid of trailing whitespace + items[#items][tags[#tags]] = string.gsub(str, "%s*$", "") + end + end; + + EndElement = function (parser, tagname) + --assuming well formed xml + tags[#tags] = nil + end; +} + +-- create and setup easy handle +c = cURL.easy{url = "http://www.lua.org/news.rss"} + +-- setup writer function with context +c:setopt_writefunction(p.parse, p) + +-- perform request and close easy handle +-- perform raise error if parser fail +c:perform():close() + +--finish document +assert(p:parse()) +p:close() + +for i, item in ipairs(items) do + for k, v in pairs(item) do + print(k,v) + end + print() +end \ No newline at end of file diff --git a/src/lua/cURL/impl/cURL.lua b/src/lua/cURL/impl/cURL.lua index ec43355..401bae4 100644 --- a/src/lua/cURL/impl/cURL.lua +++ b/src/lua/cURL/impl/cURL.lua @@ -58,10 +58,12 @@ local function make_iterator(self, perform) end - local remain = #self._easy - for _, e in ipairs(self._easy) do - e:setopt_writefunction (function(str) buffers:append(e, "data", str) end) - e:setopt_headerfunction(function(str) buffers:append(e, "header", str) end) + local remain = self._easy.n + for h, e in pairs(self._easy) do + if h ~= 'n' then + e:setopt_writefunction (function(str) buffers:append(e, "data", str) end) + e:setopt_headerfunction(function(str) buffers:append(e, "header", str) end) + end end assert(perform(self)) @@ -78,11 +80,9 @@ local function make_iterator(self, perform) if n <= remain then while true do - local e, ok, err = assert(self:info_read()) - if e == 0 then break end - for _, a in ipairs(self._easy) do - if e == a:handle() then e = a break end - end + local h, ok, err = assert(self:info_read()) + if h == 0 then break end + local e = assert(self._easy[h]) if ok then ok = e:getinfo_response_code() or ok buffers:append(e, "done", ok) @@ -90,7 +90,6 @@ local function make_iterator(self, perform) end remain = n end - end end end @@ -276,7 +275,7 @@ local add_handle = wrap_function("add_handle") local remove_handle = wrap_function("remove_handle") function Multi:__init() - self._easy = {} + self._easy = {n = 0} return self end @@ -285,14 +284,26 @@ function Multi:perform() end function Multi:add_handle(e) - self._easy = self._easy or {} - self._easy[#self._easy + 1] = e - return add_handle(self, e:handle()) + assert(self._easy.n >= 0) + + local h = e:handle() + if self._easy[h] then return self end + + local ok, err = add_handle(self, h) + if not ok then return nil, err end + self._easy[h], self._easy.n = e, self._easy.n + 1 + return self end function Multi:remove_handle(e) - self._easy[#self._easy + 1] = e - return remove_handle(self, e:handle()) + local h = e:handle() + + if self._easy[h] then + self._easy[h], self._easy.n = nil, self._easy.n - 1 + end + assert(self._easy.n >= 0) + + return remove_handle(self, h) end end @@ -347,8 +358,11 @@ end ------------------------------------------- local Multi = class(curl.multi) do +local add_handle = wrap_function("add_handle") +local remove_handle = wrap_function("remove_handle") + function Multi:__init() - self._easy = {} + self._easy = {n = 0} return self end @@ -356,18 +370,31 @@ function Multi:iperform() return make_iterator(self, self.perform) end -local add_handle = wrap_function("add_handle") function Multi:add_handle(e) - self._easy[#self._easy + 1] = e - return add_handle(self, e:handle()) + assert(self._easy.n >= 0) + + local h = e:handle() + if self._easy[h] then return self end + + local ok, err = add_handle(self, h) + if not ok then return nil, err end + self._easy[h], self._easy.n = e, self._easy.n + 1 + return self end -local remove_handle = wrap_function("remove_handle") function Multi:remove_handle(e) - self._easy[#self._easy + 1] = e - return remove_handle(self, e:handle()) + local h = e:handle() + + if self._easy[h] then + self._easy[h], self._easy.n = nil, self._easy.n - 1 + end + assert(self._easy.n >= 0) + + return remove_handle(self, h) end +--! @fixme Multi:info_read(true) should also remove easy handle from self._easy + end -------------------------------------------