/*
* Copyright (c) 2007-2008 Nokia Corporation and/or its subsidiary(-ies).
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of the License "Eclipse Public License v1.0"
* which accompanies this distribution, and is available
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
*
* Initial Contributors:
* Nokia Corporation - initial contribution.
*
* Contributors:
*
* Description: 
*
*/



//  INCLUDE FILES
#include "cmmsmsgsmaddress.h"
#include <ctsy/serviceapi/cmmsmsutility.h> // for kmaxamountofdigits
#include "tsylogger.h"
#include "OstTraceDefinitions.h"
#ifdef OST_TRACE_COMPILER_IN_USE
#include "cmmsmsgsmaddressTraces.h"
#endif
      // for logging purposes

//  External Data Structures  

//  External Function Prototypes  

//  LOCAL CONSTANTS AND MACROS 
const TUint8 KAddressMinLength = 2;
const TUint8 KAddressLengthAndTon = 2;
const TUint8 KDataByteInUnicode = 2;
const TUint8 KHalfByte = 4;
const TUint8 KLengthOfByte = 8;
const TUint8 KLengthOfPackedByte = 7;
const TUint8 KTwoCharInByte = 2;

//  MODULE DATA STRUCTURES  

//  Local Data Structures  

//  Local Function Prototypes  

// Converts semioct-code to character, semioctet can be 0x00 - 0x0F
#define GSMSMSSEMIOCTETTOCHAR( bcd )  gsmSmsSemiOctetToCharTable[ bcd ]

//  MEMBER FUNCTIONS

//=============================================================================

// -----------------------------------------------------------------------------
// CMmSmsGsmAddress::CMmSmsGsmAddress
// C++ constructor. Private (this class should not be instantiated).
// ----------------------------------------------------------------------------- 
// 
CMmSmsGsmAddress::CMmSmsGsmAddress
        (
        //None
        )
    {
TFLOGSTRING("TSY: CMmSmsGsmAddress::CMmSmsGsmAddress");
OstTrace0( TRACE_NORMAL,  CMMSMSGSMADDRESS_CMMSMSGSMADDRESS_TD, "CMmSmsGsmAddress::CMmSmsGsmAddress" );
    //none
    }

// -----------------------------------------------------------------------------
// CMmSmsGsmAddress::GsmConvUnicodeTo0340Addr
// Converts type of number, numbering plan identification and
// phone number given in unicode string to the Gsm 03.40 
// standard
// ----------------------------------------------------------------------------- 
//
void CMmSmsGsmAddress::GsmConvUnicodeTo0340Addr
        (
        TUint8 aTon,            //Type of number
        TUint8 aNpi,            //Numbering plan identification
        TDes8& aDest,           //Service center address
        TDesC16 const& aSource  //Telephone number
        )    
    {
TFLOGSTRING("TSY: CMmSmsGsmAddress::GsmConvUnicodeTo0340Addr");
OstTrace0( TRACE_NORMAL,  CMMSMSGSMADDRESS_GSMCONVUNICODETO0340ADDR_TD, "CMmSmsGsmAddress::GsmConvUnicodeTo0340Addr" );
    
    if ( 0 != aSource.Length() )
        {
        GsmConvUnicodeToAddr( aTon, aNpi, aDest, aSource, ETrue );  
        }
    else
        {
        // Address length of 0 is a special case
        aDest.Append( 0 );      

        // Type-of-Address: TON = Unknown, NPI = ISDN/telephone num plan
        aDest.Append( 0x81 );  
        }
    }

// -----------------------------------------------------------------------------
// CMmSmsGsmAddress::GsmConv0340AddrToUnicode
// This function converts an address format string specified in 
// GSM 03.40 into unicode string
// ----------------------------------------------------------------------------- 
//
void CMmSmsGsmAddress::GsmConv0340AddrToUnicode
        ( 
        TDes& aDest,                            //Service center address
        TDesC8 const& aSource,                  //Telephone number
        RMobilePhone::TMobileTON& aTon,         //Type of number
        RMobilePhone::TMobileNPI& aNpi          //Telephone number
        )
    {
TFLOGSTRING("TSY: CMmSmsGsmAddress::GsmConv0340AddrToUnicode");
OstTrace0( TRACE_NORMAL,  CMMSMSGSMADDRESS_GSMCONV0340ADDRTOUNICODE_TD, "CMmSmsGsmAddress::GsmConv0340AddrToUnicode" );
    
    if ( KAddressMinLength <= aSource.Length() ) 
        {
        //Address length and address type fields included
        GsmConvAddrToUnicode( aDest, aSource, aTon, aNpi, ETrue );
        }
    else
        {
        //Corrupted address
        aDest.SetLength( 0 );
        aTon = RMobilePhone::EUnknownNumber;
        aNpi = RMobilePhone::EUnknownNumberingPlan;
        }
    }

