bool checkreturn pb_read(pb_istream_t *stream, uint8_t *buf, size_t count)
{
#ifndef PB_BUFFER_ONLY
	if (buf == NULL && stream->callback != buf_read)
	{
		/* Skip input bytes */
		uint8_t tmp[16];
		while (count > 16)
		{
			if (!pb_read(stream, tmp, 16))
				return false;
			
			count -= 16;
		}
		
		return pb_read(stream, tmp, count);
	}
#endif

    if (stream->bytes_left < count)
        PB_RETURN_ERROR(stream, "end-of-stream");
    
#ifndef PB_BUFFER_ONLY
    if (!stream->callback(stream, buf, count))
        PB_RETURN_ERROR(stream, "io error");
#else
    if (!buf_read(stream, buf, count))
        return false;
#endif
    
    stream->bytes_left -= count;
    return true;
}
Exemple #2
0
static inline int  pb_decode_tag(pb_field_t *f)
{
    if (pb_decode_varint(f))
    {
        if(f->left == 0)
            f->eom = 1; // signal end-of-message
        return -1;
    }

    if (f->val.i64 == 0)
    {
        f->eom = 1; // Allow 0-terminated messages.
        PB_RETURN_ERROR(f, -2, "0-terminated msg");
    }

    f->tag = f->val.i64 >> 3;
    f->type = (pb_wire_type_t)(f->val.i32 & 7);

    DBGOUT("tag %u, type %u\n", f->tag, f->type);
    switch (f->type)
    {
        case PB_WT_VARINT: return pb_decode_varint(f);
        case PB_WT_FIXED64: return pb_decode_fixed64(f);
        case PB_WT_STRING: return pb_decode_string(f);
        case PB_WT_FIXED32: return pb_decode_fixed32(f);
        default: PB_RETURN_ERROR(f, -3, "invalid wire_type");
    }

    return 0;
}
Exemple #3
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;
}
Exemple #4
0
bool checkreturn pb_read(pb_istream_t *stream, uint8_t *buf, size_t count)
{
    if (stream->bytes_left < count)
        PB_RETURN_ERROR(stream, "end-of-stream");

    if (!stream->callback(stream, buf, count))
        PB_RETURN_ERROR(stream, "io error");

    stream->bytes_left -= count;
    return true;
}
Exemple #5
0
bool checkreturn pb_encode_submessage(pb_ostream_t *stream, const pb_field_t fields[], const void *src_struct)
{
    /* First calculate the message size using a non-writing substream. */
    pb_ostream_t substream = PB_OSTREAM_SIZING;
    size_t size;
    bool status;
    
    if (!pb_encode(&substream, fields, src_struct))
    {
#ifndef PB_NO_ERRMSG
        stream->errmsg = substream.errmsg;
#endif
        return false;
    }
    
    size = substream.bytes_written;
    
    if (!pb_encode_varint(stream, (uint64_t)size))
        return false;
    
    if (stream->callback == NULL)
        return pb_write(stream, NULL, size); /* Just sizing */
    
    if (stream->bytes_written + size > stream->max_size)
        PB_RETURN_ERROR(stream, "stream full");
        
    /* Use a substream to verify that a callback doesn't write more than
     * what it did the first time. */
    substream.callback = stream->callback;
    substream.state = stream->state;
    substream.max_size = size;
    substream.bytes_written = 0;
#ifndef PB_NO_ERRMSG
    substream.errmsg = NULL;
#endif
    
    status = pb_encode(&substream, fields, src_struct);
    
    stream->bytes_written += substream.bytes_written;
    stream->state = substream.state;
#ifndef PB_NO_ERRMSG
    stream->errmsg = substream.errmsg;
#endif
    
    if (substream.bytes_written != size)
        PB_RETURN_ERROR(stream, "submsg size changed");
    
    return status;
}
Exemple #6
0
static bool checkreturn pb_enc_submessage(pb_ostream_t *stream, const pb_field_t *field, const void *src)
{
    if (field->ptr == NULL)
        PB_RETURN_ERROR(stream, "invalid field descriptor");
    
    return pb_encode_submessage(stream, (const pb_field_t*)field->ptr, src);
}
Exemple #7
0
bool checkreturn pb_encode_tag_for_field(pb_ostream_t *stream, const pb_field_t *field)
{
    pb_wire_type_t wiretype;
    switch (PB_LTYPE(field->type))
    {
        case PB_LTYPE_VARINT:
        case PB_LTYPE_UVARINT:
        case PB_LTYPE_SVARINT:
            wiretype = PB_WT_VARINT;
            break;
        
        case PB_LTYPE_FIXED32:
            wiretype = PB_WT_32BIT;
            break;
        
        case PB_LTYPE_FIXED64:
            wiretype = PB_WT_64BIT;
            break;
        
        case PB_LTYPE_BYTES:
        case PB_LTYPE_STRING:
        case PB_LTYPE_SUBMESSAGE:
            wiretype = PB_WT_STRING;
            break;
        
        default:
            PB_RETURN_ERROR(stream, "invalid field type");
    }
    
    return pb_encode_tag(stream, wiretype, field->tag);
}
static bool checkreturn pb_decode_varint32(pb_istream_t *stream, uint32_t *dest)
{
    uint8_t byte;
    uint32_t result;
    
    if (!pb_read(stream, &byte, 1))
        return false;
    
    if (!(byte & 0x80))
    {
        /* Quick case, 1 byte value */
        result = byte;
    }
    else
    {
        /* Multibyte case */
        uint8_t bitpos = 7;
        result = byte & 0x7F;
        
        do
        {
            if (bitpos >= 32)
                PB_RETURN_ERROR(stream, "varint overflow");
            
            if (!pb_read(stream, &byte, 1))
                return false;
            
            result |= (uint32_t)(byte & 0x7F) << bitpos;
            bitpos = (uint8_t)(bitpos + 7);
        } while (byte & 0x80);
   }
   
   *dest = result;
   return true;
}
Exemple #9
0
/* Read a raw value to buffer, for the purpose of passing it to callback as
 * a substream. Size is maximum size on call, and actual size on return.
 */
