Mercurial > wow > reaction
comparison libs/AceLibrary/AceLibrary.lua @ 7:f920db5fc6b1
version 0.3
author | Flick <flickerstreak@gmail.com> |
---|---|
date | Tue, 20 Mar 2007 21:25:29 +0000 |
parents | c11ca1d8ed91 |
children |
comparison
equal
deleted
inserted
replaced
6:2da5089ab7ff | 7:f920db5fc6b1 |
---|---|
1 --[[ | 1 --[[ |
2 Name: AceLibrary | 2 Name: AceLibrary |
3 Revision: $Rev: 19062 $ | 3 Revision: $Rev$ |
4 Developed by: The Ace Development Team (http://www.wowace.com/index.php/The_Ace_Development_Team) | 4 Developed by: The Ace Development Team (http://www.wowace.com/index.php/The_Ace_Development_Team) |
5 Inspired By: Iriel (iriel@vigilance-committee.org) | 5 Inspired By: Iriel (iriel@vigilance-committee.org) |
6 Tekkub (tekkub@gmail.com) | 6 Tekkub (tekkub@gmail.com) |
7 Revision: $Rev: 19062 $ | 7 Revision: $Rev$ |
8 Website: http://www.wowace.com/ | 8 Website: http://www.wowace.com/ |
9 Documentation: http://www.wowace.com/index.php/AceLibrary | 9 Documentation: http://www.wowace.com/index.php/AceLibrary |
10 SVN: http://svn.wowace.com/root/trunk/Ace2/AceLibrary | 10 SVN: http://svn.wowace.com/root/trunk/Ace2/AceLibrary |
11 Description: Versioning library to handle other library instances, upgrading, | 11 Description: Versioning library to handle other library instances, upgrading, |
12 and proper access. | 12 and proper access. |
13 It also provides a base for libraries to work off of, providing | 13 It also provides a base for libraries to work off of, providing |
14 proper error tools. It is handy because all the errors occur in the | 14 proper error tools. It is handy because all the errors occur in the |
15 file that called it, not in the library file itself. | 15 file that called it, not in the library file itself. |
16 Dependencies: None | 16 Dependencies: None |
17 License: LGPL v2.1 | |
17 ]] | 18 ]] |
18 | 19 |
19 local ACELIBRARY_MAJOR = "AceLibrary" | 20 local ACELIBRARY_MAJOR = "AceLibrary" |
20 local ACELIBRARY_MINOR = "$Revision: 19062 $" | 21 local ACELIBRARY_MINOR = "$Revision: 20000 $" |
21 | 22 |
22 local _G = getfenv(0) | 23 local _G = getfenv(0) |
23 local previous = _G[ACELIBRARY_MAJOR] | 24 local previous = _G[ACELIBRARY_MAJOR] |
24 if previous and not previous:IsNewVersion(ACELIBRARY_MAJOR, ACELIBRARY_MINOR) then return end | 25 if previous and not previous:IsNewVersion(ACELIBRARY_MAJOR, ACELIBRARY_MINOR) then return end |
25 | 26 |
26 local function safecall(func,...) | 27 local function safecall(func,...) |
27 local success, err = pcall(func,...) | 28 local success, err = pcall(func,...) |
28 if not success then geterrorhandler()(err) end | 29 if not success then geterrorhandler()(err:find("%.lua:%d+:") and err or (debugstack():match("\n(.-: )in.-\n") or "") .. err) end |
29 end | 30 end |
30 | 31 |
31 -- @table AceLibrary | 32 -- @table AceLibrary |
32 -- @brief System to handle all versioning of libraries. | 33 -- @brief System to handle all versioning of libraries. |
33 local AceLibrary = {} | 34 local AceLibrary = {} |
34 local AceLibrary_mt = {} | 35 local AceLibrary_mt = {} |
35 setmetatable(AceLibrary, AceLibrary_mt) | 36 setmetatable(AceLibrary, AceLibrary_mt) |
36 | 37 |
37 local function error(self, message, ...) | 38 local function error(self, message, ...) |
38 if type(self) ~= "table" then | 39 if type(self) ~= "table" then |
39 return _G.error(string.format("Bad argument #1 to `error' (table expected, got %s)", type(self)), 2) | 40 return _G.error(("Bad argument #1 to `error' (table expected, got %s)"):format(type(self)), 2) |
40 end | 41 end |
41 | 42 |
42 local stack = debugstack() | 43 local stack = debugstack() |
43 if not message then | 44 if not message then |
44 local _,_,second = string.find(stack, "\n(.-)\n") | 45 local _,_,second = stack:find("\n(.-)\n") |
45 message = "error raised! " .. second | 46 message = "error raised! " .. second |
46 else | 47 else |
47 local arg = { ... } | 48 local arg = { ... } -- not worried about table creation, as errors don't happen often |
48 | 49 |
49 for i = 1, #arg do | 50 for i = 1, #arg do |
50 arg[i] = tostring(arg[i]) | 51 arg[i] = tostring(arg[i]) |
51 end | 52 end |
52 for i = 1, 10 do | 53 for i = 1, 10 do |
53 table.insert(arg, "nil") | 54 table.insert(arg, "nil") |
54 end | 55 end |
55 message = string.format(message, unpack(arg)) | 56 message = message:format(unpack(arg)) |
56 end | 57 end |
57 | 58 |
58 if getmetatable(self) and getmetatable(self).__tostring then | 59 if getmetatable(self) and getmetatable(self).__tostring then |
59 message = string.format("%s: %s", tostring(self), message) | 60 message = ("%s: %s"):format(tostring(self), message) |
60 elseif type(rawget(self, 'GetLibraryVersion')) == "function" and AceLibrary:HasInstance(self:GetLibraryVersion()) then | 61 elseif type(rawget(self, 'GetLibraryVersion')) == "function" and AceLibrary:HasInstance(self:GetLibraryVersion()) then |
61 message = string.format("%s: %s", self:GetLibraryVersion(), message) | 62 message = ("%s: %s"):format(self:GetLibraryVersion(), message) |
62 elseif type(rawget(self, 'class')) == "table" and type(rawget(self.class, 'GetLibraryVersion')) == "function" and AceLibrary:HasInstance(self.class:GetLibraryVersion()) then | 63 elseif type(rawget(self, 'class')) == "table" and type(rawget(self.class, 'GetLibraryVersion')) == "function" and AceLibrary:HasInstance(self.class:GetLibraryVersion()) then |
63 message = string.format("%s: %s", self.class:GetLibraryVersion(), message) | 64 message = ("%s: %s"):format(self.class:GetLibraryVersion(), message) |
64 end | 65 end |
65 | 66 |
66 local first = string.gsub(stack, "\n.*", "") | 67 local first = stack:gsub("\n.*", "") |
67 local file = string.gsub(first, ".*\\(.*).lua:%d+: .*", "%1") | 68 local file = first:gsub(".*\\(.*).lua:%d+: .*", "%1") |
68 file = string.gsub(file, "([%(%)%.%*%+%-%[%]%?%^%$%%])", "%%%1") | 69 file = file:gsub("([%(%)%.%*%+%-%[%]%?%^%$%%])", "%%%1") |
69 | 70 |
70 | 71 |
71 local i = 0 | 72 local i = 0 |
72 for s in string.gmatch(stack, "\n([^\n]*)") do | 73 for s in stack:gmatch("\n([^\n]*)") do |
73 i = i + 1 | 74 i = i + 1 |
74 if not string.find(s, file .. "%.lua:%d+:") and not string.find(s, "%(tail call%)") then | 75 if not s:find(file .. "%.lua:%d+:") and not s:find("%(tail call%)") then |
75 file = string.gsub(s, "^.*\\(.*).lua:%d+: .*", "%1") | 76 file = s:gsub("^.*\\(.*).lua:%d+: .*", "%1") |
76 file = string.gsub(file, "([%(%)%.%*%+%-%[%]%?%^%$%%])", "%%%1") | 77 file = file:gsub("([%(%)%.%*%+%-%[%]%?%^%$%%])", "%%%1") |
77 break | 78 break |
78 end | 79 end |
79 end | 80 end |
80 local j = 0 | 81 local j = 0 |
81 for s in string.gmatch(stack, "\n([^\n]*)") do | 82 for s in stack:gmatch("\n([^\n]*)") do |
82 j = j + 1 | 83 j = j + 1 |
83 if j > i and not string.find(s, file .. "%.lua:%d+:") and not string.find(s, "%(tail call%)") then | 84 if j > i and not s:find(file .. "%.lua:%d+:") and not s:find("%(tail call%)") then |
84 return _G.error(message, j+1) | 85 return _G.error(message, j+1) |
85 end | 86 end |
86 end | 87 end |
87 return _G.error(message, 2) | 88 return _G.error(message, 2) |
88 end | 89 end |
89 | 90 |
90 local function assert(self, condition, message, ...) | 91 local function assert(self, condition, message, ...) |
91 if not condition then | 92 if not condition then |
92 if not message then | 93 if not message then |
93 local stack = debugstack() | 94 local stack = debugstack() |
94 local _,_,second = string.find(stack, "\n(.-)\n") | 95 local _,_,second = stack:find("\n(.-)\n") |
95 message = "assertion failed! " .. second | 96 message = "assertion failed! " .. second |
96 end | 97 end |
97 return error(self, message, ...) | 98 return error(self, message, ...) |
98 end | 99 end |
99 return condition | 100 return condition |
106 return error(self, "Bad argument #4 to `argCheck' (string expected, got %s)", type(kind)) | 107 return error(self, "Bad argument #4 to `argCheck' (string expected, got %s)", type(kind)) |
107 end | 108 end |
108 local errored = false | 109 local errored = false |
109 arg = type(arg) | 110 arg = type(arg) |
110 if arg ~= kind and arg ~= kind2 and arg ~= kind3 and arg ~= kind4 and arg ~= kind5 then | 111 if arg ~= kind and arg ~= kind2 and arg ~= kind3 and arg ~= kind4 and arg ~= kind5 then |
111 local _,_,func = string.find(debugstack(), "`argCheck'.-([`<].-['>])") | 112 local stack = debugstack() |
113 local _,_,func = stack:find("`argCheck'.-([`<].-['>])") | |
112 if not func then | 114 if not func then |
113 _,_,func = string.find(debugstack(), "([`<].-['>])") | 115 _,_,func = stack:find("([`<].-['>])") |
114 end | 116 end |
115 if kind5 then | 117 if kind5 then |
116 return error(self, "Bad argument #%s to %s (%s, %s, %s, %s, or %s expected, got %s)", tonumber(num) or 0/0, func, kind, kind2, kind3, kind4, kind5, arg) | 118 return error(self, "Bad argument #%s to %s (%s, %s, %s, %s, or %s expected, got %s)", tonumber(num) or 0/0, func, kind, kind2, kind3, kind4, kind5, arg) |
117 elseif kind4 then | 119 elseif kind4 then |
118 return error(self, "Bad argument #%s to %s (%s, %s, %s, or %s expected, got %s)", tonumber(num) or 0/0, func, kind, kind2, kind3, kind4, arg) | 120 return error(self, "Bad argument #%s to %s (%s, %s, %s, or %s expected, got %s)", tonumber(num) or 0/0, func, kind, kind2, kind3, kind4, arg) |
128 | 130 |
129 local pcall | 131 local pcall |
130 do | 132 do |
131 local function check(self, ret, ...) | 133 local function check(self, ret, ...) |
132 if not ret then | 134 if not ret then |
133 return error(self, (string.gsub(..., ".-%.lua:%d-: ", ""))) | 135 local s = ... |
136 return error(self, (s:gsub(".-%.lua:%d-: ", ""))) | |
134 else | 137 else |
135 return ... | 138 return ... |
136 end | 139 end |
137 end | 140 end |
138 | 141 |
162 end | 165 end |
163 end | 166 end |
164 | 167 |
165 local function svnRevisionToNumber(text) | 168 local function svnRevisionToNumber(text) |
166 if type(text) == "string" then | 169 if type(text) == "string" then |
167 if string.find(text, "^%$Revision: (%d+) %$$") then | 170 if text:find("^%$Revision: (%d+) %$$") then |
168 return tonumber((string.gsub(text, "^%$Revision: (%d+) %$$", "%1"))) | 171 return tonumber((text:gsub("^%$Revision: (%d+) %$$", "%1"))) |
169 elseif string.find(text, "^%$Rev: (%d+) %$$") then | 172 elseif text:find("^%$Rev: (%d+) %$$") then |
170 return tonumber((string.gsub(text, "^%$Rev: (%d+) %$$", "%1"))) | 173 return tonumber((text:gsub("^%$Rev: (%d+) %$$", "%1"))) |
171 elseif string.find(text, "^%$LastChangedRevision: (%d+) %$$") then | 174 elseif text:find("^%$LastChangedRevision: (%d+) %$$") then |
172 return tonumber((string.gsub(text, "^%$LastChangedRevision: (%d+) %$$", "%1"))) | 175 return tonumber((text:gsub("^%$LastChangedRevision: (%d+) %$$", "%1"))) |
173 end | 176 end |
174 elseif type(text) == "number" then | 177 elseif type(text) == "number" then |
175 return text | 178 return text |
176 end | 179 end |
177 return nil | 180 return nil |
365 if type(minor) == "string" then | 368 if type(minor) == "string" then |
366 local m = svnRevisionToNumber(minor) | 369 local m = svnRevisionToNumber(minor) |
367 if m then | 370 if m then |
368 minor = m | 371 minor = m |
369 else | 372 else |
370 _G.error(string.format("Bad argument #3 to `IsNewVersion'. Must be a number or SVN revision string. %q is not appropriate", minor), 2) | 373 _G.error(("Bad argument #3 to `IsNewVersion'. Must be a number or SVN revision string. %q is not appropriate"):format(minor), 2) |
371 end | 374 end |
372 end | 375 end |
373 argCheck(self, minor, 3, "number") | 376 argCheck(self, minor, 3, "number") |
374 local data = self.libs[major] | 377 local data = self.libs[major] |
375 if not data then | 378 if not data then |
391 if type(minor) == "string" then | 394 if type(minor) == "string" then |
392 local m = svnRevisionToNumber(minor) | 395 local m = svnRevisionToNumber(minor) |
393 if m then | 396 if m then |
394 minor = m | 397 minor = m |
395 else | 398 else |
396 _G.error(string.format("Bad argument #3 to `HasInstance'. Must be a number or SVN revision string. %q is not appropriate", minor), 2) | 399 _G.error(("Bad argument #3 to `HasInstance'. Must be a number or SVN revision string. %q is not appropriate"):format(minor), 2) |
397 end | 400 end |
398 end | 401 end |
399 argCheck(self, minor, 3, "number") | 402 argCheck(self, minor, 3, "number") |
400 if not self.libs[major] then | 403 if not self.libs[major] then |
401 return | 404 return |
414 argCheck(self, major, 2, "string") | 417 argCheck(self, major, 2, "string") |
415 TryToLoadStandalone(major) | 418 TryToLoadStandalone(major) |
416 | 419 |
417 local data = self.libs[major] | 420 local data = self.libs[major] |
418 if not data then | 421 if not data then |
419 _G.error(string.format("Cannot find a library instance of %s.", major), 2) | 422 _G.error(("Cannot find a library instance of %s."):format(major), 2) |
420 return | 423 return |
421 end | 424 end |
422 if minor then | 425 if minor then |
423 if type(minor) == "string" then | 426 if type(minor) == "string" then |
424 local m = svnRevisionToNumber(minor) | 427 local m = svnRevisionToNumber(minor) |
425 if m then | 428 if m then |
426 minor = m | 429 minor = m |
427 else | 430 else |
428 _G.error(string.format("Bad argument #3 to `GetInstance'. Must be a number or SVN revision string. %q is not appropriate", minor), 2) | 431 _G.error(("Bad argument #3 to `GetInstance'. Must be a number or SVN revision string. %q is not appropriate"):format(minor), 2) |
429 end | 432 end |
430 end | 433 end |
431 argCheck(self, minor, 2, "number") | 434 argCheck(self, minor, 2, "number") |
432 if data.minor ~= minor then | 435 if data.minor ~= minor then |
433 _G.error(string.format("Cannot find a library instance of %s, minor version %d.", major, minor), 2) | 436 _G.error(("Cannot find a library instance of %s, minor version %d."):format(major, minor), 2) |
434 end | 437 end |
435 end | 438 end |
436 return data.instance | 439 return data.instance |
437 end | 440 end |
438 | 441 |
461 argCheck(self, newInstance, 2, "table") | 464 argCheck(self, newInstance, 2, "table") |
462 argCheck(self, major, 3, "string") | 465 argCheck(self, major, 3, "string") |
463 if major ~= ACELIBRARY_MAJOR then | 466 if major ~= ACELIBRARY_MAJOR then |
464 for k,v in pairs(_G) do | 467 for k,v in pairs(_G) do |
465 if v == newInstance then | 468 if v == newInstance then |
466 geterrorhandler()(string.format("Cannot register library %q. It is part of the global table in _G[%q].", major, k)) | 469 geterrorhandler()((debugstack():match("(.-: )in.-\n") or "") .. ("Cannot register library %q. It is part of the global table in _G[%q]."):format(major, k)) |
467 end | 470 end |
468 end | 471 end |
469 end | 472 end |
470 if major ~= ACELIBRARY_MAJOR and not string.find(major, "^[%a%-][%a%d%-]+[%a%-]%-%d+%.%d+$") and not string.find(major, "^[%a%-]+%-%d+%.%d+$") then | 473 if major ~= ACELIBRARY_MAJOR and not major:find("^[%a%-][%a%d%-]*%-%d+%.%d+$") then |
471 _G.error(string.format("Bad argument #3 to `Register'. Must be in the form of \"Name-1.0\". %q is not appropriate", major), 2) | 474 _G.error(string.format("Bad argument #3 to `Register'. Must be in the form of \"Name-1.0\". %q is not appropriate", major), 2) |
472 end | 475 end |
473 if type(minor) == "string" then | 476 if type(minor) == "string" then |
474 local m = svnRevisionToNumber(minor) | 477 local m = svnRevisionToNumber(minor) |
475 if m then | 478 if m then |
476 minor = m | 479 minor = m |
477 else | 480 else |
478 _G.error(string.format("Bad argument #4 to `Register'. Must be a number or SVN revision string. %q is not appropriate", minor), 2) | 481 _G.error(("Bad argument #4 to `Register'. Must be a number or SVN revision string. %q is not appropriate"):format(minor), 2) |
479 end | 482 end |
480 end | 483 end |
481 argCheck(self, minor, 4, "number") | 484 argCheck(self, minor, 4, "number") |
482 if math.floor(minor) ~= minor or minor < 0 then | 485 if math.floor(minor) ~= minor or minor < 0 then |
483 error(self, "Bad argument #4 to `Register' (integer >= 0 expected, got %s)", minor) | 486 error(self, "Bad argument #4 to `Register' (integer >= 0 expected, got %s)", minor) |
524 safecall(activateFunc, instance, nil, nil) -- no old version, so explicit nil | 527 safecall(activateFunc, instance, nil, nil) -- no old version, so explicit nil |
525 | 528 |
526 --[[ if major ~= ACELIBRARY_MAJOR then | 529 --[[ if major ~= ACELIBRARY_MAJOR then |
527 for k,v in pairs(_G) do | 530 for k,v in pairs(_G) do |
528 if v == instance then | 531 if v == instance then |
529 geterrorhandler()(string.format("Cannot register library %q. It is part of the global table in _G[%q].", major, k)) | 532 geterrorhandler()((debugstack():match("(.-: )in.-\n") or "") .. ("Cannot register library %q. It is part of the global table in _G[%q]."):format(major, k)) |
530 end | 533 end |
531 end | 534 end |
532 end]] | 535 end]] |
533 end | 536 end |
534 | 537 |
555 return instance | 558 return instance |
556 end | 559 end |
557 local instance = data.instance | 560 local instance = data.instance |
558 if minor <= data.minor then | 561 if minor <= data.minor then |
559 -- This one is already obsolete, raise an error. | 562 -- This one is already obsolete, raise an error. |
560 _G.error(string.format("Obsolete library registered. %s is already registered at version %d. You are trying to register version %d. Hint: if not AceLibrary:IsNewVersion(%q, %d) then return end", major, data.minor, minor, major, minor), 2) | 563 _G.error(("Obsolete library registered. %s is already registered at version %d. You are trying to register version %d. Hint: if not AceLibrary:IsNewVersion(%q, %d) then return end"):format(major, data.minor, minor, major, minor), 2) |
561 return | 564 return |
562 end | 565 end |
563 -- This is an update | 566 -- This is an update |
564 local oldInstance = {} | 567 local oldInstance = {} |
565 | 568 |
621 end | 624 end |
622 end | 625 end |
623 if activateFunc then | 626 if activateFunc then |
624 safecall(activateFunc, instance, oldInstance, oldDeactivateFunc) | 627 safecall(activateFunc, instance, oldInstance, oldDeactivateFunc) |
625 | 628 |
626 if major ~= ACELIBRARY_MAJOR then | 629 --[[ if major ~= ACELIBRARY_MAJOR then |
627 for k,v in pairs(_G) do | 630 for k,v in pairs(_G) do |
628 if v == instance then | 631 if v == instance then |
629 geterrorhandler()(string.format("Cannot register library %q. It is part of the global table in _G[%q].", major, k)) | 632 geterrorhandler()((debugstack():match("(.-: )in.-\n") or "") .. ("Cannot register library %q. It is part of the global table in _G[%q]."):format(major, k)) |
630 end | 633 end |
631 end | 634 end |
632 end | 635 end]] |
633 else | 636 else |
634 safecall(oldDeactivateFunc, oldInstance) | 637 safecall(oldDeactivateFunc, oldInstance) |
635 end | 638 end |
636 oldInstance = nil | 639 oldInstance = nil |
637 | 640 |