]> git.openstreetmap.org Git - rails.git/blob - lib/potlatch.rb
Optimise finding of relations, partially reversing change #8443 but in
[rails.git] / lib / potlatch.rb
1 # The Potlatch module provides helper functions for potlatch and its communication with the server
2 module Potlatch
3
4   # The AMF class is a set of helper functions for encoding and decoding AMF.
5   class AMF
6     
7     # Return two-byte integer
8     def self.getint(s) 
9       s.getc*256+s.getc
10     end
11
12     # Return four-byte long
13     def self.getlong(s) 
14       ((s.getc*256+s.getc)*256+s.getc)*256+s.getc
15     end
16
17     # Return string with two-byte length 
18     def self.getstring(s) 
19       len=s.getc*256+s.getc
20       s.read(len)
21     end
22
23     # Return eight-byte double-precision float 
24     def self.getdouble(s) 
25       a=s.read(8).unpack('G')                   # G big-endian, E little-endian
26       a[0]
27     end
28
29     # Return numeric array
30     def self.getarray(s) 
31       len=getlong(s)
32       arr=[]
33       for i in (0..len-1)
34         arr[i]=getvalue(s)
35       end
36       arr
37     end
38
39     # Return object/hash 
40     def self.getobject(s) 
41       arr={}
42       while (key=getstring(s))
43         if (key=='') then break end
44         arr[key]=getvalue(s)
45       end
46       s.getc            # skip the 9 'end of object' value
47       arr
48     end
49
50     # Parse and get value
51     def self.getvalue(s) 
52       case s.getc
53       when 0;   return getdouble(s)                     # number
54       when 1;   return s.getc                           # boolean
55       when 2;   return getstring(s)                     # string
56       when 3;   return getobject(s)                     # object/hash
57       when 5;   return nil                                      # null
58       when 6;   return nil                                      # undefined
59       when 8;   s.read(4)                                       # mixedArray
60         return getobject(s)                     #  |
61       when 10;return getarray(s)                        # array
62       else;     return nil                                      # error
63       end
64     end
65
66     # Envelope data into AMF writeable form
67     def self.putdata(index,n) 
68       d =encodestring(index+"/onResult")
69       d+=encodestring("null")
70       d+=[-1].pack("N")
71       d+=encodevalue(n)
72     end
73
74     # Pack variables as AMF
75     def self.encodevalue(n) 
76       case n.class.to_s
77       when 'Array'
78         a=10.chr+encodelong(n.length)
79         n.each do |b|
80           a+=encodevalue(b)
81         end
82         a
83       when 'Hash'
84         a=3.chr
85         n.each do |k,v|
86           a+=encodestring(k.to_s)+encodevalue(v)
87         end
88         a+0.chr+0.chr+9.chr
89       when 'String'
90         2.chr+encodestring(n)
91       when 'Bignum','Fixnum','Float'
92         0.chr+encodedouble(n)
93       when 'NilClass'
94         5.chr
95       else
96         RAILS_DEFAULT_LOGGER.error("Unexpected Ruby type for AMF conversion: "+n.class.to_s)
97       end
98     end
99
100     # Encode string with two-byte length
101     def self.encodestring(n) 
102       a,b=n.size.divmod(256)
103       a.chr+b.chr+n
104     end
105
106     # Encode number as eight-byte double precision float 
107     def self.encodedouble(n) 
108       [n].pack('G')
109     end
110
111     # Encode number as four-byte long
112     def self.encodelong(n) 
113       [n].pack('N')
114     end
115
116   end
117
118
119   # The Potlatch class is a helper for Potlatch
120   class Potlatch
121
122     # ----- getpresets
123     #             in:   none
124     #             does: reads tag preset menus, colours, and autocomplete config files
125     #         out:  [0] presets, [1] presetmenus, [2] presetnames,
126     #                           [3] colours, [4] casing, [5] areas, [6] autotags
127     #                           (all hashes)
128     def self.get_presets
129       RAILS_DEFAULT_LOGGER.info("  Message: getpresets")
130
131       # Read preset menus
132       presets={}
133       presetmenus={}; presetmenus['point']=[]; presetmenus['way']=[]; presetmenus['POI']=[]
134       presetnames={}; presetnames['point']={}; presetnames['way']={}; presetnames['POI']={}
135       presettype=''
136       presetcategory=''
137       # StringIO.open(txt) do |file|
138       File.open("#{RAILS_ROOT}/config/potlatch/presets.txt") do |file|
139         file.each_line {|line|
140           t=line.chomp
141           if (t=~/(\w+)\/(\w+)/) then
142             presettype=$1
143             presetcategory=$2
144             presetmenus[presettype].push(presetcategory)
145             presetnames[presettype][presetcategory]=["(no preset)"]
146           elsif (t=~/^(.+):\s?(.+)$/) then
147             pre=$1; kv=$2
148             presetnames[presettype][presetcategory].push(pre)
149             presets[pre]={}
150             kv.split(',').each {|a|
151               if (a=~/^(.+)=(.*)$/) then presets[pre][$1]=$2 end
152             }
153           end
154         }
155       end
156
157       # Read colours/styling
158       colours={}; casing={}; areas={}
159       File.open("#{RAILS_ROOT}/config/potlatch/colours.txt") do |file|
160         file.each_line {|line|
161           t=line.chomp
162           if (t=~/(\w+)\s+([^\s]+)\s+([^\s]+)\s+([^\s]+)/) then
163             tag=$1
164             if ($2!='-') then colours[tag]=$2.hex end
165             if ($3!='-') then casing[tag]=$3.hex end
166             if ($4!='-') then areas[tag]=$4.hex end
167           end
168         }
169       end
170
171       # Read relations colours/styling
172       relcolours={}; relalphas={}; relwidths={}
173       File.open("#{RAILS_ROOT}/config/potlatch/relation_colours.txt") do |file|
174         file.each_line {|line|
175           t=line.chomp
176           if (t=~/(\w+)\s+([^\s]+)\s+([^\s]+)\s+([^\s]+)/) then
177             tag=$1
178             if ($2!='-') then relcolours[tag]=$2.hex end
179             if ($3!='-') then relalphas[tag]=$3.to_i end
180             if ($4!='-') then relwidths[tag]=$4.to_i end
181           end
182         }
183       end
184
185       # Read auto-complete
186       autotags={}; autotags['point']={}; autotags['way']={}; autotags['POI']={};
187       File.open("#{RAILS_ROOT}/config/potlatch/autocomplete.txt") do |file|
188         file.each_line {|line|
189           t=line.chomp
190           if (t=~/^(\w+)\/(\w+)\s+(.+)$/) then
191             tag=$1; type=$2; values=$3
192             if values=='-' then autotags[type][tag]=[]
193             else autotags[type][tag]=values.split(',').sort.reverse end
194           end
195         }
196       end
197
198           # Read internationalisation
199           localised = YAML::load(File.open("#{RAILS_ROOT}/config/potlatch/localised.yaml"))
200
201       [presets,presetmenus,presetnames,colours,casing,areas,autotags,relcolours,relalphas,relwidths,localised]
202     end
203   end
204
205 end
206