- // Allocate the buffer to hold the final string, position initially points to the end.
- UChar* buffer;
- if (PassRefPtr<UStringImpl> newImpl = UStringImpl::tryCreateUninitialized(m_length, buffer))
- m_value = newImpl;
- else {
- for (unsigned i = 0; i < m_fiberCount; ++i) {
- RopeImpl::deref(m_other.m_fibers[i]);
- m_other.m_fibers[i] = 0;
- }
- m_fiberCount = 0;
- ASSERT(!isRope());
- ASSERT(m_value == UString());
- if (exec)
- throwOutOfMemoryError(exec);
- return;
- }
- UChar* position = buffer + m_length;
-
- // Start with the current RopeImpl.
- Vector<RopeImpl::Fiber, 32> workQueue;
- RopeImpl::Fiber currentFiber;
- for (unsigned i = 0; i < (m_fiberCount - 1); ++i)
- workQueue.append(m_other.m_fibers[i]);
- currentFiber = m_other.m_fibers[m_fiberCount - 1];
- while (true) {
- if (RopeImpl::isRope(currentFiber)) {
- RopeImpl* rope = static_cast<RopeImpl*>(currentFiber);
- // Copy the contents of the current rope into the workQueue, with the last item in 'currentFiber'
- // (we will be working backwards over the rope).
- unsigned fiberCountMinusOne = rope->fiberCount() - 1;
- for (unsigned i = 0; i < fiberCountMinusOne; ++i)
- workQueue.append(rope->fibers()[i]);
- currentFiber = rope->fibers()[fiberCountMinusOne];
- } else {
- UStringImpl* string = static_cast<UStringImpl*>(currentFiber);
- unsigned length = string->length();
- position -= length;
- UStringImpl::copyChars(position, string->characters(), length);
-
- // Was this the last item in the work queue?
- if (workQueue.isEmpty()) {
- // Create a string from the UChar buffer, clear the rope RefPtr.
- ASSERT(buffer == position);
- for (unsigned i = 0; i < m_fiberCount; ++i) {
- RopeImpl::deref(m_other.m_fibers[i]);
- m_other.m_fibers[i] = 0;
- }
- m_fiberCount = 0;
-
- ASSERT(!isRope());
- return;
- }
-
- // No! - set the next item up to process.
- currentFiber = workQueue.last();
- workQueue.removeLast();
- }
- }