> 4. Implementation Code
Download Sample Code
You can download this sample code from http://www.vigilance-committee.org/wow/downloads/LibEmbed-0.1-11000.zip
Stub Implementation
First is the stub code, this can go in with the actual library, or in its own file. It's possible to use the same stub code for multiple libraries, just be sure to copy the instances (Sample code below)
Stub initialization and methods
local stub = {};
-- Instance replacement method, replace contents of old with that of new
function stub:ReplaceInstance(old, new)
for k,v in pairs(old) do old[k]=nil; end
for k,v in pairs(new) do old[k]=v; end
end
-- Get a new copy of the stub
function stub:NewStub()
local newStub = {};
self:ReplaceInstance(newStub, self);
newStub.lastVersion = '';
newStub.versions = {};
return newStub;
end
-- Get instance version
function stub:GetInstance(version)
if (not version) then version = self.lastVersion; end
local versionData = self.versions[version];
if (not versionData) then
message("Cannot find library instance with version '"
.. version .. "'");
return;
end
return versionData.instance;
end
-- Register new instance
function stub:Register(newInstance)
local version,minor = newInstance:GetLibraryVersion();
self.lastVersion = version;
local versionData = self.versions[version];
if (not versionData) then
-- This one is new!
versionData = { instance = newInstance,
minor = minor,
old = {}
};
self.versions[version] = versionData;
newInstance:LibActivate(self);
return newInstance;
end
if (minor <= versionData.minor) then
-- This one is already obsolete
if (newInstance.LibDiscard) then
newInstance:LibDiscard();
end
return versionData.instance;
end
-- This is an update
local oldInstance = versionData.instance;
local oldList = versionData.old;
versionData.instance = newInstance;
versionData.minor = minor;
local skipCopy = newInstance:LibActivate(self, oldInstance, oldList);
table.insert(oldList, oldInstance);
if (not skipCopy) then
for i, old in ipairs(oldList) do
self:ReplaceInstance(old, newInstance);
end
end
return newInstance;
end
Bind stub to global (Single library)
-- Bind stub to global scope if it's not already there
if (not SimpleExampleLib) then
SimplExampleLib = stub:NewStub();
end
-- Nil stub for garbage collection
stub = nil;
Bind stub to global (Multiple library)
-- Bind stub to global scope if it's not already there
if (not Library1StubName) then
Library1StubName = stub:NewStub();
end
if (not Library2StubName) then
Library2StubName = stub:NewStub();
end
if (not Library3StubName) then
Library3StubName = stub:NewStub();
end
-- Nil stub for garbage collection
stub = nil;
Simple Library
This code shows what a simple library implementation could look like.
Simple library implementation
local lib = {};
-- Return the library's current version
function lib:GetLibraryVersion()
-- You MUST update the major version whenever you make an incompatible
-- change
local MAJOR_VERSION = "example-1.0";
-- You MUST update the minor version whenever you make a compatible
-- change (And check LibActivate is still valid!)
local MINOR_VERSION = 1;
return MAJOR_VERSION, MINOR_VERSION;
end
-- Activate a new instance of this library
function lib:LibActivate(stub, oldLib, oldList)
local maj, min = self:GetLibraryVersion();
self:Print("Activating version " .. maj .. ", " .. min);
-- Migrate old data if there is any
if (oldLib) then
local omaj, omin = oldLib:GetLibraryVersion();
self:Print("Replacing old version " .. omaj .. ", " .. omin);
self.data = oldLib.data;
else
self.data = { count = 0; }
end
-- nil return makes stub do object copy
end
-- Discard this instance of the library
function lib:LibDiscard()
local maj, min = self:GetLibraryVersion();
self:Print("Discarding version " .. maj .. ", " .. min);
end
-- Return the current count
function lib:GetCount()
return self.data.count;
end
-- Add to the current count
function lib:AddCount(delta)
local data = self.data;
local ncount = data.count + delta;
data.count = ncount;
return ncount;
end
-- Print a message
function lib:Print(msg)
local maj = self:GetLibraryVersion();
DEFAULT_CHAT_FRAME:AddMessage("[SimpleExampleLib:" .. maj .. "] " .. msg);
end
-- Register this instance with the stub
SimpleExampleLib:Register(lib);
lib = nil; -- Let GC clean it up later
Simple Library Usage
This code shows how an addon using the simple library would look:
Simple Library Usage Code
-- Assume this file gets loaded right after the library does.
local lib = SimpleExampleLib:GetInstance();
local count = lib:AddCount(10);
DEFAULT_CHAT_FRAME::AddMessage("New count is " .. count);
Simple Example .toc File
A Simple .toc File
## Interface: 11000
## Title: LibEmbed (v0.1)
## Notes: Embedded Library Example (v0.1)
## Author: Iriel (iriel@vigilance-committee.org)
LibStub.lua
SimpleExampleLib.lua
LibEmbed.lua
