void main ( void ) { Deque<int> intQ; printf ( "isEmpty(1): %d\n", intQ.isEmpty ( ) ? 1 : 0 ); intQ.insertFirst ( 4 ); cout << intQ <<endl; printf ( "removeLast(4): %d\n", intQ.removeLast ( ) ); cout << intQ <<endl; intQ.insertFirst ( 5 ); intQ.insertFirst ( 12 ); intQ.insertLast ( 7 ); intQ.insertLast ( 13 ); cout << intQ <<endl; printf ( "first(12): %d\n", intQ.first ( ) ); printf ( "last(13): %d\n", intQ.last ( ) ); printf ( "size(4): %d\n", intQ.size ( ) ); printf ( "isEmpty(0): %d\n", intQ.isEmpty ( ) ? 1 : 0 ); printf ( "removeLast(13) :%d\n", intQ.removeLast ( ) ); printf ( "removeLast(7) :%d\n", intQ.removeLast ( ) ); printf ( "removeLast(5) :%d\n", intQ.removeLast ( ) ); cout << intQ <<endl; printf ( "removeFirst(12) :%d\n", intQ.removeFirst ( ) ); cout << intQ <<endl; printf ( "size(0): %d\n", intQ.size ( ) ); printf ( "isEmpty(1): %d\n", intQ.isEmpty ( ) ? 1 : 0 ); intQ.removeLast ( ); }
void findNearest(TreeNode root, double target, Deque<TreeNode> s, boolean fromLeft) { while (root != null) { s.push(root); //System.out.printf("fromLeft = %b, push %d\n", fromLeft, root.val); if (root.val == target) { break; } if (root.val < target) { root = root.right; } else { root = root.left; } } if (fromLeft) { while (!s.isEmpty() && s.peek().val > target) { //System.out.printf("pop %d\n", s.peek().val); s.pop(); } } else { while (!s.isEmpty() && s.peek().val < target) { //System.out.printf("pop %d\n", s.peek().val); s.pop(); } } }
bool AccessibilityTree::isTreeValid() const { // A valid tree can only have treeitem or group of treeitems as a child // http://www.w3.org/TR/wai-aria/roles#tree Node* node = this->node(); if (!node) return false; Deque<Node*> queue; for (auto child = node->firstChild(); child; child = child->nextSibling()) queue.append(child); while (!queue.isEmpty()) { auto child = queue.takeFirst(); if (!is<Element>(*child)) continue; if (nodeHasRole(child, "treeitem")) continue; if (!nodeHasRole(child, "group")) return false; for (auto groupChild = child->firstChild(); groupChild; groupChild = groupChild->nextSibling()) queue.append(groupChild); } return true; }
int main() { int maxSize = 5; Deque *dq = new Deque(maxSize); dq->insert(3,1); dq->insert(4,2); dq->insert(10,1); dq->insert(20,1); dq->insert(33,2); dq->insert(333,1); dq->displayDeque(); cout << "First in deque: " << dq->getFirst() << endl; cout << "Last in deque: " << dq->getLast() << endl; cout << "Removed: "; while(!dq->isEmpty()) { cout << dq->remove(1) << " " << dq->remove(2) << " "; } cout << endl; delete dq; return 0; } // end main()
void IDBDatabaseBackend::processPendingOpenCalls(bool success) { // Open calls can be requeued if an open call started a version change transaction or deletes the database. Deque<OwnPtr<IDBPendingOpenCall>> pendingOpenCalls; m_pendingOpenCalls.swap(pendingOpenCalls); while (!pendingOpenCalls.isEmpty()) { OwnPtr<IDBPendingOpenCall> pendingOpenCall = pendingOpenCalls.takeFirst(); if (success) { if (m_metadata.id == InvalidId) { // This database was deleted then quickly re-opened. // openInternalAsync() will recreate it in the backing store and then resume processing pending callbacks. pendingOpenCalls.prepend(pendingOpenCall.release()); pendingOpenCalls.swap(m_pendingOpenCalls); openInternalAsync(); return; } openConnectionInternal(pendingOpenCall->callbacks(), pendingOpenCall->databaseCallbacks(), pendingOpenCall->transactionId(), pendingOpenCall->version()); } else { String message; if (pendingOpenCall->version() == IDBDatabaseMetadata::NoIntVersion) message = "Internal error opening database with no version specified."; else message = String::format("Internal error opening database with version %llu", static_cast<unsigned long long>(pendingOpenCall->version())); pendingOpenCall->callbacks()->onError(IDBDatabaseError::create(IDBDatabaseException::UnknownError, message)); } } }
void RunLoop::runImpl(RunMode runMode) { ASSERT(this == &RunLoop::current()); Status statusOfThisLoop = Status::Clear; { LockHolder locker(m_loopLock); m_mainLoops.append(&statusOfThisLoop); } Deque<RefPtr<TimerBase::ScheduledTask>> firedTimers; while (true) { if (!populateTasks(runMode, statusOfThisLoop, firedTimers)) return; // Dispatch scheduled timers. while (!firedTimers.isEmpty()) { RefPtr<TimerBase::ScheduledTask> task = firedTimers.takeFirst(); if (task->fired()) { // Reschedule because the timer requires repeating. // Since we will query the timers' time points before sleeping, // we do not call wakeUp() here. schedule(*task); } } performWork(); } }
TEST(WTF_Deque, Remove) { Deque<int> deque; deque.append(11); deque.prepend(10); deque.append(12); deque.append(13); EXPECT_EQ(10, deque.first()); EXPECT_EQ(13, deque.last()); deque.removeLast(); EXPECT_EQ(10, deque.first()); EXPECT_EQ(12, deque.last()); deque.removeFirst(); EXPECT_EQ(11, deque.first()); EXPECT_EQ(12, deque.last()); deque.removeFirst(); EXPECT_EQ(12, deque.first()); EXPECT_EQ(12, deque.last()); deque.removeLast(); EXPECT_TRUE(deque.isEmpty()); }
void EventSender::replaySavedEvents() { replayingSavedEvents = true; while (!mouseEventQueue.isEmpty()) { SavedEvent e = mouseEventQueue.takeFirst(); switch (e.type) { case SavedEvent::MouseMove: { WebMouseEvent event; initMouseEvent(WebInputEvent::MouseMove, pressedButton, e.pos, &event); doMouseMove(event); break; } case SavedEvent::LeapForward: doLeapForward(e.milliseconds); break; case SavedEvent::MouseUp: { WebMouseEvent event; initMouseEvent(WebInputEvent::MouseUp, e.buttonType, lastMousePos, &event); doMouseUp(event); break; } default: ASSERT_NOT_REACHED(); } } replayingSavedEvents = false; }
void HistoryController::goToItem(HistoryItem* targetItem, ResourceRequestCachePolicy cachePolicy) { if (m_defersLoading) { m_deferredItem = targetItem; m_deferredCachePolicy = cachePolicy; return; } OwnPtr<HistoryEntry> newEntry = HistoryEntry::create(targetItem); Deque<HistoryNode*> historyNodes; historyNodes.append(newEntry->rootHistoryNode()); while (!historyNodes.isEmpty()) { // For each item, read the children (if any) off the HistoryItem, // create a new HistoryNode for each child and attach it, // then clear the children on the HistoryItem. HistoryNode* historyNode = historyNodes.takeFirst(); const HistoryItemVector& children = historyNode->value()->children(); for (size_t i = 0; i < children.size(); i++) { HistoryNode* childHistoryNode = historyNode->addChild(children[i].get()); historyNodes.append(childHistoryNode); } historyNode->value()->clearChildren(); } goToEntry(newEntry.release(), cachePolicy); }
public List<Integer> closestKValues(TreeNode root, double target, int k) { Deque<TreeNode> leftS = new ArrayDeque<TreeNode>(); Deque<TreeNode> rightS = new ArrayDeque<TreeNode>(); findNearest(root, target, leftS, true); findNearest(root, target, rightS, false); List<Integer> res = new ArrayList<Integer>(); while (res.size() < k) { boolean use_left = false; boolean use_right = false; if (leftS.isEmpty()) { use_right = true; } else if (rightS.isEmpty()) { use_left = true; } else if (leftS.peek().val == rightS.peek().val) { use_left = use_right = true; } else if (target - leftS.peek().val < rightS.peek().val - target) { use_left = true; } else { use_right = true; } res.add(use_left ? leftS.peek().val : rightS.peek().val); if (use_left) { TreeNode node = leftS.pop(); node = node.left; while (node != null) { leftS.push(node); node = node.right; } while (!leftS.isEmpty() && leftS.peek().val > target) { leftS.pop(); } } if (use_right) { TreeNode node = rightS.pop(); node = node.right; while (node != null) { rightS.push(node); node = node.left; } while (!rightS.isEmpty() && rightS.peek().val < target) { rightS.pop(); } } } return res; }
RefPtr<UniqueIDBDatabaseTransaction> UniqueIDBDatabase::takeNextRunnableTransaction(bool& hadDeferredTransactions) { Deque<RefPtr<UniqueIDBDatabaseTransaction>> deferredTransactions; RefPtr<UniqueIDBDatabaseTransaction> currentTransaction; while (!m_pendingTransactions.isEmpty()) { currentTransaction = m_pendingTransactions.takeFirst(); switch (currentTransaction->info().mode()) { case IndexedDB::TransactionMode::ReadOnly: // If there are any deferred transactions, the first one is a read-write transaction we need to unblock. // Therefore, skip this read-only transaction if its scope overlaps with that read-write transaction. if (!deferredTransactions.isEmpty()) { ASSERT(deferredTransactions.first()->info().mode() == IndexedDB::TransactionMode::ReadWrite); if (scopesOverlap(deferredTransactions.first()->objectStoreIdentifiers(), currentTransaction->objectStoreIdentifiers())) deferredTransactions.append(WTF::move(currentTransaction)); } break; case IndexedDB::TransactionMode::ReadWrite: // If this read-write transaction's scope overlaps with running transactions, it must be deferred. if (scopesOverlap(m_objectStoreTransactionCounts, currentTransaction->objectStoreIdentifiers())) deferredTransactions.append(WTF::move(currentTransaction)); break; case IndexedDB::TransactionMode::VersionChange: // Version change transactions should never be scheduled in the traditional manner. RELEASE_ASSERT_NOT_REACHED(); } // If we didn't defer the currentTransaction above, it can be run now. if (currentTransaction) break; } hadDeferredTransactions = !deferredTransactions.isEmpty(); if (!hadDeferredTransactions) return WTF::move(currentTransaction); // Prepend the deferred transactions back on the beginning of the deque for future scheduling passes. while (!deferredTransactions.isEmpty()) m_pendingTransactions.prepend(deferredTransactions.takeLast()); return WTF::move(currentTransaction); }
void IDBDatabaseBackendImpl::processPendingCalls() { if (m_pendingSecondHalfOpenWithVersion) { ASSERT(m_pendingSecondHalfOpenWithVersion->version() == m_metadata.intVersion); ASSERT(m_metadata.id != InvalidId); m_pendingSecondHalfOpenWithVersion->callbacks()->onSuccess(this); m_pendingSecondHalfOpenWithVersion.release(); // Fall through when complete, as pending deletes may be (partially) unblocked. } // Note that this check is only an optimization to reduce queue-churn and // not necessary for correctness; deleteDatabase and openConnection will // requeue their calls if this condition is true. if (m_runningVersionChangeTransaction) return; // Pending calls may be requeued. Deque<OwnPtr<PendingDeleteCall> > pendingDeleteCalls; m_pendingDeleteCalls.swap(pendingDeleteCalls); while (!pendingDeleteCalls.isEmpty()) { OwnPtr<PendingDeleteCall> pendingDeleteCall = pendingDeleteCalls.takeFirst(); deleteDatabase(pendingDeleteCall->callbacks()); } // This check is also not really needed, openConnection would just requeue its calls. if (m_runningVersionChangeTransaction || !m_pendingDeleteCalls.isEmpty()) return; Deque<OwnPtr<PendingOpenWithVersionCall> > pendingOpenWithVersionCalls; m_pendingOpenWithVersionCalls.swap(pendingOpenWithVersionCalls); while (!pendingOpenWithVersionCalls.isEmpty()) { OwnPtr<PendingOpenWithVersionCall> pendingOpenWithVersionCall = pendingOpenWithVersionCalls.takeFirst(); openConnectionWithVersion(pendingOpenWithVersionCall->callbacks(), pendingOpenWithVersionCall->databaseCallbacks(), pendingOpenWithVersionCall->version()); } // Open calls can be requeued if an openWithVersion call started a version // change transaction. Deque<OwnPtr<PendingOpenCall> > pendingOpenCalls; m_pendingOpenCalls.swap(pendingOpenCalls); while (!pendingOpenCalls.isEmpty()) { OwnPtr<PendingOpenCall> pendingOpenCall = pendingOpenCalls.takeFirst(); openConnection(pendingOpenCall->callbacks(), pendingOpenCall->databaseCallbacks()); } }
void FullscreenElementStack::fullScreenChangeDelayTimerFired(Timer<FullscreenElementStack>*) { // Since we dispatch events in this function, it's possible that the // document will be detached and GC'd. We protect it here to make sure we // can finish the function successfully. RefPtr<Document> protectDocument(document()); Deque<RefPtr<Node> > changeQueue; m_fullScreenChangeEventTargetQueue.swap(changeQueue); Deque<RefPtr<Node> > errorQueue; m_fullScreenErrorEventTargetQueue.swap(errorQueue); while (!changeQueue.isEmpty()) { RefPtr<Node> node = changeQueue.takeFirst(); if (!node) node = document()->documentElement(); // The dispatchEvent below may have blown away our documentElement. if (!node) continue; // If the element was removed from our tree, also message the documentElement. Since we may // have a document hierarchy, check that node isn't in another document. if (!document()->contains(node.get()) && !node->inDocument()) changeQueue.append(document()->documentElement()); node->dispatchEvent(Event::createBubble(eventNames().webkitfullscreenchangeEvent)); } while (!errorQueue.isEmpty()) { RefPtr<Node> node = errorQueue.takeFirst(); if (!node) node = document()->documentElement(); // The dispatchEvent below may have blown away our documentElement. if (!node) continue; // If the element was removed from our tree, also message the documentElement. Since we may // have a document hierarchy, check that node isn't in another document. if (!document()->contains(node.get()) && !node->inDocument()) errorQueue.append(document()->documentElement()); node->dispatchEvent(Event::createBubble(eventNames().webkitfullscreenerrorEvent)); } }
void DOMPatchSupport::markNodeAsUsed(Digest* digest) { Deque<Digest*> queue; queue.append(digest); while (!queue.isEmpty()) { Digest* first = queue.takeFirst(); m_unusedNodesMap.remove(first->m_sha1); for (size_t i = 0; i < first->m_children.size(); ++i) queue.append(first->m_children[i].get()); } }
/*-------------------------------------------------------------*\ | Main program | \*-------------------------------------------------------------*/ int main() { Deque D; char C; IBoolean ReadFront = True; int i; // Put all characters in the deque. // Then read it, changing the end to read from // with every character read. cout << endl << "Adding characters to the back end of the deque:" << endl; for (i = 0; String[i] != 0; i ++) { D.addAsLast(String[i]); cout << String[i]; } cout << endl << endl << "Current number of elements in the deque: " << D.numberOfElements() << endl; cout << endl << "Contents of the deque:" << endl; Print Aprinter; D.allElementsDo(Aprinter); cout << endl << endl << "Reading from the deque one element from front, one " << "from back, and so on:" << endl; while (!D.isEmpty()) { if (ReadFront) // Read from front of Deque { C = D.firstElement(); // Get the character D.removeFirst(); // Delete it from the Deque } else { C = D.lastElement(); D.removeLast(); } cout << C; ReadFront = !ReadFront; // Switch to other end of Deque } cout << endl; return(0); }
int main() { // Stack behavior using a general dequeue Deque q; try { if ( q.isEmpty() ) { cout << "Deque is empty" << endl; } // Push elements q.insertBack(100); q.insertBack(200); q.insertBack(300); // Size of queue cout << "Size of dequeue = " << q.size() << endl; // Pop elements cout << q.removeBack() << endl; cout << q.removeBack() << endl; cout << q.removeBack() << endl; } catch (...) { cout << "Some exception occured" << endl; } // Queue behavior using a general dequeue Deque q1; try { if ( q1.isEmpty() ) { cout << "Deque is empty" << endl; } // Push elements q1.insertBack(100); q1.insertBack(200); q1.insertBack(300); // Size of queue cout << "Size of dequeue = " << q1.size() << endl; // Pop elements cout << q1.removeFront() << endl; cout << q1.removeFront() << endl; cout << q1.removeFront() << endl; } catch (...) { cout << "Some exception occured" << endl; } }
int main(int argc, char** argv) { Deque<char> a; char base_pair; while(cin >> base_pair) a.addLast(base_pair); while(!a.isEmpty()) { if(a.size() == 1) { cout << "false" << endl; return 0; } char first = a.removeFirst(); char last = a.removeLast(); switch(first) { case 'A': if(last != 'T') { cout << "false" << endl; return 0; } continue; case 'T': if(last != 'A') { cout << "false" << endl; return 0; } continue; case 'C': if(last != 'G') { cout << "false" << endl; return 0; } continue; case 'G': if(last != 'C') { cout << "false" << endl; return 0; } continue; default: cout << "false" << endl; return 0; } } cout << "true" << endl; return 0; }
int main(){ Deque q; int NumberOfElements = 10000; try{ if (q.isEmpty()){ std::cout << "Deque is empty" << std::endl; } //Push elements to populate queue for(int i = 1; i <= NumberOfElements;i++){ q.InsertToBack(i); } //Size of queue int sizeOfDequeue = q.Size(); std::cout << "Size of dequeue = " << sizeOfDequeue << std::endl; //Pop elements for(int i = 0; i <sizeOfDequeue; i++){ std::cout << q.RemoveFromBack() << std::endl; } } catch (...){ std::cout << "Some exception occured" << std::endl; } Deque q1; try{ if (q1.isEmpty()){ std::cout << "Deque is empty" << std::endl; } //Push elements into queue for(int i = 1; i <= NumberOfElements;i++){ q1.InsertToBack(i); } //Size of queue int sizeOfDequeue = q1.Size(); std::cout << "Size of dequeue = " << q1.Size() << std::endl; //Pop elements for(int i = 0; i < sizeOfDequeue;i++){ std::cout << q1.RemoveFromFront() << std::endl; } } catch (...) { std::cout << "Some exception occured" << std::endl; } }
void IDBDatabaseBackendImpl::processPendingCalls() { // Pending calls may be requeued or aborted Deque<RefPtr<PendingSetVersionCall> > pendingSetVersionCalls; m_pendingSetVersionCalls.swap(pendingSetVersionCalls); while (!pendingSetVersionCalls.isEmpty()) { ExceptionCode ec = 0; RefPtr<PendingSetVersionCall> pendingSetVersionCall = pendingSetVersionCalls.takeFirst(); setVersion(pendingSetVersionCall->version(), pendingSetVersionCall->callbacks(), pendingSetVersionCall->databaseCallbacks(), ec); ASSERT(!ec); } while (!m_runningVersionChangeTransaction && m_pendingSetVersionCalls.isEmpty() && !m_pendingOpenCalls.isEmpty()) { RefPtr<PendingOpenCall> pendingOpenCall = m_pendingOpenCalls.takeFirst(); openConnection(pendingOpenCall->callbacks()); } }
void DatabaseThread::unscheduleDatabaseTasks(Database* database) { // Note that the thread loop is running, so some tasks for the database // may still be executed. This is unavoidable. Deque<RefPtr<DatabaseTask> > filteredReverseQueue; RefPtr<DatabaseTask> task; while (m_queue.tryGetMessage(task)) { if (task->database() != database) filteredReverseQueue.append(task); } while (!filteredReverseQueue.isEmpty()) { m_queue.append(filteredReverseQueue.first()); filteredReverseQueue.removeFirst(); } }
void CSSStyleSheet::addSubresourceStyleURLs(ListHashSet<KURL>& urls) { Deque<CSSStyleSheet*> styleSheetQueue; styleSheetQueue.append(this); while (!styleSheetQueue.isEmpty()) { CSSStyleSheet* styleSheet = styleSheetQueue.takeFirst(); for (unsigned i = 0; i < styleSheet->length(); ++i) { CSSRule* rule = styleSheet->item(i); if (rule->isImportRule()) { if (CSSStyleSheet* ruleStyleSheet = static_cast<CSSImportRule*>(rule)->styleSheet()) styleSheetQueue.append(ruleStyleSheet); } rule->addSubresourceStyleURLs(urls); } } }
void HistoryController::goToItem(HistoryItem* targetItem, ResourceRequestCachePolicy cachePolicy) { // We don't have enough information to set a correct frame id here. This might be a restore from // disk, and the frame ids might not match up if the state was saved from a different process. // Ensure the HistoryEntry's main frame id matches the actual main frame id. Its subframe ids // are invalid to ensure they don't accidentally match a potentially random frame. OwnPtr<HistoryEntry> newEntry = HistoryEntry::create(targetItem, m_page->mainFrame()->frameID()); Deque<HistoryNode*> historyNodes; historyNodes.append(newEntry->rootHistoryNode()); while (!historyNodes.isEmpty()) { // For each item, read the children (if any) off the HistoryItem, // create a new HistoryNode for each child and attach it, // then clear the children on the HistoryItem. HistoryNode* historyNode = historyNodes.takeFirst(); const HistoryItemVector& children = historyNode->value()->deprecatedChildren(); for (size_t i = 0; i < children.size(); i++) { HistoryNode* childHistoryNode = historyNode->addChild(children[i].get(), -1); historyNodes.append(childHistoryNode); } historyNode->value()->deprecatedClearChildren(); } goToEntry(newEntry.release(), cachePolicy); }
void WebSocket::EventQueue::dispatchQueuedEvents() { if (m_state != Active) return; RefPtr<EventQueue> protect(this); Deque<RefPtr<Event> > events; events.swap(m_events); while (!events.isEmpty()) { if (m_state == Stopped || m_state == Suspended) break; ASSERT(m_state == Active); ASSERT(m_target->executionContext()); m_target->dispatchEvent(events.takeFirst()); // |this| can be stopped here. } if (m_state == Suspended) { while (!m_events.isEmpty()) events.append(m_events.takeFirst()); events.swap(m_events); } }
void AccessibilityTable::addChildrenFromSection(RenderTableSection* tableSection, unsigned& maxColumnCount) { ASSERT(tableSection); if (!tableSection) return; AXObjectCache* axCache = m_renderer->document().axObjectCache(); HashSet<AccessibilityObject*> appendedRows; unsigned numRows = tableSection->numRows(); for (unsigned rowIndex = 0; rowIndex < numRows; ++rowIndex) { RenderTableRow* renderRow = tableSection->rowRendererAt(rowIndex); if (!renderRow) continue; AccessibilityObject& rowObject = *axCache->getOrCreate(renderRow); // If the row is anonymous, we should dive deeper into the descendants to try to find a valid row. if (renderRow->isAnonymous()) { Deque<AccessibilityObject*> queue; queue.append(&rowObject); while (!queue.isEmpty()) { AccessibilityObject* obj = queue.takeFirst(); if (obj->node() && is<AccessibilityTableRow>(*obj)) { addTableCellChild(obj, appendedRows, maxColumnCount); continue; } for (auto child = obj->firstChild(); child; child = child->nextSibling()) queue.append(child); } } else addTableCellChild(&rowObject, appendedRows, maxColumnCount); } maxColumnCount = std::max(tableSection->numColumns(), maxColumnCount); }
void CSSStyleSheet::addSubresourceStyleURLs(ListHashSet<KURL>& urls) { Deque<CSSStyleSheet*> styleSheetQueue; styleSheetQueue.append(this); while (!styleSheetQueue.isEmpty()) { CSSStyleSheet* styleSheet = styleSheetQueue.takeFirst(); for (unsigned i = 0; i < styleSheet->m_importRules.size(); ++i) { StyleRuleImport* importRule = styleSheet->m_importRules[i].get(); if (importRule->styleSheet()) { styleSheetQueue.append(importRule->styleSheet()); addSubresourceURL(urls, importRule->styleSheet()->baseURL()); } } for (unsigned i = 0; i < styleSheet->m_childRules.size(); ++i) { StyleRuleBase* rule = styleSheet->m_childRules[i].get(); if (rule->isStyleRule()) static_cast<StyleRule*>(rule)->properties()->addSubresourceStyleURLs(urls, this); else if (rule->isFontFaceRule()) static_cast<StyleRuleFontFace*>(rule)->properties()->addSubresourceStyleURLs(urls, this); } } }
static PassOwnPtr<ArgumentDecoder> createArgumentDecoder(mach_msg_header_t* header) { if (!(header->msgh_bits & MACH_MSGH_BITS_COMPLEX)) { // We have a simple message. size_t bodySize = header->msgh_size - sizeof(mach_msg_header_t); uint8_t* body = reinterpret_cast<uint8_t*>(header + 1); return adoptPtr(new ArgumentDecoder(body, bodySize)); } bool messageBodyIsOOL = header->msgh_id & MessageBodyIsOOL; mach_msg_body_t* body = reinterpret_cast<mach_msg_body_t*>(header + 1); mach_msg_size_t numDescriptors = body->msgh_descriptor_count; ASSERT(numDescriptors); // Build attachment list Deque<Attachment> attachments; uint8_t* descriptorData = reinterpret_cast<uint8_t*>(body + 1); // If the message body was sent out-of-line, don't treat the last descriptor // as an attachment, since it is really the message body. if (messageBodyIsOOL) --numDescriptors; for (mach_msg_size_t i = 0; i < numDescriptors; ++i) { mach_msg_descriptor_t* descriptor = reinterpret_cast<mach_msg_descriptor_t*>(descriptorData); switch (descriptor->type.type) { case MACH_MSG_PORT_DESCRIPTOR: attachments.append(Attachment(descriptor->port.name, descriptor->port.disposition)); descriptorData += sizeof(mach_msg_port_descriptor_t); break; case MACH_MSG_OOL_DESCRIPTOR: attachments.append(Attachment(descriptor->out_of_line.address, descriptor->out_of_line.size, descriptor->out_of_line.copy, descriptor->out_of_line.deallocate)); descriptorData += sizeof(mach_msg_ool_descriptor_t); break; default: ASSERT(false && "Unhandled descriptor type"); } } if (messageBodyIsOOL) { mach_msg_descriptor_t* descriptor = reinterpret_cast<mach_msg_descriptor_t*>(descriptorData); ASSERT(descriptor->type.type == MACH_MSG_OOL_DESCRIPTOR); Attachment messageBodyAttachment(descriptor->out_of_line.address, descriptor->out_of_line.size, descriptor->out_of_line.copy, descriptor->out_of_line.deallocate); uint8_t* messageBody = static_cast<uint8_t*>(messageBodyAttachment.address()); size_t messageBodySize = messageBodyAttachment.size(); ArgumentDecoder* argumentDecoder; if (attachments.isEmpty()) argumentDecoder = new ArgumentDecoder(messageBody, messageBodySize); else argumentDecoder = new ArgumentDecoder(messageBody, messageBodySize, attachments); vm_deallocate(mach_task_self(), reinterpret_cast<vm_address_t>(messageBodyAttachment.address()), messageBodyAttachment.size()); return adoptPtr(argumentDecoder); } uint8_t* messageBody = descriptorData; size_t messageBodySize = header->msgh_size - (descriptorData - reinterpret_cast<uint8_t*>(header)); return adoptPtr(new ArgumentDecoder(messageBody, messageBodySize, attachments)); }