All pastes #62712 Raw Edit

cladhaire

public lua v1 · immutable
#62712 ·published 2006-06-06 21:14 UTC
rendered paste body
WDBParser = {       -- Constructor    --   @param input:     --      Specifies the input file to use    --   @param output:    --      Specifies the output file to use    --   @param structure:    --      Specified the table that describes the file structure        new = function(self, input, output, structure)        self.__index = self                local o = setmetatable({}, self)        o.input = io.open(input, "rb")        o.output = io.open(output, "w")        o.structure = structure        o.count = 0				if not o.input then			o.input = io.open(string.gsub(input, "\\", "/"), "rb")		end				if not o.output then			o.output = io.open(string.gsub(output, "\\", "/"), "2")		end                assert(o.input, "Could not open input file: " .. input)        assert(o.output, "Could not open output file: " .. output)        assert(o.structure, "Must specify a structure in the constructor.")        o.buffer = o.input:read("*all")        o.input:close()        o.index = 1        o.len = string.len(o.buffer)                print("Reading file with header: " .. self.readAny(o, 20))        return o    end,        -- WDBParser:readAny()    --   Used as a debug function, to read an arbitrary length of bytes in from the buffer    readAny = function(self, len)        local t = ""                for i=1,len do            local c = self:read(1)            if string.find(c, "%w") then                t = t .. c            else                t = string.format("%s0x%02X", t, string.byte(c))            end        end                return t    end,    -- WDBParser:readInteger()    --    Reads an integer into the system.  Treats all integer input as    --    32-bit signed integers.    readInteger = function(self)        local num = self:readBinary()		return self:bin2dec(num)    end,	-- WDBParser:readBinary()	--	  Reads 4 bytes of data from a binary file, and displays it in true binary format	--	  converts from ASCII display characters to their binary representation	readBinary = function(self)        local a,b,c,d = self:read(1),self:read(1),self:read(1),self:read(1)        a,b,c,d = string.byte(a),string.byte(b),string.byte(c),string.byte(d)        a,b,c,d = self:dec2bin(a),self:dec2bin(b),self:dec2bin(c),self:dec2bin(d)        return d..c..b..a    end,	-- WDBParser:readString()	--	  Reads a null-terminated string in from the standard buffer	--	  Returns the string without trailing 0x00    readString = function(self)        local txt = ""        while true do            local b = self:read(1)                        if b == string.char(0) then                return txt            else                txt = txt .. b            end        end    end,	-- WDBParser:readString()	--	  Reads a null-terminated string in from the standard buffer	--	  Returns the string without trailing 0x00    readFloat = function(self)		local num = self:readBinary()                local sign = string.sub(num,1,1)        local exp = string.sub(num,2,9)        local mantissa = string.sub(num,10,-1)                if sign == "1" then sign = -1 else sign = 1 end        exp = self:bin2dec(exp) - 127        mantissa = self:bin2float(mantissa)                if exp < 0 then return 0 end                return mantissa * math.pow(2, exp)    end,	-- WDBParser:bin2dec()	--	  Converts a number from IEEE uint32 format to a decimal number	bin2dec = function(self, num)		local sign,int               if string.sub(num, 1, 1) == "1" then            -- Take twos complement, one's complement it and add one            num = string.gsub(num, "0", "*")            num = string.gsub(num, "1", "0")			num = string.gsub(num, "*", "1")            num = tonumber(num, 2) + 1            num = num * -1        else            num = tonumber(num, 2)        end       		return num	end,		-- WDBParser:dec2bin()	--	  Takes an 8 bit number and coverts it to binary representation	-- 	  Used as a helper function for WDBParser:readBin()    dec2bin = function(self, num)        local i = {128,64,32,16,8,4,2,1}        local output = ""                for k,v in ipairs(i) do            if num >= v then                num = num - v                output = output .. "1"            else                output = output .. "0"            end        end        return output    end,	-- WDBParser:bin2float()	--	  Used to convert a mantissa into decimal form for final conversion	-- 	  Takes a length of bits, and converts it with the most signifigant	-- 	  digit being 1/2, followed by 1/4, and so on.    bin2float = function(self, num)       local answer = 1.0              for i=1,string.len(num) do          if tonumber(string.sub(num,i,i)) == 1 then             answer = answer + (1 / math.pow(2, i))          end       end              return answer    end,  	-- WDBParser:readItem()	--	  Reads the next item in the file, given the table structure	-- 	  Currently handles Integer, BitMask, Float and String input.    readItem = function(self)        self.item = {}        self.count = 0               for k,v in ipairs(self.structure) do                       self.field = v.field            if v.type == "Integer" then                self.item[v.field] = self:readInteger()            elseif v.type == "BitMask" then                self.item[v.field] = self:readBinary()            elseif v.type == "Float" then                self.item[v.field] = self:readFloat()            elseif v.type == "String" then                self.item[v.field] = self:readString()            else                error("Error in structure")            end	        end	        return self.item    end,    	-- WDBParser:printHeader()	--	  Used in CSV output.  Prints the column header    printHeader = function(self)        for k,v in ipairs(self.structure) do            self.output:write(v.field..",")        end        self.output:write('\n')    end,	-- WDBParser:printItem()	--	  Parses the file and writes the listing to the output file.    printItem = function(self)        local i = self:readItem()        if not i then return end                for k,v in ipairs(self.structure) do            local t = i[v.field]            if string.find(t, ",") then                i[v.field] = string.format("\"%s\"", string.gsub(i[v.field], "\"", "'"))            end            if v.type == "BitMask" then				i[v.field] = string.sub(i[v.field], -8, -1)            end                        self.output:write(i[v.field]..",")        end		self.output:write("," .. "http://wow.allakhazam.com/db/item.html?witem=" .. i.itemID)        self.output:write('\n')    end,	-- WDBParser:parse()	--	  Performs a parse of the loaded file    parse = function(self)        self:printHeader()        local i = 1                while not self:eof() do            i = i + 1            self:printItem()        end    end,    	-- WDBParser:eof()	-- 	  Used as a check to see whether we're out of range on a file    eof = function(self)        return self.index >= (self.len - 8)    end,	-- WDBParser:read(len)	--	  Performs an arbitrary read of len bytes and returns it in ASCII format    read = function(self, len)               if (self.index + len) > self.len then            self:error("Attempt to read beyond the end of file.  Index: %s, Length: %s, BufferLength: %s", self.index, len, self.len)        else            local t = string.sub(self.buffer, self.index, self.index + (len - 1))            self.index = self.index + len            return t        end    end,	-- WDBParser:error(format, ...)	--	  More robust error function, to allow for string.format() implicitly    error = function(self, format, ...)        error(string.format(format, unpack(arg)))    end,}local structure = {-- These are parsed specially in parseItem	{field = "itemID", type = "Integer"},	{field = "entryLength", type = "Integer"},	{field = "itemClassID", type = "Integer"},	{field = "itemSubClassID", type = "Integer"},	{field = "name1", type = "String"},	{field = "name2", type = "String"},	{field = "name3", type = "String"},	{field = "name4", type = "String"},	{field = "itemdisplayID", type = "Integer"},	{field = "qualityID", type = "Integer"},	{field = "typeBinFlag", type = "BitMask"},	{field = "buyPrice", type = "Integer"},	{field = "sellPrice", type = "Integer"},	{field = "inventorySlotID", type = "Integer"},	{field = "classBinFlag", type = "BitMask"},	{field = "raceBinFlag", type = "BitMask"},	{field = "itemLevel", type = "Integer"},	{field = "requiredLevel", type = "Integer"},	{field = "requiredSkillID", type = "Integer"},	{field = "requiredSkillLevel", type = "Integer"},	{field = "requiredSpellID", type = "Integer"},	{field = "requiredRankID", type = "Integer"},	{field = "Unknown", type = "Integer"},	{field = "requiredFactionID", type = "Integer"},	{field = "requiredFactionLevel", type = "Integer"},	{field = "isUnique", type = "BitMask"},	{field = "stackAmount", type = "Integer"},	{field = "containerSlots", type = "Integer"},	{field = "stat1ID", type = "Integer"},	{field = "stat1Value", type = "Integer"},	{field = "stat2ID", type = "Integer"},	{field = "stat2Value", type = "Integer"},	{field = "stat3ID", type = "Integer"},	{field = "stat3Value", type = "Integer"},	{field = "stat4ID", type = "Integer"},	{field = "stat4Value", type = "Integer"},	{field = "stat5ID", type = "Integer"},	{field = "stat5Value", type = "Integer"},	{field = "stat6ID", type = "Integer"},	{field = "stat6Value", type = "Integer"},	{field = "stat7ID", type = "Integer"},	{field = "stat7Value", type = "Integer"},	{field = "stat8ID", type = "Integer"},	{field = "stat8Value", type = "Integer"},	{field = "stat9ID", type = "Integer"},	{field = "stat9Value", type = "Integer"},	{field = "stat10ID", type = "Integer"},	{field = "stat10Value", type = "Integer"},	{field = "damage1Min", type = "Float"},	{field = "damage1Max", type = "Float"},	{field = "damage1TypeID", type = "Integer"},	{field = "damage2Min", type = "Float"},	{field = "damage2Max", type = "Float"},	{field = "damage2TypeID", type = "Integer"},	{field = "damage3Min", type = "Float"},	{field = "damage3Max", type = "Float"},	{field = "damage3TypeID", type = "Integer"},	{field = "damage4Min", type = "Float"},	{field = "damage4Max", type = "Float"},	{field = "damage4TypeID", type = "Integer"},	{field = "damage5Min", type = "Float"},	{field = "damage5Max", type = "Float"},	{field = "damage5TypeID", type = "Integer"},	{field = "resistPhysical", type = "Integer"},	{field = "resistHoly", type = "Integer"},	{field = "resistFire", type = "Integer"},	{field = "resistNature", type = "Integer"},	{field = "resistFrost", type = "Integer"},	{field = "resistShadow", type = "Integer"},	{field = "resistArcane", type = "Integer"},	{field = "weaponDelay", type = "Integer"},	{field = "ammoType", type = "Integer"},	{field = "rangeModifier", type = "Float"},	{field = "spell1ID", type = "Integer"},	{field = "spell1TriggerID", type = "Integer"},	{field = "spell1Charges", type = "Integer"},	{field = "spell1Cooldown", type = "Integer"},	{field = "spell1CategoryID", type = "Integer"},	{field = "spell1CategoryCooldown", type = "Integer"},	{field = "spell2ID", type = "Integer"},	{field = "spell2TriggerID", type = "Integer"},	{field = "spell2Charges", type = "Integer"},	{field = "spell2Cooldown", type = "Integer"},	{field = "spell2CategoryID", type = "Integer"},	{field = "spell2CategoryCooldown", type = "Integer"},	{field = "spell3ID", type = "Integer"},	{field = "spell3TriggerID", type = "Integer"},	{field = "spell3Charges", type = "Integer"},	{field = "spell3Cooldown", type = "Integer"},	{field = "spell3CategoryID", type = "Integer"},	{field = "spell3CategoryCooldown", type = "Integer"},	{field = "spell4ID", type = "Integer"},	{field = "spell4TriggerID", type = "Integer"},	{field = "spell4Charges", type = "Integer"},	{field = "spell4Cooldown", type = "Integer"},	{field = "spell4CategoryID", type = "Integer"},	{field = "spell4CategoryCooldown", type = "Integer"},	{field = "spell5ID", type = "Integer"},	{field = "spell5TriggerID", type = "Integer"},	{field = "spell5Charges", type = "Integer"},	{field = "spell5Cooldown", type = "Integer"},	{field = "spell5CategoryID", type = "Integer"},	{field = "spell5CategoryCooldown", type = "Integer"},	{field = "bondID", type = "Integer"},	{field = "description", type = "String"},	{field = "bookTextID", type = "Integer"},	{field = "bookPages", type = "Integer"},	{field = "bookStationaryID", type = "Integer"},	{field = "beginQuestID", type = "Integer"},	{field = "lockPickTalent", type = "Integer"},	{field = "materialID", type = "Integer"},	{field = "sheathID", type = "Integer"},	{field = "randompropertyID", type = "Integer"},	{field = "blockValue", type = "Integer"},	{field = "itemSetID", type = "Integer"},	{field = "durabilityValue", type = "Integer"},	{field = "itemAreaID", type = "Integer"},	{field = "itemMapID", type = "Integer"},	{field = "bagFamily", type = "Integer"},}local parser = WDBParser:new("g:\\world of warcraft\\wowtest\\wdb\\itemcache.wdb", "c:\\temp\\output.csv", structure)parser:parse()