コード例 #1
0
ファイル: enum-cache.cpp プロジェクト: swtaarrs/hhvm
const EnumValues* EnumCache::loadEnumValues(const Class* klass,
                                            bool recurse) {
  auto const numConstants = klass->numConstants();
  auto values = Array::CreateDArray();
  auto names = Array::CreateDArray();
  auto const consts = klass->constants();
  bool persist = true;
  for (size_t i = 0; i < numConstants; i++) {
    if (consts[i].isAbstract() || consts[i].isType()) {
      continue;
    }
    if (consts[i].cls != klass && !recurse) {
      continue;
    }
    Cell value = consts[i].val;
    // Handle dynamically set constants
    if (value.m_type == KindOfUninit) {
      persist = false;
      value = klass->clsCnsGet(consts[i].name);
    }
    assertx(value.m_type != KindOfUninit);
    if (UNLIKELY(!(isIntType(value.m_type) || tvIsString(&value)))) {
      // only int and string values allowed for enums.
      std::string msg;
      msg += klass->name()->data();
      msg += " enum can only contain string and int values";
      EnumCache::failLookup(msg);
    }
    values.set(StrNR(consts[i].name), cellAsCVarRef(value));

    // Manually perform int-like key coercion even if names is a dict for
    // backwards compatibility.
    int64_t n;
    if (tvIsString(&value) && value.m_data.pstr->isStrictlyInteger(n)) {
      names.set(n, make_tv<KindOfPersistentString>(consts[i].name));
    } else {
      names.set(value, make_tv<KindOfPersistentString>(consts[i].name), true);
    }
  }

  assertx(names.isDictOrDArray());
  assertx(values.isDictOrDArray());

  // If we saw dynamic constants we cannot cache the enum values across requests
  // as they may not be the same in every request.
  return persist
    ? cachePersistentEnumValues(
      klass,
      recurse,
      std::move(names),
      std::move(values))
    : cacheRequestEnumValues(
      klass,
      recurse,
      std::move(names),
      std::move(values));
}
コード例 #2
0
ファイル: ext_wddx.cpp プロジェクト: CryQ/hhvm
void find_var_recursive(const TypedValue* tv, WddxPacket* wddxPacket) {
  if (tvIsString(tv)) {
    String var_name = tvCastToString(tv);
    wddxPacket->add_var(var_name, true);
  }
  if (tv->m_type == KindOfArray) {
    for (ArrayIter iter(tv->m_data.parr); iter; ++iter) {
      find_var_recursive(iter.secondRef().asTypedValue(), wddxPacket);
    }
  }
}
コード例 #3
0
ファイル: ext_wddx.cpp プロジェクト: anthonyattard/hhvm
void find_var_recursive(const TypedValue* tv,
                        const req::ptr<WddxPacket>& wddxPacket) {
  if (tvIsString(tv)) {
    String var_name{tvCastToString(tv)};
    wddxPacket->add_var(var_name, true);
  }
  if (isArrayType(tv->m_type)) {
    for (ArrayIter iter(tv->m_data.parr); iter; ++iter) {
      find_var_recursive(iter.secondRef().asTypedValue(), wddxPacket);
    }
  }
}
コード例 #4
0
ファイル: enum-cache.cpp プロジェクト: aruiz14/hhvm
const EnumCache::EnumValues* EnumCache::loadEnumValues(const Class* klass,
                                                       bool recurse) {
  auto const numConstants = klass->numConstants();
  size_t foundOnClass = 0;
  Array values;
  Array names;
  auto const consts = klass->constants();
  for (size_t i = 0; i < numConstants; i++) {
    if (consts[i].isAbstract() || consts[i].isType()) {
      continue;
    }
    if (consts[i].m_class == klass) foundOnClass++;
    else if (!recurse) continue;
    Cell value = consts[i].m_val;
    // Handle dynamically set constants
    if (value.m_type == KindOfUninit) {
      value = klass->clsCnsGet(consts[i].m_name);
    }
    assert(value.m_type != KindOfUninit);
    if (UNLIKELY(!(isIntType(value.m_type) ||
        (tvIsString(&value) && value.m_data.pstr->isStatic())))) {
      // only int and string values allowed for enums. Moreover the strings
      // must be static
      std::string msg;
      msg += klass->name()->data();
      msg += " enum can only contain static string and int values";
      EnumCache::failLookup(msg);
    }
    values.set(StrNR(consts[i].m_name), cellAsCVarRef(value));
    names.set(cellAsCVarRef(value), VarNR(consts[i].m_name));
  }
  if (UNLIKELY(foundOnClass == 0)) {
    std::string msg;
    msg += klass->name()->data();
    msg += " enum must contain values";
    EnumCache::failLookup(msg);
  }

  {
    std::unique_ptr<EnumCache::EnumValues> enums(new EnumCache::EnumValues());
    enums->values = ArrayData::GetScalarArray(values.get());
    enums->names = ArrayData::GetScalarArray(names.get());

    intptr_t key = getKey(klass, recurse);
    EnumValuesMap::accessor acc;
    if (!m_enumValuesMap.insert(acc, key)) {
      return acc->second;
    }
    // add to the map the newly created values
    acc->second = enums.release();
    return acc->second;
  }
}
コード例 #5
0
ファイル: enum-cache.cpp プロジェクト: smcshaner/hhvm
const EnumValues* EnumCache::loadEnumValues(const Class* klass,
                                            bool recurse) {
  auto const numConstants = klass->numConstants();
  auto values = Array::Create();
  auto names = Array::Create();
  auto const consts = klass->constants();
  bool persist = true;
  for (size_t i = 0; i < numConstants; i++) {
    if (consts[i].isAbstract() || consts[i].isType()) {
      continue;
    }
    if (consts[i].cls != klass && !recurse) {
      continue;
    }
    Cell value = consts[i].val;
    // Handle dynamically set constants
    if (value.m_type == KindOfUninit) {
      persist = false;
      value = klass->clsCnsGet(consts[i].name);
    }
    assert(value.m_type != KindOfUninit);
    if (UNLIKELY(!(isIntType(value.m_type) ||
        (tvIsString(&value) && value.m_data.pstr->isStatic())))) {
      // only int and string values allowed for enums. Moreover the strings
      // must be static
      std::string msg;
      msg += klass->name()->data();
      msg += " enum can only contain static string and int values";
      EnumCache::failLookup(msg);
    }
    values.set(StrNR(consts[i].name), cellAsCVarRef(value));
    names.set(value, make_tv<KindOfPersistentString>(consts[i].name));
  }

  // If we saw dynamic constants we cannot cache the enum values across requests
  // as they may not be the same in every request.
  return persist
    ? cachePersistentEnumValues(
      klass,
      recurse,
      std::move(names),
      std::move(values))
    : cacheRequestEnumValues(
      klass,
      recurse,
      std::move(names),
      std::move(values));
}