/*=============================================================================
FILE: logparser.c

SERVICES: A Sample ILogger parser dll

DESCRIPTION:
          Implementation of the decoding functionality for ILogger

 Copyright © 2000-2001 Qualcomm Incorporated.  All Rights Reserved.
                        Qualcomm Proprietary/GTDR

=============================================================================*/

/*-----------------------------------------------------------------------------
   Include Files
-----------------------------------------------------------------------------*/



#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <iostream.h>
#include <fstream.h>
#include <iomanip.h>
#include<Windows.h>
#include "com.h"
#include "logparser.h"



int ILOGGER_LOG_CODE_BASE = 4189; // default




/*===========================================================================
 * METHOD: BrewLogItemHdr
 *    
 * ALGORITHM DESCRIPTION:
 *
 * Allocates memory for the brewlogitemhdr_type struct.
 *
 *=========================================================================*/
BrewLogItemHdr::BrewLogItemHdr()
{
    logitemhdr = new brewlogitemhdr_type;
}

/*===========================================================================
 * METHOD: BrewLodItemHdr
 *    
 * ALGORITHM DESCRIPTION:
 *
 * Deallocates memory for the brewlogitemhdr_type struct.
 *
 *=========================================================================*/
BrewLogItemHdr::~BrewLogItemHdr()
{
    delete logitemhdr;
}

/*===========================================================================
 * METHOD: >> operator 
 *    
 * ALGORITHM DESCRIPTION:
 *
 * Reads the data into the logitemhdr structure.
 *
 *=========================================================================*/
ifstream & operator>>(ifstream &is, BrewLogItemHdr &logitemhdr )
{
    is.read( (char *) logitemhdr.GetLogItemHdr(), sizeof(logitemhdr) ); 
    return is;
}
//------------End BrewLogItemHdr Implementation--------------------// 



/*===========================================================================
 * METHOD: LogMsg
 *    
 * ALGORITHM DESCRIPTION:
 *
 * Allocates memory for logmsgdata, msghdr, and msgbody.
 *
 *=========================================================================*/

LogMsg::LogMsg ()
{
    logmsgdata =        new uint8[1500];
    pmsghdr =           new uint8[MSGHDRSTRLEN];
    pmsgbody =          new uint8[MSGBODYSTRLEN];
    pLogOut =           new char[LOGOUTLEN];
	hexMode = 0; // Default to 0 (no hex mode)
	dataAvailable = 0; 
  
}

/*===========================================================================
 * METHOD: ~LogMsg
 *    
 * ALGORITHM DESCRIPTION:
 *
 * Deallocates memory.
 *
 *=========================================================================*/

LogMsg::~LogMsg()
{
    delete logmsgdata;
    delete pmsghdr;
    delete pmsgbody;
    delete pLogOut;
}

/*=============================================================================
FUNCTION Decode

DESCRIPTION
   This function decodes the "data" portion of the ILogger Header structure
   defined in ILogger interface of BREW.

PARAMETERS

RETURN VALUE

SIDE EFFECTS
   None.
=============================================================================*/

void LogMsg::Decode(char *buf)
{
 	uint16 type = 0;

   char* tmpBuf = buf;
    // Check the command code
    {

        // Check the log code to see if it's a ILogger structure
		
		if ( this->GetLogCode() >= ILOGGER_LOG_CODE_BASE && 
			this->GetLogCode() <= (ILOGGER_LOG_CODE_BASE +15) )
				
        {
           
			// Copy the stream data into the log item header struct
            
			memcpy( (unsigned char *) GetLogItemHdr(), tmpBuf, 
						sizeof(brewlogitemhdr_type));
            
            // Check the protocol type
            type = GetLogItemHdr()->type;
			
			
            tmpBuf += sizeof(brewlogitemhdr_type);
            
			switch(type) {
			case 0:
				// ASCII message, the nSize denotes the size of the following 
				// ASCII data in the AEELogrecord
				if(this->GetHexMode() == 1)
				{
						
					memcpy( logmsgdata, tmpBuf, this->GetLength());
					PrintHex();
				} else {
				memcpy( logmsgdata, tmpBuf, GetLogItemHdr()->nSize);
				PrintILoggerASCII(); // Print the ASCII text
				}
				break;
			case 1:
		
				// The logmessage data contains the binary structure 
				// denoted by the AEELogBinMsgType structure
				
				if(this->GetHexMode() == 1)
				{				
					memcpy( logmsgdata, tmpBuf, this->GetLength());
					PrintHex();
				}
				else {
				memcpy( logmsgdata, tmpBuf, GetLogItemHdr()->nSize);
				PrintILoggerBinaryToASCII(GetLogItemHdr()->nSize); // Decode the binary to ASCII
				}
				break;
			default:
					if(this->GetHexMode() == 1)
					{
						
						memcpy( logmsgdata, tmpBuf, this->GetLength());
						PrintHex();
					}
                    break;
			}
		}
	    
		
		else // Its a non-ILogger based message
		{
			if(this->GetHexMode() == 1) // Does the user want a hex dump 
										// without interpretation ? 
			{
			
			memcpy( logmsgdata, tmpBuf, this->GetLength());
			PrintHex();
			}
			
			else {
				strcpy(this->pLogOut,this->GetTimeStamp());
				char csLogcode[6];
				strcat(pLogOut,"\t");
				sprintf(csLogcode, "%d", this->GetLogCode());
				strcat(this->pLogOut, csLogcode);
				strcat(pLogOut,"\t");
				strcat(pLogOut,"Other CDMA Messages\n");
				this->SetDataAvailable(1);
			}
				
		}
	
} 
}


