Simple data buffer splitter and re-assembler.
Revision 1:9f05dbd1c2c7, committed 2015-02-12
- Comitter:
- ansond
- Date:
- Thu Feb 12 20:06:15 2015 +0000
- Parent:
- 0:12a931a6161c
- Child:
- 2:5614523d641b
- Commit message:
- updates and renamed
Changed in this revision
diff -r 12a931a6161c -r 9f05dbd1c2c7 DataFragmenterAssembler.cpp --- a/DataFragmenterAssembler.cpp Thu Feb 12 20:00:36 2015 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,217 +0,0 @@ -/** - * @file DataFragmenterAssembler.cpp - * @brief data fragmenter and assembler (for BLE UARTService...) implementation - * @author Doug Anson - * @version 1.0 - * @see - * - * Copyright (c) 2014 - * - * Licensed 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. - */ - - #include "DataFragmenterAssembler.h" - -// we have to redefine DBG as its used differently here... -#ifdef DBG - #undef DBG -#endif -#define DBG printf - - // constructor - DataFragmenterAssembler::DataFragmenterAssembler() - { - this->reset(); - } - - // fragment a buffer - int DataFragmenterAssembler::fragment(uint8_t *data,int data_length) - { - // reset - this->reset(); - - // get our number of fragments - this->m_num_fragments = this->calculateNumFragments(data,data_length); - - // DEBUG - //DBG("fragment() num_fragments=%d data_length=%d\r\n",this->m_num_fragments,data_length); - - // make sure we have a positive number... - if (this->m_num_fragments > 0) { - // check for the simple case first - if (this->m_num_fragments == 1) { - // simple case... just 1 fragment - memcpy(this->m_fragments[0],data,data_length); - this->m_last_fragment_length = data_length; - } - else { - // must iterate over the buffer and fragment... - for(int i=0;i<this->m_num_fragments;++i) { - int offset = i*DEF_FRAGMENT_LENGTH; - if (i < (this->m_num_fragments-1)) { - // interior... will always be fixed length - memcpy(this->m_fragments[i],(data + offset),DEF_FRAGMENT_LENGTH); - } - else { - // trailing... may be partial length... - this->m_last_fragment_length = data_length - offset; - memcpy(this->m_fragments[i],(data + offset),this->m_last_fragment_length); - } - } - } - } - else { - // unable to fragment... invalid parameters - DBG("ERROR: invalid parameters in fragment()\r\n"); - } - - // DEBUG - //this->dump(); - - // return our number of fragments - return this->m_num_fragments; - } - - // calculate the number of fragments - int DataFragmenterAssembler::calculateNumFragments(uint8_t *data,int data_length) - { - int num_fragments = 0; - - // param checking - if (data != NULL && data_length > 0) { - // check for simple case... - if (data_length <= DEF_FRAGMENT_LENGTH) { - num_fragments = 1; - } - else { - num_fragments = 1; - data_length -= DEF_FRAGMENT_LENGTH; - while(data_length > 0) { - ++num_fragments; - data_length -= DEF_FRAGMENT_LENGTH; - } - } - } - else { - // invalid parameters - DBG("ERROR: invalid parameters in calculateNumFragments() data_length=%d\r\n",data_length); - } - - return num_fragments; - } - - // get the ith fragment - uint8_t *DataFragmenterAssembler::get(int index) - { - if (index >= 0 && index < this->m_num_fragments) - return this->m_fragments[index]; - return NULL; - } - - // reset the Fragmenter/Assembler - void DataFragmenterAssembler::reset(void) - { - memset(this->m_fragments,0,sizeof(this->m_fragments)); - this->m_num_fragments = 0; - this->m_last_fragment_length = 0; - } - - // add a fragment to assemble later - int DataFragmenterAssembler::add(uint8_t *fragment,int fragment_length) - { - if (this->m_num_fragments < (MAX_FRAGMENTS-1)) { - int length = fragment_length; - if (length > DEF_FRAGMENT_LENGTH) { - length = DEF_FRAGMENT_LENGTH; - //DBG("WARNING: Truncating input fragment in add() fragment_length=%d\r\n",fragment_length); - } - memcpy(this->m_fragments[this->m_num_fragments],fragment,length); - ++this->m_num_fragments; - } - else { - // not enough memory to hold all the fragments - DBG("ERROR: Maximum number of fragments permissible reached, Please increase MAX_FRAGMENTS...\r\n"); - } - return this->m_num_fragments; - } - - // assemble all input fragments - void DataFragmenterAssembler::assemble(uint8_t *buffer,int buffer_length,bool reset_after_assemble) - { - // calculate the final assembly length - int length = this->calculateAssemblyLength(buffer_length); - if (length > 0) { - // initialize the return buffer - memset(buffer,0,buffer_length); - - // check for the simple case.. 1 fragment - if (this->m_num_fragments == 1) { - // simple case detected... just copy over - memset(buffer,0,buffer_length); - memcpy(buffer,this->m_fragments[0],length); - } - else { - // we have to loop and copy/append - for(int i=0;i<this->m_num_fragments;++i) { - int offset = (i*DEF_FRAGMENT_LENGTH); - if (i < (this->m_num_fragments-1)) { - // interior... will always be fixed length - memcpy((buffer+offset),this->m_fragments[i],DEF_FRAGMENT_LENGTH); - } - else { - // trailing... may be partial length... - memcpy((buffer+offset),this->m_fragments[i],this->m_last_fragment_length); - } - } - } - - // DEBUG - //DBG("assemble(): buffer=[%s] length=%d\r\n",buffer,buffer_length); - } - else { - // unable to assemble... - DBG("ERROR: Unable to assemble. calculateAssemblyLength() failed (%d)\r\n",length); - } - } - - // calculate the assembled packet length - int DataFragmenterAssembler::calculateAssemblyLength(int buffer_length) { - int length = 0; - - for(int i=0;i<this->m_num_fragments;++i) { - if (i < (this->m_num_fragments-1)) length += DEF_FRAGMENT_LENGTH; - else length += this->m_last_fragment_length; - } - - // sanity check - if (length > buffer_length) { - // input buffer is too small... - DBG("ERROR: calculateAssemblyLength() input buffer too small: %d bytes. required length: %d bytes.\r\n",buffer_length,length); - length = -1; - } - - return length; - } - - // dump the state of the Fragmenter/Assembler - void DataFragmenterAssembler::dump(void) - { - DBG("\r\nDUMP: Number of fragments: %d last_length=%d\r\n",this->m_num_fragments,this->m_last_fragment_length); - for(int i=0;i<this->m_num_fragments;++i) { - DBG("DUMP: Fragment[%d]=[%s] length=%d\r\n",i,this->m_fragments[i],strlen((const char *)this->m_fragments[i])); - } - DBG("\r\n"); - } - - - \ No newline at end of file
diff -r 12a931a6161c -r 9f05dbd1c2c7 DataFragmenterAssembler.h --- a/DataFragmenterAssembler.h Thu Feb 12 20:00:36 2015 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,85 +0,0 @@ -/** - * @file DataFragmenterAssembler.h - * @brief data fragmenter and assembler (for BLE UARTService...) header - * @author Doug Anson - * @version 1.0 - * @see - * - * Copyright (c) 2014 - * - * Licensed 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. - */ - -#ifndef __DATA_FRAGMENTER_ASSEMBLER_H__ -#define __DATA_FRAGMENTER_ASSEMBLER_H__ - -#include "mbed.h" - -// TUNABLES -#define MAX_FRAGMENTS 100 // maximum number of supported fragments... increase as needed... -#define DEF_FRAGMENT_LENGTH 20 // Typically identical to BLE_UART_SERVICE_MAX_DATA_LEN in UARTService.h - -class DataFragmenterAssembler { - public: - /** - Constructor - */ - DataFragmenterAssembler(); - - /** - Fragment a data stream into "n" fragments of the given input fragement (from constructor) size - @param data input input data buffer - @param data_length input input data buffer length - @returns number of fragments created for the input buffer - */ - int fragment(uint8_t *data,int data_length); - - /** - Get the ith fragment - @param index input the ith index value - @return the ith fragment pointer (null terminated) - */ - uint8_t *get(int index); - - /** - Reset the Fragmenter/Assembler - */ - void reset(void); - - /** - Add a fragment - @param fragment input fragment to add - @param fragment_length input the input fragment length (sanity checks...) - @return the number of fragments currently stored - */ - int add(uint8_t *fragment,int fragment_length); - - /** - Assemble fragments - @param buffer input the result buffer - @param buffer_length input the result buffer length (maximum) - @param reset_after_assemble input reset the Fragmenter/Assembler after assembly is complete (default: TRUE) - */ - void assemble(uint8_t *buffer,int buffer_length,bool reset_after_assemble = true); - - private: - int calculateNumFragments(uint8_t *data,int data_length); - int calculateAssemblyLength(int buffer_length); - void dump(void); - - int m_num_fragments; - int m_last_fragment_length; - uint8_t m_fragments[DEF_FRAGMENT_LENGTH+1][MAX_FRAGMENTS]; -}; - -#endif // __DATA_FRAGMENTER_ASSEMBLER_H__ \ No newline at end of file
diff -r 12a931a6161c -r 9f05dbd1c2c7 SplitterAssembler.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/SplitterAssembler.cpp Thu Feb 12 20:06:15 2015 +0000 @@ -0,0 +1,217 @@ +/** + * @file SplitterAssembler.cpp + * @brief data buffer splitter and assembler implementation + * @author Doug Anson + * @version 1.0 + * @see + * + * Copyright (c) 2014 + * + * Licensed 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. + */ + + #include "SplitterAssembler.h" + +// we have to redefine DBG as its used differently here... +#ifdef DBG + #undef DBG +#endif +#define DBG printf + + // constructor + SplitterAssembler::SplitterAssembler() + { + this->reset(); + } + + // fragment a buffer + int SplitterAssembler::split(uint8_t *data,int data_length) + { + // reset + this->reset(); + + // get our number of fragments + this->m_num_fragments = this->calculateNumFragments(data,data_length); + + // DEBUG + //DBG("fragment() num_fragments=%d data_length=%d\r\n",this->m_num_fragments,data_length); + + // make sure we have a positive number... + if (this->m_num_fragments > 0) { + // check for the simple case first + if (this->m_num_fragments == 1) { + // simple case... just 1 fragment + memcpy(this->m_fragments[0],data,data_length); + this->m_last_fragment_length = data_length; + } + else { + // must iterate over the buffer and fragment... + for(int i=0;i<this->m_num_fragments;++i) { + int offset = i*DEF_FRAGMENT_LENGTH; + if (i < (this->m_num_fragments-1)) { + // interior... will always be fixed length + memcpy(this->m_fragments[i],(data + offset),DEF_FRAGMENT_LENGTH); + } + else { + // trailing... may be partial length... + this->m_last_fragment_length = data_length - offset; + memcpy(this->m_fragments[i],(data + offset),this->m_last_fragment_length); + } + } + } + } + else { + // unable to fragment... invalid parameters + DBG("ERROR: invalid parameters in fragment()\r\n"); + } + + // DEBUG + this->dump(); + + // return our number of fragments + return this->m_num_fragments; + } + + // calculate the number of fragments + int SplitterAssembler::calculateNumFragments(uint8_t *data,int data_length) + { + int num_fragments = 0; + + // param checking + if (data != NULL && data_length > 0) { + // check for simple case... + if (data_length <= DEF_FRAGMENT_LENGTH) { + num_fragments = 1; + } + else { + num_fragments = 1; + data_length -= DEF_FRAGMENT_LENGTH; + while(data_length > 0) { + ++num_fragments; + data_length -= DEF_FRAGMENT_LENGTH; + } + } + } + else { + // invalid parameters + DBG("ERROR: invalid parameters in calculateNumFragments() data_length=%d\r\n",data_length); + } + + return num_fragments; + } + + // get the ith fragment + uint8_t *SplitterAssembler::get(int index) + { + if (index >= 0 && index < this->m_num_fragments) + return this->m_fragments[index]; + return NULL; + } + + // reset the Fragmenter/Assembler + void SplitterAssembler::reset(void) + { + memset(this->m_fragments,0,sizeof(this->m_fragments)); + this->m_num_fragments = 0; + this->m_last_fragment_length = 0; + } + + // add a fragment to assemble later + int SplitterAssembler::add(uint8_t *fragment,int fragment_length) + { + if (this->m_num_fragments < (MAX_FRAGMENTS-1)) { + int length = fragment_length; + if (length > DEF_FRAGMENT_LENGTH) { + length = DEF_FRAGMENT_LENGTH; + //DBG("WARNING: Truncating input fragment in add() fragment_length=%d\r\n",fragment_length); + } + memcpy(this->m_fragments[this->m_num_fragments],fragment,length); + ++this->m_num_fragments; + } + else { + // not enough memory to hold all the fragments + DBG("ERROR: Maximum number of fragments permissible reached, Please increase MAX_FRAGMENTS...\r\n"); + } + return this->m_num_fragments; + } + + // assemble all input fragments + void SplitterAssembler::assemble(uint8_t *buffer,int buffer_length,bool reset_after_assemble) + { + // calculate the final assembly length + int length = this->calculateAssemblyLength(buffer_length); + if (length > 0) { + // initialize the return buffer + memset(buffer,0,buffer_length); + + // check for the simple case.. 1 fragment + if (this->m_num_fragments == 1) { + // simple case detected... just copy over + memset(buffer,0,buffer_length); + memcpy(buffer,this->m_fragments[0],length); + } + else { + // we have to loop and copy/append + for(int i=0;i<this->m_num_fragments;++i) { + int offset = (i*DEF_FRAGMENT_LENGTH); + if (i < (this->m_num_fragments-1)) { + // interior... will always be fixed length + memcpy((buffer+offset),this->m_fragments[i],DEF_FRAGMENT_LENGTH); + } + else { + // trailing... may be partial length... + memcpy((buffer+offset),this->m_fragments[i],this->m_last_fragment_length); + } + } + } + + // DEBUG + //DBG("assemble(): buffer=[%s] length=%d\r\n",buffer,buffer_length); + } + else { + // unable to assemble... + DBG("ERROR: Unable to assemble. calculateAssemblyLength() failed (%d)\r\n",length); + } + } + + // calculate the assembled packet length + int SplitterAssembler::calculateAssemblyLength(int buffer_length) { + int length = 0; + + for(int i=0;i<this->m_num_fragments;++i) { + if (i < (this->m_num_fragments-1)) length += DEF_FRAGMENT_LENGTH; + else length += this->m_last_fragment_length; + } + + // sanity check + if (length > buffer_length) { + // input buffer is too small... + DBG("ERROR: calculateAssemblyLength() input buffer too small: %d bytes. required length: %d bytes.\r\n",buffer_length,length); + length = -1; + } + + return length; + } + + // dump the state of the Fragmenter/Assembler + void SplitterAssembler::dump(void) + { + DBG("\r\nDUMP: Number of fragments: %d last_length=%d\r\n",this->m_num_fragments,this->m_last_fragment_length); + for(int i=0;i<this->m_num_fragments;++i) { + DBG("DUMP: Fragment[%d]=[%s] length=%d\r\n",i,this->get(i),strlen((const char *)this->get(i))); + } + DBG("\r\n"); + } + + + \ No newline at end of file
diff -r 12a931a6161c -r 9f05dbd1c2c7 SplitterAssembler.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/SplitterAssembler.h Thu Feb 12 20:06:15 2015 +0000 @@ -0,0 +1,85 @@ +/** + * @file SplitterAssembler.h + * @brief data buffer splitter and assembler header + * @author Doug Anson + * @version 1.0 + * @see + * + * Copyright (c) 2014 + * + * Licensed 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. + */ + +#ifndef __SPLITTER_ASSEMBLER_H__ +#define __SPLITTER_ASSEMBLER_H__ + +#include "mbed.h" + +// TUNABLES +#define MAX_FRAGMENTS 100 // maximum number of supported fragments... increase as needed... +#define DEF_FRAGMENT_LENGTH 20 // Typically identical to BLE_UART_SERVICE_MAX_DATA_LEN in UARTService.h + +class SplitterAssembler { + public: + /** + Constructor + */ + SplitterAssembler(); + + /** + Split a data stream into "n" fragments of the given input fragement (from constructor) size + @param data input input data buffer + @param data_length input input data buffer length + @returns number of fragments created for the input buffer + */ + int split(uint8_t *data,int data_length); + + /** + Get the ith fragment + @param index input the ith index value + @return the ith fragment pointer (null terminated) + */ + uint8_t *get(int index); + + /** + Reset the Fragmenter/Assembler + */ + void reset(void); + + /** + Add a fragment + @param fragment input fragment to add + @param fragment_length input the input fragment length (sanity checks...) + @return the number of fragments currently stored + */ + int add(uint8_t *fragment,int fragment_length); + + /** + Assemble fragments + @param buffer input the result buffer + @param buffer_length input the result buffer length (maximum) + @param reset_after_assemble input reset the Fragmenter/Assembler after assembly is complete (default: TRUE) + */ + void assemble(uint8_t *buffer,int buffer_length,bool reset_after_assemble = true); + + private: + int calculateNumFragments(uint8_t *data,int data_length); + int calculateAssemblyLength(int buffer_length); + void dump(void); + + int m_num_fragments; + int m_last_fragment_length; + uint8_t m_fragments[DEF_FRAGMENT_LENGTH+1][MAX_FRAGMENTS]; +}; + +#endif // __SPLITTER_ASSEMBLER_H__ \ No newline at end of file