Beispiel #1
0
void binary_deserialize_spec(const Object& zthis, PHPInputTransport& transport,
                             const Array& spec) {
  // SET and LIST have 'elem' => array('type', [optional] 'class')
  // MAP has 'val' => array('type', [optiona] 'class')
  while (true) {
    Variant val;

    int8_t ttype = transport.readI8();
    if (ttype == T_STOP) return;
    int16_t fieldno = transport.readI16();
    if (!(val = spec.rvalAt(fieldno)).isNull()) {
      Array fieldspec = val.toArray();
      // pull the field name
      // zend hash tables use the null at the end in the length... so strlen(hash key) + 1.
      String varname = fieldspec.rvalAt(PHPTransport::s_var).toString();

      // and the type
      int8_t expected_ttype = fieldspec.rvalAt(PHPTransport::s_type).toInt64();

      if (ttypes_are_compatible(ttype, expected_ttype)) {
        Variant rv = binary_deserialize(ttype, transport, fieldspec);
        zthis->o_set(varname, rv, zthis->getClassName());
      } else {
        skip_element(ttype, transport);
      }
    } else {
      skip_element(ttype, transport);
    }
  }
}
Beispiel #2
0
void skip_element(long thrift_typeID, PHPInputTransport& transport) {
  switch (thrift_typeID) {
    case T_STOP:
    case T_VOID:
      return;
    case T_STRUCT:
      while (true) {
        int8_t ttype = transport.readI8(); // get field type
        if (ttype == T_STOP) break;
        transport.skip(2); // skip field number, I16
        skip_element(ttype, transport); // skip field payload
      }
      return;
    case T_BOOL:
    case T_BYTE:
      transport.skip(1);
      return;
    case T_I16:
      transport.skip(2);
      return;
    case T_I32:
    case T_FLOAT:
      transport.skip(4);
      return;
    case T_U64:
    case T_I64:
    case T_DOUBLE:
      transport.skip(8);
      return;
    //case T_UTF7: // aliases T_STRING
    case T_UTF8:
    case T_UTF16:
    case T_STRING: {
      uint32_t len = transport.readU32();
      transport.skip(len);
      } return;
    case T_MAP: {
      int8_t keytype = transport.readI8();
      int8_t valtype = transport.readI8();
      uint32_t size = transport.readU32();
      for (uint32_t i = 0; i < size; ++i) {
        skip_element(keytype, transport);
        skip_element(valtype, transport);
      }
    } return;
    case T_LIST:
    case T_SET: {
      int8_t valtype = transport.readI8();
      uint32_t size = transport.readU32();
      for (uint32_t i = 0; i < size; ++i) {
        skip_element(valtype, transport);
      }
    } return;
  };

  char errbuf[128];
  sprintf(errbuf, "Unknown thrift typeID %ld", thrift_typeID);
  throw_tprotocolexception(String(errbuf, CopyString), INVALID_DATA);
}
Beispiel #3
0
int get_name_of_code(unsigned* pycbuf, struct code_obj* pobj, int cur)
{
    int n_field = 0;
    struct obj* ptrobj;
    /* skip 4 (:28 s that is cellvars, freevars */
    while(1) {
            if (pycbuf[cur] == TYPE_TUPLE)
                n_field++;
            if (n_field == 2)
                break;
            cur++; 
    }
    cur += 5;
 
    /* skip filenmae */
    cur = skip_element(pycbuf, cur);
    
    /* getting the index of the name  of the code */
    if (pycbuf[cur] == TYPE_INTERN) {
        ptrobj = init_obj();
        strncpy(ptrobj->name, (char *) &pycbuf[cur+5], length(pycbuf, cur)+1);
        objects[obj_cnt++] = ptrobj;
        pobj->name = ptrobj->name;
        return obj_cnt-1;

    } else 
        return compute_const(pycbuf, cur);
}
    ALPS_DECL params make_parameters_from_xml(boost::filesystem::path const & arg) {
        Parameters par;
        boost::filesystem::ifstream infile(arg.string());

        // read outermost tag (e.g. <SIMULATION>)
        XMLTag tag = parse_tag(infile, true);
        std::string closingtag = "/" + tag.name;

        // scan for <PARAMETERS> and read them
        tag = parse_tag(infile, true);
        while (tag.name != "PARAMETERS" && tag.name != closingtag) {
            std::cerr << "skipping tag with name " << tag.name << "\n";
            skip_element(infile, tag);
            tag = parse_tag(infile, true);
        }

        par.read_xml(tag, infile, true);
        if (!par.defined("SEED"))
            par["SEED"] = 0;
        
        params res;
        for (Parameters::const_iterator it = par.begin(); it != par.end(); ++it)
            res[it->key()] = it->value();
        return res;
    }
