Пример #1
0
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;
}
Пример #2
0
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;
}
Пример #3
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;
}