Logo Search packages:      
Sourcecode: qlandkarte version File versions  Download package

GarminStrTbl.cpp

/**********************************************************************************************
    Copyright (C) 2006, 2007 Oliver Eichler oliver.eichler@gmx.de

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA

  Garmin and MapSource are registered trademarks or trademarks of Garmin Ltd.
  or one of its subsidiaries.

**********************************************************************************************/
#include "Platform.h"
#include "GarminStrTbl.h"
#include "GarminTypedef.h"

#include <QtCore>

IGarminStrTbl * createStringTable(const quint8* pDataLBL,  quint32 sizeLBL, QObject * parent)
{
    IGarminStrTbl * tbl = 0;

    hdr_lbl_t * hdr = (hdr_lbl_t*)pDataLBL;

    switch(hdr->coding) {
        case 0x06:
            tbl = new CGarminStrTbl6(pDataLBL,sizeLBL,parent);
            break;

        case 0x09:
            tbl = new CGarminStrTbl8(pDataLBL,sizeLBL,parent);
            break;

        case 0x0A:
            //             tbl = new IGarminStrTbl(pDataLBL,sizeLBL,parent);
            tbl = new CGarminStrTbl10(pDataLBL,sizeLBL,parent);
            //qWarning() << "10 bit label encoding is not implemented";
            break;

        default:;
        qWarning() << "Unknown label coding" << hex << hdr->coding;
    }
    return tbl;
}


// --------------------------------------
// ---------- base class ----------------
// --------------------------------------
IGarminStrTbl::IGarminStrTbl(const quint8* pDataLBL, quint32 sizeLBL, QObject * parent)
: QObject(parent)
, dataLBL((char*)pDataLBL,sizeLBL)
, hdrLbl((hdr_lbl_t*)dataLBL.data())
, pLbl1((quint8*)(dataLBL.data() + gar_load(uint32_t, hdrLbl->lbl1_offset)))
, pLbl6((quint8*)(dataLBL.data() + gar_load(uint32_t, hdrLbl->lbl6_offset)))
, hdrNet(0)
, pNet1(0)
, codepage(0)
, codec(0)
{
    if(gar_load(uint16_t, hdrLbl->length) > 0xAA) {

        codepage = gar_load(uint16_t, hdrLbl->codepage);

        if(1250 <= codepage && codepage <= 1258) {
            char strcp[64];
            sprintf(strcp,"Windows-%i",codepage);
            codec = QTextCodec::codecForName(strcp);
        }
        else if(codepage == 950) {
            codec = QTextCodec::codecForName("Big5");
        }
        else if(codepage == 850) {
            codec = QTextCodec::codecForName("IBM 850");
        }
        else {
            codepage = 0;
            qDebug() << "unknown codepage:" << gar_load(uint16_t, hdrLbl->codepage) << "0x" << hex << gar_load(uint16_t, hdrLbl->codepage);
        }
    }
}


IGarminStrTbl::~IGarminStrTbl()
{

}


void IGarminStrTbl::registerNETSection(const quint8* pDataNET, quint32 sizeNET)
{
    dataNET = QByteArray((char*)pDataNET,sizeNET);
    hdrNet  = (hdr_net_t*)dataNET.data();
    pNet1   = (quint8*)(dataNET.data() + gar_load(uint32_t, hdrNet->net1_offset));
}


quint32 IGarminStrTbl::calcOffset(const quint32 offset, type_e t)
{
    quint32 newOffset = offset;

    if(t == poi) {
        newOffset = gar_ptr_load(uint32_t, pLbl6 + offset);
        newOffset = (newOffset & 0x003FFFFF);
    }
    else if(t == net) {
        if(hdrNet == 0) {
            return 0xFFFFFFFF;
        }

        newOffset = gar_ptr_load(uint32_t, pNet1 + (offset << hdrNet->net1_addr_shift));
        if(newOffset & 0x00400000) {
            return 0xFFFFFFFF;
        }
        newOffset = (newOffset & 0x003FFFFF);
    }

    newOffset <<= hdrLbl->addr_shift;

    return newOffset;
}


// --------------------------------------
// ------ 6 bit string table ------------
// --------------------------------------
CGarminStrTbl6::CGarminStrTbl6(const quint8* pDataLBL, quint32 sizeLBL, QObject * parent)
: IGarminStrTbl(pDataLBL,sizeLBL,parent)
, reg(0)
, bits(0)
{
    qDebug() << "CGarminStrTbl6";
}


static const char str6tbl1[] =
{
    ' ','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'
    ,0,0,0,0,0
    ,'0','1','2','3','4','5','6','7','8','9'
    ,0,0,0,0,0,0
};

static const char str6tbl2[] =
{
    //@   !   "   #   $   %   &    '   (   )   *   +   ,   -   .   /
    '@','!','"','#','$','%','&','\'','(',')','*','+',',','-','.','/'
    ,0,0,0,0,0,0,0,0,0,0
    //:   ;   <   =   >   ?
    ,':',';','<','=','>','?'
    ,0,0,0,0,0,0,0,0,0,0,0
    //[    \   ]   ^   _
    ,'[','\\',']','^','_'
};

static const char str6tbl3[] =
{
    '`','a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'
};

CGarminStrTbl6::~CGarminStrTbl6()
{
}


