| 121 | str_container::str_container() : impl(xr_new<str_container_impl>()) {} |
| 122 | |
| 123 | str_value* str_container::dock(pcstr value) const |
| 124 | { |
| 125 | if (nullptr == value) |
| 126 | return nullptr; |
| 127 | |
| 128 | impl->cs.Enter(); |
| 129 | |
| 130 | // calc len |
| 131 | const auto s_len = xr_strlen(value); |
| 132 | const auto s_len_with_zero = s_len + 1; |
| 133 | VERIFY(sizeof(str_value) + s_len_with_zero < 4096); |
| 134 | |
| 135 | // setup find structure |
| 136 | char header[sizeof(str_value)]; |
| 137 | str_value* sv = (str_value*)header; |
| 138 | sv->dwReference = 0; |
| 139 | sv->dwLength = static_cast<u32>(s_len); |
| 140 | sv->dwCRC = crc32(value, s_len); |
| 141 | |
| 142 | // search |
| 143 | str_value* result = impl->find(sv, value); |
| 144 | |
| 145 | #ifdef DEBUG |
| 146 | const bool is_leaked_string = !xr_strcmp(value, "enter leaked string here"); |
| 147 | #endif // DEBUG |
| 148 | |
| 149 | // it may be the case, string is not found or has "non-exact" match |
| 150 | if (nullptr == result |
| 151 | #ifdef DEBUG |
| 152 | || is_leaked_string |
| 153 | #endif // DEBUG |
| 154 | ) |
| 155 | { |
| 156 | result = static_cast<str_value*>(xr_malloc(sizeof(str_value) + s_len_with_zero)); |
| 157 | |
| 158 | #ifdef DEBUG |
| 159 | static int num_leaked_string = 0; |
| 160 | if (is_leaked_string) |
| 161 | { |
| 162 | ++num_leaked_string; |
| 163 | Msg("leaked_string: %d 0x%08x", num_leaked_string, result); |
| 164 | } |
| 165 | #endif // DEBUG |
| 166 | |
| 167 | result->dwReference = 0; |
| 168 | result->dwLength = sv->dwLength; |
| 169 | result->dwCRC = sv->dwCRC; |
| 170 | CopyMemory(result->value, value, s_len_with_zero); |
| 171 | |
| 172 | impl->insert(result); |
| 173 | } |
| 174 | impl->cs.Leave(); |
| 175 | |
| 176 | return result; |
| 177 | } |
| 178 | |
| 179 | void str_container::clean() const |
| 180 | { |