| /* $Id$ | |
| * | |
| * Licensed to the Apache Software Foundation (ASF) under one or more | |
| * contributor license agreements. See the NOTICE file distributed with | |
| * this work for additional information regarding copyright ownership. | |
| * The ASF licenses this file to you under the Apache License, Version | |
| * 2.0 (the "License"); you may not use this file except in compliance | |
| * with the License. You may obtain a copy of the License at | |
| * | |
| * http://www.apache.org/licenses/LICENSE-2.0 | |
| * | |
| * Unless required by applicable law or agreed to in writing, software | |
| * distributed under the License is distributed on an "AS IS" BASIS, | |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| * See the License for the specific language governing permissions and | |
| * limitations under the License. | |
| */ | |
| /* | |
| * etchflexbuf.c | |
| * flex buffer | |
| */ | |
| #include "etchflexbuf.h" | |
| #include "etchobjtypes.h" | |
| #include "etch_global.h" | |
| #include "etchlog.h" | |
| #define ETCH_INIT_FLEXBUFSIZE 2048 | |
| #define ETCH_MAX_FLEXBUFSIZE (4*1024*1024) | |
| void etch_flexbuf_fix_length (etch_flexbuffer*); | |
| BOOLEAN etch_flexbuf_ensure_size (etch_flexbuffer*, size_t); | |
| /* | |
| * java binding syntax is confusing and ambiguous so we change it a bit. java | |
| * calls the data region in the buffer "length". since "length" is non-specific, | |
| * and there are other "length"s, such as "buffer.length", and "object.length", | |
| * we'll call it "datalen", to mean "meaningful bytes within the buffer". java | |
| * also uses "buffer.length", which is the size of the allocated buffer. c of | |
| * course does not associate properties with arrays, so we carry an additional | |
| * property "bufsize" to indicate the allocated length of the byte array. | |
| */ | |
| /** | |
| * new_flexbuffer() | |
| * etch_flexbuffer constructor | |
| */ | |
| etch_flexbuffer *new_flexbuffer (size_t bufsize) | |
| { | |
| void *buf; | |
| if (bufsize <= 0 || bufsize > ETCH_MAX_FLEXBUFSIZE) bufsize = ETCH_INIT_FLEXBUFSIZE; | |
| buf = etch_malloc(bufsize, ETCHTYPEB_BYTES); | |
| memset(buf, 0, bufsize); | |
| return etch_flexbuf_create_bi (buf, bufsize, 0, 0); | |
| } | |
| /** | |
| * new_flexwriter_from() | |
| * etch_flexbuffer constructor with index set to write | |
| */ | |
| etch_flexbuffer *new_flexwriter_from (void *buf, size_t datalen, size_t bufsize) | |
| { | |
| return new_flexbuffer_from (buf, datalen, bufsize, datalen); | |
| } | |
| /** | |
| * new_flexbuffer_from() | |
| * etch_flexbuffer constructor. | |
| * @param buf data which is to become the internal buffer. caller relinquishes this memory. | |
| * @param datalen length of real data in bytes. | |
| * @param bufsize size of buffer in bytes. | |
| * @param buffer index at which to start. | |
| */ | |
| etch_flexbuffer *new_flexbuffer_from (void* buf, size_t datalen, size_t bufsize, size_t index) | |
| { | |
| if (bufsize <= 0 || bufsize > ETCH_MAX_FLEXBUFSIZE) bufsize = ETCH_INIT_FLEXBUFSIZE; | |
| if (datalen > bufsize || (!buf && datalen)) return NULL; | |
| if (NULL == buf) | |
| { buf = etch_malloc(bufsize, ETCHTYPEB_BYTES); | |
| memset(buf, 0, bufsize); | |
| } | |
| return etch_flexbuf_create_bi (buf, bufsize, datalen, index); | |
| } | |
| /** | |
| * etch_flexbuf_create_b() | |
| * create a flex buffer out of an existing buffer, ready to read to, | |
| * using specified size and an index of zero. | |
| * | |
| * @param buf the existing buffer. | |
| * @param bufsize the buffer size. | |
| * @param datalen the data length in the buffer | |
| * | |
| * @return the created and initialized the flex buffer. | |
| * | |
| */ | |
| etch_flexbuffer *etch_flexbuf_create_b (void *buf, size_t bufsize, size_t datalen) | |
| { | |
| return etch_flexbuf_create_bi(buf, bufsize, datalen, 0); | |
| } | |
| /** | |
| * etch_flexbuf_create_bi() | |
| * create a flex buffer out of an existing buffer, ready to read with specified | |
| * index and size. | |
| * @param buf the existing buffer. | |
| * @param bufsize the buffer size. | |
| * @param datalen the data length in the buffer | |
| * @param index current position of the buffer. | |
| */ | |
| etch_flexbuffer *etch_flexbuf_create_bi (void *buf, size_t bufsize, size_t datalen, size_t index) | |
| { | |
| etch_flexbuffer *fbuf = (etch_flexbuffer*) new_object | |
| (sizeof(etch_flexbuffer), ETCHTYPEB_FLEXBUF, CLASSID_FLEXBUF); | |
| fbuf->destroy = destroy_etch_flexbuffer; | |
| fbuf->buf = buf; | |
| fbuf->bufsize = bufsize; | |
| fbuf->datalen = datalen; | |
| fbuf->index = index; | |
| fbuf->is_littleendian = IS_ETCH_TRANSPORT_LITTLEENDIAN; | |
| return fbuf; | |
| } | |
| /** | |
| * etch_flexbuf_get_buffer() | |
| * @return the current byte array. might change if any operation | |
| * needs to extend length past the end of the array. | |
| */ | |
| byte* etch_flexbuf_get_buffer (etch_flexbuffer *fbuf) | |
| { | |
| return fbuf->buf; | |
| } | |
| /** | |
| * etch_flexbuf_clear() | |
| * zero fill the internal buffer | |
| */ | |
| void etch_flexbuf_clear (etch_flexbuffer *fbuf) | |
| { | |
| memset (fbuf->buf, 0, fbuf->bufsize); | |
| } | |
| /** | |
| * etch_flexbuf_ensure_size(). | |
| * verify sufficient buffer capacity, reallocating if necessary. | |
| * @return boolean value indicating if buffer is as requested. | |
| */ | |
| static int etch_flexbuf_ensure_size (etch_flexbuffer *fbuf, size_t reqsize) | |
| { | |
| byte *newbuf = NULL; | |
| size_t newsize = fbuf->bufsize; | |
| if (reqsize < ETCH_INIT_FLEXBUFSIZE) | |
| reqsize = ETCH_INIT_FLEXBUFSIZE; | |
| if (reqsize <= newsize) return TRUE; | |
| if (reqsize > ETCH_MAX_FLEXBUFSIZE) return FALSE; | |
| while(reqsize > newsize) newsize += ETCH_INIT_FLEXBUFSIZE; | |
| newbuf = etch_realloc (fbuf->buf, newsize, 0); | |
| fbuf->buf = newbuf; | |
| fbuf->bufsize = newsize; | |
| return TRUE; | |
| } | |
| /** | |
| * destroy_etch_flexbuffer() | |
| * etch_flexbuffer destructor | |
| */ | |
| int destroy_etch_flexbuffer(etch_flexbuffer *fbuf) | |
| { | |
| if (fbuf == NULL) return 0; | |
| if (fbuf->refcount > 0 && --fbuf->refcount > 0) return 0; | |
| if (!is_etchobj_static_content(fbuf)) | |
| etch_free(fbuf->buf); /* OK if null */ | |
| destroy_objectex((objmask*) fbuf); | |
| return 0; | |
| } | |
| /** | |
| * sets a new data length. If the index is larger than new length, | |
| * the index is set to the new length as well. | |
| * the method name was retained from java, however it is more properly | |
| * set_data_length, since as noted previously, "length" is ambiguous, | |
| * referring to data length, not to allocated bytes. | |
| */ | |
| int etch_flexbuf_set_length (etch_flexbuffer *fbuf, size_t new_datalen) | |
| { | |
| int result = 0; | |
| if (new_datalen >= 0 && etch_flexbuf_ensure_size(fbuf, new_datalen)) | |
| { | |
| fbuf->datalen = new_datalen; | |
| if (fbuf->index > new_datalen) | |
| fbuf->index = new_datalen; | |
| } | |
| else result = -1; | |
| return result; | |
| } | |
| /** | |
| * sets a new buffer index. the index must be greater than 0 and less | |
| * than the buffer size | |
| * @param fbuf the buffer pointer to be set. | |
| * @param index the new index for the buffer. | |
| */ | |
| int etch_flexbuf_set_index (etch_flexbuffer *fbuf, size_t index) | |
| { | |
| if (index < 0 || index > fbuf->datalen) return -1; | |
| fbuf->index = index; | |
| return 0; | |
| } | |
| /** | |
| * get the number of bytes available in the buffer. | |
| * @return the available space in the buffer. | |
| */ | |
| size_t etch_flexbuf_avail (etch_flexbuffer *fbuf) | |
| { | |
| return (fbuf->datalen - fbuf->index); | |
| } | |
| /** | |
| * etch_flexbuffer_reset_to() | |
| * set index to zero and length to specified length. | |
| */ | |
| int etch_flexbuffer_reset_to (etch_flexbuffer *fbuf, size_t new_datalen) | |
| { | |
| const int result = etch_flexbuf_set_length (fbuf, new_datalen); | |
| fbuf->index = 0; | |
| return result; | |
| } | |
| /** | |
| * etch_flexbuf_reset() | |
| * set index and length to zero, same as etch_flexbuf_set_index(buf, 0) | |
| */ | |
| etch_flexbuffer *etch_flexbuf_reset (etch_flexbuffer *fbuf) | |
| { | |
| fbuf->index = fbuf->datalen = 0; | |
| return fbuf; | |
| } | |
| /** | |
| * Compacts the buffer by moving remaining data (from index to length) | |
| * to the front of the buffer. Sets index to 0, and sets length to | |
| * avail (before index was changed). | |
| * @return this flex buffer object. | |
| */ | |
| etch_flexbuffer *etch_flexbuf_compact(etch_flexbuffer *fbuf) | |
| { | |
| size_t curlen; | |
| if (fbuf->index == 0) return fbuf; | |
| if (0 == (curlen = etch_flexbuf_avail(fbuf))) | |
| { | |
| etch_flexbuf_set_length(fbuf, 0); | |
| return fbuf; | |
| } | |
| memmove(fbuf->buf, fbuf->buf+fbuf->index, curlen); | |
| fbuf->index = 0; | |
| fbuf->datalen = curlen; | |
| return fbuf; | |
| } | |
| /** | |
| * Copies data from the internal buffer to buf. | |
| * | |
| * @param fbuf the flex buffer to get data from. | |
| * @param buf a buffer to receive the data. At most | |
| * min( len, avail() ) bytes are transferred, starting | |
| * at off. | |
| * @param off the index in buf to receive the data. | |
| * Off must be >= 0 && <= buf.datalen. | |
| * @param len the max amount of data to transfer. Len | |
| * must be >= 0 and <= buf.datalen - off. | |
| * @return the amount of data transferred. | |
| */ | |
| size_t etch_flexbuf_get(etch_flexbuffer *fbuf, byte *buf, size_t off, size_t len) | |
| { | |
| size_t bytecount = 0, avail = etch_flexbuf_avail(fbuf); | |
| if (len <= 0 || NULL == buf) return 0; | |
| bytecount = min(len, avail); | |
| /* changed 6/16 to add index */ | |
| memcpy(buf + off, fbuf->buf + fbuf->index + off, bytecount); | |
| fbuf->index += bytecount; | |
| return bytecount; | |
| } | |
| /** | |
| * etch_flexbuf_get_allfrom() | |
| * return buffer contents starting at index, in a byte vector, caller owns returned memory | |
| */ | |
| byte* etch_flexbuf_get_allfrom(etch_flexbuffer* fbuf, size_t index, size_t* out_count) | |
| { | |
| byte* newbuf = 0; | |
| size_t bytecount = 0; | |
| if (index < 0) index = fbuf->index; | |
| if (index > fbuf->datalen) index = fbuf->datalen; | |
| fbuf->index = index; /* 6/16 so etch_flexbuf_get can skip index */ | |
| bytecount = fbuf->datalen - index; | |
| newbuf = etch_malloc(bytecount, ETCHTYPEB_BYTES); | |
| bytecount = etch_flexbuf_get(fbuf, newbuf, 0, bytecount); | |
| if (out_count) *out_count = bytecount; | |
| return newbuf; | |
| } | |
| /** | |
| * etch_flexbuf_get_all() | |
| * return buffer contents in a byte array, caller owns memory | |
| */ | |
| byte* etch_flexbuf_get_all(etch_flexbuffer* fbuf, size_t* out_count) | |
| { | |
| return etch_flexbuf_get_allfrom(fbuf, fbuf->index, out_count); | |
| } | |
| /** | |
| * return next byte in buffer | |
| */ | |
| int etch_flexbuf_get_byte(etch_flexbuffer *fbuf, byte* out) | |
| { | |
| if (etch_flexbuf_avail(fbuf) < sizeof(byte)) return -1; | |
| *out = fbuf->buf[fbuf->index++]; | |
| return 0; | |
| } | |
| void reverse2(unsigned short* item) | |
| { | |
| unsigned short newitem = 0; | |
| byte *p = (byte*) &item, *q = (byte*) &newitem; | |
| p[0] = q[1]; p[1] = q[0]; | |
| *item = newitem; | |
| } | |
| void reverse4(unsigned* item) | |
| { | |
| unsigned curitem = *item, newitem = 0; | |
| byte *p = (byte*) &curitem, *q = (byte*) &newitem; | |
| q[0] = p[3]; q[1] = p[2]; q[2] = p[1]; q[3] = p[0]; | |
| *item = newitem; | |
| } | |
| /** | |
| * etch_flexbuf_get_short() | |
| * @return a short composed from the next 2 bytes. | |
| */ | |
| int etch_flexbuf_get_short(etch_flexbuffer *fbuf, short* out) | |
| { | |
| int value, svalue; | |
| if (etch_flexbuf_avail(fbuf) < sizeof(short)) return -1; | |
| if (fbuf->is_littleendian) | |
| { | |
| value = fbuf->buf[fbuf->index++] & 255; | |
| svalue = (short) (value + ((fbuf->buf[fbuf->index++] & 255) << 8)); | |
| } | |
| else | |
| { value = fbuf->buf[fbuf->index++]; /* big endian */ | |
| svalue = (short) ((value << 8) + (fbuf->buf[fbuf->index++] & 255)); | |
| } | |
| *out = svalue; | |
| return 0; | |
| } | |
| /** | |
| * etch_flexbuf_get_int() | |
| * @return an int composed from the next 4 bytes. | |
| * TODO convert the rest of these functions to not do byte by byte subscripting | |
| */ | |
| int etch_flexbuf_get_int(etch_flexbuffer *fbuf, int* out) | |
| { | |
| int value = 0, bytesavail = (int) etch_flexbuf_avail(fbuf); | |
| if (bytesavail < sizeof(int)) return -1; | |
| value = *( (int*) &fbuf->buf[fbuf->index] ); | |
| if (! fbuf->is_littleendian); | |
| reverse4(&value); | |
| fbuf->index += sizeof(int); | |
| *out = value; | |
| return 0; | |
| } | |
| #if(0) | |
| /** | |
| * @return an int composed from the next 4 bytes. | |
| * @throws IOException if avail() < 4. | |
| */ | |
| int etch_flexbuf_get_int(etch_flexbuffer *fbuf) | |
| { | |
| int value = 0; | |
| if (fbuf->is_littleendian) | |
| { | |
| // little-endian | |
| value = fbuf->buf[fbuf->index++] & 255; | |
| value += ((fbuf->buf[fbuf->index++] & 255) << 8); | |
| value += ((fbuf->buf[fbuf->index++] & 255) << 16); | |
| return value + ((fbuf->buf[fbuf->index++] & 255) << 24); | |
| } | |
| // big-endian | |
| value = fbuf->buf[fbuf->index++]; | |
| value = (value << 8) + (fbuf->buf[fbuf->index++] & 255); | |
| value = (value << 8) + (fbuf->buf[fbuf->index++] & 255); | |
| return (value << 8) + (fbuf->buf[fbuf->index++] & 255); | |
| } | |
| #endif | |
| /** | |
| * etch_flexbuf_get_long() | |
| * @return a long composed from the next 8 bytes. | |
| * note jim are we taking sign into consideration on reversal? | |
| */ | |
| int etch_flexbuf_get_long(etch_flexbuffer *fbuf, int64* out) | |
| { | |
| int64 value, valout; | |
| int bytesavail = (int) etch_flexbuf_avail(fbuf); | |
| if (bytesavail < sizeof(int64)) return -1; | |
| if (fbuf->is_littleendian) | |
| { | |
| /* little-endian */ | |
| value = fbuf->buf[fbuf->index++] & 255; | |
| value += (((int64)(fbuf->buf[fbuf->index++] & 255)) << 8); | |
| value += (((int64)(fbuf->buf[fbuf->index++] & 255)) << 16); | |
| value += (((int64)(fbuf->buf[fbuf->index++] & 255)) << 24); | |
| value += (((int64)(fbuf->buf[fbuf->index++] & 255)) << 32); | |
| value += (((int64)(fbuf->buf[fbuf->index++] & 255)) << 40); | |
| value += (((int64)(fbuf->buf[fbuf->index++] & 255)) << 48); | |
| valout = value + (((int64)(fbuf->buf[fbuf->index++] & 255)) << 56); | |
| } | |
| else /* big-endian */ | |
| { value = fbuf->buf[fbuf->index++]; | |
| value = (value << 8) + (fbuf->buf[fbuf->index++] & 255); | |
| value = (value << 8) + (fbuf->buf[fbuf->index++] & 255); | |
| value = (value << 8) + (fbuf->buf[fbuf->index++] & 255); | |
| value = (value << 8) + (fbuf->buf[fbuf->index++] & 255); | |
| value = (value << 8) + (fbuf->buf[fbuf->index++] & 255); | |
| value = (value << 8) + (fbuf->buf[fbuf->index++] & 255); | |
| valout =(value << 8) + (fbuf->buf[fbuf->index++] & 255); | |
| } | |
| *out = valout; | |
| return 0; | |
| } | |
| /** | |
| * etch_flexbuf_get_float() | |
| * @return a float from the next available bytes. | |
| */ | |
| int etch_flexbuf_get_float(etch_flexbuffer *fbuf, float* out) | |
| { | |
| float value; | |
| if (-1 == etch_flexbuf_get_int(fbuf, (int*) &value)) return -1; | |
| *out = value; | |
| return 0; | |
| } | |
| /** | |
| * etch_flexbuf_get_double() | |
| * @return a double from the next available bytes. | |
| */ | |
| int etch_flexbuf_get_double(etch_flexbuffer *fbuf, double* out) | |
| { | |
| double value; | |
| if (-1 == etch_flexbuf_get_long(fbuf, (int64*) &value)) return -1; | |
| *out = value; | |
| return 0; | |
| } | |
| /** | |
| * fills a buffer fully from the next available bytes. | |
| * @param b | |
| * @throws IOException if avail() < b.datalen. | |
| */ | |
| size_t etch_flexbuf_get_fully( etch_flexbuffer *fbuf, byte *b, size_t bufsize ) | |
| { | |
| return etch_flexbuf_get( fbuf, b, 0, bufsize ); | |
| } | |
| /** | |
| * If index has moved past length during a put, then adjust length | |
| * to track index. | |
| */ | |
| static void etch_flexbuf_fix_length(etch_flexbuffer *fbuf) | |
| { | |
| if (fbuf->index > fbuf->datalen) | |
| fbuf->datalen = fbuf->index; | |
| } | |
| /** | |
| * Puts some bytes into the buffer as if by repeated calls to put(). | |
| * @param buf the source of the bytes to put. | |
| * @param off the index to the first byte to put. | |
| * @param bytecount the number of bytes to put. | |
| * @return count of bytes put | |
| */ | |
| size_t etch_flexbuf_put (etch_flexbuffer *fbuf, byte *buf, size_t off, size_t bytecount) | |
| { | |
| if (bytecount <= 0) return 0; | |
| if (!etch_flexbuf_ensure_size (fbuf, fbuf->index + bytecount)) return 0; | |
| memcpy(fbuf->buf + fbuf->index, buf + off, bytecount); | |
| fbuf->index += bytecount; | |
| etch_flexbuf_fix_length (fbuf); | |
| return bytecount; | |
| } | |
| /** | |
| * Copies the specified number of bytes from buf[index] into buffer | |
| * as if by repeated execution of put( buf.get() ). | |
| * @param buf the source of the bytes to put. | |
| * @param len the number of bytes to put. if -1, copy everything. | |
| * @return number of bytes put | |
| */ | |
| size_t etch_flexbuf_put_from(etch_flexbuffer *dstfb, etch_flexbuffer *srcfb, size_t bytecount) | |
| { | |
| size_t bytes_put = 0; | |
| if (bytecount == -1) | |
| bytecount = srcfb->datalen - srcfb->index; | |
| bytes_put = etch_flexbuf_put (dstfb, srcfb->buf, srcfb->index, bytecount); | |
| etch_flexbuf_skip (srcfb, bytes_put, FALSE); | |
| return bytes_put; | |
| } | |
| /** | |
| * etch_flexbuf_put_byte() | |
| * @return number of bytes put | |
| */ | |
| size_t etch_flexbuf_put_byte (etch_flexbuffer *fbuf, byte value) | |
| { | |
| size_t bytes_put = 0; | |
| if (etch_flexbuf_ensure_size(fbuf, fbuf->index + 1)) | |
| { | |
| fbuf->buf[fbuf->index++] = value; | |
| etch_flexbuf_fix_length(fbuf); | |
| bytes_put = sizeof(value); | |
| } | |
| return bytes_put; | |
| } | |
| /** | |
| * etch_flexbuf_put_short() | |
| */ | |
| size_t etch_flexbuf_put_short(etch_flexbuffer *fbuf, short value) | |
| { | |
| if (!etch_flexbuf_ensure_size( fbuf, fbuf->index + sizeof(value) )) | |
| return 0; | |
| if (fbuf->is_littleendian) | |
| { | |
| fbuf->buf[fbuf->index++] = (byte) value; | |
| fbuf->buf[fbuf->index++] = (byte) (value >> 8); | |
| } | |
| else | |
| { | |
| fbuf->buf[fbuf->index++] = (byte) (((unsigned short)value) >> 8); | |
| fbuf->buf[fbuf->index++] = (byte) value; | |
| } | |
| etch_flexbuf_fix_length(fbuf); | |
| return sizeof(value); | |
| } | |
| /** | |
| * etch_flexbuf_put_int() | |
| */ | |
| size_t etch_flexbuf_put_int( etch_flexbuffer *fbuf, int value ) | |
| { | |
| if (!etch_flexbuf_ensure_size( fbuf, fbuf->index + sizeof(value) )) | |
| return 0; | |
| if (fbuf->is_littleendian) | |
| { | |
| fbuf->buf[fbuf->index++] = (byte) value; | |
| fbuf->buf[fbuf->index++] = (byte) (value >> 8); | |
| fbuf->buf[fbuf->index++] = (byte) (value >> 16); | |
| fbuf->buf[fbuf->index++] = (byte) (value >> 24); | |
| } | |
| else | |
| { | |
| fbuf->buf[fbuf->index++] = (byte) ( ((unsigned int) value) >> 24); | |
| fbuf->buf[fbuf->index++] = (byte) ( ((unsigned int) value) >> 16); | |
| fbuf->buf[fbuf->index++] = (byte) ( ((unsigned int) value) >> 8); | |
| fbuf->buf[fbuf->index++] = (byte) value; | |
| } | |
| etch_flexbuf_fix_length(fbuf); | |
| return sizeof(value); | |
| } | |
| /** | |
| * etch_flexbuf_put_long() | |
| */ | |
| size_t etch_flexbuf_put_long(etch_flexbuffer *fbuf, int64 value ) | |
| { | |
| if (!etch_flexbuf_ensure_size( fbuf, fbuf->index + sizeof(value) )) | |
| return 0; | |
| if (fbuf->is_littleendian) | |
| { | |
| fbuf->buf[fbuf->index++] = (byte) value; | |
| fbuf->buf[fbuf->index++] = (byte) (value >> 8); | |
| fbuf->buf[fbuf->index++] = (byte) (value >> 16); | |
| fbuf->buf[fbuf->index++] = (byte) (value >> 24); | |
| fbuf->buf[fbuf->index++] = (byte) (value >> 32); | |
| fbuf->buf[fbuf->index++] = (byte) (value >> 40); | |
| fbuf->buf[fbuf->index++] = (byte) (value >> 48); | |
| fbuf->buf[fbuf->index++] = (byte) (value >> 56); | |
| } | |
| else | |
| { | |
| fbuf->buf[fbuf->index++] = (byte) ( ((uint64) value ) >> 56); | |
| fbuf->buf[fbuf->index++] = (byte) (( (uint64) value ) >> 48); | |
| fbuf->buf[fbuf->index++] = (byte) (( (uint64) value ) >> 40); | |
| fbuf->buf[fbuf->index++] = (byte) (( (uint64) value ) >> 32); | |
| fbuf->buf[fbuf->index++] = (byte) (( (uint64) value ) >> 24); | |
| fbuf->buf[fbuf->index++] = (byte) (( (uint64) value ) >> 16); | |
| fbuf->buf[fbuf->index++] = (byte) (( (uint64) value ) >> 8); | |
| fbuf->buf[fbuf->index++] = (byte) value; | |
| } | |
| etch_flexbuf_fix_length(fbuf); | |
| return sizeof(value); | |
| } | |
| /** | |
| * etch_flexbuf_put_float() | |
| */ | |
| size_t etch_flexbuf_put_float( etch_flexbuffer *fbuf, float value ) | |
| { | |
| /* return etch_flexbuf_put_int( fbuf, * ((int *)( &value )) ); */ | |
| const unsigned int u = * ( (int*)&value ); | |
| return etch_flexbuf_put_int(fbuf, u); | |
| } | |
| /** | |
| * etch_flexbuf_put_double() | |
| */ | |
| size_t etch_flexbuf_put_double(etch_flexbuffer *fbuf, double value ) | |
| { | |
| /* return etch_flexbuf_put_long( fbuf, *( (int64*) &value ) ); */ | |
| const int64 u = * ( (int64*)&value ); | |
| return etch_flexbuf_put_long(fbuf, u); | |
| } | |
| /** | |
| * Adjusts index as if by a get or put but without transferring | |
| * any data. This could be used to skip over a data item in an | |
| * input or output buffer. | |
| * | |
| * @param len the number of bytes to skip over. Len must be | |
| * >= 0. If put is false, it is an error if len > avail(). | |
| * If put is true, the buffer may be extended (and the buffer | |
| * length adjusted). | |
| * | |
| * @param put if true it is ok to extend the length of the | |
| * buffer. | |
| * | |
| * @return this flex buffer object. | |
| * | |
| * @throws EOFException if put is false and len > avail(). | |
| * | |
| * @throws IOException if the max buffer size is exceeded. | |
| */ | |
| etch_flexbuffer *etch_flexbuf_skip(etch_flexbuffer *fbuf, size_t len, int put ) | |
| { | |
| if (len < 0) return NULL; | |
| if (len == 0) return fbuf; | |
| if (put) | |
| { | |
| etch_flexbuf_ensure_size( fbuf, fbuf->index+len ); | |
| fbuf->index += len; | |
| etch_flexbuf_fix_length(fbuf); | |
| return fbuf; | |
| } | |
| fbuf->index += len; | |
| return fbuf; | |
| } |