180 |
180 |
return GET_VM()->loading_table;
|
181 |
181 |
}
|
182 |
182 |
|
|
183 |
struct feature_str {
|
|
184 |
const char* str;
|
|
185 |
size_t len;
|
|
186 |
};
|
|
187 |
|
|
188 |
static struct feature_str
|
|
189 |
to_feature_str(VALUE str)
|
|
190 |
{
|
|
191 |
struct feature_str res;
|
|
192 |
res.str = RSTRING_PTR(str);
|
|
193 |
res.len = RSTRING_LEN(str);
|
|
194 |
return res;
|
|
195 |
}
|
|
196 |
|
|
197 |
static struct feature_str
|
|
198 |
feature_subseq(struct feature_str orig, size_t beg, size_t len)
|
|
199 |
{
|
|
200 |
struct feature_str res;
|
|
201 |
res.str = orig.str + beg;
|
|
202 |
res.len = len;
|
|
203 |
assert(len <= orig.len);
|
|
204 |
return res;
|
|
205 |
}
|
|
206 |
|
|
207 |
static st_data_t
|
|
208 |
feature_key(struct feature_str str)
|
|
209 |
{
|
|
210 |
return st_hash(str.str, str.len, 0xfea7009e);
|
|
211 |
}
|
|
212 |
|
183 |
213 |
static void
|
184 |
|
features_index_add_single(VALUE short_feature, VALUE offset)
|
|
214 |
features_index_add_single(struct feature_str short_feature, VALUE offset)
|
185 |
215 |
{
|
186 |
216 |
struct st_table *features_index;
|
187 |
217 |
VALUE this_feature_index = Qnil;
|
188 |
|
char *short_feature_cstr;
|
|
218 |
st_data_t short_feature_key;
|
189 |
219 |
|
190 |
220 |
Check_Type(offset, T_FIXNUM);
|
191 |
|
Check_Type(short_feature, T_STRING);
|
192 |
|
short_feature_cstr = StringValueCStr(short_feature);
|
|
221 |
short_feature_key = feature_key(short_feature);
|
193 |
222 |
|
194 |
223 |
features_index = get_loaded_features_index_raw();
|
195 |
|
st_lookup(features_index, (st_data_t)short_feature_cstr, (st_data_t *)&this_feature_index);
|
|
224 |
st_lookup(features_index, short_feature_key, (st_data_t *)&this_feature_index);
|
196 |
225 |
|
197 |
226 |
if (NIL_P(this_feature_index)) {
|
198 |
|
st_insert(features_index, (st_data_t)ruby_strdup(short_feature_cstr), (st_data_t)offset);
|
|
227 |
st_insert(features_index, short_feature_key, (st_data_t)offset);
|
199 |
228 |
}
|
200 |
229 |
else if (RB_TYPE_P(this_feature_index, T_FIXNUM)) {
|
201 |
230 |
VALUE feature_indexes[2];
|
... | ... | |
204 |
233 |
this_feature_index = (VALUE)xcalloc(1, sizeof(struct RArray));
|
205 |
234 |
RBASIC(this_feature_index)->flags = T_ARRAY; /* fake VALUE, do not mark/sweep */
|
206 |
235 |
rb_ary_cat(this_feature_index, feature_indexes, numberof(feature_indexes));
|
207 |
|
st_insert(features_index, (st_data_t)short_feature_cstr, (st_data_t)this_feature_index);
|
|
236 |
st_insert(features_index, short_feature_key, (st_data_t)this_feature_index);
|
208 |
237 |
}
|
209 |
238 |
else {
|
210 |
239 |
Check_Type(this_feature_index, T_ARRAY);
|
... | ... | |
221 |
250 |
relies on for its fast lookup.
|
222 |
251 |
*/
|
223 |
252 |
static void
|
224 |
|
features_index_add(VALUE feature, VALUE offset)
|
|
253 |
features_index_add(VALUE featurev, VALUE offset)
|
225 |
254 |
{
|
226 |
|
VALUE short_feature;
|
227 |
|
const char *feature_str, *feature_end, *ext, *p;
|
|
255 |
struct feature_str feature, short_feature;
|
|
256 |
const char *feature_end, *ext, *p;
|
228 |
257 |
|
229 |
|
feature_str = StringValuePtr(feature);
|
230 |
|
feature_end = feature_str + RSTRING_LEN(feature);
|
|
258 |
StringValue(featurev);
|
|
259 |
feature = to_feature_str(featurev);
|
|
260 |
feature_end = feature.str + feature.len;
|
231 |
261 |
|
232 |
|
for (ext = feature_end; ext > feature_str; ext--)
|
|
262 |
for (ext = feature_end; ext > feature.str; ext--)
|
233 |
263 |
if (*ext == '.' || *ext == '/')
|
234 |
264 |
break;
|
235 |
265 |
if (*ext != '.')
|
... | ... | |
242 |
272 |
long beg;
|
243 |
273 |
|
244 |
274 |
p--;
|
245 |
|
while (p >= feature_str && *p != '/')
|
|
275 |
while (p >= feature.str && *p != '/')
|
246 |
276 |
p--;
|
247 |
|
if (p < feature_str)
|
|
277 |
if (p < feature.str)
|
248 |
278 |
break;
|
249 |
279 |
/* Now *p == '/'. We reach this point for every '/' in `feature`. */
|
250 |
|
beg = p + 1 - feature_str;
|
251 |
|
short_feature = rb_str_subseq(feature, beg, feature_end - p - 1);
|
|
280 |
beg = p + 1 - feature.str;
|
|
281 |
short_feature = feature_subseq(feature, beg, feature_end - p - 1);
|
252 |
282 |
features_index_add_single(short_feature, offset);
|
253 |
283 |
if (ext) {
|
254 |
|
short_feature = rb_str_subseq(feature, beg, ext - p - 1);
|
|
284 |
short_feature = feature_subseq(feature, beg, ext - p - 1);
|
255 |
285 |
features_index_add_single(short_feature, offset);
|
256 |
286 |
}
|
257 |
287 |
}
|
258 |
288 |
features_index_add_single(feature, offset);
|
259 |
289 |
if (ext) {
|
260 |
|
short_feature = rb_str_subseq(feature, 0, ext - feature_str);
|
|
290 |
short_feature = feature_subseq(feature, 0, ext - feature.str);
|
261 |
291 |
features_index_add_single(short_feature, offset);
|
262 |
292 |
}
|
263 |
293 |
}
|
... | ... | |
270 |
300 |
rb_ary_free(obj);
|
271 |
301 |
xfree((void *)obj);
|
272 |
302 |
}
|
273 |
|
xfree((char *)key);
|
274 |
303 |
return ST_DELETE;
|
275 |
304 |
}
|
276 |
305 |
|
... | ... | |
384 |
413 |
st_table *loading_tbl, *features_index;
|
385 |
414 |
st_data_t data;
|
386 |
415 |
int type;
|
|
416 |
struct feature_str fstr;
|
|
417 |
fstr.str = feature;
|
|
418 |
fstr.len = strlen(feature);
|
387 |
419 |
|
388 |
420 |
if (fn) *fn = 0;
|
389 |
421 |
if (ext) {
|
... | ... | |
399 |
431 |
features = get_loaded_features();
|
400 |
432 |
features_index = get_loaded_features_index();
|
401 |
433 |
|
402 |
|
st_lookup(features_index, (st_data_t)feature, (st_data_t *)&this_feature_index);
|
|
434 |
st_lookup(features_index, feature_key(fstr), (st_data_t *)&this_feature_index);
|
403 |
435 |
/* We search `features` for an entry such that either
|
404 |
436 |
"#{features[i]}" == "#{load_path[j]}/#{feature}#{e}"
|
405 |
437 |
for some j, or
|
... | ... | |
1196 |
1228 |
rb_define_virtual_variable("$LOADED_FEATURES", get_loaded_features, 0);
|
1197 |
1229 |
vm->loaded_features = rb_ary_new();
|
1198 |
1230 |
vm->loaded_features_snapshot = rb_ary_tmp_new(0);
|
1199 |
|
vm->loaded_features_index = st_init_strtable();
|
|
1231 |
vm->loaded_features_index = st_init_numtable();
|
1200 |
1232 |
|
1201 |
1233 |
rb_define_global_function("load", rb_f_load, -1);
|
1202 |
1234 |
rb_define_global_function("require", rb_f_require, 1);
|
1203 |
|
-
|