示例#1
0
String uint16StrToStr(v8::Handle<v8::String> toDeserialize)
{
    uint16* toReadArray = new uint16[toDeserialize->Length()];
    char* binArray = new char[toDeserialize->Length()];

    toDeserialize->Write(toReadArray,0, toDeserialize->Length());

    for (int s=0; s < toDeserialize->Length(); ++s)
        binArray[s] = (char)(toReadArray[s]);

    String returner (binArray, toDeserialize->Length());

    delete[] toReadArray;
    delete[] binArray;
    return returner;
}
jarray TypeConverter::jsArrayToJavaArray(v8::Handle<v8::Array> jsArray)
{
	JNIEnv *env = JNIScope::getEnv();
	if (env == NULL) {
		return NULL;
	}
	
	int arrayLength = jsArray->Length();
	jobjectArray javaArray = env->NewObjectArray(arrayLength, JNIUtil::objectClass, NULL);
	if (javaArray == NULL) {
		LOGE(TAG, "unable to create new jobjectArray");
		return NULL;
	}

	for (int i = 0; i < arrayLength; i++) {
		v8::Local<v8::Value> element = jsArray->Get(i);
		bool isNew;

		jobject javaObject = jsValueToJavaObject(element, &isNew);
		env->SetObjectArrayElement(javaArray, i, javaObject);

		if (isNew) {
			env->DeleteLocalRef(javaObject);
		}
	}

	return javaArray;
}
示例#3
0
 static String fromV8String(v8::Handle<v8::String> v8String, int length)
 {
     ASSERT(v8String->Length() == length);
     // NOTE: as of now, String(const UChar*, int) performs String::createUninitialized
     // anyway, so no need to optimize like we do for AtomicString below.
     UChar* buffer;
     String result = String::createUninitialized(length, buffer);
     v8String->Write(reinterpret_cast<uint16_t*>(buffer), 0, length);
     return result;
 }
示例#4
0
static Value v8ValueToValue(v8::Handle<v8::Value> v8Value)
{
    v8::HandleScope scope;
    if (v8Value->IsArray()) {
        List<Value> value;
        const v8::Handle<v8::Array> v8Array = v8::Handle<v8::Array>::Cast(v8Value);
        const uint32_t size = v8Array->Length();
        for (uint32_t i = 0; i < size; ++i) {
            if (v8Array->Has(i))
                value.append(v8ValueToValue(v8Array->Get(i)));
            else
                value.append(Value());
        }
        return Value(value);
    } else if (v8Value->IsObject()) {
        Map<String, Value> value;
        const v8::Handle<v8::Object> v8Object = v8Value->ToObject();
        const v8::Handle<v8::Array> props = v8Object->GetPropertyNames();
        const uint32_t size = props->Length();
        for (uint32_t i = 0; i < size; ++i) {
            assert(props->Has(i));
            const v8::Handle<v8::Value> name = props->Get(i);
            value[String(*v8::String::Utf8Value(name))] = v8ValueToValue(v8Object->Get(name));
        }
        return Value(value);
    } else if (v8Value->IsBoolean()) {
        return Value(v8Value->BooleanValue());
    } else if (v8Value->IsInt32() || v8Value->IsUint32()) {
        return Value(v8Value->Int32Value());
    } else if (v8Value->IsNumber()) {
        return Value(v8Value->NumberValue());
    } else if (v8Value->IsString()) {
        return Value(String(*v8::String::Utf8Value(v8Value)));
    } else {
        error() << "Unexpected v8 value type in JSONParser";
    }
    // undefined or null?
    return Value();
}
示例#5
0
 static AtomicString fromV8String(v8::Handle<v8::String> v8String, int length)
 {
     ASSERT(v8String->Length() == length);
     static const int inlineBufferSize = 16;
     if (length <= inlineBufferSize) {
         UChar inlineBuffer[inlineBufferSize];
         v8String->Write(reinterpret_cast<uint16_t*>(inlineBuffer), 0, length);
         return AtomicString(inlineBuffer, length);
     }
     UChar* buffer;
     String tmp = String::createUninitialized(length, buffer);
     v8String->Write(reinterpret_cast<uint16_t*>(buffer), 0, length);
     return AtomicString(tmp);
 }
