Ejemplo n.º 1
0
static int  pb_encode_array(pb_ostream_t *stream, const pc_JSON *gprotos, const pc_JSON *protos,
        const pc_JSON *proto, pc_JSON *array) {
    pc_JSON *type = pc_JSON_GetObjectItem(proto, "type");
    const char *type_text = type->valuestring;
    size_t len = pc_JSON_GetArraySize(array);
    size_t i;
    /* simple msg */
    if (pb_get_type(type_text) && pb_get_type(type_text) != PB_string) {
        if (!pb_encode_tag_for_field(stream, proto)) {
            return 0;
        }

        if (!pb_encode_varint(stream, len)) {
            return 0;
        }
        for (i = 0; i < len; i++) {
            if (!pb_encode_proto(stream, gprotos, protos, proto,
                        pc_JSON_GetArrayItem(array, i))) {
                return 0;
            }
        }
    } else {
        for (i = 0; i < len; i++) {
            if (!pb_encode_tag_for_field(stream, proto)) {
                return 0;
            }
            if (!pb_encode_proto(stream, gprotos, protos, proto,
                        pc_JSON_GetArrayItem(array, i))) {
                return 0;
            }
        }
    }
    return 1;
}
Ejemplo n.º 2
0
static int checkreturn pb_encode_array(pb_ostream_t *stream, const json_t *gprotos, const json_t *protos,
                                       const json_t *proto, json_t *array) {
    json_t *type = json_object_get(proto, "type");
    const char *type_text = json_string_value(type);
    size_t len = json_array_size(array);
    size_t i;
    // simple msg
    if (pb__get_type(type_text) && pb__get_type(type_text) != PB_string) {
        if (!pb_encode_tag_for_field(stream, proto)) {
            return 0;
        }

        if (!pb_encode_varint(stream, len)) {
            return 0;
        }
        for (i = 0; i < len; i++) {
            if (!pb_encode_proto(stream, gprotos, protos, proto,
                                 json_array_get(array, i))) {
                return 0;
            }
        }
    } else {
        for (i = 0; i < len; i++) {
            if (!pb_encode_tag_for_field(stream, proto)) {
                return 0;
            }
            if (!pb_encode_proto(stream, gprotos, protos, proto,
                                 json_array_get(array, i))) {
                return 0;
            }
        }
    }
    return 1;
}
Ejemplo n.º 3
0
bool checkreturn pb_encode(pb_ostream_t *stream, const pb_field_t fields[], const void *src_struct)
{
    const pb_field_t *field = fields;
    const void *pData = src_struct;
    const void *pSize;
    size_t prev_size = 0;
    
    while (field->tag != 0)
    {
        pb_encoder_t func = PB_ENCODERS[PB_LTYPE(field->type)];
        pData = (const char*)pData + prev_size + field->data_offset;
        pSize = (const char*)pData + field->size_offset;
        
        prev_size = field->data_size;
        if (PB_HTYPE(field->type) == PB_HTYPE_ARRAY)
            prev_size *= field->array_size;
                
        switch (PB_HTYPE(field->type))
        {
            case PB_HTYPE_REQUIRED:
                if (!pb_encode_tag_for_field(stream, field))
                    return false;
                if (!func(stream, field, pData))
                    return false;
                break;
            
            case PB_HTYPE_OPTIONAL:
                if (*(const bool*)pSize)
                {
                    if (!pb_encode_tag_for_field(stream, field))
                        return false;
                
                    if (!func(stream, field, pData))
                        return false;
                }
                break;
            
            case PB_HTYPE_ARRAY:
                if (!encode_array(stream, field, pData, *(const size_t*)pSize, func))
                    return false;
                break;
            
            case PB_HTYPE_CALLBACK:
            {
                const pb_callback_t *callback = (const pb_callback_t*)pData;
                if (callback->funcs.encode != NULL)
                {
                    if (!callback->funcs.encode(stream, field, callback->arg))
                        return false;
                }
                break;
            }
        }
    
        field++;
    }
    
    return true;
}
Ejemplo n.º 4
0
/* Encode a field with static or pointer allocation, i.e. one whose data
 * is available to the encoder directly. */
