Esempio n. 1
0
Array f_get_defined_constants(CVarRef categorize /* = null_variant */) {
  if (categorize.toBoolean()) {
    throw NotSupportedException(__func__, "constant categorization not "
                                "supported");
  }
  return StringData::GetConstants();
}
Esempio n. 2
0
bool Array::more(CVarRef v2) const {
  if (m_px == NULL || v2.isNull()) {
    return HPHP::more(toBoolean(), v2.toBoolean());
  }
  if (v2.getType() == KindOfArray) {
    return v2.toArray().get()->compare(m_px) < 0;
  }
  return v2.less(*this);
}
Esempio n. 3
0
bool Array::less(CVarRef v2) const {
  if (m_px == nullptr || v2.isNull()) {
    return HPHP::less(toBoolean(), v2.toBoolean());
  }
  if (v2.getType() == KindOfArray) {
    return m_px->compare(v2.toArray().get()) < 0;
  }
  return v2.more(*this);
}
Esempio n. 4
0
static bool HHVM_METHOD(IntlCalendar, roll, int64_t field, CVarRef value) {
  CAL_FETCH(data, this_, false);
  CAL_CHECK_FIELD(field, "intlcal_roll");
  UErrorCode error = U_ZERO_ERROR;
  if (value.isBoolean()) {
    data->calendar()->roll((UCalendarDateFields)field,
                           (UBool)value.toBoolean(), error);
  } else {
    data->calendar()->roll((UCalendarDateFields)field,
                           (int32_t)value.toInt64(), error);
  }
  if (U_FAILURE(error)) {
    data->setError(error, "intlcal_roll: Error calling ICU Calendar::roll");
    return false;
  }
  return true;
}
Esempio n. 5
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;
  }
}
Esempio n. 6
0
Variant f_assert(CVarRef assertion) {
  if (!s_option_data->assertActive) return true;

  Transl::CallerFrame cf;
  Offset callerOffset;
  auto const fp = cf(&callerOffset);

  auto const passed = [&]() -> bool {
    if (assertion.isString()) {
      if (RuntimeOption::RepoAuthoritative) {
        // We could support this with compile-time string literals,
        // but it's not yet implemented.
        throw NotSupportedException(__func__,
          "assert with strings argument in RepoAuthoritative mode");
      }
      return eval_for_assert(fp, assertion.toString()).toBoolean();
    }
    return assertion.toBoolean();
  }();
  if (passed) return true;

  if (!s_option_data->assertCallback.isNull()) {
    auto const unit = fp->m_func->unit();

    VectorInit ai(3);
    ai.add(String(unit->filepath()));
    ai.add(Variant(unit->getLineNumber(callerOffset)));
    ai.add(assertion.isString() ? assertion.toString() : String(""));
    f_call_user_func(1, s_option_data->assertCallback, ai.toArray());
  }

  if (s_option_data->assertWarning) {
    auto const str = !assertion.isString()
      ? String("Assertion failed")
      : concat3("Assertion \"", assertion.toString(), "\" failed");
    raise_warning("%s", str.data());
  }
  if (s_option_data->assertBail) {
    throw Assertion();
  }

  return uninit_null();
}
Esempio n. 7
0
bool register_intercept(const String& name, CVarRef callback, CVarRef data) {
  StringIMap<Variant> &handlers = s_intercept_data->m_intercept_handlers;
  if (!callback.toBoolean()) {
    if (name.empty()) {
      s_intercept_data->m_global_handler.reset();
      handlers.clear();
    } else {
      handlers.erase(name);
    }
    return true;
  }

  EventHook::EnableIntercept();

  Array handler = make_packed_array(callback, data);

  if (name.empty()) {
    s_intercept_data->m_global_handler = handler;
    handlers.clear();
  } else {
    handlers[name] = handler;
  }

  Lock lock(s_mutex);
  if (name.empty()) {
    for (auto& entry : s_registered_flags) {
      flag_maybe_intercepted(entry.second.second);
    }
  } else {
    StringData* sd = name.get();
    if (!sd->isStatic()) {
      sd = makeStaticString(sd);
    }
    auto &entry = s_registered_flags[StrNR(sd)];
    entry.first = true;
    flag_maybe_intercepted(entry.second);
  }

  return true;
}
Esempio n. 8
0
bool register_intercept(CStrRef name, CVarRef callback, CVarRef data) {
  StringIMap<Variant> &handlers = s_intercept_data->m_intercept_handlers;
  if (!callback.toBoolean()) {
    if (name.empty()) {
      s_intercept_data->m_global_handler.reset();
      handlers.clear();
    } else {
      handlers.erase(name);
    }
    return true;
  }

  EventHook::EnableIntercept();

  Array handler = CREATE_VECTOR2(callback, data);

  if (name.empty()) {
    s_intercept_data->m_global_handler = handler;
    handlers.clear();
  } else {
    handlers[name] = handler;
  }

  Lock lock(s_mutex);
  if (name.empty()) {
    for (RegisteredFlagsMap::iterator iter =
           s_registered_flags.begin();
         iter != s_registered_flags.end(); ++iter) {
      flag_maybe_interrupted(iter->second);
    }
  } else {
    RegisteredFlagsMap::iterator iter =
      s_registered_flags.find(name);
    if (iter != s_registered_flags.end()) {
      flag_maybe_interrupted(iter->second);
    }
  }

  return true;
}
Esempio n. 9
0
  bool setOption(long option, CVarRef value) {
    if (m_cp == NULL) {
      return false;
    }
    m_error_no = CURLE_OK;

    switch (option) {
    case CURLOPT_INFILESIZE:
    case CURLOPT_VERBOSE:
    case CURLOPT_HEADER:
    case CURLOPT_NOPROGRESS:
    case CURLOPT_NOBODY:
    case CURLOPT_FAILONERROR:
    case CURLOPT_UPLOAD:
    case CURLOPT_POST:
    case CURLOPT_FTPLISTONLY:
    case CURLOPT_FTPAPPEND:
    case CURLOPT_NETRC:
    case CURLOPT_PUT:
    case CURLOPT_TIMEOUT:
#if LIBCURL_VERSION_NUM >= 0x071002
    case CURLOPT_TIMEOUT_MS:
#endif
    case CURLOPT_FTP_USE_EPSV:
    case CURLOPT_LOW_SPEED_LIMIT:
    case CURLOPT_SSLVERSION:
    case CURLOPT_LOW_SPEED_TIME:
    case CURLOPT_RESUME_FROM:
    case CURLOPT_TIMEVALUE:
    case CURLOPT_TIMECONDITION:
    case CURLOPT_TRANSFERTEXT:
    case CURLOPT_HTTPPROXYTUNNEL:
    case CURLOPT_FILETIME:
    case CURLOPT_MAXREDIRS:
    case CURLOPT_MAXCONNECTS:
    case CURLOPT_CLOSEPOLICY:
    case CURLOPT_FRESH_CONNECT:
    case CURLOPT_FORBID_REUSE:
    case CURLOPT_CONNECTTIMEOUT:
#if LIBCURL_VERSION_NUM >= 0x071002
    case CURLOPT_CONNECTTIMEOUT_MS:
#endif
    case CURLOPT_SSL_VERIFYHOST:
    case CURLOPT_SSL_VERIFYPEER:
      //case CURLOPT_DNS_USE_GLOBAL_CACHE: not thread-safe when set to true
    case CURLOPT_NOSIGNAL:
    case CURLOPT_PROXYTYPE:
    case CURLOPT_BUFFERSIZE:
    case CURLOPT_HTTPGET:
    case CURLOPT_HTTP_VERSION:
    case CURLOPT_CRLF:
    case CURLOPT_DNS_CACHE_TIMEOUT:
    case CURLOPT_PROXYPORT:
    case CURLOPT_FTP_USE_EPRT:
    case CURLOPT_HTTPAUTH:
    case CURLOPT_PROXYAUTH:
    case CURLOPT_FTP_CREATE_MISSING_DIRS:
    case CURLOPT_FTPSSLAUTH:
    case CURLOPT_FTP_SSL:
    case CURLOPT_UNRESTRICTED_AUTH:
    case CURLOPT_PORT:
    case CURLOPT_AUTOREFERER:
    case CURLOPT_COOKIESESSION:
    case CURLOPT_TCP_NODELAY:
    case CURLOPT_IPRESOLVE:
    case CURLOPT_FOLLOWLOCATION:
      m_error_no = curl_easy_setopt(m_cp, (CURLoption)option, value.toInt64());
      break;
    case CURLOPT_RETURNTRANSFER:
      m_write.method = value.toBoolean() ? PHP_CURL_RETURN : PHP_CURL_STDOUT;
      break;
    case CURLOPT_BINARYTRANSFER:
      m_write.type = value.toBoolean() ? PHP_CURL_BINARY : PHP_CURL_ASCII;
      break;
    case CURLOPT_PRIVATE:
    case CURLOPT_URL:
    case CURLOPT_PROXY:
    case CURLOPT_USERPWD:
    case CURLOPT_PROXYUSERPWD:
    case CURLOPT_RANGE:
    case CURLOPT_CUSTOMREQUEST:
    case CURLOPT_USERAGENT:
    case CURLOPT_FTPPORT:
    case CURLOPT_COOKIE:
    case CURLOPT_REFERER:
    case CURLOPT_INTERFACE:
    case CURLOPT_KRB4LEVEL:
    case CURLOPT_EGDSOCKET:
    case CURLOPT_CAINFO:
    case CURLOPT_CAPATH:
    case CURLOPT_SSL_CIPHER_LIST:
    case CURLOPT_SSLKEY:
    case CURLOPT_SSLKEYTYPE:
    case CURLOPT_SSLKEYPASSWD:
    case CURLOPT_SSLENGINE:
    case CURLOPT_SSLENGINE_DEFAULT:
    case CURLOPT_SSLCERTTYPE:
    case CURLOPT_ENCODING:
    case CURLOPT_COOKIEJAR:
    case CURLOPT_SSLCERT:
    case CURLOPT_RANDOM_FILE:
    case CURLOPT_COOKIEFILE:
      {
        String svalue = value.toString();
#if LIBCURL_VERSION_NUM >= 0x071100
        /* Strings passed to libcurl as 'char *' arguments, are copied
           by the library... NOTE: before 7.17.0 strings were not copied. */
        m_error_no = curl_easy_setopt(m_cp, (CURLoption)option, svalue.c_str());
#else
        char *copystr = strndup(svalue.data(), svalue.size());
        m_to_free->str.push_back(copystr);
        m_error_no = curl_easy_setopt(m_cp, (CURLoption)option, copystr);
#endif
        if (option == CURLOPT_URL) m_url = value;
      }
      break;
    case CURLOPT_FILE:
    case CURLOPT_INFILE:
    case CURLOPT_WRITEHEADER:
    case CURLOPT_STDERR:
      {
        if (!value.is(KindOfObject)) {
          return false;
        }

        Object obj = value.toObject();
        if (obj.isNull() || obj.getTyped<File>(true) == NULL) {
          return false;
        }

        switch (option) {
          case CURLOPT_FILE:
            m_write.fp = obj;
            m_write.method = PHP_CURL_FILE;
            break;
          case CURLOPT_WRITEHEADER:
            m_write_header.fp = obj;
            m_write_header.method = PHP_CURL_FILE;
            break;
          case CURLOPT_INFILE:
            m_read.fp = obj;
            m_emptyPost = false;
            break;
          default: {
            if (obj.getTyped<PlainFile>(true) == NULL) {
              return false;
            }
            FILE *fp = obj.getTyped<PlainFile>()->getStream();
            if (!fp) {
              return false;
            }
            m_error_no = curl_easy_setopt(m_cp, (CURLoption)option, fp);
            break;
          }
        }
      }
      break;
    case CURLOPT_WRITEFUNCTION:
      m_write.callback = value;
      m_write.method = PHP_CURL_USER;
      break;
    case CURLOPT_READFUNCTION:
      m_read.callback = value;
      m_read.method = PHP_CURL_USER;
      m_emptyPost = false;
      break;
    case CURLOPT_HEADERFUNCTION:
      m_write_header.callback = value;
      m_write_header.method = PHP_CURL_USER;
      break;
    case CURLOPT_POSTFIELDS:
      m_emptyPost = false;
      if (value.is(KindOfArray) || value.is(KindOfObject)) {
        Array arr = value.toArray();
        curl_httppost *first = NULL;
        curl_httppost *last  = NULL;
        for (ArrayIter iter(arr); iter; ++iter) {
          String key = iter.first().toString();
          String val = iter.second().toString();
          const char *postval = val.data();

          /* The arguments after _NAMELENGTH and _CONTENTSLENGTH
           * must be explicitly cast to long in curl_formadd
           * use since curl needs a long not an int. */
          if (*postval == '@') {
            ++postval;
            m_error_no = (CURLcode)curl_formadd
              (&first, &last,
               CURLFORM_COPYNAME, key.data(),
               CURLFORM_NAMELENGTH, (long)key.size(),
               CURLFORM_FILE, postval,
               CURLFORM_END);
          } else {
            m_error_no = (CURLcode)curl_formadd
              (&first, &last,
               CURLFORM_COPYNAME, key.data(),
               CURLFORM_NAMELENGTH, (long)key.size(),
               CURLFORM_COPYCONTENTS, postval,
               CURLFORM_CONTENTSLENGTH,(long)val.size(),
               CURLFORM_END);
          }
        }

        if (m_error_no != CURLE_OK) {
          return false;
        }

        m_to_free->post.push_back(first);
        m_error_no = curl_easy_setopt(m_cp, CURLOPT_HTTPPOST, first);

      } else {
        String svalue = value.toString();
#if LIBCURL_VERSION_NUM >= 0x071100
        /* with curl 7.17.0 and later, we can use COPYPOSTFIELDS,
           but we have to provide size before */
        m_error_no = curl_easy_setopt(m_cp, CURLOPT_POSTFIELDSIZE,
                                      svalue.size());
        m_error_no = curl_easy_setopt(m_cp, CURLOPT_COPYPOSTFIELDS,
                                      svalue.c_str());
#else
        char *post = strndup(svalue.data(), svalue.size());
        m_to_free->str.push_back(post);

        m_error_no = curl_easy_setopt(m_cp, CURLOPT_POSTFIELDS, post);
        m_error_no = curl_easy_setopt(m_cp, CURLOPT_POSTFIELDSIZE,
                                      svalue.size());
#endif
      }
      break;
    case CURLOPT_HTTPHEADER:
    case CURLOPT_QUOTE:
    case CURLOPT_HTTP200ALIASES:
    case CURLOPT_POSTQUOTE:
      if (value.is(KindOfArray) || value.is(KindOfObject)) {
        Array arr = value.toArray();
        curl_slist *slist = NULL;
        for (ArrayIter iter(arr); iter; ++iter) {
          String key = iter.first().toString();
          String val = iter.second().toString();

          slist = curl_slist_append(slist, val.c_str());
          if (!slist) {
            raise_warning("Could not build curl_slist");
            return false;
          }
        }

        m_to_free->slist.push_back(slist);
        m_error_no = curl_easy_setopt(m_cp, (CURLoption)option, slist);

      } else {
        raise_warning("You must pass either an object or an array with "
                      "the CURLOPT_HTTPHEADER, CURLOPT_QUOTE, "
                      "CURLOPT_HTTP200ALIASES and CURLOPT_POSTQUOTE "
                      "arguments");
        return false;
      }
      break;

    case CURLINFO_HEADER_OUT:
      if (value.toInt64() == 1) {
        curl_easy_setopt(m_cp, CURLOPT_DEBUGFUNCTION, curl_debug);
        curl_easy_setopt(m_cp, CURLOPT_DEBUGDATA, (void *)this);
        curl_easy_setopt(m_cp, CURLOPT_VERBOSE, 1);
      } else {
        curl_easy_setopt(m_cp, CURLOPT_DEBUGFUNCTION, NULL);
        curl_easy_setopt(m_cp, CURLOPT_DEBUGDATA, NULL);
        curl_easy_setopt(m_cp, CURLOPT_VERBOSE, 0);
      }
      break;

    default:
      m_error_no = CURLE_FAILED_INIT;
      throw_invalid_argument("option: %d", option);
      break;
    }

    m_opts.set(int64(option), value);

    return m_error_no == CURLE_OK;
  }
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;
    }
  }
}
ProcessSharedVariant::ProcessSharedVariant(CVarRef source,
                                           ProcessSharedVariantLock* lock)
  : m_lock(putPtr(lock)) {
  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 LiteralString:
  case KindOfStaticString:
  case KindOfString:
    {
      String s = source.toString();
      m_type = KindOfString;
      if (lock) {
        m_data.str = putPtr(SharedMemoryManager::GetSegment()
                            ->construct<SharedMemoryString>
                            (boost::interprocess::anonymous_instance)
                            (s.data(), s.size()));
      } else {
        // Just need this string to live long enough for the key lookup so
        // don't store in shared memory.
        m_data.str = putPtr(new SharedMemoryString(s.data(), s.size()));
      }
      break;
    }
  case KindOfArray:
    {
      ASSERT(lock);
      m_type = KindOfArray;
      uint i = 0;
      ProcessSharedVariantMapData* mapData = SharedMemoryManager::GetSegment()
        ->construct<ProcessSharedVariantMapData>
        (boost::interprocess::anonymous_instance)();
      m_data.map = putPtr(mapData);
      ProcessSharedVariantToIntMap* map = SharedMemoryManager::GetSegment()
        ->construct<ProcessSharedVariantToIntMap>
        (boost::interprocess::anonymous_instance)();
      mapData->map = putPtr(map);
      SharedMemoryVector<SharedVariant*>* keys =
        SharedMemoryManager::GetSegment()
        ->construct<SharedMemoryVector<SharedVariant*> >
        (boost::interprocess::anonymous_instance)();
      mapData->keys = putPtr(keys);
      SharedMemoryVector<SharedVariant*>* vals =
        SharedMemoryManager::GetSegment()
        ->construct<SharedMemoryVector<SharedVariant*> >
        (boost::interprocess::anonymous_instance)();
      mapData->vals = putPtr(vals);
      for (ArrayIterPtr it = source.begin(); !it->end(); it->next()) {
        ProcessSharedVariant* key = SharedMemoryManager::GetSegment()
          ->construct<ProcessSharedVariant>
          (boost::interprocess::anonymous_instance)
          (it->first(), getLock());
        ProcessSharedVariant* val = SharedMemoryManager::GetSegment()
          ->construct<ProcessSharedVariant>
          (boost::interprocess::anonymous_instance)
          (it->second(), getLock());
        (*map)[key] = i++;
        keys->push_back(putPtr(key));
        vals->push_back(putPtr(val));
      }
      break;
    }
  default:
    {
      m_type = KindOfObject;
      String s = f_serialize(source);
      m_data.str = putPtr(SharedMemoryManager::GetSegment()
                          ->construct<SharedMemoryString>
                          (boost::interprocess::anonymous_instance)
                          (s.data(), s.size()));
      break;
    }
  }
}
Esempio n. 12
0
void binary_serialize(int8_t thrift_typeID, PHPOutputTransport& transport,
                      CVarRef value, CArrRef fieldspec) {
  // At this point the typeID (and field num, if applicable) should've already
  // been written to the output so all we need to do is write the payload.
  switch (thrift_typeID) {
    case T_STOP:
    case T_VOID:
      return;
    case T_STRUCT: {
      if (!value.is(KindOfObject)) {
        throw_tprotocolexception("Attempt to send non-object "
                                 "type as a T_STRUCT", INVALID_DATA);
      }
      binary_serialize_spec(value.toObject(), transport,
                            f_hphp_get_static_property(value.toObject()->
                                                       o_getClassName(),
                                                       s_TSPEC,
                                                       false).toArray());
    } return;
    case T_BOOL:
      transport.writeI8(value.toBoolean() ? 1 : 0);
      return;
    case T_BYTE:
      transport.writeI8(value.toByte());
      return;
    case T_I16:
      transport.writeI16(value.toInt16());
      return;
    case T_I32:
      transport.writeI32(value.toInt32());
      return;
    case T_I64:
    case T_U64:
      transport.writeI64(value.toInt64());
      return;
    case T_DOUBLE: {
      union {
        int64_t c;
        double d;
      } a;
      a.d = value.toDouble();
      transport.writeI64(a.c);
    } return;
    case T_FLOAT: {
      union {
        int32_t c;
        float d;
      } a;
      a.d = (float)value.toDouble();
      transport.writeI32(a.c);
    } return;
    //case T_UTF7:
    case T_UTF8:
    case T_UTF16:
    case T_STRING: {
        String sv = value.toString();
        transport.writeString(sv.data(), sv.size());
    } return;
    case T_MAP: {
      Array ht = value.toArray();
      uint8_t keytype = fieldspec.rvalAt(PHPTransport::s_ktype,
                                         AccessFlags::Error_Key).toByte();
      transport.writeI8(keytype);
      uint8_t valtype = fieldspec.rvalAt(PHPTransport::s_vtype,
                                         AccessFlags::Error_Key).toByte();
      transport.writeI8(valtype);

      Array valspec = fieldspec.rvalAt(PHPTransport::s_val,
                                       AccessFlags::Error_Key).toArray();

      transport.writeI32(ht.size());
      for (ArrayIter key_ptr = ht.begin(); !key_ptr.end(); ++key_ptr) {
        binary_serialize_hashtable_key(keytype, transport, key_ptr.first());
        binary_serialize(valtype, transport, key_ptr.second(), valspec);
      }
    } return;
    case T_LIST: {
      Array ht = value.toArray();
      Variant val;

      uint8_t valtype = fieldspec.rvalAt(PHPTransport::s_etype,
                                         AccessFlags::Error_Key).toInt64();
      transport.writeI8(valtype);
      Array valspec = fieldspec.rvalAt(PHPTransport::s_elem,
                                       AccessFlags::Error_Key).toArray();
      transport.writeI32(ht.size());
      for (ArrayIter key_ptr = ht.begin(); !key_ptr.end(); ++key_ptr) {
        binary_serialize(valtype, transport, key_ptr.second(), valspec);
      }
    } return;
    case T_SET: {
      Array ht = value.toArray();

      uint8_t keytype = fieldspec.rvalAt(PHPTransport::s_etype,
                                         AccessFlags::Error_Key).toByte();
      transport.writeI8(keytype);

      transport.writeI32(ht.size());
      for (ArrayIter key_ptr = ht.begin(); !key_ptr.end(); ++key_ptr) {
        binary_serialize_hashtable_key(keytype, transport, key_ptr.first());
      }
    } return;
  };
  char errbuf[128];
  sprintf(errbuf, "Unknown thrift typeID %d", thrift_typeID);
  throw_tprotocolexception(String(errbuf, CopyString), INVALID_DATA);
}
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;
    }
  }
}
Esempio n. 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);
}