// -----------------------------------------------------------------------------
// CMmSmsGsmAddress::GsmConvUnicodeTo0411Addr
// Converts type of number, numbering plan identification and
// phone number given in unicode string to the Gsm 04.11 
// standard
// ----------------------------------------------------------------------------- 
//
void CMmSmsGsmAddress::GsmConvUnicodeTo0411Addr
        (
        TUint8 aTon,            //Type of number
        TUint8 aNpi,            //Numbering plan identification
        TDes8& aDest,           //Service center address
        TDesC16 const& aSource  //Telephone number
        )
    { 
TFLOGSTRING("TSY: CMmSmsGsmAddress::GsmConvUnicodeTo0411Addr");
OstTrace0( TRACE_NORMAL,  CMMSMSGSMADDRESS_GSMCONVUNICODETO0411ADDR_TD, "CMmSmsGsmAddress::GsmConvUnicodeTo0411Addr" );
    
    if ( 0 != aSource.Length() )
        {
        GsmConvUnicodeToAddr( aTon, aNpi, aDest, aSource, EFalse );
        }
    else
        {
        // Address length of 0 is a special case: no address type is given.
        aDest.Append( 0 );
        }
    }

// -----------------------------------------------------------------------------
// CMmSmsGsmAddress::GsmConv0411AddrToUnicode
// This function converts an address format string specified in 
// GSM 04.11 into unicode string
// ----------------------------------------------------------------------------- 
//
void CMmSmsGsmAddress::GsmConv0411AddrToUnicode
        (
        TDes& aDest,                        //Destination
        TDesC8 const& aSource,              //Source
        RMobilePhone::TMobileTON& aTon,     //Type of number
        RMobilePhone::TMobileNPI& aNpi      //Numbering plan identification
        )
    {
TFLOGSTRING("TSY: CMmSmsGsmAddress::GsmConv0411AddrToUnicode");
OstTrace0( TRACE_NORMAL,  CMMSMSGSMADDRESS_GSMCONV0411ADDRTOUNICODE_TD, "CMmSmsGsmAddress::GsmConv0411AddrToUnicode" );
    
    if ( KAddressMinLength <= aSource.Length() )
        {
        //Address length and address type fields included
        GsmConvAddrToUnicode( aDest, aSource, aTon, aNpi, EFalse );
        }
    else
        {
        //No address type field
        aDest.SetLength( 0 );
        aTon = RMobilePhone::EUnknownNumber;
        aNpi = RMobilePhone::EUnknownNumberingPlan;
        }
    }