static bool checkreturn encode_basic_field(pb_ostream_t *stream,
    const pb_field_t *field, const void *pData)
{
    pb_encoder_t func;
    const void *pSize;
    bool implicit_has = true;
    
    func = PB_ENCODERS[PB_LTYPE(field->type)];
    
    if (field->size_offset)
        pSize = (const char*)pData + field->size_offset;
    else
        pSize = &implicit_has;

    if (PB_ATYPE(field->type) == PB_ATYPE_POINTER)
    {
        /* pData is a pointer to the field, which contains pointer to
         * the data. If the 2nd pointer is NULL, it is interpreted as if
         * the has_field was false.
         */
        
        pData = *(const void* const*)pData;
        implicit_has = (pData != NULL);
    }

    switch (PB_HTYPE(field->type))
    {
        case PB_HTYPE_REQUIRED:
            if (!pData)
                PB_RETURN_ERROR(stream, "missing required field");
            if (!pb_encode_tag_for_field(stream, field))
                return false;
            if (!func(stream, field, pData))
                return false;
            break;
        
        case PB_HTYPE_OPTIONAL:
            if (*(const bool*)pSize)
            {
                if (!pb_encode_tag_for_field(stream, field))
                    return false;
            
                if (!func(stream, field, pData))
                    return false;
            }
            break;
        
        case PB_HTYPE_REPEATED:
            if (!encode_array(stream, field, pData, *(const size_t*)pSize, func))
                return false;
            break;
        
        default:
            PB_RETURN_ERROR(stream, "invalid field type");
    }
    
    return true;
}
static bool write_repeated_string(pb_ostream_t *stream, const pb_field_t *field, void * const *arg)
{
    return pb_encode_tag_for_field(stream, field) &&
           pb_encode_string(stream, 0, 0) &&
           pb_encode_tag_for_field(stream, field) &&
           pb_encode_string(stream, 0, 0) &&
           pb_encode_tag_for_field(stream, field) &&
           pb_encode_string(stream, 0, 0) &&
           pb_encode_tag_for_field(stream, field) &&
           pb_encode_string(stream, 0, 0) &&
           pb_encode_tag_for_field(stream, field) &&
           pb_encode_string(stream, *arg, strlen(*arg));
}
static bool write_repeated_svarint(pb_ostream_t *stream, const pb_field_t *field, void * const *arg)
{
    return pb_encode_tag_for_field(stream, field) &&
           pb_encode_svarint(stream, 0) &&
           pb_encode_tag_for_field(stream, field) &&
           pb_encode_svarint(stream, 0) &&
           pb_encode_tag_for_field(stream, field) &&
           pb_encode_svarint(stream, 0) &&
           pb_encode_tag_for_field(stream, field) &&
           pb_encode_svarint(stream, 0) &&
           pb_encode_tag_for_field(stream, field) &&
           pb_encode_svarint(stream, (long)*arg);
}
static bool write_repeated_emptymsg(pb_ostream_t *stream, const pb_field_t *field, void * const *arg)
{
    EmptyMessage emptymsg = {0};
    return pb_encode_tag_for_field(stream, field) &&
           pb_encode_submessage(stream, EmptyMessage_fields, &emptymsg) &&
           pb_encode_tag_for_field(stream, field) &&
           pb_encode_submessage(stream, EmptyMessage_fields, &emptymsg) &&
           pb_encode_tag_for_field(stream, field) &&
           pb_encode_submessage(stream, EmptyMessage_fields, &emptymsg) &&
           pb_encode_tag_for_field(stream, field) &&
           pb_encode_submessage(stream, EmptyMessage_fields, &emptymsg) &&
           pb_encode_tag_for_field(stream, field) &&
           pb_encode_submessage(stream, EmptyMessage_fields, &emptymsg);
}
static bool write_repeated_submsg(pb_ostream_t *stream, const pb_field_t *field, void * const *arg)
{
    SubMessage dummy = {""};

    return pb_encode_tag_for_field(stream, field) &&
           pb_encode_submessage(stream, SubMessage_fields, &dummy) &&
           pb_encode_tag_for_field(stream, field) &&
           pb_encode_submessage(stream, SubMessage_fields, &dummy) &&
           pb_encode_tag_for_field(stream, field) &&
           pb_encode_submessage(stream, SubMessage_fields, &dummy) &&
           pb_encode_tag_for_field(stream, field) &&
           pb_encode_submessage(stream, SubMessage_fields, &dummy) &&
           pb_encode_tag_for_field(stream, field) &&
           pb_encode_submessage(stream, SubMessage_fields, *arg);
}
Ejemplo n.º 9
0
/* Parse a dictionary in format {'name': value} and encode it directly to protobuf */
static bool encode_dictionary(pb_ostream_t *stream, const pb_field_t *field, void * const *arg)
{
    int textlen;
    char *p = (char*)*arg;
    if (*p == '{') p++;
    while (*p != '}')
    {
        KeyValuePair pair = KeyValuePair_init_zero;
        
        if (*p != '\'')
            PB_RETURN_ERROR(stream, "invalid key, missing quote");
        
        p++; /* Starting quote of key */
        textlen = strchr(p, '\'') - p;
        strncpy(pair.key, p, textlen);
        pair.key[textlen] = 0;
        p += textlen + 2;
        
        while (*p == ' ') p++;
        
        if (*p == '[')
        {
            /* Value is a tree */
            pair.treeValue.funcs.encode = encode_tree;
            pair.treeValue.arg = p;
        }
        else if (*p == '\'')
        {
            /* Value is a string */
            pair.has_stringValue = true;
            p++;
            textlen = strchr(p, '\'') - p;
            strncpy(pair.stringValue, p, textlen);
            pair.stringValue[textlen] = 0;
        }
        else if (*p == '{')
        {
            /* Value is a dictionary */
            pair.has_dictValue = true;
            pair.dictValue.dictItem.funcs.encode = encode_dictionary;
            pair.dictValue.dictItem.arg = p;
        }
        else
        {
            /* Value is integer */
            pair.has_intValue = true;
            pair.intValue = atoi(p);
        }
        
        p = find_end_of_item(p);
        
        if (!pb_encode_tag_for_field(stream, field))
            return false;
        
        if (!pb_encode_submessage(stream, KeyValuePair_fields, &pair))
            return false;
    }

    return true;
}
Ejemplo n.º 10
0
bool chargesensor_callback(pb_ostream_t *stream, const pb_field_t *field, void * const *arg)
{
  SensorReading sensormsg = SensorReading_init_zero;

  /* Fill in the lucky number */
  sensormsg.id = 6;
  sensormsg.has_id = true;
  if (ltc.isValid())
  {
    sensormsg.value1 = (int32_t)(ltc.getCharge()*1000);
    sensormsg.has_value1 = true;
  }
  else
  {
    sensormsg.error = 1;
    sensormsg.has_error = true;
  }

  /* This encodes the header for the field, based on the constant info
     from pb_field_t. */
  if (!pb_encode_tag_for_field(stream, field))
    return false;

  /* This encodes the data for the field, based on our FileInfo structure. */
  if (!pb_encode_submessage(stream, SensorReading_fields, &sensormsg))
    return false;

  return true;
}
Ejemplo n.º 11
0
bool npb_encode_string(pb_ostream_t *stream, const pb_field_t *field, void * const *arg)
{
    char *str = (char *)*arg;
    if (!pb_encode_tag_for_field(stream, field))
        return false;
    return pb_encode_string(stream, (uint8_t*)str, strlen(str));
}
Ejemplo n.º 12
0
/* Parse a tree in format [[1 2] 3] and encode it directly to protobuf */
static bool encode_tree(pb_ostream_t *stream, const pb_field_t *field, void * const *arg)
{
    TreeNode tree = TreeNode_init_zero;
    char *p = (char*)*arg;
    
    if (*p == '[')
    {
        /* This is a tree branch */
        p++;
        tree.left.funcs.encode = encode_tree;
        tree.left.arg = p;
        
        p = find_end_of_item(p);
        tree.right.funcs.encode = encode_tree;
        tree.right.arg = p;
    }
    else
    {
        /* This is a leaf node */
        tree.has_leaf = true;
        tree.leaf = atoi(p);
    }
    
    return pb_encode_tag_for_field(stream, field) &&
           pb_encode_submessage(stream, TreeNode_fields, &tree);
}
Ejemplo n.º 13
0
static bool write_string_from_arg(pb_ostream_t *stream, const pb_field_t *field,
                                  void *const *arg) {
  const char *str = *arg;
  if (!pb_encode_tag_for_field(stream, field)) return false;

  return pb_encode_string(stream, (uint8_t *)str, strlen(str));
}
Ejemplo n.º 14
0
bool motordataEncoderCallback(pb_ostream_t *stream, const pb_field_t *field, void * const *arg) {

	MotorMsg_Data_Param *tuple = ((MotorMsg_Data_Param *) (*arg));

	pb_encode_tag_for_field(stream, field);
	return pb_encode_submessage(stream, MotorMsg_Data_Param_fields, tuple);

}
Ejemplo n.º 15
0
/* Encode a field with static allocation, i.e. one whose data is stored
 * in the structure itself. */
