/*
* 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