void CGarminStrTbl6::get(quint32 offset, type_e t, str_info_t& info)
{

    offset = calcOffset(offset,t);

    if(offset == 0xFFFFFFFF) return;

    if(offset > (quint32)dataLBL.size()) {
        qWarning() << "Index into string table to large" << hex << offset << dataLBL.size() << hdrLbl->addr_shift << hdrNet->net1_addr_shift;
        return;
    }

    quint8  c1  = 0;
    quint8  c2  = 0;
    quint32 idx = 0;
    reg         = 0;
    bits        = 0;

    p = pLbl1 + offset;

    fill();
    while(idx < sizeof(buffer)) {
        c1 = reg >> 26; reg <<= 6; bits -= 6; fill();
        //terminator
        if(c1 > 0x2F) break;

        c2 = str6tbl1[c1];
        if(c2 == 0) {
            if(c1 == 0x1C) {
                c1 = reg >> 26; reg <<= 6; bits -= 6; fill();
                buffer[idx++] = str6tbl2[c1];
            }
            else if(c1 == 0x1B) {
                c1 = reg >> 26; reg <<= 6; bits -= 6; fill();
                buffer[idx++] = str6tbl3[c1];
            }
            else if(c1 > 0x1C && c1 < 0x20) {
                buffer[idx] = 0;
                if(strlen(buffer)) {
                    if (codepage != 0)
                        info.labels << codec->toUnicode(buffer);
                    else
                        info.labels << buffer;
                }
                idx = 0;
                buffer[0] = 0;
            }
        }
        else {
            buffer[idx++] = str6tbl1[c1];
        }
    }

    buffer[idx] = 0;
    if(strlen(buffer)) {
        if (codepage != 0)
            info.labels << codec->toUnicode(buffer);
        else
            info.labels << buffer;
    }

}


void CGarminStrTbl6::fill()
{
    quint32 tmp;
    if(bits < 6) {
        tmp = *p++;
        reg |= tmp << (24 - bits);
        bits += 8;
    }
}


// --------------------------------------
// ------ 8 bit string table ------------
// --------------------------------------
CGarminStrTbl8::CGarminStrTbl8(const quint8* pDataLBL, quint32 sizeLBL, QObject * parent)
: IGarminStrTbl(pDataLBL,sizeLBL,parent)
{
    qDebug() << "CGarminStrTbl8";
}


CGarminStrTbl8::~CGarminStrTbl8()
{
}


void CGarminStrTbl8::get(quint32 offset, type_e t, str_info_t& info)
{
    offset = calcOffset(offset,t);

    if(offset == 0xFFFFFFFF) return;

    if(offset > (quint32)dataLBL.size()) {
        //qWarning() << "Index into string table to large" << hex << offset << dataLBL.size() << hdrLbl->addr_shift << hdrNet->net1_addr_shift;
        return;
    }

    char * lbl = (char*)(pLbl1 + offset);

    char * pBuffer = buffer; *pBuffer = 0;
    while(*lbl != 0) {
        if((unsigned)*lbl >= 0x1B && (unsigned)*lbl <= 0x1F) {
            *pBuffer = 0;
            if(strlen(buffer)) {
                if (codepage != 0)
                    info.labels << codec->toUnicode(buffer);
                else
                    info.labels << buffer;
                pBuffer = buffer; *pBuffer = 0;
            }
            ++lbl;
            continue;
        }
        else if((unsigned)*lbl < 0x07) {
            ++lbl;
            continue;
        }
        else {
            *pBuffer++ = *lbl++;
        }
    }

    *pBuffer = 0;
    if(strlen(buffer)) {
        if (codepage != 0)
            info.labels << codec->toUnicode(buffer);
        else
            info.labels << buffer;
    }
}


// --------------------------------------
// ------ 10 bit string table -----------
// --------------------------------------
CGarminStrTbl10::CGarminStrTbl10(const quint8* pDataLBL, quint32 sizeLBL, QObject * parent)
: IGarminStrTbl(pDataLBL,sizeLBL,parent)
{
    qDebug() << "CGarminStrTbl10";
}


CGarminStrTbl10::~CGarminStrTbl10()
{
}


void CGarminStrTbl10::get(quint32 offset, type_e t, str_info_t& info)
{
    offset = calcOffset(offset,t);

    if(offset == 0xFFFFFFFF) return;

    if(offset > (quint32)dataLBL.size()) {
        qWarning() << "Index into string table to large" << hex << offset << dataLBL.size() << hdrLbl->addr_shift << hdrNet->net1_addr_shift;
        return;
    }

    char * lbl = (char*)(pLbl1 + offset);

    char * pBuffer = buffer; *pBuffer = 0;
    while(*lbl != 0) {
        if((unsigned)*lbl >= 0x1B && (unsigned)*lbl <= 0x1F) {
            *pBuffer = 0;
            if(strlen(buffer)) {
                info.labels << buffer;
                pBuffer = buffer; *pBuffer = 0;
            }
            ++lbl;
            continue;
        }
        else if((unsigned)*lbl < 0x07) {
            ++lbl;
            continue;
        }
        else {
            *pBuffer++ = *lbl++;
        }
    }

    *pBuffer = 0;
    if(strlen(buffer)) {
        //         qDebug() << QString(buffer);
        info.labels << QString(buffer);
    }
}

Generated by  Doxygen 1.6.0   Back to index