/* =========================================================================
 * METHOD: PrintHex
 * ALOGRITHM DESCRIPTION:
 *
 * Does a hex dump for messages not understood by it into the file.
 * =========================================================================*/

void LogMsg::PrintHex()
{
	char timeStamp[30];

    // Decode the timestamp
    strcpy(timeStamp, this->GetTimeStamp());
	
	int size =0;
	size = this->GetLength();
	int LengthOfHexString =  (size*2)+(size/2)+10;
	int x = sizeof(char);
	char* convertedHexStr;
	convertedHexStr= new char[LengthOfHexString]; // For each byte 2 characters used for display
														 // After every 2 bytes, put a " " 
														 // At the end , put a '\n'
	strcpy(convertedHexStr ,"\0");
	char* tmpBuf = convertedHexStr; // Point to the starting address of Converted Hex String.
	for(int i = 0; i< size; i++)
	{
		if(logmsgdata[i] == 0)
		{
			strcpy(tmpBuf, "00");
			tmpBuf +=2;
		}
		else if (logmsgdata[i] <= 15)
		{
			strcpy(tmpBuf, "0");
			tmpBuf++;
			_itoa(logmsgdata[i],tmpBuf, 16);
			tmpBuf++;
		}
		else
		{
			_itoa(logmsgdata[i],tmpBuf, 16);
			tmpBuf +=2;
		}
		if(i%2 == 1)
		{
			strcpy(tmpBuf, " ");
			tmpBuf ++;
		}
	}
	
	strcpy(pLogOut,"---------------Hex Dump--------------\n");
	strcat(pLogOut, timeStamp);
	strcat(pLogOut,"\t");
	char logCode[5];
	_itoa(this->GetLogCode(), logCode, 10);
	strcat(pLogOut, logCode);
	strcat(pLogOut,"\t");
	strcat(pLogOut, convertedHexStr);
	strcat(pLogOut,"\n");
	delete convertedHexStr;
	this->SetDataAvailable(1);

}
 


void LogMsg::PrintILoggerASCII( void )
{
    char timeStamp[30];

	strcpy(timeStamp,this->GetTimeStamp());
    
    const brewlogitemhdr_type* myloghdr = GetLogItemHdr(); 
    
    sprintf( pTmp, "%s\t%d\t%d\t%d\t%s\n",                timeStamp, 
                                                          myloghdr->classID,
                                                          myloghdr->instanceID,
                                                          myloghdr->type,
                                                          LogLevels[myloghdr->level] );
    strcpy( pLogOut, pTmp );
  
	sprintf( pTmp, "----------------------Message-----------------------------------------\n");
  
	strcat( pLogOut, pTmp );
	
	// Now concatenate the logmsgdata
	if(strlen((char*)logmsgdata) >= (MSGBODYSTRLEN -1))
		strncpy(pTmp,(char*)logmsgdata,MSGBODYSTRLEN-1); // Clip the message
	else
		strcpy(pTmp,(char*)logmsgdata);

    strcat(pTmp,"\n");
	strcat(pLogOut, pTmp);
	this->SetDataAvailable(1);
}