// -----------------------------------------------------------------------------
// CMmSmsGsmAddress::GsmConvUnicodeToAddr
// Converts type of number, numbering plan identification and
// phone number given in unicode string to the GSM 03.40 or
// 04.11 standard
// ----------------------------------------------------------------------------- 
//
void CMmSmsGsmAddress::GsmConvUnicodeToAddr
        (
        TUint8 aTon,             //Type of number
        TUint8 aNpi,             //Numbering plan identification
        TDes8& aDest,            //Service center address
        TDesC16 const& aSource,  //Telephone number
        TBool a0340Address       //GSM 03.40 address
        )
    { 
TFLOGSTRING4("TSY: CMmSmsGsmAddress::GsmConvUnicodeToAddr - number type: %d, numbering plan: %d, number: %S", aTon, aNpi, &aSource);
OstTraceExt3( TRACE_NORMAL,  CMMSMSGSMADDRESS_GSMCONVUNICODETOADDR_TD, "CMmSmsGsmAddress::GsmConvUnicodeToAddr;aTon=%hhu;aNpi=%hhu;aSource=%S", aTon, aNpi, aSource );
TFLOGSTRING2("TSY: CMmSmsGsmAddress::GsmConvUnicodeToAddr - GSM 03.40 address: %d", a0340Address);
OstTraceExt1( TRACE_NORMAL,  DUP1_CMMSMSGSMADDRESS_GSMCONVUNICODETOADDR_TD, "CMmSmsGsmAddress::GsmConvUnicodeToAddr;a0340Address=%hhu", a0340Address );
    
    //get address length (always < 255)
    TUint8 numberLength( static_cast< TUint8 >( aSource.Length() ) );
    TUint8 destLength( numberLength );
    TInt i( 0 );

    /*  Solve type of address
        Type of Address field format is as follows:

           7      6     5     4      3      2       1       0    bit
        |     |      |     |     |      |       |       |       |
        |  1  | Type of number   | Numbering-plan-identification|
        |     |      |     |     |      |       |       |       |
    */

    //type of number is three bits from left and fourth bit must be '1'
    TUint8 typeOfNumber( TUint8( aTon | 0x08 ) );
    //move four bit to the left
    typeOfNumber = TUint8( typeOfNumber << 4 );
    //numbering plan is four bits from left
    TUint8 numberingPlan( TUint8( aNpi & 0x0F ) );
    //set type of number and numbering plan to the typeOfNumber variable
    typeOfNumber = TUint8( typeOfNumber | numberingPlan );

    if ( RMobilePhone::EAlphanumericNumber == aTon )
        {
        TBuf8< KMaxLengthOfAddressData > addressData;
        TUint8 amountOfsemiOctets( 0 );
  
        GsmUnicodeAddrToAlphanumericAddr( 
            aSource, 
            addressData,
            amountOfsemiOctets );           

        //fill address length field
        if ( a0340Address )
            {
            //amount of used semi-octets in address data
            aDest.Append( amountOfsemiOctets );
            }
        else    //0411 address
            {
            //Actually alphanumeric address data for 0411 address is not 
            //supported (see GSM 24.011 and 24.008)...
            //Length of address data + length of address type field
            //lint -e{732} Warning about "loss of sign". 
            //Root cause is that TDesC::Length() returns a signed TInt
            aDest.Append( addressData.Length() + 1 );
            }

        //add typeOfNumber to the buffer
        aDest.Append( typeOfNumber );

        //add address data to the buffer. 
        aDest.Insert( KAddressLengthAndTon, addressData );  
        }
    else
        {
        //number can contain character '+'
        if ( '+' == aSource[ i ] )
            {
            i++;
            destLength--;

            // Maximum amount of digits is 20 (3GPP TS 23.040)
            if ( KMaxAmountOfDigits < destLength ) 
                {                                                   
                destLength = KMaxAmountOfDigits;
                // + 1 comes from '+'
                numberLength = KMaxAmountOfDigits + 1;
                }
            }
        else
            {
            // Maximum amount of digits is 20 (3GPP TS 23.040)
            if ( KMaxAmountOfDigits < destLength ) 
                {                                                   
                destLength = KMaxAmountOfDigits;
                numberLength = KMaxAmountOfDigits;
                }
            }

        // calculate address length in bytes (always < 255). 
        // destLength + 1 ensures that there is enough space in case of odd
        // destLength. 
        TUint8 bufferLength( static_cast< TUint8 >( 
            ( destLength + 1 ) / 2 + KAddressLengthAndTon ) );

        //set buffer length
        aDest.SetLength( bufferLength );

        //add length to the buffer
        if ( a0340Address )
            {
            //amount of used semi-octets in address data
            aDest[ 0 ] = destLength;   
            }
        else
            {
            //length of whole address data - length of address length field
            aDest[ 0 ] = static_cast< TUint8 >( bufferLength - 1 );
            }

        //add typeOfNumber to the buffer
        aDest[1] = typeOfNumber; 

        //needed variables
        TUint8 numLsb( 0 );
        TUint8 numMsb( 0 );
        TInt index( KAddressLengthAndTon );

        //add numbers to the buffer
        for ( ; ( i + 1 ) < numberLength ; i += 2 )
            {
            numLsb = TUint8( aSource[ i ] - '0' );
            numMsb = TUint8( static_cast< TUint8 >( 
                aSource[ i + 1 ] - '0' ) << KHalfByte );

            aDest[index++] = TUint8( numLsb | numMsb );
            }

        //if numberLength is odd, last number is fixed with 0xF0
        if ( i < numberLength )
            {
            aDest[ index ] = TUint8( 0xF0 | ( aSource[ i ] - '0' ) );
            }
        }  
    }

