root/HTTP/Trie.lua

Revision 1476 (checked in by rsz, 5 days ago)

cleanup

Line 
1 --------------------------------------------------------------------------------
2 -- Title:               Trie.lua
3 -- Description:         Like a square peg in a round hole
4 -- Author:              Raphaël Szwarc http://alt.textdrive.com/lua/
5 -- Creation Date:       January 30, 2007
6 -- Legal:               Copyright (C) 2007 Raphaël Szwarc
7 --                      Under the terms of the MIT License
8 --                      http://www.opensource.org/licenses/mit-license.html
9 --------------------------------------------------------------------------------
10
11 -- import dependencies
12 local File = require( 'File' )
13 local string = require( 'string' )
14
15 local getmetatable = getmetatable
16 local setmetatable = setmetatable
17 local tostring = tostring
18
19 --------------------------------------------------------------------------------
20 -- Trie
21 --------------------------------------------------------------------------------
22
23 module( 'Trie' )
24 _VERSION = '1.0'
25
26 local self = setmetatable( _M, {} )
27 local meta = getmetatable( self )
28
29 --------------------------------------------------------------------------------
30 -- Utilities
31 --------------------------------------------------------------------------------
32
33 local paths = setmetatable( {}, { __mode = 'k' } )
34
35 local function SetPath( self, aPath )
36     paths[ self ] = tostring( aPath )
37 end
38
39 local function GetPath( self )
40     return paths[ self ]
41 end
42
43 local function Key( aKey )
44     return tostring( aKey ):lower():gsub( '%W', '' ):sub( 1, 9 )
45 end
46
47 local function KeyPath( self, aKey, shouldMake )
48     local aKey = Key( aKey )
49    
50     if aKey:len() > 1 then
51         local aPath = GetPath( self )
52         local aFile = File( aPath )
53        
54         if shouldMake == nil then
55             shouldMake = true
56         end
57    
58         if shouldMake then
59             aFile.mkdir = true
60         end
61        
62         for anIndex = 1, aKey:len() do
63             local aChar = string.char( aKey:byte( anIndex ) )
64            
65             aFile = File( aFile.path, aChar )
66            
67             if shouldMake then
68                 aFile.mkdir = true
69             end
70         end
71        
72         return aFile.path
73     end
74 end
75
76 --------------------------------------------------------------------------------
77 -- Metamethods
78 --------------------------------------------------------------------------------
79
80 function meta:__call( aPath )
81     local aTrie = {}
82
83     setmetatable( aTrie, self )
84     SetPath( aTrie, aPath or '.' )
85    
86     return aTrie
87 end
88
89 function meta:__index( aKey )
90     return Key( aKey )
91 end
92
93 function meta:__concat( aValue )
94     return tostring( self ) .. tostring( aValue )
95 end
96
97 function meta:__tostring()
98     return ( '%s/%s' ):format( self._NAME, self._VERSION )
99 end
100
101 function self:__call()
102     local aPath = GetPath( self )
103     local aDirectory = File( aPath )
104    
105     if aDirectory.exists then
106         local anIterator = aDirectory( true )
107        
108         return function()
109             local aFile = anIterator()
110            
111             while aFile and aFile.extension ~= 'id' do
112                 aFile = anIterator()
113             end
114            
115             if aFile and aFile.extension == 'id' then
116                 local aKey = aFile.path:sub( aPath:len() + 1, aFile.path:len() - aFile.name:len() ):gsub( File.separator, '' )
117                 local aValue = aFile.name:sub( 1, aFile.name:len() - aFile.extension:len() - 1 )
118                
119                 return aKey, aValue
120             end
121         end
122     end
123    
124     return function() end
125 end
126
127 function self:__newindex( aKey, aValue )
128     local aPath = KeyPath( self, aKey )
129    
130     if aPath then
131         local aFile = File( aPath, aValue .. '.id' )
132        
133         aFile.mkdir = true
134     end
135 end
136
137 function self:__index( aKey )
138     local aPath = KeyPath( self, aKey, false )
139    
140     if aPath then
141         local aDirectory = File( aPath )
142        
143         if aDirectory.exists then
144             local anIterator = aDirectory( true )
145            
146             return function()
147                 local aFile = anIterator()
148                
149                 while aFile and aFile.extension ~= 'id' do
150                     aFile = anIterator()
151                 end
152                
153                 if aFile and aFile.extension == 'id' then
154                     local anID = aFile.name:sub( 1, aFile.name:len() - aFile.extension:len() - 1 )
155                    
156                     return anID
157                 end
158             end
159         end
160     end
161    
162     return function() end
163 end
Note: See TracBrowser for help on using the browser.