laatzen/CRC_CCITT/txtFileHandler.cs
2021-10-01 11:09:20 +02:00

398 lines
16 KiB
C#

/*********************************************************************************************************************/
/*!@file txtFileHandler.cs
* @brief Handle for Texas Instruments-txt files.
*
*====================================================================================================================\n
* @copyright
*
* ___________________________________________________________________________________________________________________\n
* Copyright (c) 2016 SENSUS, GmbH.\n
* All Rights Reserved.\n
* \n
* Confidential property of\n
* SENSUS GmbH,\n
* Meineckestr. 10, 30880 LAATZEN, GERMANY\n
* \n
* Design by\n
* Hard- und Softwareentwicklung Thomas Wiedebusch,\n
* Ostermarsch 17c, 31191 ALGERMISSEN/UMMELN, GERMANY\n
* \n
*====================================================================================================================\n
* @intro
*
*____________________________________________________________________________________________________________________\n
* Functions:\n
* Reading txt files,\n
* Replacing bytes with CRC.\n
*
*====================================================================================================================\n
* @version
*
*____________________________________________________________________________________________________________________\n
* V1.00 25-Feb-2016..27-Feb-2016 by Thomas Wiedebusch\n
* - Initial.
*
*
*====================================================================================================================\n
*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
namespace CRC_CCITT
{
/*---------------------------------------------------------------------------------------------------------------*/
/*!@brief txtFileHandler class.
* @author Thomas Wiedebusch
* @date 25-Feb-2016
*
*/
/*---------------------------------------------------------------------------------------------------------------*/
class txtFileHandler_t
{
//class variables
String inputFile_str; //file name
String outputFile_str; //file name
String fileLine_str; //one line of the file
crcGenrator_memSetFn_t MemSetFn_vdp; //set data to address of working memory
crcGenrator_memGetFn_t MemGetFn_u8p; //get data from working memory
UInt32 crcFileLineBaseAddress_u32 = 0; //CRC file line address reminder set during input file processing
UInt32 crcFileLine_u32 = 0; //CRC address line in file reminder set during input file processing
bool crcFileLineFound_bol = false; //CRC address in file found reminder
UInt32 memAddressCtr_u32 = 0; //CRC memory address counter
bool placeCrcToFile_bol; //CRC output to file is required
UInt32 crcAddress_u32; //CRC address given as parameter at startup
//txt file markers
const Char addressMarker_cchr = '@'; //base address marker
const Char endOfFileMarker_cchr = 'q'; //end of file marker
const Byte maxDataOfFileLine_cu8 = 16; //maximum data at one file line
const Byte fileLineDataCellIncrement_cu8 = 3; //3 digits increment for one data byte e.g. A5_
//calculations
UInt32 fileLineCtr_u32 = 0; //actual accessed file line
bool memoryAddressSetup_bol = false; //initial memory address has been set
/*---------------------------------------------------------------------------------------------------------------*/
/*!@brief Constructor for txt file handler class:\n
* -initializes file,\n
* -this constructor will only be called if the input file has been found,\n
* -sets delegates to memory set and get function being able to dispatch read data.\n
* @author Thomas Wiedebusch
* @date 25-Feb-2016
* @param[in] inputFileIn_str file name for input file
* @param[in] outputFileIn_str file name for output file, can be identical with input file
* @param[in] MemSetInFn_vdp set function to dispatch data to memory
* @param[in] MemGetInFn_vdp get function to read data from memory
*
*/
/*---------------------------------------------------------------------------------------------------------------*/
public txtFileHandler_t(String inputFileIn_str, String outputFileIn_str, crcGenrator_memSetFn_t MemSetInFn_vdp,
crcGenrator_memGetFn_t MemGetInFn_u8p, UInt32 crcAddressIn_u32, bool placeCrcToFileIn_bol)
{
inputFile_str = inputFileIn_str;
outputFile_str = outputFileIn_str;
MemSetFn_vdp = MemSetInFn_vdp;
MemGetFn_u8p = MemGetInFn_u8p;
placeCrcToFile_bol = placeCrcToFileIn_bol;
crcAddress_u32 = crcAddressIn_u32;
}
/**/
/*---------------------------------------------------------------------------------------------------------------*/
/*!@brief Read file and dispatch the data to the CRC generator:\n
* -reads every line and checks format.
* @author Thomas Wiedebusch
* @date 25-Feb-2016
* @return file format valid
*
*/
/*---------------------------------------------------------------------------------------------------------------*/
public bool ValidateInputFile_bol()
{
bool returnValue_bol = false;
fileLineCtr_u32 = 0;
try
{
//check if file exits
if (File.Exists(inputFile_str))
{
//opens file for read
StreamReader inputFile_st = new StreamReader(inputFile_str);
//read single line until file end or validation failed
do
{
fileLine_str = inputFile_st.ReadLine();
//decode the file line
returnValue_bol = ProcessInputFileLine_bol();
//change file line counter after check and line counter reminder for the records
fileLineCtr_u32++;
} while (returnValue_bol && !inputFile_st.EndOfStream);
//release file
inputFile_st.Close();
}
}//try
catch
{
}
return returnValue_bol;
}
/**/
/*---------------------------------------------------------------------------------------------------------------*/
/*!@brief Extract the information given by the read line from file:\n
* -builds base address from '@' input,\n
* -extracts bytes and dispatches these to CRC generator memory,\n
* -searches for CRC address and reminds file line for this,\n
* -validates file with file end marker 'q'.
* @author Thomas Wiedebusch
* @date 25-Feb-2016..26-Feb-2016
* @return txt file valid
*
*/
/*---------------------------------------------------------------------------------------------------------------*/
bool ProcessInputFileLine_bol()
{
bool returnValue_bol = false;
try
{
//read first byte of line
Char lineStart_chr = fileLine_str[0];
switch (lineStart_chr)
{
case addressMarker_cchr:
//extract new base address
String mem_str = fileLine_str.Substring(1, fileLine_str.Length - 1);
memAddressCtr_u32 = UInt32.Parse( mem_str, System.Globalization.NumberStyles.HexNumber);
//check memory address range
if( crcGenerator_t.maxMemBytes_cu32 > memAddressCtr_u32)
{
memoryAddressSetup_bol = true;
returnValue_bol = true;
}
break;
case endOfFileMarker_cchr:
//if end of file marker read on first line then the file is invalid
if (0 != fileLineCtr_u32)
{
returnValue_bol = true;
}
break;
default:
//if data read on first line then the file is invalid
if ((0 != fileLineCtr_u32) && (memoryAddressSetup_bol))
{
Byte data_u8;
Byte fileLineDataCtr_u8 = 0;
String data_str;
//remind the base address of this file line to save it for CRC replacement
UInt32 fileLineBaseAddress_u32 = memAddressCtr_u32;
//search file line
for (Byte ctr_u8 = 0; ctr_u8 < maxDataOfFileLine_cu8; ctr_u8++)
{
//inner loop limitation to actual file line length
while (fileLine_str.Length > fileLineDataCtr_u8)
{
//remind file line for CRC output
if (crcAddress_u32 == memAddressCtr_u32)
{
//remind the file entry
crcFileLine_u32 = fileLineCtr_u32;
//remind the base address for the file line for CRC replacement
crcFileLineBaseAddress_u32 = fileLineBaseAddress_u32;
//mark that entry has been found
crcFileLineFound_bol = true;
}
//extract data
data_str = fileLine_str.Substring(fileLineDataCtr_u8, fileLineDataCellIncrement_cu8);
data_u8 = Byte.Parse(data_str, System.Globalization.NumberStyles.HexNumber);
//dispatch data to CRC generator
MemSetFn_vdp(memAddressCtr_u32, data_u8);
memAddressCtr_u32++;
fileLineDataCtr_u8 += fileLineDataCellIncrement_cu8;
}//file line length
}//data counter
returnValue_bol = true;
}
break;
}//switch
}//try
catch
{
}
return returnValue_bol;
}
/**/
/*---------------------------------------------------------------------------------------------------------------*/
/*!@brief Read input file and store it to output file:\n
* -reads every line, format has been checked,\n
* -replaces CRC if required.
* @author Thomas Wiedebusch
* @date 25-Feb-2016..26-Feb-2016
* @param[in] crcResult_u16 result of CRC calculation
*
*/
/*---------------------------------------------------------------------------------------------------------------*/
public void CreateOutputFile_vd(UInt16 crcResult_u16)
{
//the file line counter will be used to reference the input of already detected records
fileLineCtr_u32 = 0;
try
{
//check if file exits
if (File.Exists(inputFile_str))
{
//opens file for read
StreamReader inputFile_st = new StreamReader(inputFile_str);
if (File.Exists(outputFile_str))
{
//erase it
File.Delete(outputFile_str);
}
//open it for write access
StreamWriter outputFile_st = new StreamWriter(outputFile_str, true);
//read single line until and output it to the output file
do
{
//read one line of the input file
fileLine_str = inputFile_st.ReadLine();
//output of CRC to file is required
if (placeCrcToFile_bol)
{
//if CRC address is not in file generate a new address with CRC only at the beginning
if (!crcFileLineFound_bol)
{
//build a new file entry for CRC which is not inside the file address range
BuildAndWriteNewCrc_vd(crcResult_u16, outputFile_st);
//remove CRC to file request
placeCrcToFile_bol = false;
}
//search for file entry to replace CRC
else if (crcFileLine_u32 == fileLineCtr_u32)
{
//the base address for this file line has been set in advance during file scan
ReplaceCrcData_vd(crcResult_u16);
//remove CRC to file request
placeCrcToFile_bol = false;
}
}//output of CRC to file is required
//write all lines to output file
outputFile_st.WriteLine(fileLine_str);
//change file line of input file
fileLineCtr_u32++;
} while (!inputFile_st.EndOfStream);
//release files
inputFile_st.Close();
outputFile_st.Close();
//if the output file is equal to the input file, erase input file and rename temporary output file
if (crcProgram_t.fileUndefined_cstr == outputFile_str)
{
File.Delete(inputFile_str);
if (File.Exists(outputFile_str))
{
//rename output to input file name, output file will be deleted
File.Move(outputFile_str, inputFile_str);
}
}
}//input file exists
}//try
catch
{
}
}
/**/
/*---------------------------------------------------------------------------------------------------------------*/
/*!@brief Replaces the CRC data if CRC address is inside the file address range:\n
* -search for CRC address,\n
* -replace CRC data in fileLine_str.
* @author Thomas Wiedebusch
* @date 26-Feb-2016..27-Feb-2016
* @param[in] crcResult_u16 result of CRC calculation
*
*/
/*---------------------------------------------------------------------------------------------------------------*/
void ReplaceCrcData_vd(UInt16 crcResult_u16)
{
//build the CRC sub string for replacement
Byte dataLsb_u8 = (Byte)(crcResult_u16 & 0x00FF);
Byte dataMsb_u8 = (Byte)((crcResult_u16 >> 8) & 0x00FF);
String crcSubStringOutput_str = dataLsb_u8.ToString("X2") + " " + dataMsb_u8.ToString("X2") + " ";
//search for address entry in file
memAddressCtr_u32 = crcFileLineBaseAddress_u32;
UInt32 beforeCrcAddress_u32 = crcFileLineBaseAddress_u32;
Byte ctr_u8 = 0;
while (memAddressCtr_u32 < crcAddress_u32)
{
ctr_u8 += fileLineDataCellIncrement_cu8;
memAddressCtr_u32++;
}
//extract string before CRC address from fileLine_str
String beforeCrcAddress_str = "";
if (beforeCrcAddress_u32 < crcAddress_u32)
{
beforeCrcAddress_str = fileLine_str.Substring(0, ctr_u8);
}
//extract string after CRC address from fileLine_str
String afterCrcAddress_str = "";
if (fileLine_str.Length > ctr_u8 + 2 * fileLineDataCellIncrement_cu8)
{
afterCrcAddress_str = fileLine_str.Substring(ctr_u8 + 2 * fileLineDataCellIncrement_cu8,
fileLine_str.Length - (ctr_u8 + 2 * fileLineDataCellIncrement_cu8));
}
//replace fileLine_str with substring at ctr position
fileLine_str = beforeCrcAddress_str + crcSubStringOutput_str + afterCrcAddress_str;
}
/**/
/*---------------------------------------------------------------------------------------------------------------*/
/*!@brief Builds and writes a new CRC entry if CRC address is outside the file address range:\n
* -assemble and write CRC address,\n
* -assemble and write CRC data.
* @author Thomas Wiedebusch
* @date 26-Feb-2016
* @param[in] crcResult_u16 result of CRC calculation
* @param[in] outputFile_st output file stream object
*
*/
/*---------------------------------------------------------------------------------------------------------------*/
void BuildAndWriteNewCrc_vd(UInt16 crcResult_u16, StreamWriter outputFile_st)
{
//build the NEW address for CRC
String crcOutput_str = addressMarker_cchr.ToString();
crcOutput_str += crcAddress_u32.ToString("X");
//write address to file
outputFile_st.WriteLine(crcOutput_str);
//build the CRC file line (line contains CRC only)
Byte dataLsb_u8, dataMsb_u8;
dataLsb_u8 = (Byte)(crcResult_u16 & 0x00FF);
dataMsb_u8 = (Byte)((crcResult_u16 >> 8) & 0x00FF);
crcOutput_str = dataLsb_u8.ToString("X2") + " " + dataMsb_u8.ToString("X2");
//write CRC data to file
outputFile_st.WriteLine(crcOutput_str);
}
/**/
/*---------------------------------------------------------------------------------------------------------------*/
}//class txtFileHandler
}//namespace CRC_CCITT
/*=====================================END OF FILE===================================================================*/