diff -r 000000000000 -r 3da2a79470a7 testexecmgmt/ucc/Source/Uccs.v2/Core/UCCS_CCommandDecoder.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/testexecmgmt/ucc/Source/Uccs.v2/Core/UCCS_CCommandDecoder.cpp Mon Mar 08 15:04:18 2010 +0800 @@ -0,0 +1,503 @@ +/* +* Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies). +* All rights reserved. +* This component and the accompanying materials are made available +* under the terms of "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: +* Filename: UCCS_CCommandDecoder.cpp +* System Includes +* +*/ + + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/*********************************************************************************** + * + * Local Includes + * + **********************************************************************************/ +#include "UCCS_CCommandDecoder.h" + + +/*********************************************************************************** + * + * Macro Functions + * + **********************************************************************************/ +#define IS_WHITESPACE(c) ((c == '\t')||(c == ' ')||(c == '\n')) +#define NOT_IS_WHITESPACE_OR_TERM(c) ((IS_WHITESPACE(c) == 0)&&(c != 0)) +#define IS_NAME_CHAR(c) (isdigit(c)||isalpha(c)||(c == '_')) + +/*********************************************************************************** + * + * Definitions + * + **********************************************************************************/ +#define TA_FILENAME 1 +#define TA_ASSIGNEDVALUE 2 +#define TA_INTEGERLITERAL 4 +#define TA_STRINGLITERAL 8 + +//-------------------------------------------------------------------------------------------------- +// +// Construction +// +//-------------------------------------------------------------------------------------------------- +CCommandDecoder::CCommandDecoder( CDataRecord *aEnvironment ) +{ + iEnvironment = aEnvironment; + iLastReply = NULL; +} + +CCommandDecoder::~CCommandDecoder() +{ +} + + +//-------------------------------------------------------------------------------------------------- +// +// Parse commands here and store as a list of field descriptions +// +//-------------------------------------------------------------------------------------------------- +int CCommandDecoder::ParseCommand( char* aCommandstring, TFieldDesc *aFieldList, int aListLength ) +{ + char *start_name; + char *start_value; + int element_attributes; + char *end_value; + int i; + int err; + + // if the command string is null then there is nothing to do + if( aCommandstring == NULL ) + return UCCS_OK; + + // process the entire string + start_name = aCommandstring; + for( i = 0; (i < aListLength) && (*start_name != 0); i++ ) { + + // init the vars + element_attributes = 0; + + // skip over any whitespace to the next start + for( start_name; IS_WHITESPACE(*start_name); start_name++ ) + ; + + // if we are at NULL then exit + if( *start_name == 0 ) { + continue; + } + + // if the character is not alpha then exit + if( isalpha(*start_name) == 0 ) { + return UCCS_PARSERFAILEDTOSTOREVALUE; + } + + // otherwise this is the start of the token, look for the '=', only alpha, digit, and '_' + // characters are allowed in names + for( start_value = start_name; (start_value != NULL) && IS_NAME_CHAR(*start_value); start_value++ ) + ; + if( start_value == NULL ) { + break; + } + if( *start_value != '=' ) { + return UCCS_PARSERFAILEDTOSTOREVALUE; + } + *start_value = 0; + start_value++; + + // if the character at start_value is alpha then this is an assigned value + if( isalpha(*start_value) ) { + element_attributes |= TA_ASSIGNEDVALUE; + } + + // if the character at the start is numeric then this is an integer literal + if( isdigit(*start_value) ) { + element_attributes |= TA_INTEGERLITERAL; + } + + // if the character at the start is '"' then this is a string literal + if( *start_value == '"' ) { + element_attributes |= TA_STRINGLITERAL; + } + + // if the character is whitespace then this is an error + if( IS_WHITESPACE(*start_value) ) { + return UCCS_PARSERFAILEDTOSTOREVALUE; + } + + // if the character at start_value is '"' then this is a string literal that may include + // whitespace and escaped '\' and '"' characters. At the end of this the start_value should + // point to a null terminated string that is what we want + if( *start_value == '"' ) { + end_value = FindEndOfDoubleQuotes( start_value ); + if( end_value == NULL ) { + continue; + } + start_value++; + } else { + end_value = start_value; + for( end_value; NOT_IS_WHITESPACE_OR_TERM(*end_value); end_value++ ) + ; + } + + // terminate the value + *end_value = 0; + + // remove the escape sequences - eg. \" to " + if(DecodeEscapeSequences(start_value)) { + Cleanup( aFieldList, aListLength ); + return UCCS_PARSERFAILEDTOSTOREVALUE; + } + + // save the new value + err = StoreNextValue( start_name, start_value, element_attributes, aFieldList, i ); + if( err != 0 ) { + Cleanup( aFieldList, aListLength ); + return UCCS_PARSERFAILEDTOSTOREVALUE; + } + + // now move to the next potential token + start_name = end_value + 1; + } + + // done + return UCCS_OK; +} + + +//-------------------------------------------------------------------------------------------------- +// +// Parse commands here and store as a data record +// +//-------------------------------------------------------------------------------------------------- +int CCommandDecoder::ParseCommandToRecord( char *aCommandstring, CDataRecord *aRecord ) +{ + int err; + int i; + TFieldDesc iFieldList[MAXFIELDCOUNT]; + + // Check params + assert( aRecord != NULL ); + + // clear the field descriptions + memset( iFieldList, 0, sizeof(TFieldDesc)*MAXFIELDCOUNT ); + + // Parse the command into buffers + err = ParseCommand( aCommandstring, iFieldList, MAXFIELDCOUNT ); + if( err != UCCS_OK ) { + return err; + } + + // Now add all the fields to the record + for( i = 0; (iFieldList[i].iName != NULL) && (i < MAXFIELDCOUNT); i++ ) { + if( iFieldList[i].iLength == 0 ) { + err = aRecord->NewField( iFieldList[i].iName, iFieldList[i].iValue ); + assert( err == UCCS_OK ); + } else { + err = aRecord->NewField( iFieldList[i].iName, iFieldList[i].iValue, iFieldList[i].iLength ); + assert( err == UCCS_OK ); + } + free( iFieldList[i].iName ); + free( iFieldList[i].iValue ); + iFieldList[i].iName = 0; + iFieldList[i].iValue = 0; + iFieldList[i].iLength = 0; + } + + //done + return UCCS_OK; +} + + +/*********************************************************************************** + * + * PUBLIC METHOD: SetLastReply - set the last reply to be used in parsing + * + **********************************************************************************/ +void CCommandDecoder::SetLastReply( CDataRecord *aLastReply ) +{ + iLastReply = aLastReply; +} + + +//-------------------------------------------------------------------------------------------------- +// +// PRIVATE METHODS +// +//-------------------------------------------------------------------------------------------------- + +//-------------------------------------------------------------------------------------------------- +// +// Store the value +// +//-------------------------------------------------------------------------------------------------- +int CCommandDecoder::StoreNextValue( char *aName, char *aValue, int aAttributes, TFieldDesc *aFieldList, int aIndex ) +{ + int namelength; + int valuelength; +// int filesize; + int err; + int variable_found = 0; + char *aAssignedValue; + + // check params + assert( aName != NULL ); + assert( aValue != NULL ); + assert( aFieldList != NULL ); + assert( aFieldList[aIndex].iName == NULL ); + assert( aFieldList[aIndex].iValue == NULL ); + + // store the name + _strupr( aName ); + namelength = strlen( aName ); + (aFieldList[aIndex].iName) = (char*)malloc( namelength + 1 ); + assert( (aFieldList[aIndex].iName) != NULL ); + strcpy( (aFieldList[aIndex].iName), aName ); + + // if the assigned values attribute is set then we: value = environment[value'] -- value = lastreply[value'] + if( aAttributes & TA_ASSIGNEDVALUE ) { + + // change the variable name to upper case to remove all case sensitivity + _strupr( aValue ); + + // look in the environment first + if( iEnvironment != NULL ) { + err = iEnvironment->GetFieldAsString( aValue, &aAssignedValue ); + if( err == UCCS_OK ) { + aValue = aAssignedValue; + variable_found = 1; + } + } + + // look in the last reply + if( (iLastReply != NULL) && (variable_found == 0) ) { + err = iLastReply->GetFieldAsString( aValue, &aAssignedValue ); + if( err == UCCS_OK ) { + aValue = aAssignedValue; + variable_found = 1; + } + } + + // if variable wasn't found then return error + if( variable_found == 0 ) { + return -1; + } + } + + // store non-file values + if( (aAttributes & TA_FILENAME) == 0 ) { + valuelength = strlen( aValue ); + (aFieldList[aIndex].iValue) = (char*)malloc( valuelength + 1 ); + assert( (aFieldList[aIndex].iValue) != NULL ); + strcpy( (aFieldList[aIndex].iValue), aValue ); + } + + // store file value +#ifdef OLDSTYLE + if( aAttributes & TA_FILENAME ) { + + // get the size of the file + filesize = GetFileSize( aValue ); + if( filesize == -1 ) { + free( (aFieldList[aIndex].iName) ); + (aFieldList[aIndex].iName) = NULL; + return -1; + } + + // allocate the memory to hold the file + (aFieldList[aIndex].iValue) = (char*)malloc( filesize ); + assert( (aFieldList[aIndex].iValue) != NULL ); + + // set the size + aFieldList[aIndex].iLength = filesize; + + // read the file into memory + err = ReadFileIntoBuffer( aValue, (aFieldList[aIndex].iValue), filesize ); + if( err != 0 ) { + free( (aFieldList[aIndex].iName) ); + (aFieldList[aIndex].iName) = NULL; + free( (aFieldList[aIndex].iValue) ); + (aFieldList[aIndex].iValue) = NULL; + return -1; + } + } +#endif + + // done + return 0; +} + + +//-------------------------------------------------------------------------------------------------- +// +// FindEndOfDoubleQuotes -- given a string starting with '"' it returns a pointer to the character +// matching '"'. It deals with escaped chars. +// +//-------------------------------------------------------------------------------------------------- +char *CCommandDecoder::FindEndOfDoubleQuotes( char *aString ) +{ + char *str; + + // the first char MUST be '"' + if( aString[0] != '"' ) { + return NULL; + } + + // now look for a non-escaped '"' + str = aString + 1; + while( 1 ) { + str = strchr( str, '"' ); + if( str == NULL ) { + return NULL; + } + if( str[-1] != '\\' ) { + return str; + } + str++; + } + + // done + assert( !"INVALID CODE PATH" ); + return NULL; +} +//-------------------------------------------------------------------------------------------------- + + +//-------------------------------------------------------------------------------------------------- +// +// GetFileSize -- return the size of a file +// +//-------------------------------------------------------------------------------------------------- +int CCommandDecoder::GetFileSize( char *aFilename ) +{ + struct _stat sinfo; + int err; + err = _stat( aFilename, &sinfo ); + if( err != 0 ) { + return -1; + } + return sinfo.st_size; +} + + +//-------------------------------------------------------------------------------------------------- +// +// GetFileSize -- return the size of a file +// +//-------------------------------------------------------------------------------------------------- +int CCommandDecoder::ReadFileIntoBuffer( char *aFilename, char *aBuff, int aBuffSize ) +{ + FILE *fp; + int err; + int i; + + // open the file + fp = fopen( aFilename, "rb" ); + if( fp == NULL ) { + return -1; + } + + // read in the bytes + for( i = 0; i < aBuffSize; i++ ) { + err = fread( &(aBuff[i]), 1, 1, fp ); + if( err != 1 ) { + fclose( fp ); + return -1; + } + } + + // done + fclose( fp ); + return 0; +} + + +//-------------------------------------------------------------------------------------------------- +// +// Cleanup +// +//-------------------------------------------------------------------------------------------------- +void CCommandDecoder::Cleanup( TFieldDesc *aFieldList, int aLen ) +{ + int i; + for( i = 0; i < aLen; i++ ) { + if( (aFieldList[i].iName) != NULL ) { + free( (aFieldList[i].iName) ); + (aFieldList[i].iName) = NULL; + } + if( (aFieldList[i].iValue) != NULL ) { + free( (aFieldList[i].iName) ); + (aFieldList[i].iName) = NULL; + } + } +} + + +//-------------------------------------------------------------------------------------------------- +// +// DecodeEscapeSequences - change \" to " and \\ to \ +// +//-------------------------------------------------------------------------------------------------- +// decode escape sequence +// - deliberately chose not to use sscanf's parser; more complicated, performance overhead, & requirement for a seperate string +int CCommandDecoder::DecodeEscapeSequences(char *start_value) +{ + int result = 0, read_pos = 0, write_pos = 0; + + // remove the escape char + while (start_value[read_pos] != 0) + { + if (start_value[read_pos++] == '\\') + { + char decodedChar = 0; + switch (start_value[read_pos++]) + { + case 'a': decodedChar = '\a'; break; + case 'b': decodedChar = '\b'; break; + case 'f': decodedChar = '\f'; break; + case 'n': decodedChar = '\n'; break; + case 'r': decodedChar = '\r'; break; + case 't': decodedChar = '\t'; break; + case 'v': decodedChar = '\v'; break; + case '\\': decodedChar = '\\'; break; + case '?': decodedChar = '\?'; break; + case '\'': decodedChar = '\''; break; + case '\"': decodedChar = '\"'; break; + // case '\x"': decodedChar = '\"'; break; - not supported, since this could overrun the char array + // case '\o"': decodedChar = '\"'; break; - not supported, functionality not needed + default: + // unknown + result = -1; + return result; + } + start_value[write_pos++] = decodedChar; + } + else + start_value[write_pos++] = start_value[read_pos - 1]; + } + + // re-insert the null char + start_value[write_pos] = 0; + + return result; +}