Arduino combine several arrays (c++) - c++

I want to know how can I combine several byte arrays into 1?
I have this:
byte MessageStart [] = {0x02};
byte Next [] = {0x5C , 0x73};
byte messgae[] = {0x30 , 0x35};
byte BeforeEnd [] = {0x5C , 0x3B};
byte MessageEnd [] = {0x03};
I want to have one byte array with all of them, the final result needs to be:
byte Final [] = {0x02, 0x5C, 0x73, 0x30, 0x35, 0x5C, 0x3B, 0x03}
How do I do this?

Maybe something like this:
byte *concatbytes(const byte *source, byte *destination, int length)
{
for (int i = 0; i < length; i++)
{
*destination++ = *source++;
}
return destination;
}
...
byte MessageStart[] = { 0x02 };
byte Next[] = { 0x5C , 0x73 };
byte messgae[] = { 0x30 , 0x35 };
byte BeforeEnd[] = { 0x5C , 0x3B };
byte MessageEnd[] = { 0x03 };
byte Final[8]; // 8 is the hardcoded length of sum of all 5 arrays
byte *dest = Final;
dest = concatbytes(dest, MessageStart, sizeof(MessageStart));
dest = concatbytes(dest, Next, sizeof(Next));
dest = concatbytes(dest, messgae, sizeof(messgae));
dest = concatbytes(dest, BeforeEnd, sizeof(BeforeEnd));
dest = concatbytes(dest, MessageEnd, sizeof(Next));
The Final array may be obtained differently, for example by dynamic memory allocation. This is left as an exercise for the reader.

Related

Generating a static ranged integer value based on an array of bytes

Okay, this is a strange one I believe, and I have absolutely no idea of how to go about it.
So basically what I'm looking for is a way to generate a fixed ranged integer value based on a given array of bytes.
Say I have an array named imALonleyArray
unsigned char imALonleyArray[16] = {0x33, 0x7E, 0xD5, 0x8F, 0xC3, 0x01, 0x39, 0x0C, 0x5B, 0x0F, 0x80, 0x9C, 0x78, 0x90, 0x89, 0xF5};
I'd like to somehow generate a static ranged integer value based on the above array.
Why you might ask?
I need to assign a fixed int value from possibly int_min to int_max or, really for this program (0-1487) based on a given users 16 byte session token.
Example:
int getIntRangeFromGivenBytes(unsigned char *arr, int minValue, int maxValue){
/*Magic here that somehow computes then returns an int value between
minValue and maxValue based on the given bytes provided by the 'arr' argument*/
}
I tried my best to describe what I'm trying to do here. I'm a newb here, please don't shoot me down.
Thanks in advance!
From what I understand, you're asking for an algorithm that for a given char array, generate an integer within a given range [a,b], where the same integer will pop up for the same input.
A really easy and simple one would be to add them all together and use % modulo to get it into the range.
int interval = maxValue - minValue;
int increment = 0;
for(int i = 0; i < array_size; ++i){
increment += array[i];
increment = increment % interval; // this ensures output is always within the interval
}
int final_answer = increment + a;
If you want one that's reversible, that'd be different. And frankly impossible if there's more possible arrangements of the array than there are elements in the interval. (If two different arrays map to the same integer, how do you reverse it?)
An example, let's say you have interval [0,5].
unsigned char array[2] = {0x00, 0x00}; // assign to 0
unsigned char array[2] = {0x00, 0x01}; // assign to 1
unsigned char array[2] = {0x00, 0x02}; // assign to 2
unsigned char array[2] = {0x00, 0x03}; // assign to 3
unsigned char array[2] = {0x00, 0x04}; // assign to 4
unsigned char array[2] = {0x00, 0x05}; // assign to 5
unsigned char array[2] = {0x00, 0x06}; // now what?
So you need to make sure that the interval is large enough, or limit the size of the char array enough that there's no collisions.
sidenote: the word static means something very specific in C++, so your question was a bit confusing.
You want a hash, and a simple hash on values that are numeric integer types to some range is division:
uint64_t to_value(const uint8_t *array) {
uint64_t result = array[0];
for (int i = 1; i < 8; ++i)
result = (result << 8) | array[i];
return result;
}
uint64_t to_range(uint64_t input, uint64_t lower, uint64_t upper) {
if (lower > upper)
std::swap(upper, lower);
if (upper == std::numeric_limits<uint64_t>::max() &&
lower == std::numeric_limits<uint64_t>::min())
return input;
auto range = upper - lower + 1;
return lower + ((input - lower) / range);
}
Use:
uint64_t my_hash(const uint8_t *data) {
auto value = to_value(data);
return to_range(value, 0, 1487);
}
Whether such a hash has some other properties that you haven’t listed is another story. But it fulfills the requirements you state.