static bool checkreturn encode_static_field(pb_ostream_t *stream,
    const pb_field_t *field, const void *pData)
{
    pb_encoder_t func;
    const void *pSize;
    bool dummy = true;
    
    func = PB_ENCODERS[PB_LTYPE(field->type)];
    
    if (field->size_offset)
        pSize = (const char*)pData + field->size_offset;
    else
        pSize = &dummy;
    
    switch (PB_HTYPE(field->type))
    {
        case PB_HTYPE_REQUIRED:
            if (!pb_encode_tag_for_field(stream, field))
                return false;
            if (!func(stream, field, pData))
                return false;
            break;
        
        case PB_HTYPE_OPTIONAL:
            if (*(const bool*)pSize)
            {
                if (!pb_encode_tag_for_field(stream, field))
                    return false;
            
                if (!func(stream, field, pData))
                    return false;
            }
            break;
        
        case PB_HTYPE_REPEATED:
            if (!encode_array(stream, field, pData, *(const size_t*)pSize, func))
                return false;
            break;
        
        default:
            PB_RETURN_ERROR(stream, "invalid field type");
    }
    
    return true;
}
Ejemplo n.º 16
0
// TODO: I'm not entirely sure why this can't be in the header...
bool micropb_callback_string_from_tensor(pb_ostream_t *stream, const pb_field_t *field, void * const *arg) {
  at::Tensor* t = static_cast<at::Tensor*>(*arg);
  JIT_ASSERT(t->is_contiguous());
  // Packed array format!
  pb_encode_tag_for_field(stream, field);
  pb_encode_string(stream, (pb_byte_t*)(t->data_ptr()),  t->type().elementSizeInBytes()*t->numel());

  return true;
}
Ejemplo n.º 17
0
bool encodeMotorMsg(pb_ostream_t *stream, const pb_field_t messagetype[], const void *message) {
	const pb_field_t *field;
	for (field = MotorMsg_fields; field->tag != 0; field++) {
		if (field->ptr == messagetype) {
			/* This is our field, encode the message using it. */
			if (!pb_encode_tag_for_field(stream, field))
				return false;

			return pb_encode_submessage(stream, messagetype, message);
		}
	}

	/* Didn't find the field for messagetype */
	return false;
}
static bool write_limits(pb_ostream_t *stream, const pb_field_t *field, void * const *arg)
{
    Limits limits = {0};
    limits.int32_min  = INT32_MIN;
    limits.int32_max  = INT32_MAX;
    limits.uint32_min = 0;
    limits.uint32_max = UINT32_MAX;
    limits.int64_min  = INT64_MIN;
    limits.int64_max  = INT64_MAX;
    limits.uint64_min = 0;
    limits.uint64_max = UINT64_MAX;
    limits.enum_min   = HugeEnum_Negative;
    limits.enum_max   = HugeEnum_Positive;
   
    return pb_encode_tag_for_field(stream, field) &&
           pb_encode_submessage(stream, Limits_fields, &limits);
}
Ejemplo n.º 19
0
/**
 * Message EPS encode callback function
 * @param stream
 * @param field
 * @param arg
 * @return
 */
