| 8285 | } |
| 8286 | |
| 8287 | xpath_string eval_string_concat(const xpath_context& c, const xpath_stack& stack) |
| 8288 | { |
| 8289 | assert(_type == ast_func_concat); |
| 8290 | |
| 8291 | xpath_allocator_capture ct(stack.temp); |
| 8292 | |
| 8293 | // count the string number |
| 8294 | size_t count = 1; |
| 8295 | for (xpath_ast_node* nc = _right; nc; nc = nc->_next) count++; |
| 8296 | |
| 8297 | // gather all strings |
| 8298 | xpath_string static_buffer[4]; |
| 8299 | xpath_string* buffer = static_buffer; |
| 8300 | |
| 8301 | // allocate on-heap for large concats |
| 8302 | if (count > sizeof(static_buffer) / sizeof(static_buffer[0])) |
| 8303 | { |
| 8304 | buffer = static_cast<xpath_string*>(stack.temp->allocate(count * sizeof(xpath_string))); |
| 8305 | assert(buffer); |
| 8306 | } |
| 8307 | |
| 8308 | // evaluate all strings to temporary stack |
| 8309 | xpath_stack swapped_stack = {stack.temp, stack.result}; |
| 8310 | |
| 8311 | buffer[0] = _left->eval_string(c, swapped_stack); |
| 8312 | |
| 8313 | size_t pos = 1; |
| 8314 | for (xpath_ast_node* n = _right; n; n = n->_next, ++pos) buffer[pos] = n->eval_string(c, swapped_stack); |
| 8315 | assert(pos == count); |
| 8316 | |
| 8317 | // get total length |
| 8318 | size_t length = 0; |
| 8319 | for (size_t i = 0; i < count; ++i) length += buffer[i].length(); |
| 8320 | |
| 8321 | // create final string |
| 8322 | char_t* result = static_cast<char_t*>(stack.result->allocate((length + 1) * sizeof(char_t))); |
| 8323 | assert(result); |
| 8324 | |
| 8325 | char_t* ri = result; |
| 8326 | |
| 8327 | for (size_t j = 0; j < count; ++j) |
| 8328 | for (const char_t* bi = buffer[j].c_str(); *bi; ++bi) |
| 8329 | *ri++ = *bi; |
| 8330 | |
| 8331 | *ri = 0; |
| 8332 | |
| 8333 | return xpath_string(result, true); |
| 8334 | } |
| 8335 | |
| 8336 | xpath_string eval_string(const xpath_context& c, const xpath_stack& stack) |
| 8337 | { |
nothing calls this directly
no test coverage detected