static bool checkreturn decode_callback_field(pb_istream_t *stream, pb_wire_type_t wire_type, pb_field_iterator_t *iter)
{
    pb_callback_t *pCallback = (pb_callback_t*)iter->pData;
    
#ifdef PB_OLD_CALLBACK_STYLE
    void *arg = pCallback->arg;
#else
    void **arg = &(pCallback->arg);
#endif
    
    if (pCallback->funcs.decode == NULL)
        return pb_skip_field(stream, wire_type);
    
    if (wire_type == PB_WT_STRING)
    {
        pb_istream_t substream;
        
        if (!pb_make_string_substream(stream, &substream))
            return false;
        
        do
        {
            if (!pCallback->funcs.decode(&substream, iter->pos, arg))
                PB_RETURN_ERROR(stream, "callback failed");
        } while (substream.bytes_left);
        
        pb_close_string_substream(stream, &substream);
        return true;
    }
    else
    {
        /* Copy the single scalar value to stack.
         * This is required so that we can limit the stream length,
         * which in turn allows to use same callback for packed and
         * not-packed fields. */
        pb_istream_t substream;
        uint8_t buffer[10];
        size_t size = sizeof(buffer);
        
        if (!read_raw_value(stream, wire_type, buffer, &size))
            return false;
        substream = pb_istream_from_buffer(buffer, size);
        
        return pCallback->funcs.decode(&substream, iter->pos, arg);
    }
}
Esempio n. 2
0
const pb_field_t* decodeMotorMsgType(pb_istream_t *stream) {
	pb_wire_type_t wire_type;
	uint32_t tag;
	bool eof;

	while (pb_decode_tag(stream, &wire_type, &tag, &eof)) {
		if (wire_type == PB_WT_STRING) {
			const pb_field_t *field;
			for (field = MotorMsg_fields; field->tag != 0; field++) {
				if (field->tag == tag && ((field->type & PB_LTYPE_MASK) == PB_LTYPE_SUBMESSAGE)) {
					return field->ptr;
				}
			}
		}
		pb_skip_field(stream, wire_type);
	}
	return NULL;
}
Esempio n. 3
0
bool checkreturn pb_decode_noinit(pb_istream_t *stream, const pb_field_t fields[], void *dest_struct)
{
    uint8_t fields_seen[(PB_MAX_REQUIRED_FIELDS + 7) / 8] = {0}; /* Used to check for required fields */
    pb_field_iterator_t iter;

    pb_field_init(&iter, fields, dest_struct);

    while (stream->bytes_left)
    {
        uint32_t tag;
        pb_wire_type_t wire_type;
        bool eof;

        if (!pb_decode_tag(stream, &wire_type, &tag, &eof))
        {
            if (eof)
                break;
            else
                return false;
        }

        if (!pb_field_find(&iter, tag))
        {
            /* No match found, skip data */
            if (!pb_skip_field(stream, wire_type))
                return false;
            continue;
        }

        if (PB_HTYPE(iter.current->type) == PB_HTYPE_REQUIRED
                && iter.required_field_index < PB_MAX_REQUIRED_FIELDS)
        {
            fields_seen[iter.required_field_index >> 3] |= (uint8_t)(1 << (iter.required_field_index & 7));
        }

        if (!decode_field(stream, wire_type, &iter))
            return false;
    }
Esempio n. 4
0
static bool checkreturn decode_field(pb_istream_t *stream, pb_wire_type_t wire_type, pb_field_iterator_t *iter)
{
    pb_decoder_t func = PB_DECODERS[PB_LTYPE(iter->current->type)];

    switch (PB_HTYPE(iter->current->type))
    {
    case PB_HTYPE_REQUIRED:
        return func(stream, iter->current, iter->pData);

    case PB_HTYPE_OPTIONAL:
        *(bool*)iter->pSize = true;
        return func(stream, iter->current, iter->pData);

    case PB_HTYPE_ARRAY:
        if (wire_type == PB_WT_STRING
                && PB_LTYPE(iter->current->type) <= PB_LTYPE_LAST_PACKABLE)
        {
            /* Packed array */
            bool status;
            size_t *size = (size_t*)iter->pSize;
            pb_istream_t substream;
            if (!pb_make_string_substream(stream, &substream))
                return false;

            while (substream.bytes_left && *size < iter->current->array_size)
            {
                void *pItem = (uint8_t*)iter->pData + iter->current->data_size * (*size);
                if (!func(&substream, iter->current, pItem))
                    return false;
                (*size)++;
            }
            status = (substream.bytes_left == 0);
            pb_close_string_substream(stream, &substream);
            return status;
        }
        else
        {
            /* Repeated field */
            size_t *size = (size_t*)iter->pSize;
            void *pItem = (uint8_t*)iter->pData + iter->current->data_size * (*size);
            if (*size >= iter->current->array_size)
                PB_RETURN_ERROR(stream, "array overflow");

            (*size)++;
            return func(stream, iter->current, pItem);
        }

    case PB_HTYPE_CALLBACK:
    {
        pb_callback_t *pCallback = (pb_callback_t*)iter->pData;

        if (pCallback->funcs.decode == NULL)
            return pb_skip_field(stream, wire_type);

        if (wire_type == PB_WT_STRING)
        {
            pb_istream_t substream;

            if (!pb_make_string_substream(stream, &substream))
                return false;

            while (substream.bytes_left)
            {
                if (!pCallback->funcs.decode(&substream, iter->current, pCallback->arg))
                    PB_RETURN_ERROR(stream, "callback failed");
            }

            pb_close_string_substream(stream, &substream);
            return true;
        }
        else
        {
            /* Copy the single scalar value to stack.
             * This is required so that we can limit the stream length,
             * which in turn allows to use same callback for packed and
             * not-packed fields. */
            pb_istream_t substream;
            uint8_t buffer[10];
            size_t size = sizeof(buffer);

            if (!read_raw_value(stream, wire_type, buffer, &size))
                return false;
            substream = pb_istream_from_buffer(buffer, size);

            return pCallback->funcs.decode(&substream, iter->current, pCallback->arg);
        }
    }

    default:
        PB_RETURN_ERROR(stream, "invalid field type");
    }
}
bool checkreturn pb_decode_noinit(pb_istream_t *stream, const pb_field_t fields[], void *dest_struct)
{
    uint8_t fields_seen[(PB_MAX_REQUIRED_FIELDS + 7) / 8] = {0}; /* Used to check for required fields */
    uint32_t extension_range_start = 0;
    pb_field_iterator_t iter;
    
    pb_field_init(&iter, fields, dest_struct);
    
    while (stream->bytes_left)
    {
        uint32_t tag;
        pb_wire_type_t wire_type;
        bool eof;
        
        if (!pb_decode_tag(stream, &wire_type, &tag, &eof))
        {
            if (eof)
                break;
            else
                return false;
        }
        
        if (!pb_field_find(&iter, tag))
        {
            /* No match found, check if it matches an extension. */
            if (tag >= extension_range_start)
            {
                if (!find_extension_field(&iter))
                    extension_range_start = (uint32_t)-1;
                else
                    extension_range_start = iter.pos->tag;
                
                if (tag >= extension_range_start)
                {
                    size_t pos = stream->bytes_left;
                
                    if (!decode_extension(stream, tag, wire_type, &iter))
                        return false;
                    
                    if (pos != stream->bytes_left)
                    {
                        /* The field was handled */
                        continue;                    
                    }
                }
            }
        
            /* No match found, skip data */
            if (!pb_skip_field(stream, wire_type))
                return false;
            continue;
        }
        
        if (PB_HTYPE(iter.pos->type) == PB_HTYPE_REQUIRED
            && iter.required_field_index < PB_MAX_REQUIRED_FIELDS)
        {
            fields_seen[iter.required_field_index >> 3] |= (uint8_t)(1 << (iter.required_field_index & 7));
        }
            
        if (!decode_field(stream, wire_type, &iter))
            return false;
    }