bool ss_eps_encode(pb_ostream_t *stream, const pb_field_t *field, void * const *arg)
{
	EPS eps=EPS_init_zero;

	log_printf(LOG_VERBOSE,"Encoding EPS SubMessage!\n");
	char** arg_eps = (char **)arg[0];

	int i;
	int count=atoi(arg_eps[0]);
	arg_eps=arg_eps+1;

	for(i=0;i<count;i++)
	{
		arg_eps=arg_eps+i*7;

		strcpy(eps.profile_id,arg_eps[0]);
		eps.has_profile_id=true;
		strcpy(eps.device_id,arg_eps[1]);
		eps.has_device_id=true;
		strcpy(eps.zone_type,arg_eps[2]);
		eps.has_zone_type=true;
		strcpy(eps.ep,arg_eps[3]);
		eps.has_ep=true;
		strcpy(eps.ep_name,arg_eps[4]);
		eps.has_ep_name=true;
		eps.rid=atoi(arg_eps[5]);
		eps.has_rid=true;
		eps.arm=atoi(arg_eps[6]);
		eps.has_arm=true;

		if (!pb_encode_tag_for_field(stream, field))
			return false;

		//This encodes the data for the field, based on our FileInfo structure.
		if (!pb_encode_submessage(stream, EPS_fields, &eps))
			return false;
	}



	return true;
}
Ejemplo n.º 20
0
bool listdir_callback(pb_ostream_t *stream, const pb_field_t *field, const void *arg)
{
    DIR *dir = (DIR*) arg;
    struct dirent *file;
    FileInfo fileinfo;
    
    while ((file = readdir(dir)) != NULL)
    {
        fileinfo.inode = file->d_ino;
        strncpy(fileinfo.name, file->d_name, sizeof(fileinfo.name));
        fileinfo.name[sizeof(fileinfo.name) - 1] = '\0';
        
        if (!pb_encode_tag_for_field(stream, field))
            return false;
        
        if (!pb_enc_submessage(stream, field, &fileinfo))
            return false;
    }
    
    return true;
}
Ejemplo n.º 21
0
bool switchsensor_callback(pb_ostream_t *stream, const pb_field_t *field, void * const *arg)
{
  SensorReading sensormsg = SensorReading_init_zero;

  /* Fill in the lucky number */
  sensormsg.id = 1;
  sensormsg.has_id = true;
  sensormsg.value1 = microSwitch.ReadState();
  sensormsg.has_value1 = true;

  /* This encodes the header for the field, based on the constant info
     from pb_field_t. */
  if (!pb_encode_tag_for_field(stream, field))
    return false;

  /* This encodes the data for the field, based on our FileInfo structure. */
  if (!pb_encode_submessage(stream, SensorReading_fields, &sensormsg))
    return false;

  return true;
}
Ejemplo n.º 22
0
static int checkreturn pb_encode(pb_ostream_t *stream, const json_t *gprotos,
                                 const json_t *protos, json_t *msg) {
    json_t *root, *value, *option, *proto;
    root = msg;

    const char *option_text;
    const char *key;
    void *iter = json_object_iter(root);
    while (iter) {
        key = json_object_iter_key(iter);
        value = json_object_iter_value(iter);

        proto = json_object_get(protos, key);
        if (proto) {
            option = json_object_get(proto, "option");
            option_text = json_string_value(option);
            if (strcmp(option_text, "required") == 0
                    || strcmp(option_text, "optional") == 0) {
                if (!pb_encode_tag_for_field(stream, proto)) {
                    return 0;
                }

                if (!pb_encode_proto(stream, gprotos, protos, proto, value)) {
                    return 0;
                }
            } else if (strcmp(option_text, "repeated") == 0) {
                if (json_is_array(value)) {
                    if (!pb_encode_array(stream, gprotos, protos, proto, value)) {
                        return 0;
                    }
                }
            }
        } else {
            return 0;
        }
        iter = json_object_iter_next(root, iter);
    }
    return 1;
}
Ejemplo n.º 23
0
/* This function is the core of the union encoding process. It handles
 * the top-level pb_field_t array manually, in order to encode a correct
 * field tag before the message. The pointer to MsgType_fields array is
 * used as an unique identifier for the message type.
 */