// -----------------------------------------------------------------------------
// CMmSmsGsmAddress::GsmConvAddrToUnicode
// Converts GSM 03.40 or 04.11 address to type of number, 
// numbering plan identification and phone number given in 
// unicode string
// ----------------------------------------------------------------------------- 
//
void CMmSmsGsmAddress::GsmConvAddrToUnicode
        ( 
        TDes& aDest,                            //Service center address
        TDesC8 const& aSource,                  //Telephone number
        RMobilePhone::TMobileTON& aTon,         //Type of number
        RMobilePhone::TMobileNPI& aNpi,         //Telephone number
        TBool a0340Address                      //GSM 03.40 address
        )
    {
TFLOGSTRING("TSY: CMmSmsGsmAddress::GsmConvAddrToUnicode");
OstTrace0( TRACE_NORMAL,  CMMSMSGSMADDRESS_GSMCONVADDRTOUNICODE_TD, "CMmSmsGsmAddress::GsmConvAddrToUnicode" );
    
    TUint8  addrDataLength( 0 );
    TBool   halfs( ETrue );
    TInt    index( 0 );               
    TUint   num2( 0 );

    //Get amount of digits in address data
    if ( a0340Address )
        {
        addrDataLength = static_cast< TUint8> ( aSource[ index ] );
        }
    else    //04.11 address
        {
        addrDataLength = static_cast< TUint8 >( KDataByteInUnicode 
            * ( aSource[ index ] - 1 ) );
        }

    // Check if there are too many digits
    // Maximum amount of digits is 20 (3GPP TS 23.040)
    if ( KMaxAmountOfDigits < addrDataLength )
        {
        addrDataLength = KMaxAmountOfDigits;
        }

    index++;

    // Lets take type of number field
    TUint8 typeOfNum( aSource[ index ] );
    GsmFindOutTonAndNpi( typeOfNum, &aTon, &aNpi );

    if ( ( RMobilePhone::EAlphanumericNumber == aTon )
        && ( 0x00 != addrDataLength ) )
        {
        //Calculate address length in bytes. If statement above check's that
        //addrDataLength is not zero.
        TInt addrDataLengthInBytes( ( addrDataLength + 1 ) 
            / KDataByteInUnicode );

        //Get address data
        TPtrC8 addressData( aSource.Mid( 
            KAddressLengthAndTon, 
            addrDataLengthInBytes ) ); 

        //amountOfCharsInAddrData = amount of used bits / length of char
        TUint amountOfCharsInAddrData( ( addrDataLength * KHalfByte ) 
            / KLengthOfPackedByte );
           
        GsmAlphanumericAddrToUnicodeAddr( 
            addressData, 
            amountOfCharsInAddrData,
            aDest );
        }
    else
        {
        // Check if number is international number and addrDataLength is 
        // bigger than zero
        if ( ( RMobilePhone::EInternationalNumber == aTon ) 
            && ( 0x00 != addrDataLength ) )
            {
            aDest.Append( '+' );
            }

        index++;

        while ( addrDataLength-- )
            {
            if ( aSource.Length() > index )
                {
                if ( halfs )
                    {               
                    // Lets take only four bits from right
                    num2 = GSMSMSSEMIOCTETTOCHAR( aSource[ index ] & 0x0F );
                    aDest.Append( num2 );
                    halfs = EFalse;
                    }
                else
                    {
                    if ( ( 0x0F == ( aSource[ index ] >> KHalfByte ) ) && !a0340Address )
                        {
                        //If 04.11 address contains odd number of digits, 
                        //bits 5 to 8 of the last octet shall be filled with an end
                        //mark coded as "1111".
                        break;
                        }

                    halfs = ETrue;  // Lets take only four bits from left
                    num2 = GSMSMSSEMIOCTETTOCHAR( aSource[ index ] >> KHalfByte );
                    aDest.Append( num2 );
                    index++;
                    }
                } // if ( aSource.Length() > index )
            } // while
        }
TFLOGSTRING4("TSY: CMmSmsGsmAddress::GsmConvAddrToUnicode - result: number type: %d, numbering plan: %d, number: %S", aTon, aNpi, &aDest);
OstTraceExt3( TRACE_NORMAL,  DUP1_CMMSMSGSMADDRESS_GSMCONVADDRTOUNICODE_TD, "CMmSmsGsmAddress::GsmConvAddrToUnicode;aTon=%d;aNpi=%d;aDest=%S", aTon, aNpi, aDest );
TFLOGSTRING2("TSY: CMmSmsGsmAddress::GsmConvAddrToUnicode - GSM 03.40 address", a0340Address);
OstTraceExt1( TRACE_NORMAL,  DUP2_CMMSMSGSMADDRESS_GSMCONVADDRTOUNICODE_TD, "CMmSmsGsmAddress::GsmConvAddrToUnicode;a0340Address=%hhu", a0340Address );
    }

// -----------------------------------------------------------------------------
// CMmSmsGsmAddress::GsmFindOutTonAndNpi
// Converts type of number and numbering plan identification
// information from the type of address parameter to the 
// RMobilePhone::TMobileTON and RMobilePhone::TMobileNPI format
// ----------------------------------------------------------------------------- 
//
void CMmSmsGsmAddress::GsmFindOutTonAndNpi
        ( 
        TUint8 typeOfAddress,               //Type of address
        RMobilePhone::TMobileTON* ton,      //Type of number
        RMobilePhone::TMobileNPI* npi       //Numbering plan identification
        )     
    {
TFLOGSTRING2("TSY: CMmSmsGsmAddress::GsmFindOutTonAndNpi - address type: %d", typeOfAddress);
OstTraceExt1( TRACE_NORMAL,  CMMSMSGSMADDRESS_GSMFINDOUTTONANDNPI_TD, "CMmSmsGsmAddress::GsmFindOutTonAndNpi;typeOfAddress=%hhu", typeOfAddress );
    
    TUint8 numberingPlanIdentification( static_cast< TUint8 >( 
        typeOfAddress & 0x0F ) );
    TUint8 temp( static_cast< TUint8 >( typeOfAddress >> KHalfByte ) );
    TUint8 typeOfNumber( static_cast< TUint8 >( temp & 0x07 ) );

    switch ( typeOfNumber )
        {
        case KInternationalNumber:
            {
            *ton = RMobilePhone::EInternationalNumber;
            break;
            }
        case KNationalNumber:
            {
            *ton = RMobilePhone::ENationalNumber;
            break;
            }
        case KNetworkSpecificNumber:
            {
            *ton = RMobilePhone::ENetworkSpecificNumber;
            break;
            }
        case KSubscriberNumber:
            {
            *ton = RMobilePhone::ESubscriberNumber;
            break;
            }
        case KAlphanumeric:
            {
            *ton = RMobilePhone::EAlphanumericNumber;
            break;
            }
        case KAbbreviatedNumber:
            {
            *ton = RMobilePhone::EAbbreviatedNumber;
            break;
            }

        default:
            {
TFLOGSTRING("TSY: CMmSmsGsmAddress::GsmFindOutTonAndNpi - unknown type of number");
OstTrace0( TRACE_NORMAL,  DUP1_CMMSMSGSMADDRESS_GSMFINDOUTTONANDNPI_TD, "CMmSmsGsmAddress::GsmFindOutTonAndNpi, unknown type of number" );
            *ton = RMobilePhone::EUnknownNumber;
            break;
            }
        }

    switch ( numberingPlanIdentification )
        {
        case KIsdnTelephoneNumPlan:
            {
            *npi = RMobilePhone::EIsdnNumberPlan;
            break;
            }
        case KDataNumPlan:
            {
            *npi = RMobilePhone::EDataNumberPlan;
            break;
            }
        case KTelexNumPlan:
            {
            *npi = RMobilePhone::ETelexNumberPlan;
            break;
            }
        case KServiceCentreSpecificPlan1:
            {
            *npi = RMobilePhone::EServiceCentreSpecificPlan1;
            break;
            }
        case KServiceCentreSpecificPlan2:
            {
            *npi = RMobilePhone::EServiceCentreSpecificPlan2;
            break;
            }
        case KNationalNumPlan:
            {
            *npi = RMobilePhone::ENationalNumberPlan;
            break;
            }
        case KPrivateNumPlan:
            {
            *npi = RMobilePhone::EPrivateNumberPlan;
            break;
            }
        case KErmesNumPlan:
            {
            *npi = RMobilePhone::EERMESNumberPlan;
            break;
            }

        default:
            {
TFLOGSTRING("TSY: CMmSmsGsmAddress::GsmFindOutTonAndNpi - unknown numbering plan");
OstTrace0( TRACE_NORMAL,  DUP2_CMMSMSGSMADDRESS_GSMFINDOUTTONANDNPI_TD, "CMmSmsGsmAddress::GsmFindOutTonAndNpi, unknown numbering plan" );
            *npi = RMobilePhone::EUnknownNumberingPlan;
            break;
            }
        }
    }

