| 7667 | } |
| 7668 | |
| 7669 | xpath_string eval_string_concat(const xpath_context& c, const xpath_stack& stack) |
| 7670 | { |
| 7671 | assert(_type == ast_func_concat); |
| 7672 | |
| 7673 | xpath_allocator_capture ct(stack.temp); |
| 7674 | |
| 7675 | // count the string number |
| 7676 | size_t count = 1; |
| 7677 | for (xpath_ast_node* nc = _right; nc; nc = nc->_next) count++; |
| 7678 | |
| 7679 | // gather all strings |
| 7680 | xpath_string static_buffer[4]; |
| 7681 | xpath_string* buffer = static_buffer; |
| 7682 | |
| 7683 | // allocate on-heap for large concats |
| 7684 | if (count > sizeof(static_buffer) / sizeof(static_buffer[0])) |
| 7685 | { |
| 7686 | buffer = static_cast<xpath_string*>(stack.temp->allocate(count * sizeof(xpath_string))); |
| 7687 | assert(buffer); |
| 7688 | } |
| 7689 | |
| 7690 | // evaluate all strings to temporary stack |
| 7691 | xpath_stack swapped_stack = {stack.temp, stack.result}; |
| 7692 | |
| 7693 | buffer[0] = _left->eval_string(c, swapped_stack); |
| 7694 | |
| 7695 | size_t pos = 1; |
| 7696 | for (xpath_ast_node* n = _right; n; n = n->_next, ++pos) buffer[pos] = n->eval_string(c, swapped_stack); |
| 7697 | assert(pos == count); |
| 7698 | |
| 7699 | // get total length |
| 7700 | size_t length = 0; |
| 7701 | for (size_t i = 0; i < count; ++i) length += buffer[i].length(); |
| 7702 | |
| 7703 | // create final string |
| 7704 | char_t* result = static_cast<char_t*>(stack.result->allocate((length + 1) * sizeof(char_t))); |
| 7705 | assert(result); |
| 7706 | |
| 7707 | char_t* ri = result; |
| 7708 | |
| 7709 | for (size_t j = 0; j < count; ++j) |
| 7710 | for (const char_t* bi = buffer[j].c_str(); *bi; ++bi) |
| 7711 | *ri++ = *bi; |
| 7712 | |
| 7713 | *ri = 0; |
| 7714 | |
| 7715 | return xpath_string(result, true); |
| 7716 | } |
| 7717 | |
| 7718 | xpath_string eval_string(const xpath_context& c, const xpath_stack& stack) |
| 7719 | { |
nothing calls this directly
no test coverage detected