bool encode_unionmessage(pb_ostream_t *stream, const pb_msgdesc_t *messagetype, void *message)
{
    pb_field_iter_t iter;

    if (!pb_field_iter_begin(&iter, UnionMessage_fields, message))
        return false;

    do
    {
        if (iter.submsg_desc == messagetype)
        {
            /* This is our field, encode the message using it. */
            if (!pb_encode_tag_for_field(stream, &iter))
                return false;
            
            return pb_encode_submessage(stream, messagetype, message);
        }
    } while (pb_field_iter_next(&iter));
    
    /* Didn't find the field for messagetype */
    return false;
}
Ejemplo n.º 24
0
static int  pb_encode(pb_ostream_t *stream, const pc_JSON *gprotos,
        const pc_JSON *protos, pc_JSON *msg) {
    pc_JSON *root = msg, *value, *option, *proto;

    const char *option_text;
    const char *key;
    value = root->child;
    while (value) {
        key = value->string;
        proto = pc_JSON_GetObjectItem(protos, key);
        if (proto) {
            option = pc_JSON_GetObjectItem(proto, "option");
            option_text = option->valuestring;
            if (strcmp(option_text, "required") == 0
                    || strcmp(option_text, "optional") == 0) {
                if (!pb_encode_tag_for_field(stream, proto)) {
                    return 0;
                }

                if (!pb_encode_proto(stream, gprotos, protos, proto, value)) {
                    return 0;
                }
            } else if (strcmp(option_text, "repeated") == 0) {
                if (value->type == pc_JSON_Array) {
                    if (!pb_encode_array(stream, gprotos, protos, proto, value)) {
                        return 0;
                    }
                }
            }
        } else {
            return 0;
        }
        value = value->next;
    }
    return 1;
}
Ejemplo n.º 25
0
/**
 * Message Dev encode callback function
 * @param stream
 * @param field
 * @param arg
 * @return
 */