C++ reference byte array

I have an issue with C++ and creating a reference byte[].
In C# my method is:
public static void SetBitAt(ref byte[] Buffer, int Pos, int Bit, bool Value)
{
byte[] Mask = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 };
if (Bit < 0) Bit = 0;
if (Bit > 7) Bit = 7;
if (Value)
Buffer[Pos] = (byte)(Buffer[Pos] | Mask[Bit]);
else
Buffer[Pos] = (byte)(Buffer[Pos] & ~Mask[Bit]);
}
I want to translate it to C++, but I can't get the refworking for C++. I saw something about the & symbol and I tried something like this:
void SetBitAt(byte& buffer[], int Pos, int Bit, bool Value)
{
byte Mask[] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 };
if (Bit < 0) Bit = 0;
if (Bit > 7) Bit = 7;
if (Value)
{
buffer[Pos] = (byte)(buffer[Pos] | Mask[Bit]);
}
else
{
buffer[Pos] = (byte)(buffer[Pos] & ~Mask[Bit]);
}
}
but then I get the Error:
'buffer': arrays of references are illegal.
So how can I change my C++ code to work with a reference array?
EDIT:
I use this method for setting a buffer, but it doesn't change when I use this method.
other class:
buffer = ReadDB(2); //Read the values in the DataBlock
SetBitAt(buffer, 0,0 true); //Set bit 0,0 to 1(true)
WriteDB(2, buffer); //Write the values to the Datablock
but the buffer doesn't change. its the same value.
If you want to pass array by reference, you should
void SetBitAt(byte (buffer&)[10], int Pos, int Bit, bool Value)
But in your case, you don't need that, just
void SetBitAt(byte buffer[], int Pos, int Bit, bool Value)
Note in this case array will decay to pointer (i.e. byte*), that means the size of array won't be reserved as pass by reference would.
'buffer': arrays of references are illegal.
This is due to operator precedence. Saying byte &buffer[] is an array of references, while saying byte (&buffer)[size] is a reference to an array.
See C++ pass an array by reference for more details.
So how can I change my C++ code to work with a reference array?
When passing your array as a function argument, you should drop & symbol. You can still modify the contents of your array because the array's address is passed instead.
Assuming you have a typedef of char to byte, your function signature should look like this:
void SetBitAt(byte buffer[], int Pos, int Bit, bool Value) { ... }
Note that the above is equivalent to passing a pointer:
void SetBitAt(byte *buffer, int Pos, int Bit, bool Value) { ... }
Modifying the contents of your array is still a matter of saying buffer[Pos] = // some value;
This post on What is array decaying? should be useful.
Shouldn't it simply be like this:
void SetBitAt(byte buffer[], int Pos, int Bit, bool Value)
{
byte Mask[] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 };
if (Bit < 0) Bit = 0;
if (Bit > 7) Bit = 7;
if (Value)
{
buffer[Pos] = (byte)(buffer[Pos] | Mask[Bit]);
}
else
{
buffer[Pos] = (byte)(buffer[Pos] & ~Mask[Bit]);
}
}
In this way, buffer is passed as a pointer, and buffer[Pos] references to the Pos-th element of buffer. It is plain C, but it should work.
You can pass it simply by address as:
void SetBitAt(byte* buffer, int Pos, int Bit, bool Value) { ... }
or simply as:
void SetBitAt(byte buffer[], int Pos, int Bit, bool Value) { ... }
Either one will tell the compiler that byte pointer is passed to function, althrough with second header you omit pointer arithmetics ;)

How to change the code using lambda expression?

