/* * usca.cc - Self explanitory * Copyright (C) 1997-2000 SpellCaster Telecommunications Inc. * $Id: usca.cc,v 1.2 2004/08/17 17:58:38 bcrl Exp $ * Released under the GNU Public License. See LICENSE file for details. */ #include #include #include #include "config.h" #include "usca.h" ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// // // Simple constructor // CuscArray::CuscArray() { m_data = m_buf; m_length = 0; m_size = USCA_BLOCKSIZE; m_length = 0; m_start = m_end = m_data; } // // Free the storage buffer when the object is destroyed // CuscArray::~CuscArray() { if (m_data && m_data != m_buf) free(m_data); m_data = NULL; } // // Construct a CuscArray from an unsigned char array and a length // If it fails, m_data will be NULL // CuscArray::CuscArray(u8* data, uint len) { if (len > USCA_BLOCKSIZE) { m_data = (u8 *)malloc(len + USCA_BLOCKSIZE); m_size = len + USCA_BLOCKSIZE; } else { m_data = m_buf; m_size = USCA_BLOCKSIZE; } if (m_data) { memcpy(m_data, data, len); m_length = len; m_start = m_data; m_end = m_start + m_size; } else { m_length = 0; m_size = 0; m_start = NULL; m_end = NULL; } } // // Make a copy of the CuscArray // CuscArray::CuscArray(const CuscArray &oa) { if (oa.m_data) { // We copy the data storage buffer but trim from // the end. We want any reserved space at the front u8* t_data = (u8 *)malloc(oa.m_start - oa.m_data + oa.m_length + USCA_BLOCKSIZE); m_data = t_data; if (t_data) { m_start = t_data + (oa.m_start - oa.m_data); m_length = oa.m_length; m_end = m_start + m_length; m_size = oa.m_start - oa.m_data + oa.m_length + USCA_BLOCKSIZE; memcpy(m_start, oa.m_start, m_length); } } } void CuscArray::Print() { LogPacket(LF_DEBUG|LF_RX|LF_TX, m_start, m_length); } int CuscArray::Reserve(size_t size) { // If we have room at the end of the buffer, just move // the data right if (m_size - (m_end - m_data) >= size) { u8* nstart = m_start + size; memcpy(nstart, m_start, m_length); m_start = nstart; m_end += size; return size; } // We need to make room in the buffer else { uint nblocks = size / USCA_BLOCKSIZE + 1; if (!(ExpandBuffer(nblocks * USCA_BLOCKSIZE))) { u8 *nstart = m_data + (m_start - m_data) + size; memmove(nstart, m_start, m_length); m_start = nstart; m_end = nstart + m_length; return size; } else { return -ENOMEM; } } } // // Return a buffer that is that much bigger than the existing // one. // int CuscArray::ExpandBuffer(size_t len) { uint t_len = m_size + len; u8* t_data = (u8 *)malloc(t_len); if (t_data == NULL) { return -ENOMEM; } memcpy(t_data, m_data, m_size); m_start = t_data + (m_start - m_data); m_end = m_start + m_length; m_size = t_len; if (m_data != NULL && m_data != m_buf) free(m_data); m_data = t_data; return 0; } // // Push a string on the front of the buffer // int CuscArray::Push(const char *string) { uint s_len = strlen(string); uint needed = s_len - (m_start - m_data); if (needed) Reserve(needed); u8* t_ptr = m_start - s_len; memcpy(t_ptr, string, s_len); m_start = t_ptr; m_length += s_len; return s_len; } int CuscArray::Push(CuscArray &oa) { uint s_len = oa.GetLength(); uint needed = s_len - (m_start - m_data); if (needed) Reserve(needed); u8* t_ptr = m_start - s_len; memcpy(t_ptr, oa.m_start, s_len); m_start = t_ptr; m_length += s_len; return s_len; } int CuscArray::Push(const u8 *array, uint len) { uint needed = len - (m_start - m_data); if (needed > 0) Reserve(needed); u8* t_ptr = m_start - len; memcpy(t_ptr, array, len); m_start = t_ptr; m_length += len; return len; } // // // void CuscArray::Pull(CuscArray *oa, uint len) { if (m_length >= len) { oa->Put(m_start, len); m_start += len; m_length -= len; } else { oa->Put(m_start, len); m_start += m_length; m_length = 0; } } int CuscArray::Pull(u8 *array, uint len) { int ret = 0; if (m_length >= len) { memcpy(array, m_start, len); m_start+=len; m_length-=len; ret = len; } else { memcpy(array, m_start, len); m_start+=m_length; ret = m_length; m_length=0; } return ret; } void CuscArray::Clear() { if (m_data && m_data != m_buf) free(m_data); m_start = m_end = m_data = NULL; m_size = m_length = 0; } bool CuscArray::operator ==(CuscArray &oa) { const u8 *t_ptr = oa.m_start; if (GetLength() != oa.GetLength()) return FALSE; for(uint i = 0 ; i < m_length ; i++) if (m_start[i] != t_ptr[i]) return FALSE; return TRUE; } bool CuscArray::operator ==(const u8 *t_ptr) { for(uint i = 0 ; i < m_length ; i++) if (m_start[i] != t_ptr[i]) return FALSE; return TRUE; } u8 CuscArray::Pull8() { u8 d; if (m_length >= 1) { d = *(u8 *)m_start; m_start++; m_length--; return d; } else { return 0; } } u16 CuscArray::Pull16() { u16 d; if (m_length >= 2) { d = *(u16 *)m_start; m_start+=2; m_length-=2; return (ntohs(d)); } else { return 0; } } u32 CuscArray::Pull32() { u32 d; if (m_length >= 4) { d = *(u32 *)m_start; m_start+=4; m_length-=4; return(ntohl(d)); } else { return 0; } } void CuscArray::Push8(u8 v) { if (m_start - m_data < 1) Reserve(USCA_BLOCKSIZE); m_start--; *m_start = v; m_length++; } void CuscArray::Push16(u16 v) { if (m_start - m_data < 2) Reserve(USCA_BLOCKSIZE); m_start -= 2; *(u16 *)m_start = htons(v); m_length += 2; } void CuscArray::Push32(u32 v) { if (m_start - m_data < 4) Reserve(USCA_BLOCKSIZE); m_start -= 4; *(u32 *)m_start = htonl(v); m_length += 4; } void CuscArray::Chop(uint len) { if (len > GetLength()) return; m_end -= len; m_length -= len; } void CuscArray::Trim(uint len) { if (len > GetLength()) return; m_start += len; m_length -= len; } void CuscArray::Put8(u8 d) { if ((m_data + m_size - m_end) < 1) { if (!(ExpandBuffer(USCA_BLOCKSIZE))) { *m_end = d; m_length++; m_end = m_start + m_length; } } else { *m_end = d; m_length++; m_end = m_start + m_length; } } void CuscArray::Put16(u16 d) { if ((m_data + m_size - m_end) < 2) { /* TODO: Handle ExpandBuffer error somewhere */ if (!(ExpandBuffer(USCA_BLOCKSIZE))) { *(u16 *)m_end = htons(d); m_length+=2; m_end = m_start + m_length; } } else { *(u16 *)m_end = htons(d); m_length+=2; m_end = m_start + m_length; } } void CuscArray::Put32(u32 d) { if ((m_data + m_size - m_end) < 4) { /* TODO: Handle ExpandBuffer error somewhere */ if (!(ExpandBuffer(USCA_BLOCKSIZE))) { *(u32 *)m_end = htonl(d); m_length+=4; m_end = m_start + m_length; } } else { *(u32 *)m_end = htonl(d); m_length+=4; m_end = m_start + m_length; } } void CuscArray::Put(u8 *d, uint len) { if ((m_data + m_size - m_end) < (int)len) { /* TODO: Handle ExpandBuffer error somewhere */ if (!(ExpandBuffer(len))) { memcpy(m_end, d, len); m_length+=len; m_end = m_start + m_length; } } else { memcpy(m_end, d, len); m_length+=len; m_end = m_start + m_length; } } void CuscArray::Put(char *str) { if ((m_data + m_size - m_end) < (int)strlen(str)) { if (!(ExpandBuffer(strlen(str)))) { memcpy(m_end, str, strlen(str)); m_length+=strlen(str); m_end = m_start + m_length; } } else { memcpy(m_end, str, strlen(str)); m_length+=strlen(str); m_end = m_start + m_length; } } void CuscArray::Put(CuscArray *str) { if ((m_data + m_size - m_end) < (int)str->GetLength()) { if (!ExpandBuffer(str->GetLength())) { memcpy(m_end, str->m_start, str->GetLength()); m_length+=str->GetLength(); m_end = m_start + m_length; } } else { memcpy(m_end, str->m_start, str->GetLength()); m_length+=str->GetLength(); m_end = m_start + m_length; } }