// -----------------------------------------------------------------------------
// CMmSmsGsmAddress::GsmMapTonToTUint8
// Converts type of number from the RMobilePhone::TMobileTON
// parameter to the TUint8 format
// ----------------------------------------------------------------------------- 
//
TUint8 CMmSmsGsmAddress::GsmMapTonToTUint8
        (
        RMobilePhone::TMobileTON aTon       //Type of number
        )
    {
TFLOGSTRING2("TSY: CMmSmsGsmAddress::GsmMapTonToTUint8 - type of number: %d", aTon);
OstTrace1( TRACE_NORMAL,  CMMSMSGSMADDRESS_GSMMAPTONTOTUINT8_TD, "CMmSmsGsmAddress::GsmMapTonToTUint8;aTon=%d", aTon );
    TUint8 typeOfNumber( 0 );

    switch ( aTon )
        {
        case RMobilePhone::EInternationalNumber:
            {
            typeOfNumber = KInternationalNumber;
            break;
            }
        case RMobilePhone::ENationalNumber:
            {
            typeOfNumber = KNationalNumber;
            break;
            }
        case RMobilePhone::ENetworkSpecificNumber:
            {
            typeOfNumber = KNetworkSpecificNumber;
            break;
            }
        case RMobilePhone::ESubscriberNumber:
            {
            typeOfNumber = KSubscriberNumber;
            break;
            } 
        case RMobilePhone::EAlphanumericNumber:
            {
            typeOfNumber = KAlphanumeric;
            break;
            } 
        case RMobilePhone::EAbbreviatedNumber:
            {
            typeOfNumber = KAbbreviatedNumber;
            break;
            } 
        case RMobilePhone::EUnknownNumber:
        default:
            {
TFLOGSTRING2("TSY: CMmSmsGsmAddress::GsmMapTonToTUint8 - unknown type of number: %d", aTon);
OstTrace1( TRACE_NORMAL,  DUP1_CMMSMSGSMADDRESS_GSMMAPTONTOTUINT8_TD, "CMmSmsGsmAddress::GsmMapTonToTUint8;unknown type of number aTon=%d", aTon );
            typeOfNumber = KTonUnknown;
            } 
        }

    return typeOfNumber;
    }

