Exemplo n.º 1
0
static int FillShapeValueArray (v8::Isolate* isolate,
                                VocShaper* shaper,
                                TRI_shape_value_t* dst,
                                v8::Handle<v8::Object> const json,
                                size_t level,
                                set<int>& seenHashes,
                                vector<v8::Handle<v8::Object>>& seenObjects,
                                bool create) {
  v8::HandleScope scope(isolate);
  TRI_shape_value_t* values;
  TRI_shape_value_t* p;
  TRI_shape_value_t* e;

  TRI_array_shape_t* a;

  TRI_shape_sid_t* sids;
  TRI_shape_aid_t* aids;
  TRI_shape_size_t* offsetsF;
  TRI_shape_size_t* offsetsV;
  TRI_shape_size_t offset;

  TRI_shape_t const* found;

  char* ptr;

  // number of attributes
  v8::Handle<v8::Array> names = json->GetOwnPropertyNames();
  uint32_t n = names->Length();

  // convert into TRI_shape_value_t array
  p = (values = static_cast<TRI_shape_value_t*>(TRI_Allocate(shaper->memoryZone(), n * sizeof(TRI_shape_value_t), true)));

  if (p == nullptr) {
    return TRI_ERROR_OUT_OF_MEMORY;
  }
  
  size_t total = 0;

  size_t f = 0;
  size_t v = 0;

  for (uint32_t i = 0;  i < n;  ++i, ++p) {
    v8::Handle<v8::Value> key = names->Get(i);

    // first find an identifier for the name
    TRI_Utf8ValueNFC keyStr(TRI_UNKNOWN_MEM_ZONE, key);

    if (*keyStr == 0 || keyStr.length() == 0) {
      --p;
      continue;
    }

    if ((*keyStr)[0] == '_' && level == 0) {
      // on top level, strip reserved attributes before shaping
      char const* k = (*keyStr);
      if (strcmp(k, "_key") == 0 || 
          strcmp(k, "_rev") == 0 ||
          strcmp(k, "_id") == 0 ||
          strcmp(k, "_from") == 0 ||
          strcmp(k, "_to") == 0) {
        // found a reserved attribute - discard it
        --p;
        continue;
      }
    }

    if (create) {
      p->_aid = shaper->findOrCreateAttributeByName(*keyStr);
    }
    else {
      p->_aid = shaper->lookupAttributeByName(*keyStr);
    }

    int res;

    // convert value
    if (p->_aid == 0) {
      if (create) {
        res = TRI_ERROR_INTERNAL;
      }
      else {
        res = TRI_RESULT_ELEMENT_NOT_FOUND;
      }
    }
    else {
      v8::Handle<v8::Value> val = json->Get(key);
      res = FillShapeValueJson(isolate, shaper, p, val, level + 1, seenHashes, seenObjects, create);
    }

    if (res != TRI_ERROR_NO_ERROR) {
      for (e = p, p = values;  p < e;  ++p) {
        if (p->_value != nullptr) {
          TRI_Free(shaper->memoryZone(), p->_value);
        }
      }

      TRI_Free(shaper->memoryZone(), values);
      return res;
    }

    total += static_cast<size_t>(p->_size);

    // count fixed and variable sized values
    if (p->_fixedSized) {
      ++f;
    }
    else {
      ++v;
    }
  }

  // adjust n
  n = (uint32_t) (f + v);

  // add variable offset table size
  total += (v + 1) * sizeof(TRI_shape_size_t);

  // now sort the shape entries
  if (n > 1) {
    TRI_SortShapeValues(values, (size_t) n);
  }

#ifdef DEBUG_JSON_SHAPER
  printf("shape values\n------------\ntotal: %u, fixed: %u, variable: %u\n",
         (unsigned int) n,
         (unsigned int) f,
         (unsigned int) v);
  TRI_PrintShapeValues(values, n);
  printf("\n");
#endif

  // generate shape structure
  size_t const totalSize =
    sizeof(TRI_array_shape_t)
    + n * sizeof(TRI_shape_sid_t)
    + n * sizeof(TRI_shape_aid_t)
    + (f + 1) * sizeof(TRI_shape_size_t);

  a = (TRI_array_shape_t*) (ptr = (char*) TRI_Allocate(shaper->memoryZone(), totalSize, true));

  if (ptr == nullptr) {
    e = values + n;

    for (p = values;  p < e;  ++p) {
      if (p->_value != nullptr) {
        TRI_Free(shaper->memoryZone(), p->_value);
      }
    }

    TRI_Free(shaper->memoryZone(), values);

    return TRI_ERROR_OUT_OF_MEMORY;
  }

  a->base._type = TRI_SHAPE_ARRAY;
  a->base._size = (TRI_shape_size_t) totalSize;
  a->base._dataSize = (v == 0) ? total : TRI_SHAPE_SIZE_VARIABLE;

  a->_fixedEntries = f;
  a->_variableEntries = v;

  ptr += sizeof(TRI_array_shape_t);

  // array of shape identifiers
  sids = (TRI_shape_sid_t*) ptr;
  ptr += n * sizeof(TRI_shape_sid_t);

  // array of attribute identifiers
  aids = (TRI_shape_aid_t*) ptr;
  ptr += n * sizeof(TRI_shape_aid_t);

  // array of offsets for fixed part (within the shape)
  offset = (v + 1) * sizeof(TRI_shape_size_t);
  offsetsF = (TRI_shape_size_t*) ptr;

  // fill destination (except sid)
  dst->_type = TRI_SHAPE_ARRAY;

  dst->_fixedSized = true;
  dst->_size = total;
  dst->_value = (ptr = static_cast<char*>(TRI_Allocate(shaper->memoryZone(), dst->_size, true)));

  if (ptr == nullptr) {
    e = values + n;

    for (p = values;  p < e;  ++p) {
      if (p->_value != nullptr) {
        TRI_Free(shaper->memoryZone(), p->_value);
      }
    }

    TRI_Free(shaper->memoryZone(), values);
    TRI_Free(shaper->memoryZone(), a);

    return TRI_ERROR_OUT_OF_MEMORY;
  }

  // array of offsets for variable part (within the value)
  offsetsV = (TRI_shape_size_t*) ptr;
  ptr += (v + 1) * sizeof(TRI_shape_size_t);

  // and fill in attributes
  e = values + n;

  for (p = values;  p < e;  ++p) {
    *aids++ = p->_aid;
    *sids++ = p->_sid;
 
    if (p->_value != nullptr) {
      memcpy(ptr, p->_value, static_cast<size_t>(p->_size));
    }
    ptr += p->_size;

    dst->_fixedSized &= p->_fixedSized;

    if (p->_fixedSized) {
      *offsetsF++ = offset;
      offset += p->_size;
      *offsetsF = offset;
    }
    else {
      *offsetsV++ = offset;
      offset += p->_size;
      *offsetsV = offset;
    }
  }

  // free TRI_shape_value_t array
  for (p = values;  p < e;  ++p) {
    if (p->_value != nullptr) {
      TRI_Free(shaper->memoryZone(), p->_value);
    }
  }

  TRI_Free(shaper->memoryZone(), values);

  // lookup this shape
  found = shaper->findShape(&a->base, create);

  if (found == nullptr) {
    LOG_TRACE("shaper failed to find shape %d", (int) a->base._type);
    TRI_Free(shaper->memoryZone(), dst->_value);
    TRI_Free(shaper->memoryZone(), a);

    if (! create) {
      return TRI_RESULT_ELEMENT_NOT_FOUND;
    }

    return TRI_ERROR_INTERNAL;
  }

  // and finally add the sid
  dst->_sid = found->_sid;
  return TRI_ERROR_NO_ERROR;
}
Exemplo n.º 2
0
static bool FillShapeValueArray (TRI_shaper_t* shaper,
                                 TRI_shape_value_t* dst,
                                 v8::Handle<v8::Object> json,
                                 set<int>& seenHashes,
                                 vector< v8::Handle<v8::Object> >& seenObjects) {
  size_t n;
  size_t i;
  size_t total;

  size_t f;
  size_t v;

  TRI_shape_value_t* values;
  TRI_shape_value_t* p;
  TRI_shape_value_t* e;

  TRI_array_shape_t* a;

  TRI_shape_sid_t* sids;
  TRI_shape_aid_t* aids;
  TRI_shape_size_t* offsetsF;
  TRI_shape_size_t* offsetsV;
  TRI_shape_size_t offset;

  TRI_shape_t const* found;

  char* ptr;

  // number of attributes
  v8::Handle<v8::Array> names = json->GetOwnPropertyNames();
  n = names->Length();

  // convert into TRI_shape_value_t array
  p = (values = (TRI_shape_value_t*) TRI_Allocate(shaper->_memoryZone, n * sizeof(TRI_shape_value_t), true));

  if (p == NULL) {
    return false;
  }

  total = 0;
  f = 0;
  v = 0;

  for (i = 0;  i < n;  ++i, ++p) {
    v8::Handle<v8::Value> key = names->Get(i);
    v8::Handle<v8::Value> val = json->Get(key);
    bool ok;

    // first find an identifier for the name
    TRI_Utf8ValueNFC keyStr(TRI_UNKNOWN_MEM_ZONE, key);

    if (*keyStr == 0) {
      --p;
      continue;
    }

    if ((*keyStr)[0] == '_') {
      --p;
      continue;
    }

    p->_aid = shaper->findAttributeName(shaper, *keyStr);

    // convert value
    if (p->_aid == 0) {
      ok = false;
    }
    else {
      ok = FillShapeValueJson(shaper, p, val, seenHashes, seenObjects);
    }

    if (! ok) {
      for (e = p, p = values;  p < e;  ++p) {
        if (p->_value != 0) {
          TRI_Free(shaper->_memoryZone, p->_value);
        }
      }

      TRI_Free(shaper->_memoryZone, values);
      return false;
    }

    total += p->_size;

    // count fixed and variable sized values
    if (p->_fixedSized) {
      ++f;
    }
    else {
      ++v;
    }
  }

  n = f + v;

  // add variable offset table size
  total += (v + 1) * sizeof(TRI_shape_size_t);

  // now sort the shape entries
  TRI_SortShapeValues(values, n);

#ifdef DEBUG_JSON_SHAPER
  printf("shape values\n------------\ntotal: %u, fixed: %u, variable: %u\n",
         (unsigned int) n,
         (unsigned int) f,
         (unsigned int) v);
  PrintShapeValues(values, n);
  printf("\n");
#endif

  // generate shape structure
  i =
    sizeof(TRI_array_shape_t)
    + n * sizeof(TRI_shape_sid_t)
    + n * sizeof(TRI_shape_aid_t)
    + (f + 1) * sizeof(TRI_shape_size_t);

  a = (TRI_array_shape_t*) (ptr = (char*) TRI_Allocate(shaper->_memoryZone, i, true));

  if (ptr == NULL) {
    e = values + n;

    for (p = values;  p < e;  ++p) {
      if (p->_value != NULL) {
        TRI_Free(shaper->_memoryZone, p->_value);
      }
    }

    TRI_Free(shaper->_memoryZone, values);

    return false;
  }

  a->base._type = TRI_SHAPE_ARRAY;
  a->base._size = i;
  a->base._dataSize = (v == 0) ? total : TRI_SHAPE_SIZE_VARIABLE;

  a->_fixedEntries = f;
  a->_variableEntries = v;

  ptr += sizeof(TRI_array_shape_t);

  // array of shape identifiers
  sids = (TRI_shape_sid_t*) ptr;
  ptr += n * sizeof(TRI_shape_sid_t);

  // array of attribute identifiers
  aids = (TRI_shape_aid_t*) ptr;
  ptr += n * sizeof(TRI_shape_aid_t);

  // array of offsets for fixed part (within the shape)
  offset = (v + 1) * sizeof(TRI_shape_size_t);
  offsetsF = (TRI_shape_size_t*) ptr;

  // fill destination (except sid)
  dst->_type = TRI_SHAPE_ARRAY;

  dst->_fixedSized = true;
  dst->_size = total;
  dst->_value = (ptr = (char*) TRI_Allocate(shaper->_memoryZone, dst->_size, true));

  if (ptr == NULL) {
    e = values + n;

    for (p = values;  p < e;  ++p) {
      if (p->_value != NULL) {
        TRI_Free(shaper->_memoryZone, p->_value);
      }
    }

    TRI_Free(shaper->_memoryZone, values);
    TRI_Free(shaper->_memoryZone, a);

    return false;
  }

  // array of offsets for variable part (within the value)
  offsetsV = (TRI_shape_size_t*) ptr;
  ptr += (v + 1) * sizeof(TRI_shape_size_t);

  // and fill in attributes
  e = values + n;

  for (p = values;  p < e;  ++p) {
    *aids++ = p->_aid;
    *sids++ = p->_sid;

    memcpy(ptr, p->_value, p->_size);
    ptr += p->_size;

    dst->_fixedSized &= p->_fixedSized;

    if (p->_fixedSized) {
      *offsetsF++ = offset;
      offset += p->_size;
      *offsetsF = offset;
    }
    else {
      *offsetsV++ = offset;
      offset += p->_size;
      *offsetsV = offset;
    }
  }

  // free TRI_shape_value_t array
  for (p = values;  p < e;  ++p) {
    if (p->_value != 0) {
      TRI_Free(shaper->_memoryZone, p->_value);
    }
  }

  TRI_Free(shaper->_memoryZone, values);

  // lookup this shape
  found = shaper->findShape(shaper, &a->base);

  if (found == 0) {
    TRI_Free(shaper->_memoryZone, a);
    return false;
  }

  // and finally add the sid
  dst->_sid = found->_sid;
  return true;
}