WindowResponse ParserWindow::Input(const Batch& ibatch) { g_log.info() << "Updating incParser " << m_incParser.Name() << " with batch: " << ibatch.Print(); m_incParser.ApplyBatch(ibatch); const statik::STree& root = m_incParser.GetRoot(); WindowResponse response; if (root.GetState().IsBad()) { g_log.debug() << " - Not extracting output, because root is bad!"; return response; } // Find first item in incParser's output list, and draw everything response.actions.push_back(WindowAction(WindowAction::MOVE, 0, 0, 0)); Batch batch; g_log.debug() << "Extracting changes from IncParser"; m_incParser.ExtractChanges(batch); g_log.info() << "Printing WindowResponse list for batch of size " << batch.Size() << ": " << batch; if (m_nodes) { g_log.debug() << "m_nodes is: " << *m_nodes; } if (!batch.IsEmpty()) { for (Batch::batch_iter i = batch.begin(); i != batch.end(); ++i) { switch (i->op) { case Batch::OP_INSERT: { g_log.debug() << "Insert node: " << i->node->name << ":" << i->node->value; List* node = new List(i->node->name, i->node->value); if (i->pos) { node_iter pos_i = m_nodeMap.find(i->pos); if (m_nodeMap.end() == pos_i) { throw ISError("Received invalid pos for Insert"); } List* pos = pos_i->second; g_log.debug() << " - at pos: " << pos->name << ":" << pos->value; node->right = pos->right; node->left = pos; pos->right = node; if (node->right) { node->right->left = node; } g_log.debug() << "Inserted " << *node; if (node->left) { g_log.debug() << " - with left: " << *node->left; if (node->left->right) { g_log.debug() << " - - which has right: " << *node->left->right; } } if (node->right) { g_log.debug() << " - with right: " << *node->right; if (node->right->left) { g_log.debug() << " - - which has left: " << *node->right->left; } } } else { g_log.debug() << "Setting this node as m_nodes"; node->right = m_nodes; if (node->right) { node->right->left = node; } m_nodes = node; } m_nodeMap.insert(std::make_pair(i->node, node)); g_log.debug() << "Done inserting node"; } break; case Batch::OP_DELETE: { // Careful! i->node is a pointer to dead data, it's just a lookup // handle for us. node_mod_iter node_i = m_nodeMap.find(i->node); if (m_nodeMap.end() == node_i) { throw ISError("Received invalid node for Delete"); } List* node = node_i->second; g_log.debug() << "Delete node: " << node->name << ":" << node->value; List* left = node->left; List* right = node->right; if (left && left->right == node) { left->right = right; } if (right && right->left == node) { right->left = left; } if (m_nodes == node) { g_log.debug() << "Deleted node is m_nodes"; if (left) { g_log.debug() << "going left"; g_log.debug() << "going left to " << *left << " from " << *node; m_nodes = left; } else if (right) { g_log.debug() << "going right"; g_log.debug() << "going right to " << *right << " from " << *node; m_nodes = right; } else { g_log.debug() << "nowhere to go; m_nodes is clear"; m_nodes = NULL; } } g_log.debug() << "Deleted " << *node; if (node->left) { g_log.debug() << " - with left: " << *node->left; } if (node->right) { g_log.debug() << " - with right: " << *node->right; } delete node; m_nodeMap.erase(node_i); g_log.debug() << "Done deleting node"; } break; case Batch::OP_UPDATE: { g_log.debug() << "Update node: " << i->node->name << ":" << i->node->value; /* node_mod_iter node_i = m_nodeMap.find(i->node); if (m_nodeMap.end() == node_i) { throw ISError("Received invalid node for Update"); } List* node = node_i->second; g_log.debug() << "Update node: " << node->name << ":" << node->value << " -> " << i->node->name << ":" << i->node->value; node->value = i->node->value; */ } break; default: throw ISError("Unknown batch operation " + Batch::UnMapBatchOp(i->op)); } } string old_str = m_str; m_str = ""; bool first = true; List* node = m_nodes; while (node) { if (first) { first = false; } else { m_str += " "; } m_str += node->name; /*if (!node->value.empty()) { m_str += "[" + node->value + "]"; }*/ node = node->right; } g_log.info() << "Printing str: '" << m_str << "'"; for (size_t i = 0; i < m_str.size(); ++i) { response.actions.push_back(WindowAction(WindowAction::INSERT, 0, i, m_str[i])); } // Clear out the rest of the line for (size_t i = m_str.size(); i < old_str.size(); ++i) { response.actions.push_back(WindowAction(WindowAction::INSERT, 0, i, ' ')); } response.batch.Accept(batch); } return response; }