void LogMsg::PrintILoggerBinaryToASCII(int size)
{

	AEELogBinMsgType* binLogAEE = new AEELogBinMsgType;
	memset((unsigned char*) binLogAEE, 0, size);
	memcpy((uint8 *)binLogAEE, logmsgdata, size);
	char timeStamp[30];    
    strcpy(timeStamp, this->GetTimeStamp());
    strcpy( pLogOut,timeStamp );
  
	sprintf( pTmp, "----------------------Message-----------------------------------------\n");
  
	strcat( pLogOut, pTmp );
	
	char szFormatStr[MAX_LOG_TYPE_BIN_MSG_TEXT_SIZE];
	char szFileStr[MAX_LOG_TYPE_BIN_MSG_FILENAME_SIZE];
	uint8 num_of_args = 0;
	int file_present =0;
	int message_level = 0;
	char line_num_str[12] = {0}; // String to store uint32

	if(binLogAEE->header & 0x20 > 0) {// Means there are some arguments present
		num_of_args = binLogAEE->header && 0x20;
		
		
	}
	if(binLogAEE->header & 0x08 > 0) // Means filename is present
		file_present = 1;
	
	
	// Need to get the filename first and then the message
	if(file_present)
	{
		int count = 0;
		while(binLogAEE->pszMsg[count] != '\0') 
		{
			strcat(szFileStr,&binLogAEE->pszMsg[count]);
			count++;
		}
		strcat(szFileStr,'\0');
		count++;
		
		while(binLogAEE->pszMsg[count] != '\0') 
		{
			strcat(szFormatStr,&binLogAEE->pszMsg[count]);
			count++;
		}

	}
	else // There is no file name present. So everything is a format string
	{
		strcpy(szFormatStr,binLogAEE->pszMsg);
		strcpy(szFileStr,"-");
	}
	// get the message Level
	message_level = binLogAEE->header & 0x07;
	
	// Convert the line number into string
	_itoa(binLogAEE->line, line_num_str, 10);
	
	// Then print the message
	// This being a sample script we are just demonstrating what needs to
	// be done. The user may use va_list as an option to print out
	// the resulting string
	switch(num_of_args)
	{
	case 1:
		sprintf(pTmp,szFormatStr,binLogAEE->args[0]); 
		break;
	case 2:
		sprintf(pTmp,szFormatStr,binLogAEE->args[0], binLogAEE->args[1]); 
		break;
	case 3:
		sprintf(pTmp,szFormatStr,binLogAEE->args[0], binLogAEE->args[1], binLogAEE->args[2]); 
		break;
	default:
		sprintf(pTmp,"%s",szFormatStr); 
		break;
	}

   	strcat(pTmp, "\t"); // tab separated
	strcat(pTmp, szFileStr);
	strcat(pTmp, "\t"); // tab separated
	strcat(pTmp, line_num_str);
	strcat(pTmp,"\n");
	strcat(pLogOut, pTmp);
	this->SetDataAvailable(1);

	delete binLogAEE;

}

#ifdef _USRDLL
//	Note!
//
/////////////////////////////////////////////////////////////////////////////
// CBREWLogParser construction

CBREWLogParser::CBREWLogParser()
{
	// TODO: add construction code here,
	// Place all significant initialization in InitInstance
}

/////////////////////////////////////////////////////////////////////////////
// The one and only CBREWLogParser object

CBREWLogParser gBREWLogParser;





int CBREWLogParser::getASCIIresponse_inStr(unsigned char* byteIn,uint16 length, char& strOut,uint16 lenOut, char* timeStamp, int logcode,int base_logcode, int hexDumpFlag)
{

		LogMsg hdr;
		char *buf;
		uint16 len = length;
		// Set the mode of output
		hdr.SetMode(BYTE_TO_STRING);
		hdr.SethexMode(hexDumpFlag);
		hdr.SetTimeStamp(timeStamp);
		hdr.SetLogCode(logcode);
		hdr.SetLength(length);
		ILOGGER_LOG_CODE_BASE = base_logcode;
				
			// Get the length of the record
		
			buf = new char[len];
			
			memcpy(buf,byteIn,len);

			hdr.Decode(buf);

			delete buf;
			// At this point the pLogOut is already formed......
			if(hdr.GetDataAvailable() )
			{
				if(strlen(hdr.pLogOut) >= lenOut)
					strncpy(&strOut,hdr.pLogOut, lenOut);
				else
					strcpy(&strOut, hdr.pLogOut);
				hdr.SetDataAvailable(0);
			}
			else
				strcpy(&strOut, "\n");

		

		return 1;

}


int CBREWLogParser::getDbgASCIIresponse(char* timeStamp,uint16 ts_len,char* szMsgData,uint16 msgLen, char* fileName, uint16 fnameLen, unsigned char level, uint16 line_num, char& strOut, uint16 lenOut)
{
	strcpy(&strOut,timeStamp);
	strcat(&strOut,"\t");
	strcat(&strOut, szMsgData);
	strcat(&strOut, "\n");
	return 1;
}



extern "C" __declspec (dllexport) int DecodeUserLogMessage(unsigned char* byteIn,uint16 len, char& strOut, uint16 lenOut,char* timeStamp, int logcode, int base_logcode, int hexDumpFlag){
	
		return gBREWLogParser.getASCIIresponse_inStr(byteIn,len,strOut,lenOut, timeStamp, logcode,base_logcode, hexDumpFlag);
}

extern "C" __declspec (dllexport) int FormatDbgMessage(char* timeStamp,uint16 ts_len,char* szMsgData,uint16 msgLen, char* fileName, uint16 fnameLen, unsigned char level, uint16 line_num, char& strOut, uint16 lenOut){
	
		return gBREWLogParser.getDbgASCIIresponse(timeStamp, ts_len, szMsgData, msgLen, fileName, fnameLen,level,line_num,strOut,lenOut);
}


#endif // USRDLL
