| 9067 | } |
| 9068 | |
| 9069 | xpath_string eval_string_concat(const xpath_context& c, const xpath_stack& stack) |
| 9070 | { |
| 9071 | assert(_type == ast_func_concat); |
| 9072 | |
| 9073 | xpath_allocator_capture ct(stack.temp); |
| 9074 | |
| 9075 | // count the string number |
| 9076 | size_t count = 1; |
| 9077 | for (xpath_ast_node* nc = _right; nc; nc = nc->_next) |
| 9078 | count++; |
| 9079 | |
| 9080 | // gather all strings |
| 9081 | xpath_string static_buffer[4]; |
| 9082 | xpath_string* buffer = static_buffer; |
| 9083 | |
| 9084 | // allocate on-heap for large concats |
| 9085 | if (count > sizeof(static_buffer) / sizeof(static_buffer[0])) |
| 9086 | { |
| 9087 | buffer = static_cast<xpath_string*>(stack.temp->allocate(count * sizeof(xpath_string))); |
| 9088 | assert(buffer); |
| 9089 | } |
| 9090 | |
| 9091 | // evaluate all strings to temporary stack |
| 9092 | xpath_stack swapped_stack = {stack.temp, stack.result}; |
| 9093 | |
| 9094 | buffer[0] = _left->eval_string(c, swapped_stack); |
| 9095 | |
| 9096 | size_t pos = 1; |
| 9097 | for (xpath_ast_node* n = _right; n; n = n->_next, ++pos) |
| 9098 | buffer[pos] = n->eval_string(c, swapped_stack); |
| 9099 | assert(pos == count); |
| 9100 | |
| 9101 | // get total length |
| 9102 | size_t length = 0; |
| 9103 | for (size_t i = 0; i < count; ++i) |
| 9104 | length += buffer[i].length(); |
| 9105 | |
| 9106 | // create final string |
| 9107 | char_t* result = static_cast<char_t*>(stack.result->allocate((length + 1) * sizeof(char_t))); |
| 9108 | assert(result); |
| 9109 | |
| 9110 | char_t* ri = result; |
| 9111 | |
| 9112 | for (size_t j = 0; j < count; ++j) |
| 9113 | for (const char_t* bi = buffer[j].c_str(); *bi; ++bi) |
| 9114 | *ri++ = *bi; |
| 9115 | |
| 9116 | *ri = 0; |
| 9117 | |
| 9118 | return xpath_string(result, true); |
| 9119 | } |
| 9120 | |
| 9121 | xpath_string eval_string(const xpath_context& c, const xpath_stack& stack) |
| 9122 | { |
nothing calls this directly
no test coverage detected