// -----------------------------------------------------------------------------
// CMmSmsGsmAddress::GsmMapNpiToTUint8
// Converts type of number from the RMobilePhone::TMobileNPI
// parameter to the TUint8 format
// ----------------------------------------------------------------------------- 
//
TUint8 CMmSmsGsmAddress::GsmMapNpiToTUint8
        ( 
        RMobilePhone::TMobileNPI aNpi   //Numbering plan identification
        )
    {
TFLOGSTRING2("TSY: CMmSmsGsmAddress::GsmMapNpiToTUint8 - numbering plan identification: %d", aNpi);
OstTrace1( TRACE_NORMAL,  CMMSMSGSMADDRESS_GSMMAPNPITOTUINT8_TD, "CMmSmsGsmAddress::GsmMapNpiToTUint8;aNpi=%d", aNpi );
    
    TUint8 numPlanIdentification( 0 );

    switch ( aNpi )
        {
        case RMobilePhone::EIsdnNumberPlan:
            {
            numPlanIdentification = KIsdnTelephoneNumPlan;
            break;
            } 
        case RMobilePhone::EDataNumberPlan:
            {
            numPlanIdentification = KDataNumPlan;
            break;
            } 
        case RMobilePhone::ETelexNumberPlan:
            {
            numPlanIdentification = KTelexNumPlan;
            break;
            } 
        case RMobilePhone::EServiceCentreSpecificPlan1:
            {
            numPlanIdentification = KServiceCentreSpecificPlan1;
            break;
            } 
        case RMobilePhone::EServiceCentreSpecificPlan2:
            {
            numPlanIdentification = KServiceCentreSpecificPlan2;
            break;
            } 
        case RMobilePhone::ENationalNumberPlan:
            {
            numPlanIdentification = KNationalNumPlan;
            break;
            } 
        case RMobilePhone::EPrivateNumberPlan:
            {
            numPlanIdentification = KPrivateNumPlan;
            break;
            } 
        case RMobilePhone::EERMESNumberPlan:
            {
            numPlanIdentification = KErmesNumPlan;
            break;
            } 
        case RMobilePhone::EUnknownNumberingPlan:
        default:
            {
TFLOGSTRING2("TSY: CMmSmsGsmAddress::GsmMapNpiToTUint8 - unknown numbering plan identification: %d", aNpi);
OstTrace1( TRACE_NORMAL,  DUP1_CMMSMSGSMADDRESS_GSMMAPNPITOTUINT8_TD, "CMmSmsGsmAddress::GsmMapNpiToTUint8;unknown numbering plan identification aNpi=%d", aNpi );
            numPlanIdentification = KNpiUnknown;
            } 
        }
        
    return numPlanIdentification;
    }

// -----------------------------------------------------------------------------
// CMmSmsGsmAddress::GsmUnicodeAddrToAlphanumericAddr
// Converts Unicode characters to GSM 7-bit bit Default Alphabet
// characters (Defined in GSM 23.038). Note that all Unicode characters 
// are not supported by the GSM 7-bit bit Default Alphabet set. Such 
// characters are converted to spaces or to the nearest substitute
// (generally the acute/grave marks are removed). Control characters and 
// special characters are converted to spaces. This method supports GSM 
// 7-bit bit Default Alphabet extension table
// mechanism.
//
// After character conversion this method packs address data by calling
// GsmLibSmsPackMessage method*/
// ----------------------------------------------------------------------------- 
//
void CMmSmsGsmAddress::GsmUnicodeAddrToAlphanumericAddr
        ( 
        TDesC16 const& aSource,     // Source address data
        TDes8& aDestination,        // Destination data
        TUint8& aAmountOfSemiOctets // Amount of semi-octets
        )
    {
    
TFLOGSTRING2("TSY: CMmSmsGsmAddress::GsmUnicodeAddrToAlphanumericAddr - source address: %S", &aSource);
OstTraceExt1( TRACE_NORMAL,  CMMSMSGSMADDRESS_GSMUNICODEADDRTOALPHANUMERICADDR_TD, "CMmSmsGsmAddress::GsmUnicodeAddrToAlphanumericAddr;aSource=%S", aSource );
    
    TUint16 j( 0 );
    TUint16 i( 0 );

    TBuf8< RMobilePhone::KMaxMobileTelNumberSize > alphaChars;
    for ( i = 0; i < aSource.Length(); i++ )
        {
        if ( ( 0x24 < aSource[ i ] ) && ( 0x5B > aSource[ i ] ) && 
             ( 0x40 != aSource[ i ] ) || 
             ( 0x60 < aSource[ i ] ) && ( 0x7B > aSource[ i ] ) )
            {
            // Conversion could be done only taking out the most significant 
            // bit from Unicode characters between 0x25 - 0x5A or 0x61 - 0x7A
            // excluding '@' (0x40).
            alphaChars.Append(aSource[ i ]);
            }
        else if ( ( 0x5A < aSource[ i ] ) && ( 0x5F > aSource[ i ] ) ||
             ( 0x7A < aSource[ i ] ) && ( 0x7F > aSource[ i ] ) ||
             ( 0x20AC == aSource[ i ] ) )
            {
            //Conversion made using GSM 7 bit default alphabet extension 
            //table. Characters: [,\,],^,{,|,},~,&euro
            for ( j = 0 ; j < KGsmExtensionConvTableSize; j++ )
                {
                if ( aSource[ i ] == KGsmExtensionConvTable[ j ].iUnicodeChar )
                    {
                    alphaChars.Append( 0x1B );// extension table flag
                    alphaChars.Append( 
                        KGsmExtensionConvTable[ j ].iGsmChar );
                    break;
                    }
                }   // end of for loop
            }   
        else
            {
            //Try to find character from conversion table.
            TBool notFound( ETrue );
            for ( j = 0; j < KGsmLibConvTableSize; j++ )
                {
                if ( aSource[ i ] == KGsmLibConvTable[ j ].iUnicodeChar )
                    {
                    alphaChars.Append( 
                        KGsmLibConvTable[ j ].iGsmChar );
                    notFound = EFalse;
                    break;
                    }
                }   // end of for loop 
            
            if( notFound )
                {
                //Couldn't found similar character. Convert to SPACE.
                alphaChars.Append( 0x20 ); 
                }
            }
        }

    TUint8 packedChars( GsmLibPackAlphanumericAddress( aDestination, 
                                                        alphaChars ) );

    //How many unused bits packed address contains
    TUint8 unusedBits( static_cast< TUint8 >( ( aDestination.Length() 
        * KLengthOfByte ) - ( packedChars * KLengthOfPackedByte ) ) );

    //How many semi-octets is used in packed address.
    if ( KHalfByte <= unusedBits )
        {
        //Last semi-octet doesn't contain address data
        aAmountOfSemiOctets = static_cast< TUint8 >( 
            ( aDestination.Length() * KTwoCharInByte ) - 1 );
        }
    else
        {
        //All semi-octets are used
        aAmountOfSemiOctets = static_cast< TUint8 >( 
            aDestination.Length() * KTwoCharInByte );
        }
    }  

