summaryrefslogtreecommitdiff
path: root/indra/newview/scripts/lua
diff options
context:
space:
mode:
Diffstat (limited to 'indra/newview/scripts/lua')
-rw-r--r--indra/newview/scripts/lua/require/LLInventory.lua38
-rw-r--r--indra/newview/scripts/lua/require/result_view.lua62
2 files changed, 82 insertions, 18 deletions
diff --git a/indra/newview/scripts/lua/require/LLInventory.lua b/indra/newview/scripts/lua/require/LLInventory.lua
index 0ff6b9fb37..ce501e75f3 100644
--- a/indra/newview/scripts/lua/require/LLInventory.lua
+++ b/indra/newview/scripts/lua/require/LLInventory.lua
@@ -1,12 +1,14 @@
local leap = require 'leap'
local mapargs = require 'mapargs'
+local result_view = require 'result_view'
local function result(keys)
return LL.setdtor(
'LLInventory result',
setmetatable(
-- the basic table wrapped by setmetatable just captures the int
- -- result-set keys from 'keys', but with underscore prefixes
+ -- result-set {key, length} pairs from 'keys', but with underscore
+ -- prefixes
{
_categories=keys.categories,
_items=keys.items,
@@ -15,7 +17,7 @@ local function result(keys)
close = function(self)
leap.send('LLInventory',
{op='closeResult',
- result={self._categories, self._items}})
+ result={self._categories[1], self._items[1]}})
end
},
-- The caller of one of our methods that returns a result set
@@ -24,25 +26,25 @@ local function result(keys)
-- either 'categories' or 'items', the __index() metamethod
-- populates that field.
{
- __index = function(t, key)
+ __index = function(t, field)
-- we really don't care about references to any other field
- if not table.find({'categories', 'items'}, key) then
+ if not table.find({'categories', 'items'}, field) then
return nil
end
- -- We cleverly saved the int result set key in a field
- -- with the same name but an underscore prefix.
- local resultkey = t['_' .. key]
- -- TODO: This only ever fetches the FIRST slice. What we
- -- really want is to return a table with metamethods that
- -- manage indexed access and table iteration.
- -- Remember our C++ entry point uses 0-relative indexing.
- local slice = leap.request(
- 'LLInventory',
- {op='getSlice', result=resultkey, index=0}).slice
- print(`getSlice({resultkey}, 0) => {slice} ({#slice} entries)`)
- -- cache this slice for future reference
- t[key] = slice
- return slice
+ local view = result_view(
+ -- We cleverly saved the result set {key, length} pair in
+ -- a field with the same name but an underscore prefix.
+ t['_' .. field],
+ function(key, start)
+ local fetched = leap.request(
+ 'LLInventory',
+ {op='getSlice', result=key, index=start})
+ return fetched.slice, fetched.start
+ end
+ )
+ -- cache that view for future reference
+ t[field] = view
+ return view
end
}
),
diff --git a/indra/newview/scripts/lua/require/result_view.lua b/indra/newview/scripts/lua/require/result_view.lua
new file mode 100644
index 0000000000..4a58636f2f
--- /dev/null
+++ b/indra/newview/scripts/lua/require/result_view.lua
@@ -0,0 +1,62 @@
+-- result_view(key_length, fetch) returns a table which stores only a slice
+-- of a result set plus some control values, yet presents read-only virtual
+-- access to the entire result set.
+-- key_length: {result set key, total result set length}
+-- fetch: function(key, start) that returns (slice, adjusted start)
+local function result_view(key_length, fetch)
+ return setmetatable(
+ {
+ key=key_length[1],
+ length=key_length[2],
+ -- C++ result sets use 0-based indexing, so internally we do too
+ start=0,
+ -- start with a dummy array with length 0
+ slice={}
+ },
+ {
+ __len = function(this)
+ return this.length
+ end,
+ __index = function(this, i)
+ -- right away, convert to 0-relative indexing
+ i -= 1
+ -- can we find this index within the current slice?
+ local reli = i - this.start
+ if 0 <= reli and reli < #this.slice then
+ return this.slice[reli]
+ end
+ -- is this index outside the overall result set?
+ if not (0 <= i and i < this.length) then
+ return nil
+ end
+ -- fetch a new slice starting at i, using provided fetch()
+ local start
+ this.slice, start = fetch(key, i)
+ -- It's possible that caller-provided fetch() function forgot
+ -- to return the adjusted start index of the new slice. In
+ -- Lua, 0 tests as true, so if fetch() returned (slice, 0),
+ -- we'll duly reset this.start to 0.
+ if start then
+ this.start = start
+ end
+ -- hopefully this slice contains the desired i
+ return this.slice[i - this.start]
+ end,
+ -- We purposely avoid putting any array entries (int keys) into
+ -- our table so that access to any int key will always call our
+ -- __index() metamethod. Moreover, we want any table iteration to
+ -- call __index(table, i) however many times; we do NOT want it to
+ -- retrieve key, length, start, slice.
+ -- So turn 'for k, v in result' into 'for k, v in ipairs(result)'.
+ __iter = ipairs,
+ -- This result set provides read-only access.
+ -- We do not support pushing updates to individual items back to
+ -- C++; for the intended use cases, that makes no sense.
+ __newindex = function(this, i, value)
+ error("result_view is a read-only data structure", 2)
+ end
+ }
+ )
+end
+
+return result_view