iriel.org

Navigation

> 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