|
| 1 | +/* |
| 2 | ++----------------------------------------------------------------------+ |
| 3 | + | Zend Engine | |
| 4 | + +----------------------------------------------------------------------+ |
| 5 | + | Copyright (c) Zend Technologies Ltd. (http://www.zend.com) | |
| 6 | + +----------------------------------------------------------------------+ |
| 7 | + | This source file is subject to version 2.00 of the Zend license, | |
| 8 | + | that is bundled with this package in the file LICENSE, and is | |
| 9 | + | available through the world-wide-web at the following url: | |
| 10 | + | http://www.zend.com/license/2_00.txt. | |
| 11 | + | If you did not receive a copy of the Zend license and are unable to | |
| 12 | + | obtain it through the world-wide-web, please send a note to | |
| 13 | + | license@zend.com so we can mail you a copy immediately. | |
| 14 | + +----------------------------------------------------------------------+ |
| 15 | + | Authors: Rob Landers <rob@bottled.codes> | |
| 16 | + | | |
| 17 | + +----------------------------------------------------------------------+ |
| 18 | +*/ |
| 19 | + |
| 20 | +#include "zend_namespaces.h" |
| 21 | + |
| 22 | +#include <zend_smart_str.h> |
| 23 | + |
| 24 | +#include "zend_API.h" |
| 25 | +#include "zend_hash.h" |
| 26 | + |
| 27 | +static zend_class_entry *global_namespace = NULL; |
| 28 | +static HashTable namespaces; |
| 29 | + |
| 30 | +static zend_class_entry *create_namespace(zend_string *name) { |
| 31 | + zend_class_entry *ns = pemalloc(sizeof(zend_class_entry), 1); |
| 32 | + memset(ns, 0, sizeof(zend_class_entry)); |
| 33 | + zend_initialize_class_data(ns, 1); |
| 34 | + ns->type = ZEND_NAMESPACE_CLASS; |
| 35 | + |
| 36 | + zend_string *interned_name = zend_new_interned_string(zend_string_copy(name)); |
| 37 | + ns->name = interned_name; |
| 38 | + |
| 39 | + return ns; |
| 40 | +} |
| 41 | + |
| 42 | +static zend_class_entry *insert_namespace(const zend_string *name) { |
| 43 | + zend_class_entry *ns = NULL; |
| 44 | + zend_class_entry *parent_ns = global_namespace; |
| 45 | + zend_string *part = NULL; |
| 46 | + const char *start = ZSTR_VAL(name); |
| 47 | + const char *end = start + ZSTR_LEN(name); |
| 48 | + const char *pos = start; |
| 49 | + size_t len = 0; |
| 50 | + |
| 51 | + smart_str current_ns = {0}; |
| 52 | + |
| 53 | + while (pos <= end) { |
| 54 | + if (pos == end || *pos == '\\') { |
| 55 | + len = pos - start; |
| 56 | + part = zend_string_init(start, len, 0); |
| 57 | + |
| 58 | + if (current_ns.s) { |
| 59 | + smart_str_appendc(¤t_ns, '\\'); |
| 60 | + } |
| 61 | + smart_str_appendl(¤t_ns, ZSTR_VAL(part), ZSTR_LEN(part)); |
| 62 | + smart_str_0(¤t_ns); |
| 63 | + |
| 64 | + zend_string *needle = zend_string_init(ZSTR_VAL(current_ns.s), ZSTR_LEN(current_ns.s), 0); |
| 65 | + ns = zend_hash_find_ptr(&namespaces, needle); |
| 66 | + |
| 67 | + if (!ns) { |
| 68 | + ns = create_namespace(needle); |
| 69 | + ns->parent = parent_ns; |
| 70 | + zend_hash_add_ptr(&namespaces, current_ns.s, ns); |
| 71 | + } |
| 72 | + |
| 73 | + zend_string_release(part); |
| 74 | + zend_string_release(needle); |
| 75 | + |
| 76 | + parent_ns = ns; |
| 77 | + start = pos + 1; |
| 78 | + } |
| 79 | + pos++; |
| 80 | + } |
| 81 | + |
| 82 | + smart_str_free(¤t_ns); |
| 83 | + |
| 84 | + return ns; |
| 85 | +} |
| 86 | + |
| 87 | +zend_class_entry *zend_resolve_namespace(zend_string *name) { |
| 88 | + if (global_namespace == NULL) { |
| 89 | + global_namespace = create_namespace(zend_empty_string); |
| 90 | + zend_hash_init(&namespaces, 8, NULL, ZEND_CLASS_DTOR, 1); |
| 91 | + zend_hash_add_ptr(&namespaces, zend_empty_string, global_namespace); |
| 92 | + } |
| 93 | + |
| 94 | + if (name == NULL || ZSTR_LEN(name) == 0) { |
| 95 | + return global_namespace; |
| 96 | + } |
| 97 | + |
| 98 | + zend_string *lc_name = zend_string_tolower(name); |
| 99 | + zend_class_entry *ns = zend_hash_find_ptr(&namespaces, lc_name); |
| 100 | + |
| 101 | + if (!ns) { |
| 102 | + ns = insert_namespace(lc_name); |
| 103 | + } |
| 104 | + |
| 105 | + zend_string_release(lc_name); |
| 106 | + |
| 107 | + return ns; |
| 108 | +} |
| 109 | + |
| 110 | +void zend_destroy_namespaces() { |
| 111 | + if (global_namespace == NULL) { |
| 112 | + return; |
| 113 | + } |
| 114 | + |
| 115 | + const zend_class_entry *ns = NULL; |
| 116 | + ZEND_HASH_FOREACH_PTR(&namespaces, ns) { |
| 117 | + zend_string_release(ns->name); |
| 118 | + } ZEND_HASH_FOREACH_END(); |
| 119 | + |
| 120 | + zend_hash_destroy(&namespaces); |
| 121 | + zend_string_release(global_namespace->name); |
| 122 | + pefree(global_namespace, 1); |
| 123 | +} |
0 commit comments