| 11137 | } |
| 11138 | |
| 11139 | xpath_string eval_string_concat(const xpath_context& c, const xpath_stack& stack) |
| 11140 | { |
| 11141 | assert(_type == ast_func_concat); |
| 11142 | |
| 11143 | xpath_allocator_capture ct(stack.temp); |
| 11144 | |
| 11145 | // count the string number |
| 11146 | size_t count = 1; |
| 11147 | for (xpath_ast_node* nc = _right; nc; nc = nc->_next) count++; |
| 11148 | |
| 11149 | // allocate a buffer for temporary string objects |
| 11150 | xpath_string* buffer = static_cast<xpath_string*>(stack.temp->allocate(count * sizeof(xpath_string))); |
| 11151 | if (!buffer) return xpath_string(); |
| 11152 | |
| 11153 | // evaluate all strings to temporary stack |
| 11154 | xpath_stack swapped_stack = {stack.temp, stack.result}; |
| 11155 | |
| 11156 | buffer[0] = _left->eval_string(c, swapped_stack); |
| 11157 | |
| 11158 | size_t pos = 1; |
| 11159 | for (xpath_ast_node* n = _right; n; n = n->_next, ++pos) buffer[pos] = n->eval_string(c, swapped_stack); |
| 11160 | assert(pos == count); |
| 11161 | |
| 11162 | // get total length |
| 11163 | size_t length = 0; |
| 11164 | for (size_t i = 0; i < count; ++i) length += buffer[i].length(); |
| 11165 | |
| 11166 | // create final string |
| 11167 | char_t* result = static_cast<char_t*>(stack.result->allocate((length + 1) * sizeof(char_t))); |
| 11168 | if (!result) return xpath_string(); |
| 11169 | |
| 11170 | char_t* ri = result; |
| 11171 | |
| 11172 | for (size_t j = 0; j < count; ++j) |
| 11173 | for (const char_t* bi = buffer[j].c_str(); *bi; ++bi) |
| 11174 | *ri++ = *bi; |
| 11175 | |
| 11176 | *ri = 0; |
| 11177 | |
| 11178 | return xpath_string::from_heap_preallocated(result, ri); |
| 11179 | } |
| 11180 | |
| 11181 | xpath_string eval_string(const xpath_context& c, const xpath_stack& stack) |
| 11182 | { |
nothing calls this directly
no test coverage detected