Beispiel #1
0
static Variant xml_call_handler(XmlParser *parser, CVarRef handler,
                                CArrRef args) {
  if (parser && handler) {
    Variant retval;
    if (handler.isString()) {
      if (!parser->object.isObject()) {
        retval = invoke(handler.toString().c_str(), args, -1);
      } else {
        retval = parser->object.toObject()->
          o_invoke(handler.toString(), args, -1);
      }
    } else if (handler.isArray() && handler.getArrayData()->size() == 2 &&
               (handler[0].isString() || handler[0].isObject()) &&
               handler[1].isString()) {
      if (handler[0].isString()) {
        // static method
        retval = ObjectData::os_invoke(handler[0].toString(),
                                       handler[1].toString(), args, -1);
      } else {
        // instance method
        retval = handler[0].toObject()->o_invoke(handler[1].toString(),
                                                 args, -1);
      }
    } else {
      raise_warning("Handler is invalid");
    }
    return retval;
  }
  return null;
}
Beispiel #2
0
bool ArrayData::hasInternalReference(PointerSet &vars) const {
  if (supportValueRef()) {
    for (ArrayIter iter(this); iter; ++iter) {
      CVarRef var = iter.secondRef();
      if (var.isReferenced()) {
        Variant *pvar = var.getVariantData();
        if (vars.find(pvar) != vars.end()) {
          return true;
        }
        vars.insert(pvar);
      }
      if (var.isObject()) {
        ObjectData *pobj = var.getObjectData();
        if (vars.find(pobj) != vars.end()) {
          return true;
        }
        vars.insert(pobj);

        if (pobj->o_toArray().get()->hasInternalReference(vars)) {
          return true;
        }
      } else if (var.isArray() &&
                 var.getArrayData()->hasInternalReference(vars)) {
        return true;
      }
    }
  }
  return false;
}
Beispiel #3
0
bool ArrayData::hasInternalReference(PointerSet &vars,
                                     bool ds /* = false */) const {
  if (isSharedMap()) return false;
  for (ArrayIter iter(this); iter; ++iter) {
    CVarRef var = iter.secondRef();
    if (var.isReferenced()) {
      Variant *pvar = var.getRefData();
      if (vars.find(pvar) != vars.end()) {
        return true;
      }
      vars.insert(pvar);
    }
    if (var.isObject()) {
      ObjectData *pobj = var.getObjectData();
      if (vars.find(pobj) != vars.end()) {
        return true;
      }
      vars.insert(pobj);
      if (ds && pobj->o_instanceof("Serializable")) {
        return true;
      }
      if (pobj->hasInternalReference(vars, ds)) {
        return true;
      }
    } else if (var.isArray() &&
               var.getArrayData()->hasInternalReference(vars, ds)) {
      return true;
    }
  }
  return false;
}
Beispiel #4
0
int64_t f_count(CVarRef var, bool recursive /* = false */) {
  switch (var.getType()) {
  case KindOfUninit:
  case KindOfNull:
    return 0;
  case KindOfObject:
    {
      Object obj = var.toObject();
      if (obj->isCollection()) {
        return obj->getCollectionSize();
      }
      if (obj.instanceof(SystemLib::s_CountableClass)) {
        return obj->o_invoke_few_args(s_count, 0).toInt64();
      }
    }
    break;
  case KindOfArray:
    if (recursive) {
      CArrRef arr_var = var.toCArrRef();
      return php_count_recursive(arr_var);
    }
    return var.getArrayData()->size();
  default:
    break;
  }
  return 1;
}
Beispiel #5
0
static void url_encode_array(StringBuffer &ret, CVarRef varr,
                             std::set<void*> &seen_arrs,
                             CStrRef num_prefix, CStrRef key_prefix,
                             CStrRef key_suffix, CStrRef arg_sep) {
  void *id = varr.is(KindOfArray) ?
    (void*)varr.getArrayData() : (void*)varr.getObjectData();
  if (!seen_arrs.insert(id).second) {
    return; // recursive
  }

  Array arr = varr.toArray();

  for (ArrayIter iter(arr); iter; ++iter) {
    Variant data = iter.second();
    if (data.isNull() || data.isResource()) continue;

    String key = iter.first();
    bool numeric = key.isNumeric();

    if (data.is(KindOfArray) || data.is(KindOfObject)) {
      String encoded;
      if (numeric) {
        encoded = key;
      } else {
        encoded = StringUtil::UrlEncode(key);
      }
      StringBuffer new_prefix(key_prefix.size() + num_prefix.size() +
                              encoded.size() + key_suffix.size() + 4);
      new_prefix += key_prefix;
      if (numeric) new_prefix += num_prefix;
      new_prefix += encoded;
      new_prefix += key_suffix;
      new_prefix += "%5B";
      url_encode_array(ret, data, seen_arrs, String(),
                       new_prefix.detach(), String("%5D", AttachLiteral),
                       arg_sep);
    } else {
      if (!ret.empty()) {
        ret += arg_sep;
      }
      ret += key_prefix;
      if (numeric) {
        ret += num_prefix;
        ret += key;
      } else {
        ret += StringUtil::UrlEncode(key);
      }
      ret += key_suffix;
      ret += "=";
      if (data.isInteger() || data.is(KindOfBoolean)) {
        ret += String(data.toInt64());
      } else if (data.is(KindOfDouble)) {
        ret += String(data.toDouble());
      } else {
        ret += StringUtil::UrlEncode(data.toString());
      }
    }
  }
}
Beispiel #6
0
bool same(CVarRef v1, CArrRef v2) {
  bool null1 = v1.isNull();
  bool null2 = v2.isNull();
  if (null1 && null2) return true;
  if (null1 || null2) return false;
  if (!v1.isArray()) return false;
  auto const ad = v1.getArrayData();
  return v2->equal(ad, true);
}
Beispiel #7
0
static void xml_set_handler(Variant * handler, CVarRef data) {
  if (same(data, false) || data.isString() ||
      (data.isArray() && data.getArrayData()->size() == 2 &&
       (data[0].isString() || data[0].isObject()) &&
       data[1].isString())) {
    *handler = data;
  } else {
    raise_warning("Handler is invalid");
  }
}
Beispiel #8
0
static void compact(HPHP::VM::VarEnv* v, Array &ret, CVarRef var) {
  if (var.isArray()) {
    for (ArrayIter iter(var.getArrayData()); iter; ++iter) {
      compact(v, ret, iter.second());
    }
  } else {
    String varname = var.toString();
    if (!varname.empty() && v->lookup(varname.get()) != NULL) {
      ret.set(varname, *reinterpret_cast<Variant*>(v->lookup(varname.get())));
    }
  }
}
Beispiel #9
0
Array Array::intersect(CVarRef array, bool by_key, bool by_value,
                       PFUNC_CMP key_cmp_function /* = NULL */,
                       const void *key_data /* = NULL */,
                       PFUNC_CMP value_cmp_function /* = NULL */,
                       const void *value_data /* = NULL */) const {
  if (!array.isArray()) {
    throw_bad_array_exception();
    return Array();
  }
  return diffImpl(array.getArrayData(), by_key, by_value, true,
                  key_cmp_function, key_data,
                  value_cmp_function, value_data);
}
Beispiel #10
0
int hphp_ffi_exportVariant(CVarRef v, void** result) {
  switch (v.getType()) {
  case KindOfNull:    return 0;
  case KindOfBoolean: *result = (void*)v.toBoolean(); return 1;
  case KindOfByte:
  case KindOfInt16:
  case KindOfInt32:
  case KindOfInt64: {
    *result = (void*)v.toInt64();
    return 2;
  }
  case KindOfDouble: {
    union {
      double d;
      void* p;
    } u;
    u.d = v.toDouble();
    *result = u.p;
    return 3;
  }
  case LiteralString: *result = (void*)v.getLiteralString(); return 4;
  case KindOfString: {
    StringData *sd = v.getStringData();
    sd->incRefCount();
    *result = (void*)sd;
    return 5;
  }
  case KindOfArray: {
    ArrayData *ad = v.getArrayData();
    ad->incRefCount();
    *result = (void*)ad;
    return 6;
  }
  case KindOfObject: {
    ObjectData *od = v.getObjectData();
    od->incRefCount();
    *result = (void*)od;
    return 7;
  }
  default:
    ASSERT(false);
    return 0;
  }
}
Beispiel #11
0
String f_serialize(CVarRef value) {
  switch (value.getType()) {
  case KindOfUninit:
  case KindOfNull:
    return "N;";
  case KindOfBoolean:
    return value.getBoolean() ? "b:1;" : "b:0;";
  case KindOfInt64: {
    StringBuffer sb;
    sb.append("i:");
    sb.append(value.getInt64());
    sb.append(';');
    return sb.detach();
  }
  case KindOfStaticString:
  case KindOfString: {
    StringData *str = value.getStringData();
    StringBuffer sb;
    sb.append("s:");
    sb.append(str->size());
    sb.append(":\"");
    sb.append(str->data(), str->size());
    sb.append("\";");
    return sb.detach();
  }
  case KindOfArray: {
    ArrayData *arr = value.getArrayData();
    if (arr->empty()) return "a:0:{}";
    // fall-through
  }
  case KindOfObject:
  case KindOfResource:
  case KindOfDouble: {
    VariableSerializer vs(VariableSerializer::Type::Serialize);
    return vs.serialize(value, true);
  }
  default:
    assert(false);
    break;
  }
  return "";
}
Beispiel #12
0
static Variant xml_call_handler(XmlParser *parser, CVarRef handler,
                                CArrRef args) {
  if (parser && handler) {
    Variant retval;
    if (handler.isString()) {
      if (!parser->object.isObject()) {
        retval = invoke(handler.toString().c_str(), args, -1);
      } else {
        retval = parser->object.toObject()->
          o_invoke(handler.toString(), args);
      }
    } else if (handler.isArray() && handler.getArrayData()->size() == 2 &&
               (handler[0].isString() || handler[0].isObject()) &&
               handler[1].isString()) {
      vm_call_user_func(handler, args);
    } else {
      raise_warning("Handler is invalid");
    }
    return retval;
  }
  return uninit_null();
}
Beispiel #13
0
bool ArrayData::hasInternalReference(PointerSet &vars,
                                     bool ds /* = false */) const {
    if (isSharedMap()) return false;
    for (ArrayIter iter(this); iter; ++iter) {
        CVarRef var = iter.secondRef();
        if (var.isReferenced()) {
            Variant *pvar = var.getVariantData();
            if (vars.find(pvar) != vars.end()) {
                return true;
            }
            vars.insert(pvar);
        }
        if (var.isObject()) {
            ObjectData *pobj = var.getObjectData();
            if (vars.find(pobj) != vars.end()) {
                return true;
            }
            vars.insert(pobj);
            if (pobj->o_instanceof("Serializable")) {
                if (ds) {
                    // We want to detect Serializable object as well
                    return true;
                } else {
                    // Serializable object does not have internal reference issue
                    return false;
                }
            }
            if (pobj->o_toArray().get()->hasInternalReference(vars, ds)) {
                return true;
            }
        } else if (var.isArray() &&
                   var.getArrayData()->hasInternalReference(vars, ds)) {
            return true;
        }
    }
    return false;
}
Beispiel #14
0
SharedVariant::SharedVariant(CVarRef source, bool serialized,
                             bool inner /* = false */,
                             bool unserializeObj /* = false */)
  : m_shouldCache(false), m_flags(0) {
  assert(!serialized || source.isString());
  m_count = 1;
  m_type = source.getType();
  switch (m_type) {
  case KindOfBoolean:
    {
      m_data.num = source.toBoolean();
      break;
    }
  case KindOfInt64:
    {
      m_type = KindOfInt64;
      m_data.num = source.toInt64();
      break;
    }
  case KindOfDouble:
    {
      m_data.dbl = source.toDouble();
      break;
    }
  case KindOfStaticString:
    {
      if (serialized) goto StringCase;
      m_data.str = source.getStringData();
      break;
    }
StringCase:
  case KindOfString:
    {
      String s = source.toString();
      if (serialized) {
        m_type = KindOfObject;
        // It is priming, and there might not be the right class definitions
        // for unserialization.
        s = apc_reserialize(s);
      }
      StringData* st = StringData::LookupStaticString(s.get());
      if (st) {
        m_data.str = st;
        m_type = KindOfStaticString;
        break;
      }
      m_data.str = s->copy(true);
      break;
    }
  case KindOfArray:
    {
      ArrayData *arr = source.getArrayData();

      if (!inner) {
        // only need to call hasInternalReference() on the toplevel array
        PointerSet seen;
        if (arr->hasInternalReference(seen)) {
          setSerializedArray();
          m_shouldCache = true;
          String s = apc_serialize(source);
          m_data.str = StringData::MakeMalloced(s.data(), s.size());
          break;
        }
      }

      if (arr->isVectorData()) {
        setIsVector();
        m_data.vec = new (arr->size()) VectorData();
        for (ArrayIter it(arr); !it.end(); it.next()) {
          SharedVariant* val = Create(it.secondRef(), false, true,
                                      unserializeObj);
          if (val->m_shouldCache) m_shouldCache = true;
          m_data.vec->vals()[m_data.vec->m_size++] = val;
        }
      } else {
        m_data.map = ImmutableMap::Create(arr, unserializeObj, m_shouldCache);
      }
      break;
    }
  case KindOfUninit:
  case KindOfNull:
    {
      break;
    }
  case KindOfResource:
    {
      // TODO Task #2661075: Here and elsewhere in the runtime, we convert
      // Resources to the empty array during various serialization operations,
      // which does not match Zend behavior. We should fix this.
      m_type = KindOfArray;
      setIsVector();
      m_data.vec = new (0) VectorData();
      break;
    }
  default:
    {
      assert(source.isObject());
      m_shouldCache = true;
      if (unserializeObj) {
        // This assumes hasInternalReference(seen, true) is false
        ImmutableObj* obj = new ImmutableObj(source.getObjectData());
        m_data.obj = obj;
        setIsObj();
      } else {
        String s = apc_serialize(source);
        m_data.str = StringData::MakeMalloced(s.data(), s.size());
      }
      break;
    }
  }
  assert(m_type != KindOfResource);
}
ThreadSharedVariant::ThreadSharedVariant(CVarRef source, bool serialized,
                                         bool inner /* = false */) {
  ASSERT(!serialized || source.isString());

  setOwner();
  m_ref = 1;

  switch (source.getType()) {
  case KindOfBoolean:
    {
      m_type = KindOfBoolean;
      m_data.num = source.toBoolean();
      break;
    }
  case KindOfByte:
  case KindOfInt16:
  case KindOfInt32:
  case KindOfInt64:
    {
      m_type = KindOfInt64;
      m_data.num = source.toInt64();
      break;
    }
  case KindOfDouble:
    {
      m_type = KindOfDouble;
      m_data.dbl = source.toDouble();
      break;
    }
  case KindOfStaticString:
  case KindOfString:
    {
      String s = source.toString();
      m_type = serialized ? KindOfObject : KindOfString;
      if (serialized) {
        // It is priming, and there might not be the right class definitions
        // for unserialization.
        s = apc_reserialize(s);
      }
      m_data.str = s->copy(true);
      break;
    }
  case KindOfArray:
    {
      m_type = KindOfArray;

      ArrayData *arr = source.getArrayData();

      if (!inner) {
        // only need to call hasInternalReference() on the toplevel array
        PointerSet seen;
        if (arr->hasInternalReference(seen)) {
          setSerializedArray();
          setShouldCache();
          String s = apc_serialize(source);
          m_data.str = new StringData(s.data(), s.size(), CopyString);
          break;
        }
      }

      size_t size = arr->size();
      if (arr->isVectorData()) {
        setIsVector();
        m_data.vec = new VectorData(size);
        uint i = 0;
        for (ArrayIter it(arr); !it.end(); it.next(), i++) {
          ThreadSharedVariant* val = createAnother(it.second(), false, true);
          if (val->shouldCache()) setShouldCache();
          m_data.vec->vals[i] = val;
        }
      } else {
        m_data.map = new ImmutableMap(size);
        uint i = 0;
        for (ArrayIter it(arr); !it.end(); it.next(), i++) {
          ThreadSharedVariant* key = createAnother(it.first(), false);
          ThreadSharedVariant* val = createAnother(it.second(), false, true);
          if (val->shouldCache()) setShouldCache();
          m_data.map->add(key, val);
        }
      }
      break;
    }
  default:
    {
      m_type = KindOfObject;
      setShouldCache();
      String s = apc_serialize(source);
      m_data.str = new StringData(s.data(), s.size(), CopyString);
      break;
    }
  }
}
Beispiel #16
0
static void url_encode_array(StringBuffer &ret, CVarRef varr,
                             std::set<void*> &seen_arrs,
                             const String& num_prefix, const String& key_prefix,
                             const String& key_suffix, const String& arg_sep) {
  void *id = varr.is(KindOfArray) ?
    (void*)varr.getArrayData() : (void*)varr.getObjectData();
  if (!seen_arrs.insert(id).second) {
    return; // recursive
  }

  Array arr;
  if (varr.is(KindOfObject)) {
    Object o = varr.toObject();
    arr = (o.objectForCall()->isCollection()) ?
      varr.toArray() :
      f_get_object_vars(o).toArray();
  } else {
    arr = varr.toArray();
  }

  for (ArrayIter iter(arr); iter; ++iter) {
    Variant data = iter.second();
    if (data.isNull() || data.isResource()) continue;

    String key = iter.first();
    bool numeric = key.isNumeric();

    if (data.is(KindOfArray) || data.is(KindOfObject)) {
      String encoded;
      if (numeric) {
        encoded = key;
      } else {
        encoded = StringUtil::UrlEncode(key);
      }
      StringBuffer new_prefix(key_prefix.size() + num_prefix.size() +
                              encoded.size() + key_suffix.size() + 4);
      new_prefix.append(key_prefix);
      if (numeric) new_prefix.append(num_prefix);
      new_prefix.append(encoded);
      new_prefix.append(key_suffix);
      new_prefix.append("%5B");
      url_encode_array(ret, data, seen_arrs, String(),
                       new_prefix.detach(), String("%5D", CopyString),
                       arg_sep);
    } else {
      if (!ret.empty()) {
        ret.append(arg_sep);
      }
      ret.append(key_prefix);
      if (numeric) {
        ret.append(num_prefix);
        ret.append(key);
      } else {
        ret.append(StringUtil::UrlEncode(key));
      }
      ret.append(key_suffix);
      ret.append("=");
      if (data.isInteger() || data.is(KindOfBoolean)) {
        ret.append(String(data.toInt64()));
      } else if (data.is(KindOfDouble)) {
        ret.append(String(data.toDouble()));
      } else {
        ret.append(StringUtil::UrlEncode(data.toString()));
      }
    }
  }
}
Beispiel #17
0
Array Array::operator+(CVarRef var) const {
  if (var.getType() != KindOfArray) {
    throw BadArrayMergeException();
  }
  return operator+(var.getArrayData());
}
SharedVariant::SharedVariant(CVarRef source, bool serialized,
                             bool inner /* = false */,
                             bool unserializeObj /* = false */)
  : m_count (1), m_shouldCache(false), m_flags(0){
  ASSERT(!serialized || source.isString());

  m_type = source.getType();

  switch (m_type) {
  case KindOfBoolean:
    {
      m_data.num = source.toBoolean();
      break;
    }
  case KindOfByte:
  case KindOfInt16:
  case KindOfInt32:
  case KindOfInt64:
    {
      m_type = KindOfInt64;
      m_data.num = source.toInt64();
      break;
    }
  case KindOfDouble:
    {
      m_data.dbl = source.toDouble();
      break;
    }
  case KindOfStaticString:
  case KindOfString:
    {
      String s = source.toString();
      if (serialized) {
        m_type = KindOfObject;
        // It is priming, and there might not be the right class definitions
        // for unserialization.
        s = apc_reserialize(s);
      }
      m_data.str = s->copy(true);
      break;
    }
  case KindOfArray:
    {
      ArrayData *arr = source.getArrayData();

      if (!inner) {
        // only need to call hasInternalReference() on the toplevel array
        PointerSet seen;
        if (arr->hasInternalReference(seen)) {
          setSerializedArray();
          m_shouldCache = true;
          String s = apc_serialize(source);
          m_data.str = new StringData(s.data(), s.size(), CopyString);
          break;
        }
      }

      size_t size = arr->size();
      if (arr->isVectorData()) {
        setIsVector();
        m_data.vec = new VectorData(size);
        uint i = 0;
        for (ArrayIter it(arr); !it.end(); it.next(), i++) {
          SharedVariant* val = Create(it.secondRef(), false, true,
                                      unserializeObj);
          if (val->m_shouldCache) m_shouldCache = true;
          m_data.vec->vals[i] = val;
        }
      } else {
        m_data.map = new ImmutableMap(size);
        for (ArrayIter it(arr); !it.end(); it.next()) {
          SharedVariant* key = Create(it.first(), false, true,
                                      unserializeObj);
          SharedVariant* val = Create(it.secondRef(), false, true,
                                      unserializeObj);
          if (val->m_shouldCache) m_shouldCache = true;
          m_data.map->add(key, val);
        }
      }
      break;
    }
  case KindOfNull:
    {
      m_data.num = 0;
      break;
    }
  default:
    {
      ASSERT(source.isObject());
      m_shouldCache = true;
      if (unserializeObj) {
        // This assumes hasInternalReference(seen, true) is false
        ImmutableObj* obj = new ImmutableObj(source.getObjectData());
        m_data.obj = obj;
        setIsObj();
      } else {
        String s = apc_serialize(source);
        m_data.str = new StringData(s.data(), s.size(), CopyString);
      }
      break;
    }
  }
}