vanilla-wow-addons – Blame information for rev 1
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
1 | office | 1 | --[[ |
2 | |||
3 | Sea String (mostly Sea.string) |
||
4 | |||
5 | A Mini-Library for string functions. |
||
6 | |||
7 | Compiler: |
||
8 | AnduinLothar (karlkfi@cosmosui.org) |
||
9 | |||
10 | Contributors: |
||
11 | Thott (thott@thottbot.com) |
||
12 | Legorol (legorol@cosmosui.org) |
||
13 | Mugendai (mugekun@gmail.com) |
||
14 | Iriel (iriel@vigilance-committee.org) |
||
15 | |||
16 | |||
17 | ==Installation/Utilization== |
||
18 | |||
19 | Embedding: |
||
20 | - Drop the SeaString folder into your Interface\AddOns\YourAddon\ folder |
||
21 | - Add Sea and SeaString as optional dependancies |
||
22 | - Add the following line to the end of your TOC file, before your addon files: |
||
23 | SeaString\SeaString.lua |
||
24 | |||
25 | Standard: |
||
26 | - Drop the SeaString folder into your Interface\AddOns\ directory |
||
27 | - Add SeaString as a required dependancy |
||
28 | |||
29 | |||
30 | Change Log: |
||
31 | v0.2 |
||
32 | - Changed lua file name |
||
33 | v0.1 (Alpha) |
||
34 | - SeaString Forked into Mini-Library from the main Sea. Still backwards compatible. |
||
35 | |||
36 | |||
37 | $LastChangedBy: karlkfi $ |
||
38 | $Rev: 2577 $ |
||
39 | $Date: 2005-10-10 14:44:01 -0700 (Mon, 10 Oct 2005) $ |
||
40 | ]]-- |
||
41 | |||
42 | local SEA_STRING_VERSION = 0.11; |
||
43 | local loadThisEmbeddedInstance; |
||
44 | SEA_STRING_DEBUG = nil; |
||
45 | ------------------------------------------------------------------------------ |
||
46 | --[[ Embedded Sub-Library Load Algorithm ]]-- |
||
47 | ------------------------------------------------------------------------------ |
||
48 | |||
49 | if(not Sea) then |
||
50 | Sea = {}; |
||
51 | Sea.versions = {}; |
||
52 | Sea.versions.SeaString = SEA_STRING_VERSION; |
||
53 | loadThisEmbeddedInstance = true; |
||
54 | Sea.string = {}; |
||
55 | else |
||
56 | if(not Sea.versions) then |
||
57 | Sea.versions = {}; |
||
58 | end |
||
59 | if (not Sea.versions.SeaString) or (Sea.versions.SeaString < SEA_STRING_VERSION) then |
||
60 | Sea.versions.SeaString = SEA_STRING_VERSION; |
||
61 | loadThisEmbeddedInstance = true; |
||
62 | end |
||
63 | if(not Sea.string) then |
||
64 | Sea.string = {}; |
||
65 | end |
||
66 | end |
||
67 | |||
68 | if (loadThisEmbeddedInstance) then |
||
69 | loadThisEmbeddedInstance = nil; |
||
70 | |||
71 | |||
72 | ------------------------------------------------------------------------------ |
||
73 | --[[ Function Definitions - User Functions ]]-- |
||
74 | ------------------------------------------------------------------------------ |
||
75 | |||
76 | -- |
||
77 | -- byte(string) |
||
78 | -- |
||
79 | -- Converts a character to its bytecode |
||
80 | -- |
||
81 | -- Args: |
||
82 | -- string - the string |
||
83 | -- |
||
84 | -- Returns: |
||
85 | -- (string) |
||
86 | -- string - the string in byte code with format <##> |
||
87 | -- |
||
88 | Sea.string.byte = function(c) |
||
89 | return string.format("<%02X>",string.byte(c)); |
||
90 | end |
||
91 | |||
92 | -- |
||
93 | -- byteSum (string s) |
||
94 | -- returns the bytecode sum for s |
||
95 | -- |
||
96 | -- Args: |
||
97 | -- s - the string |
||
98 | -- |
||
99 | -- Returns: |
||
100 | -- (number) |
||
101 | -- number - the value of the string with all of its |
||
102 | -- chars summed together. |
||
103 | -- |
||
104 | |||
105 | Sea.string.byteSum = function(s) |
||
106 | local sum = 0; |
||
107 | local len = string.len(s); |
||
108 | local sbyte = string.byte; |
||
109 | for i=1,len do |
||
110 | sum = sum + sbyte(s,i); |
||
111 | end |
||
112 | return sum; |
||
113 | end |
||
114 | |||
115 | -- |
||
116 | -- toInt (string s) |
||
117 | -- |
||
118 | -- Converts the specified string to an int |
||
119 | -- |
||
120 | -- Returns: |
||
121 | -- (Number int) |
||
122 | -- int - the string S as a number |
||
123 | -- |
||
124 | Sea.string.toInt = tonumber; |
||
125 | |||
126 | -- |
||
127 | -- fromTime(Number time, Number decimalplaces) |
||
128 | -- |
||
129 | -- Creates a readable time from a number time in WoW |
||
130 | -- Decimal places gives the number of .### to display |
||
131 | -- |
||
132 | -- Returns: |
||
133 | -- (String timeString) |
||
134 | -- timeString - the time |
||
135 | -- |
||
136 | |||
137 | Sea.string.fromTime = function (time, decimalplaces) |
||
138 | if (time < 0) then |
||
139 | time = 0; |
||
140 | end |
||
141 | if ( not decimalplaces ) then |
||
142 | decimalplaces = 0; |
||
143 | end |
||
144 | |||
145 | local floor = math.floor; |
||
146 | local mod = math.mod; |
||
147 | |||
148 | local seconds = mod(time, 60); |
||
149 | local minutes = mod(floor(time/60), 60); |
||
150 | local hours = floor(time/(3600)); |
||
151 | local spfx = ''; |
||
152 | if (seconds < 10) then |
||
153 | spfx = '0'; |
||
154 | end |
||
155 | |||
156 | if (hours > 0) then |
||
157 | return string.format("%d:%.2d:%s%."..decimalplaces.."f", hours, minutes, spfx, seconds); |
||
158 | else |
||
159 | return string.format("%d:%s%."..decimalplaces.."f", minutes, spfx, seconds); |
||
160 | end |
||
161 | end |
||
162 | |||
163 | -- |
||
164 | -- capitalizeWords(String phrase) |
||
165 | -- |
||
166 | -- Takes a string like "hello world" and turns |
||
167 | -- it into "Hello World". |
||
168 | -- |
||
169 | -- Returns: |
||
170 | -- (String capitalizedPhrase) |
||
171 | -- |
||
172 | |||
173 | Sea.string.capitalizeWords = function ( text ) |
||
174 | if (not text) then |
||
175 | return text; |
||
176 | end |
||
177 | local capitalizedPhrase = ""; |
||
178 | local value, mend; |
||
179 | local mstart = 1; |
||
180 | local regexKey = "([^%s]+[%s]*)"; |
||
181 | local sfind = strfind; -- string.find if not in WoW (n calls) |
||
182 | local supper = strupper; |
||
183 | local slower = strlower; |
||
184 | local ssub = strsub; |
||
185 | |||
186 | -- Using string.find instead of string.gfind to avoid garbage generation |
||
187 | mstart, mend, value = sfind(text, regexKey, mstart); |
||
188 | while (value) do |
||
189 | if( sfind(text, "^[a-zA-Z].*") ) then |
||
190 | capitalizedPhrase = capitalizedPhrase..supper(ssub(value,1,1))..slower(ssub(value,2)); |
||
191 | else |
||
192 | capitalizedPhrase = capitalizedPhrase..supper(ssub(value,1,2))..slower(ssub(value,3)); |
||
193 | end |
||
194 | mstart = mend + 1; |
||
195 | mstart, mend, value = sfind(text, regexKey, mstart); |
||
196 | end |
||
197 | |||
198 | return capitalizedPhrase; |
||
199 | end |
||
200 | |||
201 | |||
202 | -- |
||
203 | -- objectToString( value, [name] ) |
||
204 | -- |
||
205 | -- Converts a value to a serialized string. |
||
206 | -- Cannot serialize functions. |
||
207 | -- |
||
208 | -- returns: |
||
209 | -- A string which represents the object, |
||
210 | -- minus functions. |
||
211 | -- |
||
212 | -- |
||
213 | Sea.string.objectToString = function( value, name ) |
||
214 | local output = ""; |
||
215 | |||
216 | if ( name == nil ) then name = ""; |
||
217 | else |
||
218 | -- Serialize the name |
||
219 | name = Sea.string.objectToString(name); |
||
220 | -- Remove the <> |
||
221 | name = string.gsub(name, "<(.*)>", "%1"); |
||
222 | end |
||
223 | |||
224 | if (type(value) == "nil" ) then |
||
225 | output = name.."<".."nil:nil"..">"; |
||
226 | elseif ( type(value) == "string" ) then |
||
227 | value = string.gsub(value, "<", "<"); |
||
228 | value = string.gsub(value, ">", ">"); |
||
229 | output = name.."<".."s:"..value..">"; |
||
230 | elseif ( type(value) == "number" ) then |
||
231 | output = name.."<".."n:"..value..">"; |
||
232 | elseif ( type(value) == "boolean" ) then |
||
233 | if ( value ) then |
||
234 | output = name.."<".."b:".."true"..">"; |
||
235 | else |
||
236 | output = name.."<".."b:".."false"..">"; |
||
237 | end |
||
238 | elseif ( type(value) == "function" ) then |
||
239 | output = name.."<".."func:".."*invalid*"..">"; |
||
240 | elseif ( type(value) == "table" ) then |
||
241 | output = name.."<".."t:"; |
||
242 | for k,v in value do |
||
243 | output = output.." "..Sea.string.objectToString(v,k); |
||
244 | end |
||
245 | output = output .. ">"; |
||
246 | end |
||
247 | |||
248 | return output; |
||
249 | end |
||
250 | |||
251 | -- |
||
252 | -- stringToObject(string) |
||
253 | -- |
||
254 | -- Turns a string serialized by objectToString into |
||
255 | -- and object. |
||
256 | -- |
||
257 | -- returns: |
||
258 | -- nil or number or string or boolean or table |
||
259 | -- |
||
260 | -- |
||
261 | Sea.string.stringToObject = function ( str ) |
||
262 | -- check for the format "keytype:keyvalue<valuetype:value>" |
||
263 | -- take the stuff in <> |
||
264 | typevalue = string.gsub(str, "%s*(%w*:?%w*)%s*(<.*>)","%2"); |
||
265 | |||
266 | local value = nil; |
||
267 | local typeString = string.gsub(typevalue, "<%s*(%w*):(.*)>","%1"); |
||
268 | local valueString = string.gsub(typevalue, "<%s*(%w*):(.*)>","%2"); |
||
269 | |||
270 | |||
271 | --print("str: ", str, " typevalue: ", typevalue); |
||
272 | --print("valueString: (", valueString, ") typeString: (", typeString,")"); |
||
273 | |||
274 | -- Error! |
||
275 | if ( typeString == typevalue ) then |
||
276 | Sea.io.error ( "Unparsable string passed to stringToObject: ", str ); |
||
277 | return nil; |
||
278 | end |
||
279 | |||
280 | -- Maybe no error! |
||
281 | if ( typeString == "nil" ) then |
||
282 | value = nil; |
||
283 | |||
284 | elseif ( typeString == "n" ) then |
||
285 | value = tonumber(valueString); |
||
286 | |||
287 | elseif ( typeString == "b" ) then |
||
288 | if ( valueString == "true" ) then |
||
289 | value = true; |
||
290 | else |
||
291 | value = false; |
||
292 | end |
||
293 | |||
294 | elseif ( typeString == "s" ) then |
||
295 | value = valueString; |
||
296 | -- Parse the <> back in |
||
297 | value = string.gsub(value, "<", "<"); |
||
298 | value = string.gsub(value, ">", ">"); |
||
299 | |||
300 | elseif ( typeString == "f" ) then |
||
301 | -- Functions are not supported, but if they were.. |
||
302 | |||
303 | -- ...this is how it should work |
||
304 | -- value = getglobal(typeString); |
||
305 | value = Sea.io.error; |
||
306 | |||
307 | elseif ( typeString == "t" ) then |
||
308 | -- Here's the hard part |
||
309 | -- I have to extract each set of <> |
||
310 | -- which might have nested tables! |
||
311 | -- |
||
312 | -- So I start off by tracking < until I get 0 |
||
313 | -- |
||
314 | value = {}; |
||
315 | |||
316 | local left = 1; |
||
317 | local right = 1; |
||
318 | |||
319 | local count = 0; |
||
320 | |||
321 | while ( valueString and valueString ~= "" ) do |
||
322 | local object = nil; |
||
323 | local key = nil; |
||
324 | |||
325 | -- Extract the key and convert it |
||
326 | key = string.gsub(valueString, "%s*(%w*:?.-)<.*>", "%1" ); |
||
327 | key = Sea.string.stringToObject("<"..key..">"); |
||
328 | |||
329 | |||
330 | left = string.find(valueString, "<", 1 ); |
||
331 | right = string.find(valueString, ">", 1 ); |
||
332 | |||
333 | if ( left < right ) then |
||
334 | nextleft = string.find(valueString, "<", left+1 ); |
||
335 | while ( nextleft and nextleft < right ) do |
||
336 | nextleft = string.find(valueString, "<", nextleft+1 ); |
||
337 | right = string.find(valueString, ">", right+1 ); |
||
338 | end |
||
339 | else |
||
340 | --error ( "we all die." ); |
||
341 | end |
||
342 | |||
343 | objectString = string.sub(valueString, left, right); |
||
344 | |||
345 | -- Create the object |
||
346 | object = Sea.string.stringToObject(objectString); |
||
347 | |||
348 | -- Add it to the table |
||
349 | value[key] = object; |
||
350 | |||
351 | -- See if there's another entry |
||
352 | valueString = string.sub(valueString, right+1); |
||
353 | end |
||
354 | end |
||
355 | |||
356 | return value; |
||
357 | end |
||
358 | |||
359 | -- |
||
360 | -- startsWith(String text, String prefix) |
||
361 | -- |
||
362 | -- Looks for 'prefix' at the beginning of 'text' |
||
363 | -- |
||
364 | -- Returns: |
||
365 | -- boolean |
||
366 | -- |
||
367 | |||
368 | Sea.string.startsWith = function ( text, prefix ) |
||
369 | if ( strfind(text, "^"..prefix, 1) ) then |
||
370 | return true; |
||
371 | else |
||
372 | return false; |
||
373 | end |
||
374 | end |
||
375 | |||
376 | -- |
||
377 | -- endsWith(String text, String suffix) |
||
378 | -- |
||
379 | -- Looks for 'suffix' at the end of 'text' |
||
380 | -- |
||
381 | -- Returns: |
||
382 | -- boolean |
||
383 | -- |
||
384 | |||
385 | Sea.string.endsWith = function ( text, suffix ) |
||
386 | if ( strfind(text, suffix.."$") ) then |
||
387 | return true; |
||
388 | else |
||
389 | return false; |
||
390 | end |
||
391 | end |
||
392 | |||
393 | -- |
||
394 | -- colorToString(Table{r,g,b,a}) |
||
395 | -- |
||
396 | -- Converts a table to a Blizzard color code |
||
397 | -- |
||
398 | -- Returns: |
||
399 | -- string |
||
400 | -- The blizzard color code AARRGGBB |
||
401 | -- |
||
402 | |||
403 | Sea.string.colorToString = function ( color ) |
||
404 | if ( not color ) then |
||
405 | return "FFFFFFFF"; |
||
406 | end |
||
407 | return string.format("%.2X%.2X%.2X%.2X", |
||
408 | (color.a or color.opacity or 1) * 255, |
||
409 | (color.r or 0) * 255, |
||
410 | (color.g or 0) * 255, |
||
411 | (color.b or 0) * 255 |
||
412 | ); |
||
413 | end |
||
414 | |||
415 | -- stringToColor(String colorCode) |
||
416 | -- |
||
417 | -- Converts a Blizzard color code to a table |
||
418 | -- |
||
419 | -- Returns: |
||
420 | -- table{r,g,b,a,opacity} |
||
421 | -- |
||
422 | -- a & opacity are the same thing here (this could change) |
||
423 | -- |
||
424 | Sea.string.stringToColor = function ( colorCode ) |
||
425 | local red, green, blue, alpha = Sea.math.rgbaFromHex( colorCode ); |
||
426 | return { r = red; g = green; b = blue; a = alpha; opacity = alpha }; |
||
427 | end |
||
428 | |||
429 | |||
430 | end |
||
431 |