示例#6
0
// Helper function to create an NPN String Identifier from a v8 string.
NPIdentifier GetStringIdentifier(v8::Handle<v8::String> str) {
  const int kStackBufSize = 100;

  int buf_len = str->Length() + 1;
  if (buf_len <= kStackBufSize) {
    // Use local stack buffer to avoid heap allocations for small strings.
    // Here we should only use the stack space for stack_buf when it's used,
    // not when we use the heap.
    char stack_buf[kStackBufSize];
    str->WriteAscii(stack_buf);
    return NPN_GetStringIdentifier(stack_buf);
  }

  scoped_array<char> heap_buf(new char[buf_len]);
  str->WriteAscii(heap_buf.get());
  return NPN_GetStringIdentifier(heap_buf.get());
}
jdoubleArray TypeConverter::jsArrayToJavaDoubleArray(JNIEnv *env, v8::Handle<v8::Array> jsArray)
{
	int arrayLength = jsArray->Length();
	jdoubleArray javaDoubleArray = env->NewDoubleArray(arrayLength);
	if (javaDoubleArray == NULL) {
		LOGE(TAG, "unable to create new jdoubleArray");
		return NULL;
	}

	jdouble* doubleBuffer = new jdouble[arrayLength];
	for (int i = 0; i < arrayLength; i++) {
		v8::Local<v8::Value> element = jsArray->Get(i);
		doubleBuffer[i] = TypeConverter::jsNumberToJavaDouble(element->ToNumber());
	}
	env->SetDoubleArrayRegion(javaDoubleArray, 0, arrayLength, doubleBuffer);

	return javaDoubleArray;
}
示例#8
0
v8::Local<v8::Script> V8ScriptRunner::compileScript(v8::Handle<v8::String> code, const String& fileName, const TextPosition& scriptStartPosition, ScriptResource* resource, v8::Isolate* isolate, AccessControlStatus corsStatus)
{
    // A pseudo-randomly chosen ID used to store and retrieve V8 ScriptData from
    // the ScriptResource. If the format changes, this ID should be changed too.
    static const unsigned dataTypeID = 0xECC13BD7;

    // Very small scripts are not worth the effort to store cached data.
    static const int minLengthForCachedData = 1024;

    TRACE_EVENT0("v8", "v8.compile");
    TRACE_EVENT_SCOPED_SAMPLING_STATE("V8", "V8Compile");

    // NOTE: For compatibility with WebCore, ScriptSourceCode's line starts at
    // 1, whereas v8 starts at 0.
    v8::Handle<v8::String> name = v8String(isolate, fileName);
    v8::Handle<v8::Integer> line = v8::Integer::New(isolate, scriptStartPosition.m_line.zeroBasedInt());
    v8::Handle<v8::Integer> column = v8::Integer::New(isolate, scriptStartPosition.m_column.zeroBasedInt());
    v8::Handle<v8::Boolean> isSharedCrossOrigin = corsStatus == SharableCrossOrigin ? v8::True(isolate) : v8::False(isolate);
    v8::ScriptOrigin origin(name, line, column, isSharedCrossOrigin);

    v8::ScriptCompiler::CompileOptions options = v8::ScriptCompiler::kNoCompileOptions;
    OwnPtr<v8::ScriptCompiler::CachedData> cachedData;
    if (resource) {
        CachedMetadata* cachedMetadata = resource->cachedMetadata(dataTypeID);
        if (cachedMetadata) {
            // Ownership of the buffer is not transferred to CachedData.
            cachedData = adoptPtr(new v8::ScriptCompiler::CachedData(reinterpret_cast<const uint8_t*>(cachedMetadata->data()), cachedMetadata->size()));
        } else if (code->Length() >= minLengthForCachedData) {
            options = v8::ScriptCompiler::kProduceDataToCache;
        }
    }
    // source takes ownership of cachedData.
    v8::ScriptCompiler::Source source(code, origin, cachedData.leakPtr());
    v8::Local<v8::Script> script = v8::ScriptCompiler::Compile(isolate, &source, options);
    if (options == v8::ScriptCompiler::kProduceDataToCache) {
        const v8::ScriptCompiler::CachedData* newCachedData = source.GetCachedData();
        if (newCachedData) {
            // Ownership of the buffer is not transferred; source's cachedData continues to own it.
            resource->setCachedMetadata(dataTypeID, reinterpret_cast<const char*>(newCachedData->data), newCachedData->length);
        }
    }
    return script;
}
jobjectArray TypeConverter::jsArrayToJavaStringArray(JNIEnv *env, v8::Handle<v8::Array> jsArray)
{
	int arrayLength = jsArray->Length();
	jobjectArray javaArray = env->NewObjectArray(arrayLength, JNIUtil::stringClass, NULL);
	if (javaArray == NULL) {
		LOGE(TAG, "unable to create new jobjectArray");
		return NULL;
	}

	for (int i = 0; i < arrayLength; i++) {
		v8::Local<v8::Value> element = jsArray->Get(i);
		jstring javaObject = jsStringToJavaString(env, element->ToString());
		env->SetObjectArrayElement(javaArray, i, javaObject);

		env->DeleteLocalRef(javaObject);
	}

	return javaArray;
}
std::vector<BaseIndicator *> IndicatorFactory::CreateFromArray(v8::Handle<v8::Array> array)
{
	unsigned indicatorCount = array->Length();
	std::vector<std::string> indicatorNames;

	for (unsigned i = 0; i < indicatorCount; i++)
	{
		indicatorNames.push_back(std::string(*v8::String::Utf8Value(array->Get(i)->ToString())));
	}

	std::vector<BaseIndicator *> indicators;

	for (unsigned long i = 0; i < indicatorNames.size(); i++)
	{
		BaseIndicator* indicator = IndicatorFactory::Create(indicatorNames[i]);
		indicators.push_back(indicator);
	}

	return indicators;
}
StringType v8StringToWebCoreString(v8::Handle<v8::String> v8String, ExternalMode external)
{
    WebCoreStringResource* stringResource = WebCoreStringResource::toStringResource(v8String);
    if (stringResource)
        return StringTraits<StringType>::fromStringResource(stringResource);

    int length = v8String->Length();
    if (!length)
        return String("");

    StringType result(StringTraits<StringType>::fromV8String(v8String, length));

    if (external == Externalize && v8String->CanMakeExternal()) {
        stringResource = new WebCoreStringResource(result);
        if (!v8String->MakeExternal(stringResource)) {
            // In case of a failure delete the external resource as it was not used.
            delete stringResource;
        }
    }
    return result;
}
示例#12
0
PassOwnPtr<v8::ScriptData> V8Proxy::precompileScript(v8::Handle<v8::String> code, CachedScript* cachedScript)
{
    // A pseudo-randomly chosen ID used to store and retrieve V8 ScriptData from
    // the CachedScript. If the format changes, this ID should be changed too.
    static const unsigned dataTypeID = 0xECC13BD7;

    // Very small scripts are not worth the effort to preparse.
    static const int minPreparseLength = 1024;

    if (!cachedScript || code->Length() < minPreparseLength)
        return 0;

    CachedMetadata* cachedMetadata = cachedScript->cachedMetadata(dataTypeID);
    if (cachedMetadata)
        return v8::ScriptData::New(cachedMetadata->data(), cachedMetadata->size());

    OwnPtr<v8::ScriptData> scriptData(v8::ScriptData::PreCompile(code));
    cachedScript->setCachedMetadata(dataTypeID, scriptData->Data(), scriptData->Length());

    return scriptData.release();
}
示例#13
0
jintArray TypeConverter::jsArrayToJavaIntArray(v8::Handle<v8::Array> jsArray)
{
	JNIEnv *env = JNIScope::getEnv();
	if (env == NULL) {
		return NULL;
	}

	int arrayLength = jsArray->Length();
	jintArray javaIntArray = env->NewIntArray(arrayLength);
	if (javaIntArray == NULL) {
		LOGE(TAG, "unable to create new jintArray");
		return NULL;
	}

	jint* intBuffer = new jint[arrayLength];
	for (int i = 0; i < arrayLength; i++) {
		v8::Local<v8::Value> element = jsArray->Get(i);
		intBuffer[i] = TypeConverter::jsNumberToJavaInt(element->ToNumber());
	}
	env->SetIntArrayRegion(javaIntArray, 0, arrayLength, intBuffer);

	return javaIntArray;
}
示例#14
0
StringType v8StringToWebCoreString(v8::Handle<v8::String> v8String, ExternalMode external)
{
    WebCoreStringResource* stringResource = WebCoreStringResource::toStringResource(v8String);
    if (stringResource)
        return StringTraits<StringType>::fromStringResource(stringResource);

    int length = v8String->Length();
    if (!length) {
        // Avoid trying to morph empty strings, as they do not have enough room to contain the external reference.
        return StringImpl::empty();
    }

    StringType result(StringTraits<StringType>::fromV8String(v8String, length));

    if (external == Externalize && v8String->CanMakeExternal()) {
        stringResource = new WebCoreStringResource(result);
        if (!v8String->MakeExternal(stringResource)) {
            // In case of a failure delete the external resource as it was not used.
            delete stringResource;
        }
    }
    return result;
}
示例#15
0
StringType v8StringToWebCoreString(v8::Handle<v8::String> v8String, ExternalMode external)
{
    {
        // This portion of this function is very hot in certain Dromeao benchmarks.
        v8::String::Encoding encoding;
        v8::String::ExternalStringResourceBase* resource = v8String->GetExternalStringResourceBase(&encoding);
        if (LIKELY(!!resource)) {
            WebCoreStringResourceBase* base;
            if (encoding == v8::String::ONE_BYTE_ENCODING)
                base = static_cast<WebCoreStringResource8*>(resource);
            else
                base = static_cast<WebCoreStringResource16*>(resource);
            return StringTraits<StringType>::fromStringResource(base);
        }
    }

    int length = v8String->Length();
    if (UNLIKELY(!length))
        return StringType("");

    bool oneByte = v8String->ContainsOnlyOneByte();
    StringType result(oneByte ? StringTraits<StringType>::template fromV8String<V8StringOneByteTrait>(v8String, length) : StringTraits<StringType>::template fromV8String<V8StringTwoBytesTrait>(v8String, length));

    if (external != Externalize || !v8String->CanMakeExternal())
        return result;

    if (result.is8Bit()) {
        WebCoreStringResource8* stringResource = new WebCoreStringResource8(result);
        if (UNLIKELY(!v8String->MakeExternal(stringResource)))
            delete stringResource;
    } else {
        WebCoreStringResource16* stringResource = new WebCoreStringResource16(result);
        if (UNLIKELY(!v8String->MakeExternal(stringResource)))
            delete stringResource;
    }
    return result;
}
示例#16
0
static int FillShapeValueList (v8::Isolate* isolate,
                               VocShaper* shaper,
                               TRI_shape_value_t* dst,
                               v8::Handle<v8::Array> const json,
                               size_t level,
                               set<int>& seenHashes,
                               vector<v8::Handle<v8::Object>>& seenObjects,
                               bool create) {
  size_t total;

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

  bool hs;
  bool hl;

  TRI_shape_sid_t s;
  TRI_shape_sid_t l;

  TRI_shape_size_t* offsets;
  TRI_shape_size_t offset;

  TRI_shape_t const* found;

  char* ptr;

  // check for special case "empty list"
  uint32_t n = json->Length();

  if (n == 0) {
    dst->_type = TRI_SHAPE_LIST;
    dst->_sid = BasicShapes::TRI_SHAPE_SID_LIST;
    dst->_fixedSized = false;
    dst->_size = sizeof(TRI_shape_length_list_t);
    dst->_value = (ptr = static_cast<char*>(TRI_Allocate(shaper->memoryZone(), dst->_size, false)));

    if (dst->_value == nullptr) {
      return TRI_ERROR_OUT_OF_MEMORY;
    }

    * (TRI_shape_length_list_t*) ptr = 0;

    return TRI_ERROR_NO_ERROR;
  }

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

  if (p == nullptr) {
    return TRI_ERROR_OUT_OF_MEMORY;
  }

  total = 0;
  e = values + n;

  for (uint32_t i = 0;  i < n;  ++i, ++p) {
    v8::Handle<v8::Value> el = json->Get(i);
    int res = FillShapeValueJson(isolate, shaper, p, el, 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);
  }

  // check if this list is homoegenous
  hs = true;
  hl = true;

  s = values[0]._sid;
  l = values[0]._size;
  p = values;

  for (;  p < e;  ++p) {
    if (p->_sid != s) {
      hs = false;
      break;
    }

    if (p->_size != l) {
      hl = false;
    }
  }

  // homogeneous sized
  if (hs && hl) {
    auto shape = static_cast<TRI_homogeneous_sized_list_shape_t*>(TRI_Allocate(shaper->memoryZone(), sizeof(TRI_homogeneous_sized_list_shape_t), true));

    if (shape == nullptr) {
      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;
    }

    shape->base._size = sizeof(TRI_homogeneous_sized_list_shape_t);
    shape->base._type = TRI_SHAPE_HOMOGENEOUS_SIZED_LIST;
    shape->base._dataSize = TRI_SHAPE_SIZE_VARIABLE;
    shape->_sidEntry = s;
    shape->_sizeEntry = l;

    found = shaper->findShape(&shape->base, create);

    if (found == nullptr) {
      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(), shape);

      LOG_TRACE("shaper failed to find shape of type %d", (int) shape->base._type);

      if (! create) {
        return TRI_RESULT_ELEMENT_NOT_FOUND;
      }

      return TRI_ERROR_INTERNAL;
    }

    TRI_ASSERT(found != nullptr);

    dst->_type = found->_type;
    dst->_sid = found->_sid;

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

    if (dst->_value == nullptr) {
      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;
    }

    // copy sub-objects into data space
    * (TRI_shape_length_list_t*) ptr = (TRI_shape_length_list_t) n;
    ptr += sizeof(TRI_shape_length_list_t);

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

  // homogeneous
  else if (hs) {
    auto shape = static_cast<TRI_homogeneous_list_shape_t*>(TRI_Allocate(shaper->memoryZone(), sizeof(TRI_homogeneous_list_shape_t), true));

    if (shape == nullptr) {
      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;
    }

    shape->base._size = sizeof(TRI_homogeneous_list_shape_t);
    shape->base._type = TRI_SHAPE_HOMOGENEOUS_LIST;
    shape->base._dataSize = TRI_SHAPE_SIZE_VARIABLE;
    shape->_sidEntry = s;

    // if found returns non-NULL, it will free the shape!!
    found = shaper->findShape(&shape->base, create);

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

      LOG_TRACE("shaper failed to find shape %d", (int) shape->base._type);

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

      if (! create) {
        return TRI_RESULT_ELEMENT_NOT_FOUND;
      }

      return TRI_ERROR_INTERNAL;
    }

    TRI_ASSERT(found != nullptr);

    dst->_type = found->_type;
    dst->_sid = found->_sid;

    offset = sizeof(TRI_shape_length_list_t) + (n + 1) * sizeof(TRI_shape_size_t);

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

    if (dst->_value == nullptr) {
      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;
    }

    // copy sub-objects into data space
    * (TRI_shape_length_list_t*) ptr = (TRI_shape_length_list_t) n;
    ptr += sizeof(TRI_shape_length_list_t);

    offsets = (TRI_shape_size_t*) ptr;
    ptr += (n + 1) * sizeof(TRI_shape_size_t);

    for (p = values;  p < e;  ++p) {
      *offsets++ = offset;
      offset += p->_size;

      if (p->_value != nullptr) {
        memcpy(ptr, p->_value, static_cast<size_t>(p->_size));
      }
      ptr += p->_size;
    }

    *offsets = offset;
  }

  // in-homogeneous
  else {
    dst->_type = TRI_SHAPE_LIST;
    dst->_sid = BasicShapes::TRI_SHAPE_SID_LIST;

    offset =
      sizeof(TRI_shape_length_list_t)
      + n * sizeof(TRI_shape_sid_t)
      + (n + 1) * sizeof(TRI_shape_size_t);

    dst->_fixedSized = false;
    dst->_size = offset + total;
    dst->_value = (ptr = (char*) TRI_Allocate(shaper->memoryZone(), dst->_size, true));

    if (dst->_value == nullptr) {
      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;
    }

    // copy sub-objects into data space
    * (TRI_shape_length_list_t*) ptr = (TRI_shape_length_list_t) n;
    ptr += sizeof(TRI_shape_length_list_t);

    TRI_shape_sid_t* sids = (TRI_shape_sid_t*) ptr;
    ptr += n * sizeof(TRI_shape_sid_t);

    offsets = (TRI_shape_size_t*) ptr;
    ptr += (n + 1) * sizeof(TRI_shape_size_t);

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

      *offsets++ = offset;
      offset += p->_size;

      if (p->_value != nullptr) {
        memcpy(ptr, p->_value, static_cast<size_t>(p->_size));
      }
      ptr += p->_size;
    }

    *offsets = 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);
  return TRI_ERROR_NO_ERROR;
}
示例#17
0
unsigned JS_GetArrayLength(v8::Handle<v8::Array> pArray)
{
	if(pArray.IsEmpty()) return 0;
	return pArray->Length();
}
示例#18
0
static bool FillShapeValueList (TRI_shaper_t* shaper,
                                TRI_shape_value_t* dst,
                                v8::Handle<v8::Array> json,
                                set<int>& seenHashes,
                                vector< v8::Handle<v8::Object> >& seenObjects) {
  size_t i;
  size_t n;
  size_t total;

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

  bool hs;
  bool hl;

  TRI_shape_sid_t s;
  TRI_shape_sid_t l;

  TRI_shape_sid_t* sids;
  TRI_shape_size_t* offsets;
  TRI_shape_size_t offset;

  TRI_shape_t const* found;

  char* ptr;

  // check for special case "empty list"
  n = json->Length();

  if (n == 0) {
    dst->_type = TRI_SHAPE_LIST;
    dst->_sid = shaper->_sidList;

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

    if (dst->_value == NULL) {
      return false;
    }

    * (TRI_shape_length_list_t*) ptr = 0;

    return true;
  }

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

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

  memset(values, 0, sizeof(TRI_shape_value_t) * n);

  total = 0;
  e = values + n;

  for (i = 0;  i < n;  ++i, ++p) {
    v8::Local<v8::Value> el = json->Get(i);
    bool ok = FillShapeValueJson(shaper, p, el, 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;
  }

  // check if this list is homoegenous
  hs = true;
  hl = true;

  s = values[0]._sid;
  l = values[0]._size;
  p = values;

  for (;  p < e;  ++p) {
    if (p->_sid != s) {
      hs = false;
      break;
    }

    if (p->_size != l) {
      hl = false;
    }
  }

  // homogeneous sized
  if (hs && hl) {
    TRI_homogeneous_sized_list_shape_t* shape;

    shape = (TRI_homogeneous_sized_list_shape_t*) TRI_Allocate(shaper->_memoryZone, sizeof(TRI_homogeneous_sized_list_shape_t), true);

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

      TRI_Free(shaper->_memoryZone, values);

      return false;
    }

    shape->base._size = sizeof(TRI_homogeneous_sized_list_shape_t);
    shape->base._type = TRI_SHAPE_HOMOGENEOUS_SIZED_LIST;
    shape->base._dataSize = TRI_SHAPE_SIZE_VARIABLE;
    shape->_sidEntry = s;
    shape->_sizeEntry = l;

    found = shaper->findShape(shaper, &shape->base);

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

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

      return false;
    }

    dst->_type = found->_type;
    dst->_sid = found->_sid;

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

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

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

      return false;
    }

    // copy sub-objects into data space
    * (TRI_shape_length_list_t*) ptr = n;
    ptr += sizeof(TRI_shape_length_list_t);

    for (p = values;  p < e;  ++p) {
      memcpy(ptr, p->_value, p->_size);
      ptr += p->_size;
    }
  }

  // homogeneous
  else if (hs) {
    TRI_homogeneous_list_shape_t* shape;

    shape = (TRI_homogeneous_list_shape_t*) TRI_Allocate(shaper->_memoryZone, sizeof(TRI_homogeneous_list_shape_t), true);

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

      TRI_Free(shaper->_memoryZone, values);

      return false;
    }

    shape->base._size = sizeof(TRI_homogeneous_list_shape_t);
    shape->base._type = TRI_SHAPE_HOMOGENEOUS_LIST;
    shape->base._dataSize = TRI_SHAPE_SIZE_VARIABLE;
    shape->_sidEntry = s;

    found = shaper->findShape(shaper, &shape->base);

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

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

      return false;
    }

    dst->_type = found->_type;
    dst->_sid = found->_sid;

    offset = sizeof(TRI_shape_length_list_t) + (n + 1) * sizeof(TRI_shape_size_t);

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

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

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

      return false;
    }

    // copy sub-objects into data space
    * (TRI_shape_length_list_t*) ptr = n;
    ptr += sizeof(TRI_shape_length_list_t);

    offsets = (TRI_shape_size_t*) ptr;
    ptr += (n + 1) * sizeof(TRI_shape_size_t);

    for (p = values;  p < e;  ++p) {
      *offsets++ = offset;
      offset += p->_size;

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

    *offsets = offset;
  }

  // in-homogeneous
  else {
    dst->_type = TRI_SHAPE_LIST;
    dst->_sid = shaper->_sidList;

    offset =
      sizeof(TRI_shape_length_list_t)
      + n * sizeof(TRI_shape_sid_t)
      + (n + 1) * sizeof(TRI_shape_size_t);

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

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

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

    // copy sub-objects into data space
    * (TRI_shape_length_list_t*) ptr = n;
    ptr += sizeof(TRI_shape_length_list_t);

    sids = (TRI_shape_sid_t*) ptr;
    ptr += n * sizeof(TRI_shape_sid_t);

    offsets = (TRI_shape_size_t*) ptr;
    ptr += (n + 1) * sizeof(TRI_shape_size_t);

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

      *offsets++ = offset;
      offset += p->_size;

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

    *offsets = 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);
  return true;
}