]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/tools/build/src/engine/modules/property-set.c
Add patch for failing prerm scripts
[ceph.git] / ceph / src / boost / tools / build / src / engine / modules / property-set.c
CommitLineData
7c673cae
FG
1/*
2 * Copyright 2013 Steven Watanabe
3 * Distributed under the Boost Software License, Version 1.0.
4 * (See accompanying file LICENSE_1_0.txt or copy at
5 * http://www.boost.org/LICENSE_1_0.txt)
6 */
7
8#include "../object.h"
9#include "../lists.h"
10#include "../modules.h"
11#include "../rules.h"
12#include "../variable.h"
13#include "../native.h"
14#include "../compile.h"
15#include "../mem.h"
16#include "../constants.h"
17#include "string.h"
18
19struct ps_map_entry
20{
21 struct ps_map_entry * next;
22 LIST * key;
23 OBJECT * value;
24};
25
26struct ps_map
27{
28 struct ps_map_entry * * table;
29 size_t table_size;
30 size_t num_elems;
31};
32
33static unsigned list_hash(LIST * key)
34{
35 unsigned int hash = 0;
36 LISTITER iter = list_begin( key ), end = list_end( key );
37 for ( ; iter != end; ++iter )
38 {
39 hash = hash * 2147059363 + object_hash( list_item( iter ) );
40 }
41 return hash;
42}
43
44static int list_equal( LIST * lhs, LIST * rhs )
45{
46 LISTITER lhs_iter, lhs_end, rhs_iter;
47 if ( list_length( lhs ) != list_length( rhs ) )
48 {
49 return 0;
50 }
51 lhs_iter = list_begin( lhs );
52 lhs_end = list_end( lhs );
53 rhs_iter = list_begin( rhs );
54 for ( ; lhs_iter != lhs_end; ++lhs_iter, ++rhs_iter )
55 {
56 if ( ! object_equal( list_item( lhs_iter ), list_item( rhs_iter ) ) )
57 {
58 return 0;
59 }
60 }
61 return 1;
62}
63
64static void ps_map_init( struct ps_map * map )
65{
66 size_t i;
67 map->table_size = 2;
68 map->num_elems = 0;
69 map->table = BJAM_MALLOC( map->table_size * sizeof( struct ps_map_entry * ) );
70 for ( i = 0; i < map->table_size; ++i )
71 {
72 map->table[ i ] = NULL;
73 }
74}
75
76static void ps_map_destroy( struct ps_map * map )
77{
78 size_t i;
79 for ( i = 0; i < map->table_size; ++i )
80 {
81 struct ps_map_entry * pos;
82 for ( pos = map->table[ i ]; pos; )
83 {
84 struct ps_map_entry * tmp = pos->next;
85 object_free( pos->value );
86 BJAM_FREE( pos );
87 pos = tmp;
88 }
89 }
90 BJAM_FREE( map->table );
91}
92
93static void ps_map_rehash( struct ps_map * map )
94{
95 struct ps_map old = *map;
96 size_t i;
97 map->table = BJAM_MALLOC( map->table_size * 2 * sizeof( struct ps_map_entry * ) );
98 map->table_size *= 2;
99 for ( i = 0; i < map->table_size; ++i )
100 {
101 map->table[ i ] = NULL;
102 }
103 for ( i = 0; i < old.table_size; ++i )
104 {
105 struct ps_map_entry * pos;
106 for ( pos = old.table[ i ]; pos; )
107 {
108 struct ps_map_entry * tmp = pos->next;
109
110 unsigned hash_val = list_hash( pos->key );
111 unsigned bucket = hash_val % map->table_size;
112 pos->next = map->table[ bucket ];
113 map->table[ bucket ] = pos;
114
115 pos = tmp;
116 }
117 }
118 BJAM_FREE( old.table );
119}
120
121static struct ps_map_entry * ps_map_insert(struct ps_map * map, LIST * key)
122{
123 unsigned hash_val = list_hash( key );
124 unsigned bucket = hash_val % map->table_size;
125 struct ps_map_entry * pos;
126 for ( pos = map->table[bucket]; pos ; pos = pos->next )
127 {
128 if ( list_equal( pos->key, key ) )
129 return pos;
130 }
131
132 if ( map->num_elems >= map->table_size )
133 {
134 ps_map_rehash( map );
135 bucket = hash_val % map->table_size;
136 }
137 pos = BJAM_MALLOC( sizeof( struct ps_map_entry ) );
138 pos->next = map->table[bucket];
139 pos->key = key;
140 pos->value = 0;
141 map->table[bucket] = pos;
142 ++map->num_elems;
143 return pos;
144}
145
146static struct ps_map all_property_sets;
147
148LIST * property_set_create( FRAME * frame, int flags )
149{
150 LIST * properties = lol_get( frame->args, 0 );
151 LIST * sorted = list_sort( properties );
152 LIST * unique = list_unique( sorted );
153 struct ps_map_entry * pos = ps_map_insert( &all_property_sets, unique );
154 list_free( sorted );
155 if ( pos->value )
156 {
157 list_free( unique );
158 return list_new( object_copy( pos->value ) );
159 }
160 else
161 {
162 OBJECT * rulename = object_new( "new" );
163 OBJECT * varname = object_new( "self.raw" );
164 LIST * val = call_rule( rulename, frame,
165 list_new( object_new( "property-set" ) ), 0 );
166 LISTITER iter, end;
167 object_free( rulename );
168 pos->value = object_copy( list_front( val ) );
169 var_set( bindmodule( pos->value ), varname, unique, VAR_SET );
170 object_free( varname );
171
172 for ( iter = list_begin( unique ), end = list_end( unique ); iter != end; ++iter )
173 {
174 const char * str = object_str( list_item( iter ) );
175 if ( str[ 0 ] != '<' || ! strchr( str, '>' ) )
176 {
177 string message[ 1 ];
178 string_new( message );
179 string_append( message, "Invalid property: '" );
180 string_append( message, str );
181 string_append( message, "'" );
182 rulename = object_new( "errors.error" );
183 call_rule( rulename, frame,
184 list_new( object_new( message->value ) ), 0 );
185 /* unreachable */
186 string_free( message );
187 object_free( rulename );
188 }
189 }
190
191 return val;
192 }
193}
194
195/* binary search for the property value */
196LIST * property_set_get( FRAME * frame, int flags )
197{
198 OBJECT * varname = object_new( "self.raw" );
199 LIST * props = var_get( frame->module, varname );
200 const char * name = object_str( list_front( lol_get( frame->args, 0 ) ) );
201 size_t name_len = strlen( name );
202 LISTITER begin, end;
203 LIST * result = L0;
204 object_free( varname );
205
206 /* Assumes random access */
207 begin = list_begin( props ), end = list_end( props );
208
209 while ( 1 )
210 {
211 ptrdiff_t diff = (end - begin);
212 LISTITER mid = begin + diff / 2;
213 int res;
214 if ( diff == 0 )
215 {
216 return L0;
217 }
218 res = strncmp( object_str( list_item( mid ) ), name, name_len );
219 if ( res < 0 )
220 {
221 begin = mid + 1;
222 }
223 else if ( res > 0 )
224 {
225 end = mid;
226 }
227 else /* We've found the property */
228 {
229 /* Find the beginning of the group */
230 LISTITER tmp = mid;
231 while ( tmp > begin )
232 {
233 --tmp;
234 res = strncmp( object_str( list_item( tmp ) ), name, name_len );
235 if ( res != 0 )
236 {
237 ++tmp;
238 break;
239 }
240 }
241 begin = tmp;
242 /* Find the end of the group */
243 tmp = mid + 1;
244 while ( tmp < end )
245 {
246 res = strncmp( object_str( list_item( tmp ) ), name, name_len );
247 if ( res != 0 ) break;
248 ++tmp;
249 }
250 end = tmp;
251 break;
252 }
253 }
254
255 for ( ; begin != end; ++begin )
256 {
257 result = list_push_back( result,
258 object_new( object_str( list_item( begin ) ) + name_len ) );
259 }
260
261 return result;
262}
263
264/* binary search for the property value */
265LIST * property_set_contains_features( FRAME * frame, int flags )
266{
267 OBJECT * varname = object_new( "self.raw" );
268 LIST * props = var_get( frame->module, varname );
269 LIST * features = lol_get( frame->args, 0 );
270 LIST * result = L0;
271 LISTITER features_iter = list_begin( features );
272 LISTITER features_end = list_end( features ) ;
273 object_free( varname );
274
275 for ( ; features_iter != features_end; ++features_iter )
276 {
277 const char * name = object_str( list_item( features_iter ) );
278 size_t name_len = strlen( name );
279 LISTITER begin, end;
280 /* Assumes random access */
281 begin = list_begin( props ), end = list_end( props );
282
283 while ( 1 )
284 {
285 ptrdiff_t diff = (end - begin);
286 LISTITER mid = begin + diff / 2;
287 int res;
288 if ( diff == 0 )
289 {
290 /* The feature is missing */
291 return L0;
292 }
293 res = strncmp( object_str( list_item( mid ) ), name, name_len );
294 if ( res < 0 )
295 {
296 begin = mid + 1;
297 }
298 else if ( res > 0 )
299 {
300 end = mid;
301 }
302 else /* We've found the property */
303 {
304 break;
305 }
306 }
307 }
308 return list_new( object_copy( constant_true ) );
309}
310
311void init_property_set()
312{
313 {
314 char const * args[] = { "raw-properties", "*", 0 };
315 declare_native_rule( "property-set", "create", args, property_set_create, 1 );
316 }
317 {
318 char const * args[] = { "feature", 0 };
319 declare_native_rule( "class@property-set", "get", args, property_set_get, 1 );
320 }
321 {
322 char const * args[] = { "features", "*", 0 };
323 declare_native_rule( "class@property-set", "contains-features", args, property_set_contains_features, 1 );
324 }
325 ps_map_init( &all_property_sets );
326}
327
328void property_set_done()
329{
330 ps_map_destroy( &all_property_sets );
331}