I'm study about c++ using lambda expression.
I'm just tried change the code that already coded using for or while, then i have the question about lambda.
I'm just change the code using lambda or for_each (c++11). How to change?
Here is a code that want to change.
std::string PointToString(void* p_pData)
{
char* p = (char*)p_pData;
int iLength = 0;
std::memcpy(&iLength, p, sizeof(int));
p += sizeof(int);
std::string sRet;
std::array<char, 3> szB;
sRet.append("0x");
for ( int i = 0; i < iLength; i++ )
{
sprintf(szB.data(), "%02X", (unsigned char)*(p++));
sRet.append(szB.data());
}
return sRet;
}
This code just convert a memory value to hex code.
That function called like this.
char szB[15] = {0x0b, 0x00, 0x00, 0x00, 0xc7, 0xd1, 0xb1, 0xdb, 0xc0, 0xd4, 0xb4, 0xcf, 0xb4, 0xd9, 0x2e};
void* p = nullptr;
p = (void*)szB;
sRet = PointToString(p);
The Result may be 0x0B000000C7D1.....
I want to try lambda in PointToString function. How can I change that function?
Well, you could write:
std::for_each(p, p + iLength, [&](unsigned char ch)
{
sprintf(szB.data(), "%02X", ch);
sRet.append(szB.data());
});
The & means that you will operate on szB and sRet by reference, instead of operating on copies of them.
IMHO it's not a significant improvement over your original code though.

C++ zLib Byte array Compressing

After getting my first problem solved at C++ zLib compress byte array i faced another problem
void CGGCBotDlg::OnBnClickedButtonCompress()
{
// TODO: Add your control notification handler code here
z_const char hello[256];
hello[0] = 0x0A;
hello[1] = 0x0A;
hello[2] = 0x0A;
hello[3] = 0x0A;
hello[4] = 0x0A;
hello[5] = PKT_END;
hello[6] = PKT_END;
hello[7] = PKT_END;
Byte compr[256];
uLong comprLen = sizeof(compr);
int ReturnCode;
ReturnCode = Compress(compr, comprLen, hello, Z_DEFAULT_COMPRESSION);
g_CS.Send(&compr,comprLen);
}
int CGGCBotDlg::Compress(Byte Compressed[], uLong CompressedLength, CHAR YourByte[], int CompressionLevel)
{
int zReturnCode;
int Len;
for (int i = 0 ; i <= 10240 ; i++)
{
if (YourByte[i] == PKT_END && YourByte[i+1] == PKT_END && YourByte[i+2] == PKT_END)
{
Len = i - 1;
break;
}
}
uLong Length = (uLong)(sizeof(YourByte) * 1.0001) + 12;
zReturnCode = compress2(Compressed, &Length, (const Bytef*)YourByte, Len,CompressionLevel);
return zReturnCode;
}
Im trying to compress hello[] wich is actually 5 bytes (I want to compress first 5 bytes)
The expected result after compressing is : 0x78,0x9C,0xE3,0xE2,0x02,0x02,0x06,0x00,0x00,0xCE,0x00,0x33
But what I get after compressing is just the first 4 bytes of expected result and another bytes are just something else.
And my second problem is that i want to replcae 256 in Byte compr[256] with the exact number of bytes after decompressing original buffer (which is 12 in my case)
Would be great if someone correct me
Thanks
this line is wrong:
Len = i - 1;
because when i is 5, you do Len = i - 1; so len will be 4, but you want compress 5 bytes. just use:
Len = i;
another problem comprLen is never been assigned a value. In Compress(Byte Compressed[], uLong CompressedLength..), itCompressedLength is not used. I assume you want its value back. you should define like this:
Compress(Byte Compressed[], uLong& CompressedLength..)
and change the line to use CompressedLength instead of using length:
zReturnCode = compress2(Compressed, &CompressedLength, (const Bytef*)YourByte, Len,CompressionLevel);

How to declare an array of pointers to multidimensional arrays

