Project

General

Profile

Feature #5427 ยป load.c.patch

load.c patch against ruby-trunk - funny_falcon (Yura Sokolov), 12/14/2011 05:59 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
static int feature_basename_length(const char *, long);
136

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

  
261
static int
262
feature_basename_length(const char *feature, long flen)
263
{
264
    if (sorted_loaded_features) {
265
	const char *ext;
266
	for (ext = feature + (flen - 1); ext >= feature; ext--) {
267
	    if (*ext == '.') return ext - feature;
268
	    if (*ext == '/') return flen;
269
	}
270
	return flen;
271
    } else {
272
	return 0;
273
    }
274
}
275

  
276
static int
277
compare_feature_name(const char *left, long llen, const char *right, long rlen)
278
{
279
    int diff = 0;
280
    while (llen-- && rlen--) {
281
	diff = left[llen] - right[rlen];
282
	if (diff) break;
283
	if (left[llen] == '/') break;
284
    }
285
    return diff;
286
}
287

  
288
static int
289
rb_compare_feature_name(VALUE loaded, const char *feature, long flen)
290
{
291
    const char *loaded_name = StringValuePtr(loaded);
292
    long loaded_len = feature_basename_length(loaded_name, RSTRING_LEN(loaded));
293
    return compare_feature_name(loaded_name, loaded_len, feature, flen);
294
}
295

  
296
/* used to find when equal features run out */
297
static int
298
rb_stop_search_feature(VALUE loaded, const char *feature, long flen)
299
{
300
    if (sorted_loaded_features)
301
	return rb_compare_feature_name(loaded, feature, flen) > 0;
302
    else
303
	return FALSE;
304
}
305

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

  
318
	while (first - before > 1) {
319
	    int mid = (first + before) / 2;
320
	    int cmp = rb_compare_feature_name(values[mid], feature, flen);
321
	    if (cmp >= 0)
322
		first = mid;
323
	    else
324
		before = mid;
325
	}
326
	return first;
327
    } else {
328
	return 0;
329
    }
330
}
331

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

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

  
360

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

  
376
static VALUE
377
rb_push_feature_m(int argc, VALUE *argv, VALUE features)
378
{
379
    while (argc--) {
380
	rb_push_feature_1(features, *argv++);
381
    }
382
    return features;
383
}
384

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

  
400
static VALUE
401
rb_loaded_features_init(void)
402
{
403
    char *sorted_flag;
404
    const char **name;
405
    VALUE loaded_features = rb_ary_new();
406
    VALUE loaded_features_c = rb_singleton_class(loaded_features);
407

  
408
    sorted_flag = getenv("RUBY_LOADED_FEATURES_SORTED");
409
    if (sorted_flag != NULL) {
410
	int sorted_set = atoi(sorted_flag);
411
	if (RTEST(ruby_verbose))
412
	    fprintf(stderr, "sorted_loaded_features=%d (%d)\n", sorted_set, sorted_loaded_features);
413
	sorted_loaded_features = sorted_set;
414
    }
415

  
416
    for(name = load_features_undefined_methods; *name; name++) {
417
	rb_undef_method(loaded_features_c, *name);
418
    }
419

  
420
    if (sorted_loaded_features) {
421
	rb_define_method(loaded_features_c, "<<", rb_push_feature_1, 1);
422
	rb_define_method(loaded_features_c, "push", rb_push_feature_m, -1);
423
	rb_define_method(loaded_features_c, "concat", rb_concat_features, 1);
424
	rb_define_method(loaded_features_c, "unshift", rb_push_feature_m, -1);
425
    }
426
    return loaded_features;
427
}
428

  
254 429
static void
255 430
rb_provide_feature(VALUE feature)
256 431
{
......
258 433
	rb_raise(rb_eRuntimeError,
259 434
		 "$LOADED_FEATURES is frozen; cannot append feature");
260 435
    }
261
    rb_ary_push(get_loaded_features(), feature);
436
    rb_push_feature_1(get_loaded_features(), feature);
262 437
}
263 438

  
264 439
void
......
788 963

  
789 964
    rb_define_virtual_variable("$\"", get_loaded_features, 0);
790 965
    rb_define_virtual_variable("$LOADED_FEATURES", get_loaded_features, 0);
791
    vm->loaded_features = rb_ary_new();
966
    vm->loaded_features = rb_loaded_features_init();
792 967

  
793 968
    rb_define_global_function("load", rb_f_load, -1);
794 969
    rb_define_global_function("require", rb_f_require, 1);