static void new_parser (BtorBTORParser * parser, BtorOpParser op_parser, const char *op) { unsigned p, d; p = hash_op (op, 0); assert (p < SIZE_PARSERS); if (parser->ops[p]) { d = hash_op (op, 1); if (!(d & 1)) d++; do { p += d; if (p >= SIZE_PARSERS) p -= SIZE_PARSERS; assert (p < SIZE_PARSERS); } while (parser->ops[p]); } parser->ops[p] = op; parser->parsers[p] = op_parser; }
static BtorOpParser find_parser (BtorBTORParser * parser, const char *op) { const char *str; unsigned p, d; p = hash_op (op, 0); if ((str = parser->ops[p]) && strcasecmp (str, op)) { d = hash_op (op, 1); if (!(d & 1)) d++; do { p += d; if (p >= SIZE_PARSERS) p -= SIZE_PARSERS; } while ((str = parser->ops[p]) && strcasecmp (str, op)); } return str ? parser->parsers[p] : 0; }
ot_err ot_doc_append(ot_doc* doc, ot_op** op) { if (doc->max_size > 0 && ot_size(*op) + doc->size > doc->max_size) { return OT_ERR_MAX_SIZE; } // Move the op into the document's history array. ot_op* head = array_append(&doc->history); memcpy(head, *op, sizeof(ot_op)); size_t len = doc->history.len; if (len > 1) { ot_op* history = (ot_op*)doc->history.data; ot_op* prev = &history[len - 2]; memcpy(head->parent, prev->hash, 20); } else { char zero[20] = { 0 }; memcpy(head->parent, zero, 20); } // If we're appending the first op, then the composed state will simply be // the first op in the history. If we're appending the second op, then we // must ensure that the composed op still points to the first op in the // history in case its location changed after calling array_append (which // may have reallocated the array to a different location in memory). if (doc->history.len <= 2) { doc->composed = (ot_op*)doc->history.data; } // If we're appending any op after the first, then we must compose the new // op with the currently composed state to get the new composed state. if (doc->history.len > 1) { ot_op* new_composed = ot_compose(doc->composed, head); if (new_composed == NULL) { doc->history.len--; return OT_ERR_APPEND_FAILED; } // Only free the previously composed op if this is at least the 2nd // composition (aka 3rd op in the history). This is because the first // composed op for a document points to the first op in the doc's // history, and we don't want to free anything in the history. if (doc->history.len > 2) { ot_free_op(doc->composed); } doc->composed = new_composed; } // Don't use ot_free_op because we only want to free the ot_op struct, not // its components. We must also only free op if the composition was a // success. free(*op); *op = head; // The newly composed operation wil have the same hash as the appended op, // so we can get away with calculating the hash once and then copying it. hash_op(doc->composed); memcpy(head->hash, doc->composed->hash, 20); doc->size = ot_size(doc->composed); return OT_ERR_NONE; }