Beispiel #5
0
static
void binary_deserialize_spec(zval* zthis, PHPInputTransport& transport, HashTable* spec) {
  // SET and LIST have 'elem' => array('type', [optional] 'class')
  // MAP has 'val' => array('type', [optiona] 'class')
  zend_class_entry* ce = Z_OBJCE_P(zthis);
  while (true) {
    int8_t ttype = transport.readI8();
    if (ttype == T_STOP) {
      validate_thrift_object(zthis);
      return;
    }

    int16_t fieldno = transport.readI16();
    zval* val_ptr = zend_hash_index_find(spec, fieldno);
    if (val_ptr != nullptr) {
      HashTable* fieldspec = Z_ARRVAL_P(val_ptr);
      // pull the field name
      val_ptr = zend_hash_str_find(fieldspec, "var", sizeof("var")-1);
      char* varname = Z_STRVAL_P(val_ptr);

      // and the type
      val_ptr = zend_hash_str_find(fieldspec, "type", sizeof("type")-1);
      if (Z_TYPE_P(val_ptr) != IS_LONG) convert_to_long(val_ptr);
      int8_t expected_ttype = Z_LVAL_P(val_ptr);

      if (ttypes_are_compatible(ttype, expected_ttype)) {
        zval rv;
        ZVAL_UNDEF(&rv);

        binary_deserialize(ttype, transport, &rv, fieldspec);
        zend_update_property(ce, zthis, varname, strlen(varname), &rv);

        zval_ptr_dtor(&rv);
      } else {
        skip_element(ttype, transport);
      }
    } else {
      skip_element(ttype, transport);
    }
  }
}
Beispiel #6
0
int find_end_of_code(unsigned* pycbuf, int cur)
{
    cur += 17; /* cur is at s:73 */
    cur = skip_element(pycbuf, cur); /* skipping the code string */
   
    /* skipping the co_consts field */
    int n_const = length(pycbuf, cur);
    cur += 5;
    while(n_const--) {
        if (pycbuf[cur] == TYPE_INTEGER)
            cur += 5;
        else if (pycbuf[cur] == TYPE_NONE)
            cur += 1;
        else if (pycbuf[cur] == TYPE_CODE)
            cur = find_end_of_code(pycbuf, cur);
        else 
            cur++;
    }
    /* skip 4 (:28 s that is co_names, varnames, cellvars, freevars */
    n_const = 0;
    while(1) {
            if (pycbuf[cur] == TYPE_TUPLE)
                n_const++;
            if (n_const == 4)
                break;
            cur++; 
    }
    cur += 5;
    /* skip filenmae */
    cur = skip_element(pycbuf, cur);
    /* skip function name */
    cur = skip_element(pycbuf, cur);
    /* skip first line number */
    cur += 4;
    /* skip lnotab */
    cur = skip_element(pycbuf, cur);
    return cur;
}
Beispiel #7
0
void binary_deserialize_spec(zval* zthis, PHPInputTransport& transport, HashTable* spec) {
    // SET and LIST have 'elem' => array('type', [optional] 'class')
    // MAP has 'val' => array('type', [optiona] 'class')
    TSRMLS_FETCH();
    zend_class_entry* ce = zend_get_class_entry(zthis TSRMLS_CC);
    while (true) {
        zval** val_ptr = NULL;

        int8_t ttype = transport.readI8();
        if (ttype == T_STOP) return;
        int16_t fieldno = transport.readI16();
        if (zend_hash_index_find(spec, fieldno, (void**)&val_ptr) == SUCCESS) {
            HashTable* fieldspec = Z_ARRVAL_PP(val_ptr);
            // pull the field name
            // zend hash tables use the null at the end in the length... so strlen(hash key) + 1.
            zend_hash_find(fieldspec, "var", 4, (void**)&val_ptr);
            char* varname = Z_STRVAL_PP(val_ptr);

            // and the type
            zend_hash_find(fieldspec, "type", 5, (void**)&val_ptr);
            if (Z_TYPE_PP(val_ptr) != IS_LONG) convert_to_long(*val_ptr);
            int8_t expected_ttype = Z_LVAL_PP(val_ptr);

            if (ttypes_are_compatible(ttype, expected_ttype)) {
                zval* rv = NULL;
                MAKE_STD_ZVAL(rv);
                binary_deserialize(ttype, transport, rv, fieldspec);
                zend_update_property(ce, zthis, varname, strlen(varname), rv TSRMLS_CC);
                zval_ptr_dtor(&rv);
            } else {
                skip_element(ttype, transport);
            }
        } else {
            skip_element(ttype, transport);
        }
    }
}
Beispiel #8
0
int get_varnames(unsigned* pycbuf, struct code_obj* pobj, int cur)
{
    struct obj* ptrobj;
    int n_varnames = (pobj->varnames).length = compute_const(pycbuf, cur);
    cur += 5;
    while(n_varnames--) {
        if (pycbuf[cur] == TYPE_INTERN) {
            ptrobj = init_obj();
            copy(ptrobj->name, pycbuf, cur+5, length(pycbuf, cur));
            objects[obj_cnt++] = ptrobj;
        
            cur = skip_element(pycbuf,  cur);
        } else if (pycbuf[cur] == TYPE_SREF) {
            cur += 5;
        } else
            cur++;
    }
    return cur;
}
Beispiel #9
0
/* astreich, 06/17 */
Parameters Task::parse_ext_task_file(std::string infilename)
{
  Parameters res;
  boost::filesystem::ifstream infile(infilename);

  // read outermost tag (e.g. <SIMULATION>)
  XMLTag tag=parse_tag(infile,true);
  std::string closingtag = "/"+tag.name;

  // scan for <PARAMETERS> and read them
  tag=parse_tag(infile,true);
  while (tag.name!="PARAMETERS" && tag.name != closingtag) {
    std::cerr << "skipping tag with name " << tag.name << "\n";
    skip_element(infile,tag);
    tag=parse_tag(infile,true);
  }
  res.read_xml(tag,infile,true);
  if (!res.defined("SEED"))
    res["SEED"]=0;
  return res;
}
Beispiel #10
0
int get_names(unsigned* pycbuf, struct code_obj* pobj, int cur)
{
    int n_names = length(pycbuf, cur);
    int func_idx = 0;
    struct obj* ptrobj;
    cur += 5;
    while(n_names--) {
        if (pycbuf[cur] == TYPE_INTERN) {
            ptrobj = malloc(sizeof *ptrobj);
            copy(ptrobj->name, pycbuf, cur+5, length(pycbuf, cur));
            objects[obj_cnt++] = ptrobj; /* adding names or functions */
            
            pobj->names[pobj->name_cnt++] = ptrobj; /* adding names or functions to co_names */
            cur = skip_element(pycbuf, cur);
        } else if (pycbuf[cur] == TYPE_SREF) {
            func_idx = compute_const(pycbuf, cur);
            ptrobj = pobj->names[pobj->name_cnt++] = objects[func_idx];
            cur += 5;
        } else 
            cur ++;
    }
    return cur;
}
Beispiel #11
0
Variant binary_deserialize(int8_t thrift_typeID, PHPInputTransport& transport,
                           const Array& fieldspec) {
  Variant ret;
  switch (thrift_typeID) {
    case T_STOP:
    case T_VOID:
      return init_null();
    case T_STRUCT: {
      Variant val;
      if ((val = fieldspec.rvalAt(PHPTransport::s_class)).isNull()) {
        throw_tprotocolexception("no class type in spec", INVALID_DATA);
        skip_element(T_STRUCT, transport);
        return init_null();
      }
      String structType = val.toString();
      ret = createObject(structType);
      if (ret.isNull()) {
        // unable to create class entry
        skip_element(T_STRUCT, transport);
        return init_null();
      }
      Variant spec = HHVM_FN(hphp_get_static_property)(structType, s_TSPEC,
                                                                   false);
      if (!spec.is(KindOfArray)) {
        char errbuf[128];
        snprintf(errbuf, 128, "spec for %s is wrong type: %d\n",
                 structType.data(), ret.getType());
        throw_tprotocolexception(String(errbuf, CopyString), INVALID_DATA);
        return init_null();
      }
      binary_deserialize_spec(ret.toObject(), transport, spec.toArray());
      return ret;
    } break;
    case T_BOOL: {
      uint8_t c;
      transport.readBytes(&c, 1);
      return c != 0;
    }
  //case T_I08: // same numeric value as T_BYTE
    case T_BYTE: {
      uint8_t c;
      transport.readBytes(&c, 1);
      return Variant((int8_t)c);
    }
    case T_I16: {
      uint16_t c;
      transport.readBytes(&c, 2);
      return Variant((int16_t)ntohs(c));
    }
    case T_I32: {
      uint32_t c;
      transport.readBytes(&c, 4);
      return Variant((int32_t)ntohl(c));
    }
    case T_U64:
    case T_I64: {
      uint64_t c;
      transport.readBytes(&c, 8);
      return Variant((int64_t)ntohll(c));
    }
    case T_DOUBLE: {
      union {
        uint64_t c;
        double d;
      } a;
      transport.readBytes(&(a.c), 8);
      a.c = ntohll(a.c);
      return a.d;
    }
    case T_FLOAT: {
      union {
        uint32_t c;
        float d;
      } a;
      transport.readBytes(&(a.c), 4);
      a.c = ntohl(a.c);
      return a.d;
    }
    //case T_UTF7: // aliases T_STRING
    case T_UTF8:
    case T_UTF16:
    case T_STRING: {
      uint32_t size = transport.readU32();
      if (size && (size + 1)) {
        String s = String(size, ReserveString);
        char* strbuf = s.mutableData();
        transport.readBytes(strbuf, size);
        s.setSize(size);
        return s;
      } else {
        return empty_string_variant();
      }
    }
    case T_MAP: { // array of key -> value
      uint8_t types[2];
      transport.readBytes(types, 2);
      uint32_t size = transport.readU32();

      Array keyspec = fieldspec.rvalAt(PHPTransport::s_key,
                                       AccessFlags::Error_Key).toArray();
      Array valspec = fieldspec.rvalAt(PHPTransport::s_val,
                                       AccessFlags::Error_Key).toArray();
      String format = fieldspec.rvalAt(PHPTransport::s_format,
                                       AccessFlags::None).toString();
      if (format.equal(PHPTransport::s_collection)) {
        ret = newobj<c_Map>();
        for (uint32_t s = 0; s < size; ++s) {
          Variant key = binary_deserialize(types[0], transport, keyspec);
          Variant value = binary_deserialize(types[1], transport, valspec);
          collectionSet(ret.getObjectData(), key.asCell(), value.asCell());
        }
      } else {
        ret = Array::Create();
        for (uint32_t s = 0; s < size; ++s) {
          Variant key = binary_deserialize(types[0], transport, keyspec);
          Variant value = binary_deserialize(types[1], transport, valspec);
          ret.toArrRef().set(key, value);
        }
      }
      return ret; // return_value already populated
    }
    case T_LIST: { // array with autogenerated numeric keys
      int8_t type = transport.readI8();
      uint32_t size = transport.readU32();
      Variant elemvar = fieldspec.rvalAt(PHPTransport::s_elem,
                                         AccessFlags::Error_Key);
      Array elemspec = elemvar.toArray();
      String format = fieldspec.rvalAt(PHPTransport::s_format,
                                       AccessFlags::None).toString();

      if (format.equal(PHPTransport::s_collection)) {
        auto const pvec = newobj<c_Vector>();
        ret = pvec;
        for (uint32_t s = 0; s < size; ++s) {
          Variant value = binary_deserialize(type, transport, elemspec);
          pvec->t_add(value);
        }
      } else {
        PackedArrayInit pai(size);
        for (auto s = uint32_t{0}; s < size; ++s) {
          pai.append(binary_deserialize(type, transport, elemspec));
        }
        ret = pai.toArray();
      }

      return ret;
    }
    case T_SET: { // array of key -> TRUE
      uint8_t type;
      uint32_t size;
      transport.readBytes(&type, 1);
      transport.readBytes(&size, 4);
      size = ntohl(size);
      Variant elemvar = fieldspec.rvalAt(PHPTransport::s_elem,
                                         AccessFlags::Error_Key);
      Array elemspec = elemvar.toArray();
      String format = fieldspec.rvalAt(PHPTransport::s_format,
                                       AccessFlags::None).toString();
      if (format.equal(PHPTransport::s_collection)) {
        auto set_ret = makeSmartPtr<c_Set>();

        for (uint32_t s = 0; s < size; ++s) {
          Variant key = binary_deserialize(type, transport, elemspec);

          if (key.isInteger()) {
            set_ret->t_add(key);
          } else {
            set_ret->t_add(key.toString());
          }
        }

        ret = Variant(std::move(set_ret));
      } else {
        ArrayInit init(size, ArrayInit::Mixed{});
        for (uint32_t s = 0; s < size; ++s) {
          Variant key = binary_deserialize(type, transport, elemspec);
          if (key.isInteger()) {
            init.set(key, true);
          } else {
            init.setKeyUnconverted(key, true);
          }
        }
        ret = init.toArray();
      }
      return ret;
    }
  };

  char errbuf[128];
  sprintf(errbuf, "Unknown thrift typeID %d", thrift_typeID);
  throw_tprotocolexception(String(errbuf, CopyString), INVALID_DATA);
  return init_null();
}
Beispiel #12
0
void binary_deserialize(int8_t thrift_typeID, PHPInputTransport& transport, zval* return_value, HashTable* fieldspec) {
    zval** val_ptr;
    Z_TYPE_P(return_value) = IS_NULL; // just in case

    switch (thrift_typeID) {
    case T_STOP:
    case T_VOID:
        RETURN_NULL();
        return;
    case T_STRUCT: {
        if (zend_hash_find(fieldspec, "class", 6, (void**)&val_ptr) != SUCCESS) {
            throw_tprotocolexception("no class type in spec", INVALID_DATA);
            skip_element(T_STRUCT, transport);
            RETURN_NULL();
        }
        char* structType = Z_STRVAL_PP(val_ptr);
        createObject(structType, return_value);
        if (Z_TYPE_P(return_value) == IS_NULL) {
            // unable to create class entry
            skip_element(T_STRUCT, transport);
            RETURN_NULL();
        }
        TSRMLS_FETCH();
        zval* spec = zend_read_static_property(zend_get_class_entry(return_value TSRMLS_CC), "_TSPEC", 6, false TSRMLS_CC);
        if (Z_TYPE_P(spec) != IS_ARRAY) {
            char errbuf[128];
            snprintf(errbuf, 128, "spec for %s is wrong type: %d\n", structType, Z_TYPE_P(spec));
            throw_tprotocolexception(errbuf, INVALID_DATA);
            RETURN_NULL();
        }
        binary_deserialize_spec(return_value, transport, Z_ARRVAL_P(spec));
        return;
    }
    break;
    case T_BOOL: {
        uint8_t c;
        transport.readBytes(&c, 1);
        RETURN_BOOL(c != 0);
    }
    //case T_I08: // same numeric value as T_BYTE
    case T_BYTE: {
        uint8_t c;
        transport.readBytes(&c, 1);
        RETURN_LONG(c);
    }
    case T_I16: {
        uint16_t c;
        transport.readBytes(&c, 2);
        RETURN_LONG(ntohs(c));
    }
    case T_I32: {
        uint32_t c;
        transport.readBytes(&c, 4);
        RETURN_LONG(ntohl(c));
    }
    case T_U64:
    case T_I64: {
        uint64_t c;
        transport.readBytes(&c, 8);
        RETURN_LONG(ntohll(c));
    }
    case T_DOUBLE: {
        union {
            uint64_t c;
            double d;
        } a;
        transport.readBytes(&(a.c), 8);
        a.c = ntohll(a.c);
        RETURN_DOUBLE(a.d);
    }
    //case T_UTF7: // aliases T_STRING
    case T_UTF8:
    case T_UTF16:
    case T_STRING: {
        uint32_t size = transport.readU32();
        if (size) {
            char* strbuf = (char*) emalloc(size + 1);
            transport.readBytes(strbuf, size);
            strbuf[size] = '\0';
            ZVAL_STRINGL(return_value, strbuf, size, 0);
        } else {
            ZVAL_EMPTY_STRING(return_value);
        }
        return;
    }
    case T_MAP: { // array of key -> value
        uint8_t types[2];
        transport.readBytes(types, 2);
        uint32_t size = transport.readU32();
        array_init(return_value);

        zend_hash_find(fieldspec, "key", 4, (void**)&val_ptr);
        HashTable* keyspec = Z_ARRVAL_PP(val_ptr);
        zend_hash_find(fieldspec, "val", 4, (void**)&val_ptr);
        HashTable* valspec = Z_ARRVAL_PP(val_ptr);

        for (uint32_t s = 0; s < size; ++s) {
            zval *value;
            MAKE_STD_ZVAL(value);

            zval* key;
            MAKE_STD_ZVAL(key);

            binary_deserialize(types[0], transport, key, keyspec);
            binary_deserialize(types[1], transport, value, valspec);
            if (Z_TYPE_P(key) == IS_LONG) {
                zend_hash_index_update(return_value->value.ht, Z_LVAL_P(key), &value, sizeof(zval *), NULL);
            }
            else {
                if (Z_TYPE_P(key) != IS_STRING) convert_to_string(key);
                zend_hash_update(return_value->value.ht, Z_STRVAL_P(key), Z_STRLEN_P(key) + 1, &value, sizeof(zval *), NULL);
            }
            zval_ptr_dtor(&key);
        }
        return; // return_value already populated
    }
    case T_LIST: { // array with autogenerated numeric keys
        int8_t type = transport.readI8();
        uint32_t size = transport.readU32();
        zend_hash_find(fieldspec, "elem", 5, (void**)&val_ptr);
        HashTable* elemspec = Z_ARRVAL_PP(val_ptr);

        array_init(return_value);
        for (uint32_t s = 0; s < size; ++s) {
            zval *value;
            MAKE_STD_ZVAL(value);
            binary_deserialize(type, transport, value, elemspec);
            zend_hash_next_index_insert(return_value->value.ht, &value, sizeof(zval *), NULL);
        }
        return;
    }
    case T_SET: { // array of key -> TRUE
        uint8_t type;
        uint32_t size;
        transport.readBytes(&type, 1);
        transport.readBytes(&size, 4);
        size = ntohl(size);
        zend_hash_find(fieldspec, "elem", 5, (void**)&val_ptr);
        HashTable* elemspec = Z_ARRVAL_PP(val_ptr);

        array_init(return_value);

        for (uint32_t s = 0; s < size; ++s) {
            zval* key;
            zval* value;
            MAKE_STD_ZVAL(key);
            MAKE_STD_ZVAL(value);
            ZVAL_TRUE(value);

            binary_deserialize(type, transport, key, elemspec);

            if (Z_TYPE_P(key) == IS_LONG) {
                zend_hash_index_update(return_value->value.ht, Z_LVAL_P(key), &value, sizeof(zval *), NULL);
            }
            else {
                if (Z_TYPE_P(key) != IS_STRING) convert_to_string(key);
                zend_hash_update(return_value->value.ht, Z_STRVAL_P(key), Z_STRLEN_P(key) + 1, &value, sizeof(zval *), NULL);
            }
            zval_ptr_dtor(&key);
        }
        return;
    }
    };

    char errbuf[128];
    sprintf(errbuf, "Unknown thrift typeID %d", thrift_typeID);
    throw_tprotocolexception(errbuf, INVALID_DATA);
}
Beispiel #13
0
static
void binary_deserialize(int8_t thrift_typeID, PHPInputTransport& transport, zval* return_value, HashTable* fieldspec) {
  ZVAL_NULL(return_value);

  switch (thrift_typeID) {
    case T_STOP:
    case T_VOID:
      RETURN_NULL();
      return;
    case T_STRUCT: {
      zval* val_ptr = zend_hash_str_find(fieldspec, "class", sizeof("class")-1);
      if (val_ptr == nullptr) {
        throw_tprotocolexception("no class type in spec", INVALID_DATA);
        skip_element(T_STRUCT, transport);
        RETURN_NULL();
      }

      char* structType = Z_STRVAL_P(val_ptr);
      // Create an object in PHP userland based on our spec
      createObject(structType, return_value);
      if (Z_TYPE_P(return_value) == IS_NULL) {
        // unable to create class entry
        skip_element(T_STRUCT, transport);
        RETURN_NULL();
      }

      zval* spec = zend_read_static_property(Z_OBJCE_P(return_value), "_TSPEC", sizeof("_TSPEC")-1, false);
      if (Z_TYPE_P(spec) != IS_ARRAY) {
        char errbuf[128];
        snprintf(errbuf, 128, "spec for %s is wrong type: %d\n", structType, Z_TYPE_P(spec));
        throw_tprotocolexception(errbuf, INVALID_DATA);
        RETURN_NULL();
      }
      binary_deserialize_spec(return_value, transport, Z_ARRVAL_P(spec));
      return;
    } break;
    case T_BOOL: {
      uint8_t c;
      transport.readBytes(&c, 1);
      RETURN_BOOL(c != 0);
    }
  //case T_I08: // same numeric value as T_BYTE
    case T_BYTE: {
      uint8_t c;
      transport.readBytes(&c, 1);
      RETURN_LONG((int8_t)c);
    }
    case T_I16: {
      uint16_t c;
      transport.readBytes(&c, 2);
      RETURN_LONG((int16_t)ntohs(c));
    }
    case T_I32: {
      uint32_t c;
      transport.readBytes(&c, 4);
      RETURN_LONG((int32_t)ntohl(c));
    }
    case T_U64:
    case T_I64: {
      uint64_t c;
      transport.readBytes(&c, 8);
      RETURN_LONG((int64_t)ntohll(c));
    }
    case T_DOUBLE: {
      union {
        uint64_t c;
        double d;
      } a;
      transport.readBytes(&(a.c), 8);
      a.c = ntohll(a.c);
      RETURN_DOUBLE(a.d);
    }
    //case T_UTF7: // aliases T_STRING
    case T_UTF8:
    case T_UTF16:
    case T_STRING: {
      uint32_t size = transport.readU32();
      if (size) {
        char strbuf[size+1];
        transport.readBytes(strbuf, size);
        strbuf[size] = '\0';
        ZVAL_STRINGL(return_value, strbuf, size);
      } else {
        ZVAL_EMPTY_STRING(return_value);
      }
      return;
    }
    case T_MAP: { // array of key -> value
      uint8_t types[2];
      transport.readBytes(types, 2);
      uint32_t size = transport.readU32();
      array_init(return_value);

      zval *val_ptr;
      val_ptr = zend_hash_str_find(fieldspec, "key", sizeof("key")-1);
      HashTable* keyspec = Z_ARRVAL_P(val_ptr);
      val_ptr = zend_hash_str_find(fieldspec, "val", sizeof("val")-1);
      HashTable* valspec = Z_ARRVAL_P(val_ptr);

      for (uint32_t s = 0; s < size; ++s) {
        zval key, value;

        binary_deserialize(types[0], transport, &key, keyspec);
        binary_deserialize(types[1], transport, &value, valspec);
        if (Z_TYPE(key) == IS_LONG) {
          zend_hash_index_update(Z_ARR_P(return_value), Z_LVAL(key), &value);
        } else {
          if (Z_TYPE(key) != IS_STRING) convert_to_string(&key);
          zend_symtable_update(Z_ARR_P(return_value), Z_STR(key), &value);
        }
        zval_dtor(&key);
      }
      return; // return_value already populated
    }
    case T_LIST: { // array with autogenerated numeric keys
      int8_t type = transport.readI8();
      uint32_t size = transport.readU32();
      zval *val_ptr = zend_hash_str_find(fieldspec, "elem", sizeof("elem")-1);
      HashTable* elemspec = Z_ARRVAL_P(val_ptr);

      array_init(return_value);
      for (uint32_t s = 0; s < size; ++s) {
        zval value;
        binary_deserialize(type, transport, &value, elemspec);
        zend_hash_next_index_insert(Z_ARR_P(return_value), &value);
      }
      return;
    }
    case T_SET: { // array of key -> TRUE
      uint8_t type;
      uint32_t size;
      transport.readBytes(&type, 1);
      transport.readBytes(&size, 4);
      size = ntohl(size);
      zval *val_ptr = zend_hash_str_find(fieldspec, "elem", sizeof("elem")-1);
      HashTable* elemspec = Z_ARRVAL_P(val_ptr);

      array_init(return_value);

      for (uint32_t s = 0; s < size; ++s) {
        zval key, value;
        ZVAL_TRUE(&value);

        binary_deserialize(type, transport, &key, elemspec);

        if (Z_TYPE(key) == IS_LONG) {
          zend_hash_index_update(Z_ARR_P(return_value), Z_LVAL(key), &value);
        } else {
          if (Z_TYPE(key) != IS_STRING) convert_to_string(&key);
          zend_symtable_update(Z_ARR_P(return_value), Z_STR(key), &value);
        }
        zval_dtor(&key);
      }
      return;
    }
  };

  char errbuf[128];
  sprintf(errbuf, "Unknown thrift typeID %d", thrift_typeID);
  throw_tprotocolexception(errbuf, INVALID_DATA);
}
Beispiel #14
0
Variant binary_deserialize(int8_t thrift_typeID, PHPInputTransport& transport,
                           CArrRef fieldspec) {
  Variant ret;
  switch (thrift_typeID) {
    case T_STOP:
    case T_VOID:
      return uninit_null();
    case T_STRUCT: {
      Variant val;
      if ((val = fieldspec.rvalAt(PHPTransport::s_class)).isNull()) {
        throw_tprotocolexception("no class type in spec", INVALID_DATA);
        skip_element(T_STRUCT, transport);
        return uninit_null();
      }
      String structType = val.toString();
      ret = createObject(structType);
      if (ret.isNull()) {
        // unable to create class entry
        skip_element(T_STRUCT, transport);
        return uninit_null();
      }
      Variant spec = f_hphp_get_static_property(structType, s_TSPEC, false);
      if (!spec.is(KindOfArray)) {
        char errbuf[128];
        snprintf(errbuf, 128, "spec for %s is wrong type: %d\n",
                 structType.data(), ret.getType());
        throw_tprotocolexception(String(errbuf, CopyString), INVALID_DATA);
        return uninit_null();
      }
      binary_deserialize_spec(ret.toObject(), transport, spec.toArray());
      return ret;
    } break;
    case T_BOOL: {
      uint8_t c;
      transport.readBytes(&c, 1);
      return c != 0;
    }
  //case T_I08: // same numeric value as T_BYTE
    case T_BYTE: {
      uint8_t c;
      transport.readBytes(&c, 1);
      return Variant((int8_t)c);
    }
    case T_I16: {
      uint16_t c;
      transport.readBytes(&c, 2);
      return Variant((int16_t)ntohs(c));
    }
    case T_I32: {
      uint32_t c;
      transport.readBytes(&c, 4);
      return Variant((int32_t)ntohl(c));
    }
    case T_U64:
    case T_I64: {
      uint64_t c;
      transport.readBytes(&c, 8);
      return Variant((int64_t)ntohll(c));
    }
    case T_DOUBLE: {
      union {
        uint64_t c;
        double d;
      } a;
      transport.readBytes(&(a.c), 8);
      a.c = ntohll(a.c);
      return a.d;
    }
    case T_FLOAT: {
      union {
        uint32_t c;
        float d;
      } a;
      transport.readBytes(&(a.c), 4);
      a.c = ntohl(a.c);
      return a.d;
    }
    //case T_UTF7: // aliases T_STRING
    case T_UTF8:
    case T_UTF16:
    case T_STRING: {
      uint32_t size = transport.readU32();
      if (size && (size + 1)) {
        String s = String(size, ReserveString);
        char* strbuf = s.bufferSlice().ptr;
        transport.readBytes(strbuf, size);
        return s.setSize(size);
      } else {
        return "";
      }
    }
    case T_MAP: { // array of key -> value
      uint8_t types[2];
      transport.readBytes(types, 2);
      uint32_t size = transport.readU32();

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

      for (uint32_t s = 0; s < size; ++s) {
        Variant key = binary_deserialize(types[0], transport, keyspec);
        Variant value = binary_deserialize(types[1], transport, valspec);
        ret.set(key, value);
      }
      return ret; // return_value already populated
    }
    case T_LIST: { // array with autogenerated numeric keys
      int8_t type = transport.readI8();
      uint32_t size = transport.readU32();
      Variant elemvar = fieldspec.rvalAt(PHPTransport::s_elem,
                                         AccessFlags::Error_Key);
      Array elemspec = elemvar.toArray();
      ret = Array::Create();

      for (uint32_t s = 0; s < size; ++s) {
        Variant value = binary_deserialize(type, transport, elemspec);
        ret.append(value);
      }
      return ret;
    }
    case T_SET: { // array of key -> TRUE
      uint8_t type;
      uint32_t size;
      transport.readBytes(&type, 1);
      transport.readBytes(&size, 4);
      size = ntohl(size);
      Variant elemvar = fieldspec.rvalAt(PHPTransport::s_elem,
                                         AccessFlags::Error_Key);
      Array elemspec = elemvar.toArray();
      ret = Array::Create();

      for (uint32_t s = 0; s < size; ++s) {
        Variant key = binary_deserialize(type, transport, elemspec);

        if (key.isInteger()) {
          ret.set(key, true);
        } else {
          ret.set(key.toString(), true);
        }
      }
      return ret;
    }
  };

  char errbuf[128];
  sprintf(errbuf, "Unknown thrift typeID %d", thrift_typeID);
  throw_tprotocolexception(String(errbuf, CopyString), INVALID_DATA);
  return uninit_null();
}