// LED definitions for each step
static uint8_t route1Step0LedsOn[] = { 0x30, 0xff };
static uint8_t route1Step0LedsOff[] = { 0x26, 0xff };
static uint8_t route1Step1LedsOn[] = { 0x18, 0x45, 0x21, 0xff };
static uint8_t route1Step2LedsOn[] = { 0x56, 0x33, 0x42, 0x31, 0xff };
// First route (consisting of 3 steps + terminator).
static uint8_t* routeLeds1[][2] =
{
{ route1Step0LedsOff, route1Step0LedsOn },
{ NULL, route1Step0LedsOn },
{ NULL, route1Step0LedsOn },
{ NULL, NULL }
};
// Second route.
static uint8_t* routeLeds2[][2] =
{
// LED elements not shown, but similar to route 1.
{ NULL, NULL }
};
// Array of routes.
static ??? routes[] =
{
NULL,
routeLeds1,
routeLeds2,
NULL
};
I'm not sure of the correct type for routes[].
I'd like to know what the ??? should be?
I'm using a micro controller and MUST use arrays in order to force the arrays into flash memory instead of RAM.
You can't convert arrays to "pointers to pointers... to pointers" because they're dereferenced differently; trying to use a multidimensional array as a "pointer to... pointer" to something will cause undefined behaviour the same way dereferencing an invalid pointer would.
In memory, a "pointer to a pointer..." to an object is represented by
a -> b -> c -> ... -> object
Where a, b, c, ..., and object are in completely different parts of memory. To index a pointer, the pointer is dereferenced.
Arrays, however, are stored in a contiguous memory. For instance, int a[2][2] would be
[0,0][0,1][1,0][1,1]
Indexing a multidimensional array does not dereference a pointer, it changes the arithmetic that is used to calculate the offset from the beginning of the array that the desired value is at. The formula would be
address of array + index1 * sizeof(first dimension) + index2 * sizeof(second dimension) + ... + indexn * sizeof(object)
Where sizeof(nth dimension) is the size of all the subdimensions put together. For instance with int a[3][2] which is represented by
[0,0][0,1][1,0][1,1][2,0][2,1]
, the index a[2][1] would be
address of a + 2 * (sizeof(int) * 2) + 1 * sizeof(int)
Which, in C++, would be (char*)a + 16 + 4, the last element of the array.
To solve this problem, you need to use pointers only. You should not (and cannot) be storing multidimensional arrays alongside pointers in the same array.
I'm having a hard time putting this all into words; if I'm not making sense, please say so.
Try this:
typedef uint8* Array1; // first column/row
typedef Array1 Array2[2]; // uint* name[2]
typedef Array2* Array3; // get the idea?
// Array of routes.
static Array3 routes[] =
{
NULL,
routeLeds1,
routeLeds2,
NULL
};
Your problem is the multidimensional array:
If you need to go the array route, you can just add an extra step:
static uint8_t route1Step0LedsOn[] = { 0x30, 0xff };
static uint8_t* route1Step0[] = { NULL, route1Step0LedsOn };
static uint8_t** routeLeds1[] = { route1Step0 };
static uint8_t*** routes[] =
{
NULL,
routeLeds1,
NULL
};
If some of the arrays are fixed lengths, it may be possible to clean some of this up a little.
But IMO this is getting pretty ugly and could do with some real structs, rather than raw arrays.
If you're not tied to ussing arrays for some technical reason, you could change to use a structure like this: (Note if you're using C++11, then the constructors and construction can be made a lot nicer). You'll also need a make_vector helper, of which there are several floating around, if you want a nicer construction.
struct LedList
{
LedList( const std::vector<uint8_t> & v ) : leds( v ) {}
std::vector<uint8_t> leds;
};
struct LedStep
{
LedStep( const & LedList on_, const & LedList off_ ) : on_leds(on_), off_leds(off_) {}
RouteStepLedList on_leds;
RouteStepLedList off_leds;
};
struct LedRoute
{
LedRoute( const std::vector<LedStep> & steps_ ) : steps(steps_) {}
std::vector<LedStep> steps;
};
struct Route
{
Route( const std::vector<LedRoute> & routes_ ) : routes(routes_) {}
std::vector<LedRoute> routes;
};
//All routes
Route r( make_vector<LedRoute>()(
//First route
make_vector<LedStep>()(
//First step of first route
LedStep(
make_vector<uint8_t>()( 0x30 ),
make_vector<uint8_t>()( 0x26 )
) )(
//Second step of first route
LedStep(
make_vector<uint8_t>(),
make_vector<uint8_t>()( 0x18 )( 0x45 )( 0x21 )
) )(
//Third step of first route
LedStep(
make_vector<uint8_t>(),
make_vector<uint8_t>()( 0x56 )( 0x33 )( 0x42 )( 0x31 )
) ) ),
//Second route.
make_vector<LedStep>()(
//First step of second route
LedStep(
...
) ) (
//Second step of second route
...
);