static bool checkreturn read_raw_value(pb_istream_t *stream, pb_wire_type_t wire_type, uint8_t *buf, size_t *size)
{
    size_t max_size = *size;
    switch (wire_type)
    {
    case PB_WT_VARINT:
        *size = 0;
        do
        {
            (*size)++;
            if (*size > max_size) return false;
            if (!pb_read(stream, buf, 1)) return false;
        } while (*buf++ & 0x80);
        return true;

    case PB_WT_64BIT:
        *size = 8;
        return pb_read(stream, buf, 8);

    case PB_WT_32BIT:
        *size = 4;
        return pb_read(stream, buf, 4);

    default:
        PB_RETURN_ERROR(stream, "invalid wire_type");
    }
}
/* 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;
}
/* Read a single byte from input stream. buf may not be NULL.
 * This is an optimization for the varint decoding. */
static bool checkreturn pb_readbyte(pb_istream_t *stream, uint8_t *buf)
{
    if (!stream->bytes_left)
        PB_RETURN_ERROR(stream, "end-of-stream");

#ifndef PB_BUFFER_ONLY
    if (!stream->callback(stream, buf, 1))
        PB_RETURN_ERROR(stream, "io error");
#else
    *buf = *(uint8_t*)stream->state;
    stream->state = (uint8_t*)stream->state + 1;
#endif

    stream->bytes_left--;
    
    return true;    
}
bool checkreturn pb_enc_bytes(pb_ostream_t *stream, const pb_field_t *field, const void *src)
{
    const pb_bytes_array_t *bytes = (const pb_bytes_array_t*)src;

    if (bytes->size + offsetof(pb_bytes_array_t, bytes) > field->data_size)
        PB_RETURN_ERROR(stream, "bytes size exceeded");
    
    return pb_encode_string(stream, bytes->bytes, bytes->size);
}
Exemple #13
0
bool checkreturn pb_write(pb_ostream_t *stream, const uint8_t *buf, size_t count)
{
    if (stream->callback != NULL)
    {
        if (stream->bytes_written + count > stream->max_size)
            PB_RETURN_ERROR(stream, "stream full");

#ifdef PB_BUFFER_ONLY
        if (!buf_write(stream, buf, count))
            PB_RETURN_ERROR(stream, "io error");
#else        
        if (!stream->callback(stream, buf, count))
            PB_RETURN_ERROR(stream, "io error");
#endif
    }
    
    stream->bytes_written += count;
    return true;
}
Exemple #14
0
static inline int  pb_get_byte(pb_field_t *f, uint8_t *buf)
{
    if (f->left < 1)
        PB_RETURN_ERROR(f, -1, "end-of-buffer");

    if(buf) *buf = *(uint8_t*)f->ptr;
    f->ptr += 1;
    f->left -= 1;
    return 0;
}
Exemple #15
0
static inline int  pb_get_ddword(pb_field_t *f, uint64_t *buf)
{
    if (f->left < 8)
        PB_RETURN_ERROR(f, -1, "end-of-buffer");

    if(buf) *buf = *(uint64_t*)f->ptr;
    f->ptr += 8;
    f->left -= 8;
    return 0;
}
Exemple #16
0
int  pb_skip_field(pb_field_t *f, pb_wire_type_t wire_type)
{
    switch (wire_type)
    {
        case PB_WT_VARINT: return pb_skip_varint(f);
        case PB_WT_FIXED64: return pb_get_ddword(f, NULL);
        case PB_WT_STRING: return pb_skip_string(f);
        case PB_WT_FIXED32: return pb_get_dword(f, NULL);
        default: PB_RETURN_ERROR(f, -1, "invalid wire_type");
    }
}
bool checkreturn pb_skip_field(pb_istream_t *stream, pb_wire_type_t wire_type)
{
    switch (wire_type)
    {
        case PB_WT_VARINT: return pb_skip_varint(stream);
        case PB_WT_64BIT: return pb_read(stream, NULL, 8);
        case PB_WT_STRING: return pb_skip_string(stream);
        case PB_WT_32BIT: return pb_read(stream, NULL, 4);
        default: PB_RETURN_ERROR(stream, "invalid wire_type");
    }
}
Exemple #18
0
static inline int  pb_get(pb_field_t *f, uint8_t *buf, size_t count)
{
    if ((size_t )f->left < count)
        PB_RETURN_ERROR(f, -1, "end-of-buffer");

    if(buf) memcpy(buf, f->ptr, count);
    f->ptr += count;
    f->left -= count;

    return 0;
}
Exemple #19
0
static inline int  pb_add_ddword(pb_buff_t *b, uint64_t val)
{
    if(b->left < 8)
        PB_RETURN_ERROR(b, -1, "buf overflow");

    *(uint64_t*)b->ptr = val;
    DBGOUT("add_ddword: %02x %02x %02x %02x %02x %02x %02x %02x\n", b->ptr[0], b->ptr[1], b->ptr[2], b->ptr[3], b->ptr[4], b->ptr[5], b->ptr[6], b->ptr[7]);
    b->ptr += 8;
    b->left -= 8;

    return 0;
}
Exemple #20
0
/*
static inline int  pb_add_byte(pb_buff_t *b, const uint8_t *buf)
{
    if(b->left < 1)
        PB_RETURN_ERROR(b, -1, "buf overflow");

    *(uint8_t*)b->ptr = *buf;
    b->ptr += 1;
    b->left -= 1;

    DBGOUT("add_byte: %02x\n", *buf);
    return 0;
}
*/
static inline int  pb_add_dword(pb_buff_t *b, uint32_t val)
{
    if(b->left < 4)
        PB_RETURN_ERROR(b, -1, "buf overflow");

    *(uint32_t*)b->ptr = val;
    DBGOUT("add_dword: %02x %02x %02x %02x\n", b->ptr[0], b->ptr[1], b->ptr[2], b->ptr[3]);
    b->ptr += 4;
    b->left -= 4;

    return 0;
}
bool checkreturn pb_enc_svarint(pb_ostream_t *stream, const pb_field_t *field, const void *src)
{
    int64_t value = 0;
    
    switch (field->data_size)
    {
        case 4: value = *(const int32_t*)src; break;
        case 8: value = *(const int64_t*)src; break;
        default: PB_RETURN_ERROR(stream, "invalid data_size");
    }
    
    return pb_encode_svarint(stream, value);
}
Exemple #22
0
bool write_callback(pb_ostream_t *stream, const uint8_t *buf, size_t count)
{
    faulty_stream_t *state = stream->state;
    
    while (count--)
    {
        if (state->fail_after == 0)
            PB_RETURN_ERROR(stream, "simulated");
        state->fail_after--;
        *state->buffer++ = *buf++;
    }
    
    return true;
}
Exemple #23
0
/* Decode string length from stream and return a substream with limited length.
 * Remember to close the substream using pb_close_string_substream().
 */
