Read and copy file with EOF indicator in the middle - c++

I used the code below to copy from one binary file to another, but the first file contains some EOF indicators (0xFF) as part of it, so the copy function actually copies the file until its first EOF indicator.
For example: if my file is {0x01, 0x02, 0x03, 0xFF, 0x01, 0x02, 0xFF, 0xFF} then only {0x01, 0x02, 0x03} will be copied to the new file. Any idea how to fix it (or maybe I'm missing something there...)
Code:
int Util_Copy_File(char* source, char* dest)
{
FILE *fs,*ft;
char ch;
char infile[100];
sprintf(infile, "%s", dest);
fs = fopen(infile,"r");
if(fs==NULL)
{
return -1;
}
ft = fopen(dest,"w");
if(ft==NULL)
{
fclose(fs);
return STATUS_FAIL;
}
while(1)
{
ch = getc(fs);
if(ch==EOF)
{
break;
}
else
putc(ch,ft);
}
fclose(fs);
fclose(ft);
return 0;
}
Thanks,
Binyamin

fgetc returns an int, not a char , so you can tell the difference between EOF and a char with the same value as EOF.
Change:
char ch;
to
int ch
And (usually not relevant if you're on *nix)
fs = fopen(infile,"r");
to
fs = fopen(infile,"rb");

0xFF is not EOF. -1 is EOF. The problem is that you're storing the int return value of getc in a char, which collapses 0xFF onto -1 (actually it's implementation-defined behavior but that's what common implementations will do).
The return value of getc is an int whose value is either in the range of unsigned char or EOF (which has value -1). And the correct type for binary data is unsigned char, not char.

Related

Comparing UART register UDR0 with an unsigned char array

I am receiving serial communication through the USB port to my Arduino (ATmega2560) by using the RX0 pin. In the receive function I want to compare the register that receives information UDR0 with unsigned char pckaffe[4]. The data that is being sent through the USB port onto the Arduino comes from a pc and if everything works correctly, it should be sending unsigned char arrays, which is why I am comparing UDR0 to unsigned char pckaffe.
However at the if statement, the compiler is saying Error ISO C++ forbids comparison between pointer and integer [-fpermissive]
Why is that?
unsigned char pckaffe[4] = { 0x0C, 0x0A, 0x0F, 0x0E };
void USART_Receive(){
while(!(UCSR0A & (1<<RXC0)) );
if(UDR0 == pckaffe){
PORTB ^= (1 << PB1);
}
}
Why is that?
unsigned char pckaffe[4] = { 0x0C, 0x0A, 0x0F, 0x0E };
pckaffe is a unsigned char pointer, which you are trying to compare to an integer here
if(UDR0 == pckaffe)
pckaffe is a pointer to an array of chars, so the if statement is comparing the value of UDR0 (an int) to the address of pckaffe, which are incompatible types.
I want to compare the register that receives information UDR0 with unsigned char pckaffe[4]
URD0 contains one byte of data. pckaffe[4] - four of them. how you want to compare them?
Of course if(UDR0 == pckaffe) has no sense, pckaffe without index is implicitly converted to a pointer to the array. That gives you compilation error.
Probably you want something like that:
unsigned char pckaffe[4] = { 0x0C, 0x0A, 0x0F, 0x0E };
unsigned int pckaffe_pos = 0;
void USART_Receive(){
while(!(UCSR0A & (1<<RXC0)) ); // Wait for next received byte
uint8_t data = UDR0; // Get received byte
if (data == pckaffe[pckaffe_pos]) { // Compare the byte with next position in the array
pckaffe_pos++; // if matches, increase position
if (pckaffe_pos >= 4) { // If all bytes matched
pckaffe_pos = 0; // reset the pointer
PORTB ^= (1 << PB1); // do something
}
} else if (data == pckaffe[0]) { // next byte does not match, but matches the first
pckaffe_pos = 1; // next byte assumed to be the second in the sequence
} else { // does not match anything
pckaffe_pos = 0; // wait for the first byte in the sequence
}
}

C++ Pass bytes from char* to a BYTE*

I would like to know how to pass/COPY a sequence of bytes represented as a char* to a BYTE* in C++ in Windows.
Let's say I have this char* :
const char *ByteString = "\x3B\xC8\x74\x1B"
How would I COPY each byte from this char* to a BYTE *Bytes and vice-versa ?
EDIT: Thanks alot for everyone's help !
The definition of BYTE is:
typedef unsigned char BYTE;
which is not the same as a const char, so you'd need to convert it, but note that casting away const from something declared const to start with results in undefined behaviour and trying to actually change the data poses an even bigger risk.
BYTE* Bytes = reinterpret_cast<BYTE*>(const_cast<char*>(ByteString));
Edit: I just noticed that converting a const char* to a BYTE* was taken out of the question but I'll leave it here for now.
Copying the data (not as a zero terminated string) could be done like this:
const char ByteString[] = "\x3B\xC8\x74\x1B";
BYTE* Bytes = new BYTE[sizeof(ByteString)-1];
std::memcpy(Bytes, ByteString, sizeof(ByteString)-1);
// Use your Bytes
delete[] Bytes; // manual delete when you are done
Or better:
const char ByteString[] = "\x3B\xC8\x74\x1B";
std::basic_string<BYTE> Bytes( reinterpret_cast<const BYTE*>(ByteString), sizeof(ByteString)-1 );
// use Bytes
// Bytes.data() returns a BYTE*
// Bytes.size() returns the length.
But given the nature of what you are doing, you could probably skip these conversions and use an array of the correct type to start with:
BYTE Bytes[] = { 0xA1, 0x00, 0x00, 0x00, 0x00, 0x3B, 0xC8, 0x74, 0x1B };
or
std::basic_string<BYTE> Bytes({ 0xA1, 0x00, 0x00, 0x00, 0x00, 0x3B, 0xC8, 0x74, 0x1B });
These won't need any conversions when all you deal with is raw BYTE data. Here's an example using ReadProcessMemory and a basic_string for a buffer and pattern.
using BYTEstr = std::basic_string<BYTE>; // just for convenience
BYTEstr Buffer(1024, 0); // 1024 BYTES initialized with 0
BYTEstr Pattern({ 0xA1, 0x00, 0x00, 0x00, 0x00, 0x3B, 0xC8, 0x74, 0x1B });
ReadProcessMemory(hProcess, lpBaseAddress, Buffer.data(), Buffer.size(), &lpNumberOfBytesRead);
BYTEstr::size_type pos = Buffer.find(Pattern);
if (pos == BYTEstr::npos) {
std::cout << "Pattern not found\n";
} else {
std::cout << "Pattern found at position " << pos << "\n";
}
To respect const, use
const BYTE *Bytes = reinterpret_cast<const BYTE*>(ByteString);
and vice versa:
const char *ByteString = reinterpret_cast<const char *>(Bytes);
If you want to make copy of the buffer so that you can modify it, use
len = LenOfChrStr;
BYTE *Bytes = new BYTE[len];
memcpy(Bytes, ByteStr, len);
Given a char const * array of characters, we can make a new buffer with readwrite BYTEs for the API to possibly edit:
char const *ByteString = "\x3B\xC8\x74\x1B";
auto len = std::strlen(ByteString) + 1;
auto ptr = std::make_unique<BYTE[]>(len);
std::memcpy(ptr.get(), ByteString, len);
If you need to surrender the ownership of the memory to the function:
Func(ptr.release());
But if you want to keep the ownership yourself:
Func(ptr.get());
In MSVC (I guess this is your compiler for WinAPI application) you can make the char type unsigned with /J option (more here: https://learn.microsoft.com/en-us/cpp/build/reference/j-default-char-type-is-unsigned?view=vs-2017). If you do this, BYTE becomes the same as char and no conversion would be necessary.
Please note, this might have some other side effects in your application.

Why is my pointer array assignment not working?

I have this method prototype
bool setMacParam(const char* paramName, const uint8_t* paramValue, uint16_t size)
{
debugPrint("[setMacParam] "); debugPrint(paramName); debugPrint("= [array]");
this->loraStream->print(STR_CMD_SET);
this->loraStream->print(paramName);
for (uint16_t i = 0; i < size; ++i) {
this->loraStream->print(static_cast<char>(NIBBLE_TO_HEX_CHAR(HIGH_NIBBLE(paramValue[i]))));
this->loraStream->print(static_cast<char>(NIBBLE_TO_HEX_CHAR(LOW_NIBBLE(paramValue[i]))));
}
this->loraStream->print(CRLF);
return expectOK();}
I would like to assign my variable devEUI to paramValue, I am doing this call
uint8_t DevEUI2[8] = { 0x00, 0x00, 0x00, 0x00, 0x41, 0x47, 0x30, 0x39 };
setMacParam(STR_DEV_EUI,DevEUI2,8);
However my terminal shows that paramValue is empty
[setMacParam] deveui = [array]
What do I do wrong?
debugPrint is interpretating your array as a byte array in which each byte is a char; because the first value is 0x00, incidentally is the same value for the '\0' character, that represent the "end of string".
Also the other value will be represented by their ascii representation, which is never the same as the byte value.
The print() of Serial accept some parameter that tell the function to print the ascii representation of the hex, decimal, octal or binary; maybe your SerialUSB support them too.

C++ array with command line variable

My array looks something like this;
unsigned char send_bytes[] = { 0x0B, 0x11, 0xA6, 0x05, 0x00, 0x00, 0x70 };
One of the values is a variable that can change all the time.. so I tried something like this;
const char* input = "0x05";
unsigned char send_bytes[] = { 0x0B, 0x11, 0xA6, input, 0x00, 0x00, 0x70 };
When I compile I get a warning;
warning: initialization makes integer from pointer without a cast
I am a little confused on the conversion I need to do.. since the array has hex strings in it.. and the input string is a char..
in the first line you are declaring a pointer to const char, and initializing to the beginning of string "0x05", that's fine, but it is not the thing you are trying to do.
in the second line, you try to initialize the fourth array element (an unsigned char) with the value of the pointer you assigned to the input variable in the first line. The compiler says you are pretending to embed a pointer value (the address of "0x05" string) into a char variable, so that's why it complained. And also it is not what you intend.
also, take into account that if you are using binary data (from the fact you are initializing arrays with hex numbers) you had better to use unsigned char for binaries, as signed char is valid only for -128 to +127 values, you can expect some more unpredictable behaviour. Perhaps, a declaration typedef unsigned char byte; can do things easier.
typedef unsigned char byte;
byte send_bytes[] = { 0x0b, 0x11, 0xa6, 0x00, 0x00, 0x00, 0x70 };
byte &input = send_bytes[3]; /* input is an alias of send_bytes[3] */
BR,
Luis
Maybe explaining exactly what const char* input = "0x05"; does will clear things up for you.
First the compiler computes the string data and creates it as a static object:
const char data[5] = { 0x30, 0x78, 0x30, 0x35, 0x0 };
Then your variable is initialized:
const char *input = &data[0];
Note that input is a pointer with a value that depends entirely upon the location the compiler chooses to store the string data at, and has nothing to do with the contents of the string. So if you say char c = input; then c basically gets assigned a random number.
So you should be asking yourself "Where is the value 0x05 that I want to store in the send_bytes array?" In your code it's encoded as text, rather than as a number that your program can use directly. You need to figure out how to convert from a string of symbols following the hexadecimal scheme of representing numbers into C++'s native representation of numbers.
Here are a couple hints. Part of the operation involves associating values with each digit symbol. The symbol '0' is associated with the value zero, '1' with the value one, and so on, according to the usual hexadecimal system. Second, once you can get the associated value of a symbol, then you can use those values in some basic arithmetic operations to figure out the value of the number represented by the whole string of symbols.
For example, if you have the symbols '1' '2' and 'a', in that order from left to right then the arithmetic to compute what number is represented is 1 * 16 * 16 + 2 * 16 + 10.
The error string is pretty much telling you exactly what's wrong.
input is of type const char* (a pointer to a const char), whereas your array send_bytes is of type unsigned char[] (an array of unsigned chars).
First, signed and unsigned values are still different types, though your error message isn't referring to that specifically.
In reality, your input value isn't a string (as there is no true string type in C++), but a pointer to a character. This means that the input string doesn't hold the byte x05, but rather the bytes {x30, x78, x30, x35, x00}.
The compiler is saying Hey, I've no idea what you're trying to do, so I'm just converting the address that string I don't understand (input) to an unsigned char and adding it to the array.
That means if the string "0x05" starts at location 0xAB, your array will ultimately contain { 0x0B, 0x11, 0xA6, 0xAB, 0x00, 0x00, 0x70 }.
You're going to either have to convert from a string to an integer using a radix of 16, or just not use a string at all.
I'd also recommend reading up on pointers.
The array doesn't have "hex strings" in it - if they were, they would be enclosed in quotation marks, like all strings.
The literals are integers written in hexadecimal notation, and equivalent to
unsigned char send_bytes[] = { 11, 17, 166, input, 0, 0, 112 };
Since it's an array of unsigned char you should put an unsigned char there:
unsigned char input = 0x05;
unsigned char send_bytes[] = { 0x0B, 0x11, 0xA6, input, 0x00, 0x00, 0x70 };
You had better to put in your code:
unsigned char send_bytes[] = { 0x0b, 0x11, 0xa6, 0x00, 0x00, 0x00, 0x70 };
unsigned char &input = send_bytes[3]; /* input is an alias of send_bytes[3] */
this way you can do things like:
input = 0x26;
send_packet(send_bytes);

array in C/C++ for AVR keeps appending

In C, I have an array waiting to receive bytes from a sensor, save in a buffer, and then print out like this:
unsigned char responseFrame[300];
int main(void) {
UART_init();
while(1) {
receive(responseFrame);
myLog(responseFrame, sizeof(responseFrame));
}
}
I populate the array by doing the following:
void receive(unsigned char *rcv_buff) {
uint8_t recv_data;
for (int i=0; i<300; i++){
USART1_Flush();
rcv_buff[i] = USART1_RX();
}
}
Then I print out what's in the buffer using the following:
// Logs this output to the serial port; used for debugging
void myLog(unsigned char *msg, int size) {
for (int i=0; i<size; i++) {
USART0_TX(msg[i]);
}
}
This prints out the array, but when another iteration of bytes is received, everything is appended so let's say I receive {0xFF, 0xFF} first my output for the first iteration is:
0xFF 0xFF, 0x00, 0x00 ... 0x00
But upon the next iteration let's say {0x0A, 0x0A} is received instead, in the output I see this:
0xFF, 0xFF, 0x0A, 0x0A, 0x00, 0x00 ... 0x00
NOTE: The ellipses is just saying there's more 0x00s which are printed out until we basically reach the size of the array.
Why is this appending and not overwriting from the start of the array?
Here's my USART0_TX and USART1_RX functions:
void USART0_TX(uint8_t myData) {
// Wait if a byte is being transmitted
while( !(UCSR0A & (1<<UDRE0)) );
// Transmit data
UDR0 = myData;
};
uint8_t USART1_RX(void) {
// Wait until recv buffer is full
while( !(UCSR1A & (1<<RXC1)) );
// Return recvd data
return UDR1;
};
Here's the code I'm using to flush my USART1 RX:
//USART1 flush, clears USART1 buffer
void USART1_Flush( void )
{
unsigned char dummy;
while ( UCSR1A & (1<<RXC1) ) dummy = UDR1;
}
I believe your function called "Flush" is really a "Poll" function, looking for a character to appear (this would be normal usage, wait for the char to appear). The logic where you use RXC1 appears inverted. Try looking at this quite professional looking AVR driver (that has a poll option just as you are doing):
usart.c
Another nicely commented polled driver (and small with lots of comments): avr uart driver