bool ss_pb_encode_devlist(pb_ostream_t *stream, const pb_field_t *field, void * const *arg)
{

	int i,j;
	FILE *fd;

	log_printf(LOG_VERBOSE,"Encoding Devlist SubMessage!\n");
	char *args[100];
	char temp_str[100][40];
	char temp[40];
	Dev devlist=Dev_init_zero;

	struct dirent *ptr=NULL;
	DIR *dir;
	dir=opendir("/gl/etc/devlist");

	while((ptr=readdir(dir))!=NULL)
	{

		//跳过’.'和’..’两个目录
		if (ptr->d_name[0] == '.')
			continue;

		//printf("%s is ready...\n",ptr->d_name);
		char path[35]={'\0'};
		strcat(path,DEVINFO_DIR);
		strcat(path, ptr->d_name);
		fd = fopen(path, "r");
		if(fd==NULL)log_printf(LOG_ERROR,"Can't open path file!\n",path);

		j=0;
		while (!feof(fd))
		{

			fgets(temp, sizeof(temp), fd);
			int L;
			L = strlen(temp);
			for (i = 0; i <= L; i++)
				if (temp[i] == '\n')
				{
					temp[i] = 0;
				}
			strcpy(temp_str[j], temp);
			args[j]=temp_str[j];
			//printf("read test:%s\n",args[j]);
			j++;
		}

		strcpy(devlist.ieee, args[0]);
		devlist.has_ieee = true;
		strcpy(devlist.nwk_addr, args[1]);
		devlist.has_nwk_addr = true;
		strcpy(devlist.node_name, args[2]);
		devlist.has_node_name = true;
		devlist.online = atoi(args[3]);
		devlist.has_online = true;
		devlist.node_status = atoi(args[4]);
		devlist.has_node_status = true;
		devlist.eps.funcs.encode = &ss_eps_encode;
		devlist.eps.arg = args + 5;

		if (!pb_encode_tag_for_field(stream, field))
			return false;

		//This encodes the data for the field, based on our FileInfo structure.
		if (!pb_encode_submessage(stream, Dev_fields, &devlist))
			return false;

		fclose(fd);
	}

	return true;
}
static bool write_submsg(pb_ostream_t *stream, const pb_field_t *field, void * const *arg)
{
   
    return pb_encode_tag_for_field(stream, field) &&
           pb_encode_submessage(stream, SubMessage_fields, *arg);
}
static bool write_fixed64(pb_ostream_t *stream, const pb_field_t *field, void * const *arg)
{
    return pb_encode_tag_for_field(stream, field) &&
           pb_encode_fixed64(stream, *arg);
}
Ejemplo n.º 28
0
/* Callbacks don't need this function because they usually know the data type
 * without examining the field structure.
 * Therefore it is static for now.
 */
