Project

General

Profile

Feature #5427 ยป load.c.patch

funny_falcon (Yura Sokolov), 12/16/2011 05:44 PM

View differences:

load.c
18 18
#define IS_DLEXT(e) (strcmp((e), DLEXT) == 0)
19 19
#endif
20 20

  
21
static int sorted_loaded_features = 1;
21 22

  
22 23
static const char *const loadable_ext[] = {
23 24
    ".rb", DLEXT,
......
129 130
    return ST_STOP;
130 131
}
131 132

  
133
static int rb_feature_first_equal_or_greater(VALUE, const char *, long);
134
static int rb_stop_search_feature(VALUE, const char *, long);
135

  
132 136
static int
133 137
rb_feature_p(const char *feature, const char *ext, int rb, int expanded, const char **fn)
134 138
{
......
151 155
	type = 0;
152 156
    }
153 157
    features = get_loaded_features();
154
    for (i = 0; i < RARRAY_LEN(features); ++i) {
158
    i = rb_feature_first_equal_or_greater(features, feature, len);
159
    for (; i < RARRAY_LEN(features); ++i) {
155 160
	v = RARRAY_PTR(features)[i];
161
	if (rb_stop_search_feature(v, feature, len)) break;
156 162
	f = StringValuePtr(v);
157 163
	if ((n = RSTRING_LEN(v)) < len) continue;
158 164
	if (strncmp(f, feature, len) != 0) {
......
176 182
	}
177 183
    }
178 184
    loading_tbl = get_loading_table();
179
    if (loading_tbl) {
185
    if (loading_tbl && loading_tbl->num_entries > 0) {
180 186
	f = 0;
181 187
	if (!expanded) {
182 188
	    struct loaded_feature_searching fs;
......
251 257
    return FALSE;
252 258
}
253 259

  
260
static int
261
feature_basename_length(const char *feature, long flen)
262
{
263
    if (sorted_loaded_features) {
264
	const char *ext = strrchr(feature, '.');
265
	return ext && !strchr(ext, '/') ? ext - feature : flen;
266
    } else {
267
	return 0;
268
    }
269
}
270

  
271
static int
272
compare_feature_name(const char *left, long llen, const char *right, long rlen)
273
{
274
    int diff = 0;
275
    while (llen-- && rlen--) {
276
	diff = left[llen] - right[rlen];
277
	if (diff) break;
278
	if (left[llen] == '/') break;
279
    }
280
    return diff;
281
}
282

  
283
static int
284
rb_compare_feature_name(VALUE loaded, const char *feature, long flen)
285
{
286
    const char *loaded_name = StringValuePtr(loaded);
287
    long loaded_len = feature_basename_length(loaded_name, RSTRING_LEN(loaded));
288
    return compare_feature_name(loaded_name, loaded_len, feature, flen);
289
}
290

  
291
/* used to find when equal features run out */
292
static int
293
rb_stop_search_feature(VALUE loaded, const char *feature, long flen)
294
{
295
    if (sorted_loaded_features)
296
	return rb_compare_feature_name(loaded, feature, flen) > 0;
297
    else
298
	return FALSE;
299
}
300

  
301
/* returns first position to search feature from */
302
static int
303
rb_feature_first_equal_or_greater(VALUE features, const char *feature, long flen)
304
{
305
    if (sorted_loaded_features) {
306
	int before = 0, first = RARRAY_LEN(features);
307
	VALUE *values = RARRAY_PTR(features);
308
	if (first == 0)
309
	    return 0;
310
	if (rb_compare_feature_name(values[0], feature, flen) >= 0)
311
	    return 0;
312

  
313
	while (first - before > 1) {
314
	    int mid = (first + before) / 2;
315
	    int cmp = rb_compare_feature_name(values[mid], feature, flen);
316
	    if (cmp >= 0)
317
		first = mid;
318
	    else
319
		before = mid;
320
	}
321
	return first;
322
    } else {
323
	return 0;
324
    }
325
}
326

  
327
/* returns position to insert new feature in */
328
static int
329
rb_feature_first_greater(VALUE features, const char *feature, long flen)
330
{
331
    if (sorted_loaded_features) {
332
	int before = 0, first = RARRAY_LEN(features);
333
	VALUE *values = RARRAY_PTR(features);
334
	if (first == 0)
335
	    return 0;
336
	if (rb_compare_feature_name(values[0], feature, flen) > 0)
337
	    return 0;
338
	if (rb_compare_feature_name(values[first-1], feature, flen) <= 0)
339
	    return first;
340

  
341
	while (first - before > 1) {
342
	    int mid = (first + before) / 2;
343
	    int cmp = rb_compare_feature_name(values[mid], feature, flen);
344
	    if (cmp > 0)
345
		first = mid;
346
	    else
347
		before = mid;
348
	}
349
	return first;
350
    } else {
351
	return RARRAY_LEN(features);
352
    }
353
}
354

  
355

  
356
static VALUE
357
rb_push_feature_1(VALUE features, VALUE feature)
358
{
359
    const char *fname = StringValuePtr(feature);
360
    long flen = feature_basename_length(fname, RSTRING_LEN(feature));
361
    int i = rb_feature_first_greater(features, fname, flen);
362
    rb_ary_push(features, feature);
363
    if ( i < RARRAY_LEN(features) - 1 ) {
364
	MEMMOVE(RARRAY_PTR(features) + i + 1, RARRAY_PTR(features) + i,
365
		VALUE, RARRAY_LEN(features) - i - 1);
366
	RARRAY_PTR(features)[i] = feature;
367
    }
368
    return features;
369
}
370

  
371
static VALUE
372
rb_push_feature_m(int argc, VALUE *argv, VALUE features)
373
{
374
    while (argc--) {
375
	rb_push_feature_1(features, *argv++);
376
    }
377
    return features;
378
}
379

  
380
static VALUE
381
rb_concat_features(VALUE features, VALUE add)
382
{
383
    add = rb_convert_type(add, T_ARRAY, "Array", "to_ary");
384
    if (RARRAY_LEN(add)) {
385
	rb_push_feature_m(RARRAY_LEN(add), RARRAY_PTR(add), features);
386
    }
387
    return features;
388
}
389
static const char *load_features_undefined_methods[] = {
390
    "[]=", "reverse!", "rotate!", "sort!", "sort_by!",
391
    "collect!", "map!", "shuffle!", "fill", "insert",
392
    NULL
393
};
394

  
395
static VALUE
396
rb_loaded_features_init(void)
397
{
398
    char *sorted_flag;
399
    const char **name;
400
    VALUE loaded_features = rb_ary_new();
401
    VALUE loaded_features_c = rb_singleton_class(loaded_features);
402

  
403
    sorted_flag = getenv("RUBY_LOADED_FEATURES_SORTED");
404
    if (sorted_flag != NULL) {
405
	int sorted_set = atoi(sorted_flag);
406
	if (RTEST(ruby_verbose))
407
	    fprintf(stderr, "sorted_loaded_features=%d (%d)\n", sorted_set, sorted_loaded_features);
408
	sorted_loaded_features = sorted_set;
409
    }
410

  
411
    for(name = load_features_undefined_methods; *name; name++) {
412
	rb_undef_method(loaded_features_c, *name);
413
    }
414

  
415
    if (sorted_loaded_features) {
416
	rb_define_method(loaded_features_c, "<<", rb_push_feature_1, 1);
417
	rb_define_method(loaded_features_c, "push", rb_push_feature_m, -1);
418
	rb_define_method(loaded_features_c, "concat", rb_concat_features, 1);
419
	rb_define_method(loaded_features_c, "unshift", rb_push_feature_m, -1);
420
    }
421
    return loaded_features;
422
}
423

  
254 424
static void
255 425
rb_provide_feature(VALUE feature)
256 426
{
......
258 428
	rb_raise(rb_eRuntimeError,
259 429
		 "$LOADED_FEATURES is frozen; cannot append feature");
260 430
    }
261
    rb_ary_push(get_loaded_features(), feature);
431
    rb_push_feature_1(get_loaded_features(), feature);
262 432
}
263 433

  
264 434
void
......
788 958

  
789 959
    rb_define_virtual_variable("$\"", get_loaded_features, 0);
790 960
    rb_define_virtual_variable("$LOADED_FEATURES", get_loaded_features, 0);
791
    vm->loaded_features = rb_ary_new();
961
    vm->loaded_features = rb_loaded_features_init();
792 962

  
793 963
    rb_define_global_function("load", rb_f_load, -1);
794 964
    rb_define_global_function("require", rb_f_require, 1);