blob: c471c195d30f4be56910a2cb5bb6133aa43b594b [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2008 - 2015 nxtControl GmbH, ACIN, fortiss GmbH
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Stanislav Meduna, Alois Zoitl, Martin Melik Merkumians
* - initial implementation and rework communication infrastructure
*******************************************************************************/
#include "stringdict.h"
#include <fortenew.h>
#ifdef FORTE_ENABLE_GENERATED_SOURCE_CPP
#include "stringdict_gen.cpp"
#endif
#include <stringlist.h>
#include <string.h>
#include <stdlib.h>
#include "devlog.h"
DEFINE_SINGLETON(CStringDictionary)
CStringDictionary::CStringDictionary(){
#ifdef FORTE_STRING_DICT_FIXED_MEMORY
m_paStringBufAddr = scm_acConstStringBuf;
m_pnStringIdBufAddr = scm_aunIdList;
m_nStringBufSize = cg_unStringDictInitialStringBufSize;
m_nMaxNrOfStrings = cg_unStringDictInitialMaxNrOfStrings;
m_nNrOfStrings = cg_nNumOfConstStrings;
m_nNextString = g_nStringIdNextFreeId;
#else
m_pnStringIdBufAddr = 0;
m_nStringBufSize = 0;
m_nMaxNrOfStrings = 0;
m_nNrOfStrings = 0;
m_nNextString = CStringDictionary::scm_nInvalidStringId;
unsigned int nStringBufSize = cg_unStringDictInitialStringBufSize;
if(nStringBufSize < g_nStringIdNextFreeId){
nStringBufSize = (g_nStringIdNextFreeId * 3) >> 1;
}
unsigned int nMaxNrOfStrings = cg_unStringDictInitialMaxNrOfStrings;
if(nMaxNrOfStrings < cg_nNumOfConstStrings){
nMaxNrOfStrings = (cg_nNumOfConstStrings * 3) >> 1;
}
m_paStringBufAddr = (char *) forte_malloc(nStringBufSize * sizeof(char));
if(0 != m_paStringBufAddr){
m_pnStringIdBufAddr = (TStringId *) forte_malloc(nMaxNrOfStrings * sizeof(TStringId));
if(0 != m_pnStringIdBufAddr){
memcpy(m_paStringBufAddr, scm_acConstStringBuf, g_nStringIdNextFreeId);
memcpy(m_pnStringIdBufAddr, scm_aunIdList, (cg_nNumOfConstStrings * sizeof(TStringId)));
m_nStringBufSize = nStringBufSize;
m_nMaxNrOfStrings = nMaxNrOfStrings;
m_nNrOfStrings = cg_nNumOfConstStrings;
m_nNextString = g_nStringIdNextFreeId;
}
else{
forte_free(m_paStringBufAddr);
m_paStringBufAddr = 0;
}
}
#endif
}
CStringDictionary::~CStringDictionary(){
clear();
}
// clear
void CStringDictionary::clear(){
#ifndef FORTE_STRING_DICT_FIXED_MEMORY
forte_free(m_paStringBufAddr);
forte_free(m_pnStringIdBufAddr);
#endif
m_pnStringIdBufAddr = 0;
m_paStringBufAddr = 0;
m_nStringBufSize = 0;
m_nMaxNrOfStrings = 0;
m_nNrOfStrings = 0;
m_nNextString = 0;
}
// get a string (0 if not found)
const char *CStringDictionary::get(TStringId pa_nId){
if(pa_nId >= m_nNextString) {
return 0;
}
const char *adr = getStringAddress(pa_nId);
if(pa_nId > 0 && adr[-1] != '\0') {
return 0;
}
return adr;
}
// insert a string and return a string id (InvalidTStringId for no memory or other error)
CStringDictionary::TStringId CStringDictionary::insert(const char *pa_sStr){
TStringId nRetVal = scm_nInvalidStringId;
if(0 != pa_sStr){
if('\0' != *pa_sStr){
unsigned int idx;
nRetVal = findEntry(pa_sStr, idx);
if(scm_nInvalidStringId == nRetVal){
TStringId len = static_cast<TStringId>(strlen(pa_sStr));
TStringId nRequiredSize = m_nNextString + len + 1;
if(m_nNrOfStrings >= m_nMaxNrOfStrings){
#ifdef FORTE_STRING_DICT_FIXED_MEMORY
return scm_nInvalidStringId;
#else
//grow exponentially by 1.5 according to Herb Sutter best strategy
if(!reallocateStringIdBuf((m_nMaxNrOfStrings * 3) >> 1)){
return scm_nInvalidStringId;
}
#endif
}
if(nRequiredSize > m_nStringBufSize){
#ifdef FORTE_STRING_DICT_FIXED_MEMORY
return scm_nInvalidStringId;
#else
//grow exponentially by 1.5 according to Herb Sutter best strategy
if(!reallocateStringBuf((nRequiredSize * 3) >> 1)){
return scm_nInvalidStringId;
}
#endif
}
nRetVal = insertAt(pa_sStr, idx, len);
}
}
else{
DEVLOG_WARNING("[CStringDictionary::insert] String to insert was empty\n");
}
}
return nRetVal;
}
// Find an exact match or place to be the new index
CStringDictionary::TStringId CStringDictionary::findEntry(const char *pa_sStr, unsigned int &pa_rnIdx) const{
pa_rnIdx = 0;
if(m_nNrOfStrings == 0) {
return scm_nInvalidStringId;
}
int r = 0;
unsigned int low = 0, high = m_nNrOfStrings;
while(low < high){
pa_rnIdx = (low + high) / 2;
r = strcmp(pa_sStr, getStringAddress(m_pnStringIdBufAddr[pa_rnIdx]));
if(!r){
return m_pnStringIdBufAddr[pa_rnIdx];
}
if(r > 0) {
low = pa_rnIdx + 1;
} else {
high = pa_rnIdx;
}
}
if(r > 0) {
pa_rnIdx++;
}
return scm_nInvalidStringId;
}
// Reallocate the Id buffer
bool CStringDictionary::reallocateStringIdBuf(unsigned int pa_nNewMaxNrOfStrings){
bool bRetval = true;
if(pa_nNewMaxNrOfStrings > m_nMaxNrOfStrings){
TStringId *adr = (TStringId *) forte_malloc(pa_nNewMaxNrOfStrings * sizeof(TStringId));
if(0 != adr){
memcpy(adr, m_pnStringIdBufAddr, m_nMaxNrOfStrings * sizeof(TStringId));
TStringId *oldData = m_pnStringIdBufAddr;
m_pnStringIdBufAddr = adr;
m_nMaxNrOfStrings = pa_nNewMaxNrOfStrings;
forte_free(oldData);
}
else{
bRetval = false;
}
}
return bRetval;
}
// Reallocate the string buffer
bool CStringDictionary::reallocateStringBuf(TForteUInt32 pa_nNewBufSize){
bool bRetval = true;
if(pa_nNewBufSize > m_nStringBufSize){
char *adr = (char *) forte_malloc(pa_nNewBufSize * sizeof(char));
if(0 != adr){
memcpy(adr, m_paStringBufAddr, m_nStringBufSize * sizeof(char));
char *oldData = m_paStringBufAddr;
m_paStringBufAddr = adr;
m_nStringBufSize = pa_nNewBufSize;
forte_free(oldData);
}
else{
bRetval = false;
}
}
return bRetval;
}
// Insert the string at the specified position
CStringDictionary::TStringId CStringDictionary::insertAt(const char *pa_sStr, unsigned int pa_nIdx, unsigned int pa_nLen){
TStringId id = m_nNextString;
char *p = getStringAddress(m_nNextString);
memcpy(p, pa_sStr, pa_nLen);
p[pa_nLen] = '\0';
m_nNextString += pa_nLen + 1;
if(pa_nIdx < m_nNrOfStrings) {
memmove(m_pnStringIdBufAddr + pa_nIdx + 1, m_pnStringIdBufAddr + pa_nIdx, (m_nNrOfStrings - pa_nIdx) * sizeof(TStringId));
}
m_pnStringIdBufAddr[pa_nIdx] = id;
m_nNrOfStrings++;
return id;
}