| /*============================================================================== | |
| ds_ASBuffer.cpp | |
| GENERAL DESCRIPTION | |
| A buffer class with utility functions for parsing raw bytes. | |
| EXTERNALIZED FUNCTIONS | |
| INITIALIZATION AND SEQUENCING REQUIREMENTS | |
| None | |
| Copyright (c) 2014 by Qualcomm Technologies Incorporated. All Rights Reserved. | |
| ==============================================================================*/ | |
| /*============================================================================== | |
| EDIT HISTORY FOR MODULE | |
| This section contains comments describing changes made to the module. | |
| Notice that changes are listed in reverse chronological order. | |
| when who what, where, why | |
| -------- --- ---------------------------------------------------------- | |
| 06/03/15 ml Remove memory allocation on default constructor | |
| 05/20/15 ml Use memory from modem heap | |
| 04/21/14 ml Created file/Initial version. | |
| ==============================================================================*/ | |
| #include "ds_ASBuffer.h" | |
| //#include "ds_appsrv_mem.h" | |
| #include <string.h> | |
| #include <mbtk_type.h> | |
| #include <stdlib.h> | |
| #include <cctype> // isspace | |
| // temp | |
| #include "ds_ASString.h" | |
| #define DEFAULT_BUFFER_SIZE 256 | |
| // static const uint8 EMPTY_STRING[] = ""; | |
| void memscpy(void* dest, size_t destLen, const void* src, size_t srcLen) { | |
| if (srcLen <= destLen) | |
| memcpy(dest, src, srcLen); | |
| } | |
| ASBuffer::ASBuffer() | |
| : buffer(NULL), buffer_size(0), buffer_capacity(DEFAULT_BUFFER_SIZE), error_status(false) | |
| { } | |
| ASBuffer::ASBuffer(uint32 capacity) | |
| : buffer(NULL), buffer_size(0), buffer_capacity(capacity), error_status(false) | |
| { } | |
| ASBuffer::ASBuffer(ASBuffer &buf) | |
| : buffer(NULL), buffer_size(0), buffer_capacity(buf.buffer_capacity), error_status(false) | |
| { | |
| init(); | |
| append(buf); | |
| } | |
| ASBuffer::ASBuffer(const ASBuffer &buf) | |
| : buffer(NULL), buffer_size(0), buffer_capacity(buf.buffer_capacity), error_status(false) | |
| { | |
| init(); | |
| append(buf); | |
| } | |
| ASBuffer::ASBuffer(const uint8* buf, uint32 buf_size) | |
| : buffer(NULL), buffer_size(0), buffer_capacity(buf_size), error_status(false) | |
| { | |
| init(); | |
| append(buf, buf_size); | |
| } | |
| ASBuffer::~ASBuffer() | |
| { | |
| if(NULL != buffer) | |
| { | |
| free(buffer); | |
| buffer = NULL; | |
| } | |
| } | |
| ASBuffer& ASBuffer::operator=(const ASBuffer &rhs) | |
| { | |
| clear(); | |
| append(rhs); | |
| return *this; | |
| } | |
| void ASBuffer::init() | |
| { | |
| if(0 == buffer_capacity) | |
| { | |
| error_status = true; | |
| } | |
| else if(NULL == buffer) | |
| { | |
| buffer = (uint8*)malloc(sizeof(uint8) * (buffer_capacity+1)); | |
| error_status = (NULL == buffer); | |
| } | |
| } | |
| // temp name | |
| #define DO_NOT_DOUBLE_IF_LARGER 2147483647 | |
| bool ASBuffer::increment_buffer_capacity(const uint32 req_size) | |
| { | |
| uint32 new_capacity = buffer_capacity; | |
| uint8* tmp = NULL; | |
| while(req_size > new_capacity) | |
| { | |
| // will cause overflow if doubled | |
| if(DO_NOT_DOUBLE_IF_LARGER < new_capacity) | |
| return false; | |
| new_capacity *= 2; | |
| } | |
| tmp = (uint8*)malloc(sizeof(uint8) * new_capacity+1); | |
| if(NULL == tmp) | |
| return false; | |
| memset(tmp, 0, new_capacity+1); | |
| memscpy(tmp, new_capacity, buffer, buffer_size); | |
| free(buffer); | |
| buffer = NULL; | |
| buffer = tmp; | |
| buffer_capacity = new_capacity; | |
| return true; | |
| } | |
| uint8* ASBuffer::non_const_content() | |
| { | |
| return buffer; | |
| } | |
| const uint8* ASBuffer::content() const | |
| { | |
| return buffer; | |
| } | |
| const char* ASBuffer::c_str() const | |
| { | |
| if(NULL == buffer) | |
| return ""; | |
| else | |
| return (const char*)buffer; | |
| } | |
| uint32 ASBuffer::size() const | |
| { | |
| return buffer_size; | |
| } | |
| bool ASBuffer::empty() const | |
| { | |
| return (0 == buffer_size); | |
| } | |
| bool ASBuffer::error() const | |
| { | |
| return error_status; | |
| } | |
| void ASBuffer::clear() | |
| { | |
| if(NULL == buffer) | |
| { | |
| init(); | |
| } | |
| else | |
| { | |
| memset(buffer, 0, buffer_capacity+1); | |
| } | |
| buffer_size = 0; | |
| } | |
| bool ASBuffer::append(const uint8* append_buffer, const uint32 append_size) | |
| { | |
| if(NULL == append_buffer || 0 == append_size) | |
| return true; | |
| if(NULL == buffer) | |
| init(); | |
| if(error_status) // do nothing if in error state | |
| return false; | |
| uint32 new_size = buffer_size + append_size; | |
| if(new_size > buffer_capacity) | |
| { | |
| if(!increment_buffer_capacity(new_size)) | |
| { | |
| error_status = true; | |
| return false; | |
| } | |
| } | |
| memscpy( | |
| buffer + buffer_size, | |
| buffer_capacity - buffer_size, | |
| append_buffer, | |
| append_size | |
| ); | |
| buffer_size = new_size; | |
| return true; | |
| } | |
| bool ASBuffer::append(const char* append_buffer) | |
| { | |
| if(NULL == append_buffer) | |
| return false; | |
| else | |
| return append((uint8*)append_buffer, strlen(append_buffer)); | |
| } | |
| bool ASBuffer::append(const char append_buffer) | |
| { | |
| char buffer[1]; | |
| buffer[0] = append_buffer; | |
| return append((uint8*)buffer, 1); | |
| } | |
| bool ASBuffer::append(const char* append_buffer, const uint32 size) | |
| { | |
| if(NULL == append_buffer) | |
| return false; | |
| else | |
| return append((uint8*)append_buffer, size); | |
| } | |
| bool ASBuffer::append(const ASBuffer& append_buffer) | |
| { | |
| if(append_buffer.empty()) | |
| return false; | |
| else | |
| return append(append_buffer.content(), append_buffer.size()); | |
| } | |
| bool ASBuffer::append(const ASString& append_buffer) | |
| { | |
| if(append_buffer.empty()) | |
| return false; | |
| else | |
| return append((uint8*)append_buffer.c_str(), append_buffer.size()); | |
| } | |