// -----------------------------------------------------------------------------
// CMmSmsGsmAddress::GsmAlphanumericAddrToUnicodeAddr
// This method first decodes a address data that has been 
// coded using the algorithm described in GSM 03.40 annex 2 by calling
// GsmLibUnpackAlphanumericAddress method. After that this method 
// converts GSM 7-bit default alphabet characters to Unicode format.
// This method supports GSM 7-bit bit Default Alphabet extension table
// mechanism
// ----------------------------------------------------------------------------- 
//
void CMmSmsGsmAddress::GsmAlphanumericAddrToUnicodeAddr
        ( 
        TDesC8 const& aSource,  // Source address data
        TUint& aAmountOfChars,  // Amount of characters in address data
        TDes16& aDestination    // Destination data
        )
    {
TFLOGSTRING("TSY: CMmSmsGsmAddress::GsmAlphanumericAddrToUnicodeAddr");
OstTrace0( TRACE_NORMAL,  CMMSMSGSMADDRESS_GSMALPHANUMERICADDRTOUNICODEADDR_TD, "CMmSmsGsmAddress::GsmAlphanumericAddrToUnicodeAddr" );
    
    //Maximum length of address data is 10 bytes. These bytes can contain
    //11 packed 7-bit characters.
    TBuf8< KMaxLengthOfAddressData + 1 > unpackedSrc;
    GsmLibUnpackAlphanumericAddress( aSource, aAmountOfChars, unpackedSrc );

    TUint8 unpackedLength( static_cast< TUint8 >( unpackedSrc.Length() ) );
    TUint8 j( 0 );
    TUint8 i( 0 );

    for ( i = 0; i < unpackedLength; i++ )
        {
        unpackedSrc[ i ] &= 0x7F;     // only 7 bits used in GSM character set

        if ( ( 0x24 < unpackedSrc[ i ] ) && ( 0x5B > unpackedSrc[ i ] ) && 
             ( 0x40 != unpackedSrc[ i ] ) || 
             ( 0x60 < unpackedSrc[ i ] ) && ( 0x7B > unpackedSrc[ i ] ) )
            {
            // Character codes in Unicode and GSM 7-bit default alphabet 
            // are same between 0x25 - 0x5A and 0x61 - 0x7A
            // excluding 0x40.
            aDestination.Append( unpackedSrc[ i ] );
            }
        else if ( 0x1B == unpackedSrc[ i ] )
            { 
            //0x1B is an escape code to the extension table. Code after escape
            //code should been found from extension table.

            i++;

            //It is possible that extension table contains escape code to 
            //another extension table. Increase index i until we find something 
            //else than another escape code.
            for ( ; i < unpackedLength; i++ )
                {
                if ( 0x1B != unpackedSrc[ i ] )
                    {
                    //Found something else than escape code. Let's convert 
                    //character from extension table to Unicode character.
                    TBool notFound( ETrue );

                    for ( j = 0 ; j < KGsmExtensionConvTableSize; j++ )
                        {
                        if ( unpackedSrc[ i ] == 
                            KGsmExtensionConvTable[ j ].iGsmChar )
                            {
                            aDestination.Append( 
                                KGsmExtensionConvTable[ j ].iUnicodeChar );
                            notFound = EFalse;
                            break;
                            }
                        }  

                    if ( notFound )
                        {
                        //Couldn't find character from extension table.
                        //Convert to SPACE.
                        aDestination.Append( 0x20 );
                        }

                    break;
                    }
                else
                    {
                    //Found escape code to another extension table. 
                    //On receipt of this code, a receiving entity shall display 
                    //a space until another extension table is defined. 
                    aDestination.Append( 0x20 );
                    }
                }   // end of for loop
            }   // end of else if
        else
            {
            //Find character from conversion table.
            for ( j = 0; j < KGsmLibConvTableSize; j++ )
                {
                if ( unpackedSrc[ i ] == KGsmLibConvTable[ j ].iGsmChar )
                    {
                    aDestination.Append( 
                        KGsmLibConvTable[ j ].iUnicodeChar );
                    break;
                    }
                }   // end of for loop 
            }   // end of else
        }   // end of for loop
    }

