// ***************************************************************************** PodNode* PodNode::childByName(const std::string& name) { // TODO: Use a better data structure/algorithm. for (PodNodeDeque::const_iterator iter = asBlock().begin(); iter != asBlock().end(); ++iter) { assert(*iter); if ((*iter)->podName() == name) { return (*iter); } } return NULL; }
// ***************************************************************************** const PodNode* PodNode::firstChildOfType(const std::string& podType) const { // TODO: Use a better data structure/algorithm. for (PodNodeDeque::const_iterator iter = asBlock().begin(); iter != asBlock().end(); ++iter) { assert(*iter); if ((*iter)->podType() == podType) { return (*iter); } } return NULL; }
bool Log::BlockBuffer::readHeader(uint32_t blockId, BlockHeader *header) { if (!prepareBlock(blockId)) return false; *header = asBlock()->header; return true; }
bool Log::BlockBuffer::writeHeader(uint32_t blockId, const BlockHeader& header) { if (!prepareBlock(blockId)) return false; asBlock()->header = header; dirty = true; return true; }
bool Log::BlockBuffer::readEntry(uint32_t blockId, uint32_t entryId, Entry *entry) { if (!isValidEntryId(entryId)) return false; if (!prepareBlock(blockId)) return false; *entry = asBlock()->entries[entryId]; return true; }
// ***************************************************************************** void PodNode::dump(std::ostream& output, int indent) { for (int i = 0; i < indent; ++i) output << "\t"; output << "PodNode('" << m_podName << "'"; if (!m_podType.empty()) { output << ", type='" << m_podType << "'"; } if (m_value) { output << ", value=" << *m_value; } else { output << ", value=NULL"; } output << ", parent='" << (m_parent ? m_parent->podName() : "NULL") << "'"; if (const EmbedPodValue* embed = dynamic_cast<const EmbedPodValue*>(m_value)) { output << ", lang='" << embed->language() << "'"; } else if (isBlock()) { const PodNodeDeque& children = asBlock(); output << std::endl; for (PodNodeDeque::const_iterator iter = asBlock().begin(); iter != asBlock().end(); ++iter) { assert(*iter); (*iter)->dump(output, indent+1); } for (int i = 0; i < indent; ++i) output << "\t"; } output << " [defined in '" << m_sourcefile << "', line " << m_sourceline << "]"; output << ")" << std::endl; }
bool Log::BlockBuffer::writeEntry(uint32_t blockId, uint32_t entryId, const Entry& entry) { if (!isValidEntryId(entryId)) return false; if (!prepareBlock(blockId)) return false; asBlock()->entries[entryId] = entry; dirty = true; return true; }
// ***************************************************************************** void PodNode::write(std::ostream& output, int indent) const { if (!isValid()) return; if (valueType() == BLOCK && (!parent() && m_podName.empty() && m_podType.empty())) { // At the top-level, don't output enclosing braces, just the // nodes in the block. for (PodNodeDeque::const_iterator iter = asBlock().begin(); iter != asBlock().end(); ++iter) { assert(*iter); (*iter)->write(output, indent); } } else { for (int i = 0; i < indent; ++i) output << " "; if (!m_podType.empty()) { output << m_podType << " "; } if (!m_podName.empty()) { output << m_podName; } if (m_value) { if (!m_podName.empty()) output << " = "; m_value->write(output, indent); } output << ";" << std::endl; } }
// ***************************************************************************** PodNodeDeque& PodNode::asBlock() { if (BlockPodValue* v = dynamic_cast<BlockPodValue*>(m_value)) { return v->value(); } else if (!m_value) { // Special case: User asked for value as a block, but this node has no // current value, so set the value to be an empty block and return it. m_value = new BlockPodValue; return asBlock(); } throw ValueTypeError(__FUNCTION__, this); }
// ***************************************************************************** void PodNode::syncBlock() { if (!isBlock()) return; // // We need to remove any PodNode*s from this block if they are // already parented to some other node. If we don't they can // get double-deleted if this node is deleted during the thrown // exeception, which will cause a segfault. // // Because of this, we collect all the errors found and throw // them at once after cleaning things up. // std::ostringstream err; PodNodeDeque& block = asBlock(); PodNodeDeque::iterator iter = block.begin(); while (iter != block.end()) { PodNode* child = (*iter); if (!child) { err << "Invalid NULL pointer in block." << std::endl; block.erase(iter); iter = block.begin(); // erase() invalidates iter, so start over } else if (child->m_parent && child->m_parent != this) { err << child->repr() << " is already a child of " << child->m_parent->repr() << std::endl; block.erase(iter); iter = block.begin(); // erase() invalidates iter, so start over } else { child->m_parent = this; child->syncBlock(); ++iter; } } if (!err.str().empty()) { throw PodIntegrityError(this, err.str()); } }