static bool checkreturn encode_array(pb_ostream_t *stream, const pb_field_t *field,
                         const void *pData, size_t count, pb_encoder_t func)
{
    size_t i;
    const void *p;
    size_t size;
    
    if (count == 0)
        return true;
    
    if (PB_LTYPE(field->type) <= PB_LTYPE_LAST_PACKABLE)
    {
        if (!pb_encode_tag(stream, PB_WT_STRING, field->tag))
            return false;
        
        /* Determine the total size of packed array. */
        if (PB_LTYPE(field->type) == PB_LTYPE_FIXED32)
        {
            size = 4 * count;
        }
        else if (PB_LTYPE(field->type) == PB_LTYPE_FIXED64)
        {
            size = 8 * count;
        }
        else
        {
            pb_ostream_t sizestream = {0,0,0,0};
            p = pData;
            for (i = 0; i < count; i++)
            {
                if (!func(&sizestream, field, p))
                    return false;
                p = (const char*)p + field->data_size;
            }
            size = sizestream.bytes_written;
        }
        
        if (!pb_encode_varint(stream, (uint64_t)size))
            return false;
        
        if (stream->callback == NULL)
            return pb_write(stream, NULL, size); /* Just sizing.. */
        
        /* Write the data */
        p = pData;
        for (i = 0; i < count; i++)
        {
            if (!func(stream, field, p))
                return false;
            p = (const char*)p + field->data_size;
        }
    }
    else
    {
        p = pData;
        for (i = 0; i < count; i++)
        {
            if (!pb_encode_tag_for_field(stream, field))
                return false;
            if (!func(stream, field, p))
                return false;
            p = (const char*)p + field->data_size;
        }
    }
    
    return true;
}
Ejemplo n.º 29
0
/* Encode a static array. Handles the size calculations and possible packing. */
static bool checkreturn encode_array(pb_ostream_t *stream, const pb_field_t *field,
                         const void *pData, size_t count, pb_encoder_t func)
{
    size_t i;
    const void *p;
    size_t size;
    
    if (count == 0)
        return true;

    if (PB_ATYPE(field->type) != PB_ATYPE_POINTER && count > field->array_size)
        PB_RETURN_ERROR(stream, "array max size exceeded");
    
    /* We always pack arrays if the datatype allows it. */
    if (PB_LTYPE(field->type) <= PB_LTYPE_LAST_PACKABLE)
    {
        if (!pb_encode_tag(stream, PB_WT_STRING, field->tag))
            return false;
        
        /* Determine the total size of packed array. */
        if (PB_LTYPE(field->type) == PB_LTYPE_FIXED32)
        {
            size = 4 * count;
        }
        else if (PB_LTYPE(field->type) == PB_LTYPE_FIXED64)
        {
            size = 8 * count;
        }
        else
        { 
            pb_ostream_t sizestream = PB_OSTREAM_SIZING;
            p = pData;
            for (i = 0; i < count; i++)
            {
                if (!func(&sizestream, field, p))
                    return false;
                p = (const char*)p + field->data_size;
            }
            size = sizestream.bytes_written;
        }
        
        if (!pb_encode_varint(stream, (uint64_t)size))
            return false;
        
        if (stream->callback == NULL)
            return pb_write(stream, NULL, size); /* Just sizing.. */
        
        /* Write the data */
        p = pData;
        for (i = 0; i < count; i++)
        {
            if (!func(stream, field, p))
                return false;
            p = (const char*)p + field->data_size;
        }
    }
    else
    {
        p = pData;
        for (i = 0; i < count; i++)
        {
            if (!pb_encode_tag_for_field(stream, field))
                return false;

            /* Normally the data is stored directly in the array entries, but
             * for pointer-type string and bytes fields, the array entries are
             * actually pointers themselves also. So we have to dereference once
             * more to get to the actual data. */
            if (PB_ATYPE(field->type) == PB_ATYPE_POINTER &&
                (PB_LTYPE(field->type) == PB_LTYPE_STRING ||
                 PB_LTYPE(field->type) == PB_LTYPE_BYTES))
            {
                if (!func(stream, field, *(const void* const*)p))
                    return false;      
            }
            else
            {
                if (!func(stream, field, p))
                    return false;
            }
            p = (const char*)p + field->data_size;
        }
    }
    
    return true;
}