// -----------------------------------------------------------------------------
// CMmSmsGsmAddress::GsmLibPackAlphanumericAddress
// This function packs a given text string consisting of 7-bit
// characters into 8 bit bytes in such a way that a 11-character
// address takes only 10 bytes of memory after the compression
// ----------------------------------------------------------------------------- 
//
TUint8 CMmSmsGsmAddress::GsmLibPackAlphanumericAddress
        ( 
        TDes8& aDest,            // Packed address
        TDes8& aSource           // Unpacked address
        )
    {
TFLOGSTRING("TSY: CMmSmsGsmAddress::GsmLibPackAlphanumericAddress");
OstTrace0( TRACE_NORMAL,  CMMSMSGSMADDRESS_GSMLIBPACKALPHANUMERICADDRESS_TD, "CMmSmsGsmAddress::GsmLibPackAlphanumericAddress" );
    TUint8 si( 0 );
    TUint8 di( 0 );
    TUint tempModulo( 0 );
    
    // Set tempModulo and byteCount
    tempModulo = di % KLengthOfPackedByte;
    TUint8 byteCount( static_cast< TUint8 >( aSource.Length() ) );

    // Maximum length of address data field is 10 bytes. 10 bytes can contain
    // 11 compressed 7-bit characters. Because of this maximum
    // amount of characters in alphanumeric address is 11.
    if ( ( KMaxLengthOfAddressData + 1 ) < byteCount )
        {
        byteCount = KMaxLengthOfAddressData + 1;
        }   

    while ( si < byteCount )
        {
        // Check if this is the last character of the message.
        // If it is, just shift it to the right. Otherwise,
        // fill the rest of the byte with the bits of the next 
        // source character.
        
        if ( si == ( byteCount - 1 ) )
            {
            TUint num2( ( aSource[ si ] >> tempModulo ) );
            aDest.Append( num2 );
            }
        else
            {
            TUint num2( ( aSource[ si ] >> tempModulo ) | 
                ( aSource[ si + 1 ] << ( KLengthOfPackedByte - tempModulo ) ) );
            aDest.Append( num2 );
            }
   
        di++;
        tempModulo = di % KLengthOfPackedByte;

        // Check if the destination byte could take the entire source character.
        // In that case, the source character does not have to be divided and
        // the next source character can be taken.
        
        if ( tempModulo == 0)
            {
            si += KTwoCharInByte;
            }
        else
            {
            si++;
            }
        }
    
    // Return the length of the coded message.
    return byteCount;
    }

// -----------------------------------------------------------------------------
// CMmSmsGsmAddress::GsmLibUnpackAlphanumericAddress
//  This function decodes a address that has been coded using 
// the algorithm described in GSM 03.40 annex 2. The result string will 
// consist of bytes that contain a 7-bit character each
// ----------------------------------------------------------------------------- 
//
void CMmSmsGsmAddress::GsmLibUnpackAlphanumericAddress
        ( 
        TDesC8 const& aSource,  // Packed address data
        TUint aAmountOfChars,   // Amount of characters in address data
        TDes8& aDest            // Unpacked address data 
        )
    {
TFLOGSTRING("TSY: CMmSmsGsmAddress::GsmLibUnpackAlphanumericAddress");
OstTrace0( TRACE_NORMAL,  CMMSMSGSMADDRESS_GSMLIBUNPACKALPHANUMERICADDRESS_TD, "CMmSmsGsmAddress::GsmLibUnpackAlphanumericAddress" );
    TUint8 di( 0 );
    TUint8 si( 0 );  
    TUint tempModulo( 0 );

    // Maximum length of address data field is 10 bytes. 10 bytes can contain
    // 11 compressed 7-bit characters. Because of this maximum
    // amount of characters in alphanumeric address is 11.
    if ( ( KMaxLengthOfAddressData + 1 ) < aAmountOfChars )
        {
        aAmountOfChars = KMaxLengthOfAddressData + 1;
        }

    // The location of the current 7-bit character determines the
    // action to be taken. Only every 7th character is not divided into
    // two bytes. All other characters will have to be contructed by
    // combining bits of two consequent bytes.

    for ( di = 0; di < aAmountOfChars; di++ )
        {
        TUint num2( 0 );
        tempModulo = di % KLengthOfByte;
        switch ( tempModulo )
            {
            case 0:
                {
                num2 = aSource[ si ] & 0x7F;
                break;
                }
            case KLengthOfPackedByte:
                {
                num2 = ( aSource[ si ] >> 1 ) & 0x7F;
                si++;
                break;
                }
            default:
                {
                num2  = aSource[ si ] >> ( KLengthOfByte - tempModulo );
                num2 &= KGsmLibSmsUnpackMaskTable[ tempModulo ];
                num2 |= aSource[ si+1 ] << ( tempModulo );
                num2 &= 0x7F;
                si++;
                break;
                }
            }
            
        aDest.Append( num2 );
        }
    }

//  End of File  