bool checkreturn pb_make_string_substream(pb_istream_t *stream, pb_istream_t *substream)
{
    uint32_t size;
    if (!pb_decode_varint32(stream, &size))
        return false;

    *substream = *stream;
    if (substream->bytes_left < size)
        PB_RETURN_ERROR(stream, "parent stream too short");

    substream->bytes_left = size;
    stream->bytes_left -= size;
    return true;
}
static bool checkreturn decode_field(pb_istream_t *stream, pb_wire_type_t wire_type, pb_field_iterator_t *iter)
{
    switch (PB_ATYPE(iter->current->type))
    {
        case PB_ATYPE_STATIC:
            return decode_static_field(stream, wire_type, iter);
        
        case PB_ATYPE_CALLBACK:
            return decode_callback_field(stream, wire_type, iter);
        
        default:
            PB_RETURN_ERROR(stream, "invalid field type");
    }
}
/* Encode a single field of any callback or static type. */
static bool checkreturn encode_field(pb_ostream_t *stream,
    const pb_field_t *field, const void *pData)
{
    switch (PB_ATYPE(field->type))
    {
        case PB_ATYPE_STATIC:
            return encode_static_field(stream, field, pData);
        
        case PB_ATYPE_CALLBACK:
            return encode_callback_field(stream, field, pData);
        
        default:
            PB_RETURN_ERROR(stream, "invalid field type");
    }
}
Exemple #26
0
int pb_add_field_val(pb_buff_t *b, uint32_t tag, pb_wire_type_t type, const pb_field_val_t *val)
{
    DBGOUT("add_field_val:");
    int ret = pb_add_tag(b, type, tag);
    if(ret)
        return -1;
    switch (type)
    {
        case PB_WT_VARINT: return pb_add_vint(b, val->i64);
        case PB_WT_FIXED64: return pb_add_ddword(b, val->i64);
        case PB_WT_STRING: if(pb_add_vint(b, val->str.len)) return -2; return pb_add(b, val->str.data, val->str.len);
        case PB_WT_FIXED32: return pb_add_dword(b, val->i32);
        default: PB_RETURN_ERROR(b, -2, "invalid wire_type");
    }
}
Exemple #27
0
static inline int  pb_add(pb_buff_t *b, const void *buf, size_t count)
{
    if((size_t)b->left < count)
        PB_RETURN_ERROR(b, -1, "buf overflow");

    DBGOUT("add(len=%u):", count);
//    int i; 
//    for(i=0; i<count; i++) DBGOUT(" %02x", ((uint8_t*)buf)[i]);
    DBGOUT("\n");
    memcpy(b->ptr, buf, count);
    b->ptr += count;
    b->left -= count;

    return 0;
}
Exemple #28
0
static inline int  pb_decode_string(pb_field_t *f)
{
    uint32_t sz;
    if (pb_decode_varint(f))
        return -1;

    if (f->val.i64 > (uint64_t)f->left)
        PB_RETURN_ERROR(f, -2, "string overflow");

    sz = f->val.i64;
    f->val.str.len = sz;
    f->val.str.data = (char*)f->ptr;
    f->ptr += sz;
    f->left -= sz;
    return 0;
}
Exemple #29
0
pb_field_t *pb_begin_delimited(pb_field_t *f, const void *data, int dlen)
{
    f->start = f->ptr = (char *)data;
    f->size = f->left = dlen;
    f->eom = 0;

    if (pb_decode_varint(f))
        return NULL;
    if(f->val.i64 > (uint64_t)f->left)
        PB_RETURN_ERROR(f, NULL, "delimited overflow");
    f->left = f->val.i64;

    if(pb_decode_tag(f))
        return NULL;
    return f;
}
Exemple #30
0
bool checkreturn pb_decode_varint(pb_istream_t *stream, uint64_t *dest)
{
    uint8_t byte;
    int bitpos = 0;
    *dest = 0;

    while (bitpos < 64 && pb_read(stream, &byte, 1))
    {
        *dest |= (uint64_t)(byte & 0x7F) << bitpos;
        bitpos += 7;

        if (!(byte & 0x80))
            return true;
    }

    PB_RETURN_ERROR(stream, "varint overflow");
}