using repeated field rule in a message with nanopb in c - c

I'm having a hard time in realizing how to use the repeated field rule.
for example, this is my .proto:
message Test
{
repeated float value = 1;
}
now, I'm initialize a new Test object:
Test test = test_init_zero()
Finally, I want to assign some values. For example:
float values[] = { 1.0, 2.2, 5.5, 7.13 }
My question is how can I assign them?
is it like
test.value = values
//or
test.value[0] = values[0] //... etc.
and then, how do I read them back?

This depends on how you define the repeated field inside the proto file. According to nanopb docs, you either just specify the repeated field like you did, and then use a callback function to handle each item separately during encoding/decoding, or you use nanopb-specific settings so have a fixed length array:
Strings, bytes and repeated fields of any type map to callback functions by default.
If there is a special option (nanopb).max_size specified in the .proto file, string maps to null-terminated char array and bytes map to a structure containing a char array and a size field.
If (nanopb).fixed_length is set to true and (nanopb).max_size is also set, then bytes map to an inline byte array of fixed size.
If there is a special option (nanopb).max_count specified on a repeated field, it maps to an array of whatever type is being repeated. Another field will be created for the actual number of entries stored.
For example, byte arrays need to use max_size:
required bytes data = 1 [(nanopb).max_size = 40, (nanopb).fixed_length = true];
And this would create the following field, when compiled using nanopb:
// byte arrays get a special treatment in nanopb
pb_byte_t data[40];
Or, for a float, you would use max_count according to rule 4.:
repeated float data = 1 [(nanopb).max_count = 40];
And then you'll get:
size_t data_count;
float data[40];
If you simply define a repeated field like you did, then nanopb will create a callback function:
// repeated float value = 1;
pb_callback_t value;
Which means you will have to provide your own function which will handle each incoming item:
yourobject.value.arg = &custom_args;
yourobject.value.funcs.decode = custom_function_for_decoding;

Related

Is it possible to define the size of a Float32Array type in typescript?

I know that with tuples sizes of arrays can be defined. Not applicable to float32array which is a class itself though.
Can that somehow be done with float32arrays as well?
I tried const foo: FloatArray32[4] but that casts the type directly to the number.
I also tried to check if types might be compatible:
let foo: [number, number, number, number];
foo = new Float32Array([1, 2, 3, 4]);
But they are not.
Changing all the types in my code to '[number, number, number, number];' (in my case I need a 4 float array for a point coordinate) is a possibility, although I would need to make changes in quite a lot of places in the code.
However, I was wondering if there might be a 'childtype' extending Float32Array type, where the number of the elements of the array can be fixed in the type.
Javascript typed arrays, are in fact, fixed length - see the docs for your example. The constructors in particular:
new Float32Array(); // new in ES2017
new Float32Array(length);
new Float32Array(typedArray);
new Float32Array(object);
new Float32Array(buffer [, byteOffset [, length]]);
all have the length deducible on creation (that new first one creates an empty array with 0 elements. I guess it simplified some edge cases).
I'm not sure how you are determining the type, but as soon as you get an item from your array it will be converted to a number, the only number type available in JS - so looking at your log is misleading here. Take a look at the following static property:
Float32Array.prototype.byteLength
Returns the length (in bytes) of the Float32Array. Fixed at construction time and thus read only.
This is the only thing that counts. If you still don't believe the docs, try logging a cell after you overflow it (easier with int8 - put 200 or something). This is relevant to your example - nothing is being converted to a number. The array object is a view in fixed length numbers - again, run your test with an Int8Array and try to assign 200 to the cell, and read the cell.
This is a view into raw data. If you extract it and make mathematical operations, you are now in JS realm and working with Numbers - but once you assign stuff back, you better make sure the data fits. You cannot get JS/TS to show you something like float32 in your console, but each cell of the array itself does have an exact byte length.
unfortunately, making the length a part of the type is non-trivial within the type system as far as I can tell since the length is a property determined in construction (even if static and read only) and not a part of the type. If you do want something like this a thin wrapper could do the trick:
class vec4 extends Float32Array {
constructor(initial_values? : [number, number, number, number]) {
initial_values? super(initial_values) : super(4);
}
}
would do the trick. If you are willing to give up square brackets you can add index out-of-bound checking in the different methods (you can set in a fixed width array any cell, but it will do nothing, and retrieving it will yield undefined if out of bounds, which may be error prone):
get(index : number) {
if(index > 4 || index < 0) ...
return this.private_data[index];
}
set(index : number, value : number) {
if(index > 4 || index < 0) ...
this.private_data[index] = value;
}
Of course, without LSP in JS/TS the array and your class are still interchangeable, so enforcement is really only done on construction, and only if you do not try to break your own code (let foo : vec4; foo = new Float32Array([1, 2]); etc...).

Basic initialization of a function using arrays

Currently setting up a function to declare the cases for a 4-part seven-segment display (a digital alarm clock basically) but keep getting errors when trying to confirm that it is properly set (Specifically from the core opening line)
Have tried looking around, but nothing is specific enough to the arrays I need.
Just a note on the code. I have not properly set up a code block before, so I am unsure as to how to highlight syntaxes. If it is properly set up, just ignore this message
Originally had it set as int SegmentWrite(int...[]) but would not produce results.
Other tests I have tried is including a size [10][7] before the opening braces, to declare count and size, changing type from byte to int, char, and float (although only byte produced any sort of result, not being what I wanted)
void SegmentWrite (int SegmentDigits[]){
byte SegmentDigits = zero[7] {1,1,1,1,1,1,0};//0
one[7] = {0,1,1,0,0,0,0};//1
two[7] = {1,1,0,1,1,0,1};//2
three[7] = {1,1,1,1,0,0,1};//3
four[7] = {0,1,1,0,0,1,1};//4
five[7] = {1,0,1,1,0,1,1};//5
six[7] = {1,0,1,1,1,1,1};//6
seven[7] = {1,1,1,0,0,0,0};//7
eight[7] = {1,1,1,1,1,1,1};//8
nine[7] = {1,1,1,1,0,1,1}; //9
This particular snippet of code isn't supposed to do anything - not on it's own, at least. When verifying, to confirm proper formatting, I only got the error report "declaration of 'byte SegmentDigits' shadows a parameter' with the first line highlighted.
-Just a note, found another error, specifically with the opening line - "declaration of 'SegmentWrite' as array of void" or "'SegmentWrite' declared as function returning an array"
You need to use a different name for the parameter array and the local array in the function.
Also, the function should take another parameter, the digit that you're trying to display.
You should then declare a 2-dimensional array, and you can use the digit as an index into it.
void SegmentWrite (int SegmentDigits[7], int digit){
int allSegmentDigits[][7] = {
{1,1,1,1,1,1,0},//0
{0,1,1,0,0,0,0},//1
{1,1,0,1,1,0,1},//2
{1,1,1,1,0,0,1},//3
{0,1,1,0,0,1,1},//4
{1,0,1,1,0,1,1},//5
{1,0,1,1,1,1,1},//6
{1,1,1,0,0,0,0},//7
{1,1,1,1,1,1,1},//8
{1,1,1,1,0,1,1}} //9
memcpy(SegmentDigits, allSegmentDigits[digit], sizeof allSegmentDigits[0]);
}

Randomization of Associative Array in System Verilog

I have an associative array:
rand uvm_reg_field array_assoc[string];
The array contains the handle of the UVM register fields for registers in the DUT and is indexed by a string (string is the name of the field).
Say I have 2 register fields with names "reg_field_1" and "reg_field_2".
As described,
array_assoc["reg_field_1"]= handle of field 1;
array_assoc["reg_field_2"]= handle of field 2;
I need to randomize only one of the fields, so, I selectively turn the rand_mode off for one of the fields, say "reg_field_1":
array_assoc["reg_field_1"].rand_mode(0);
Now, if I randomize the associative array, both register fields are getting randomized.
What is even more surprising is that, if i declare a normal array with integer indexes, such that :
rand uvm_reg_field array_normal[2];
array_normal[0]= handle of field 1;
array_normal[1]= handle of field 2;
and then turn of the rand_mode for field 1:
array_normal[0].rand_mode(0);
It works fine and field 1 is not randomized.
The question is: Why is the register field "reg_field_1" getting randomized even when its rand_mode has been set to 0 in case of associative array ?
The ability to set rand_mode() on individual elements of an associative array seems to have sporadic support. The following works for me in Questa and one other simulator; gives me a "not supported yet" in another, and the results you are seeing in yet another. So I would contact your tool vendor.
module top;
class B;
rand byte m;
endclass
class A;
rand B a1[2];
rand B a2[string];
function void run;
a2["0"] = new;
a2["1"] = new;
a1[0] = new;
a1[1] = new;
a1[0].rand_mode(0);
a2["0"].rand_mode(0);
void'(randomize());
$display(a1[0].m, a1[1].m,,a2["0"].m,a2["1"].m);
endfunction
endclass
A a = new();
initial repeat(3) a.run();
endmodule

Inserting integer array with postgresql in C (libpq)

I'm trying to post an integer array into my postgresql database. I'm aware that I could format everything as a string and then send that string as one SQL command. However, I believe the PQexecParams function should also bring some help. However, I'm kind of lost as how to use it.
//we need to convert the number into network byte order
int val1 = 131;
int val2 = 2342;
int val3[5] = { 0, 7, 15, 31, 63 };
//set the values to use
const char *values[3] = { (char *) &val1, (char *) &val2, (char *) val3 };
//calculate the lengths of each of the values
int lengths[3] = { sizeof(val1), sizeof(val2), sizeof(val3) * 5 };
//state which parameters are binary
int binary[3] = { 1, 1, 1 };
PGresult *res = PQexecParams(conn, "INSERT INTO family VALUES($1::int4, $2::int4, $3::INTEGER[])", 3, //number of parameters
NULL, //ignore the Oid field
values, //values to substitute $1 and $2
lengths, //the lengths, in bytes, of each of the parameter values
binary, //whether the values are binary or not
0); //we want the result in text format
Yes this is copied from some tutorial.
However this returns :
ERROR: invalid array flags
Using a conventional method does work:
PQexec(conn, "INSERT INTO family VALUES (2432, 31, '{0,1,2,3,4,5}')");
Inserts data just fine, and I can read it out fine as well.
Any help would be greatly appreciated! :)
libpq's PQexecParams can accept values in text or binary form.
For text values, you must sprintf the integer into a buffer that you put in your char** values array. This is usually how it's done. You can use text format with query parameters, there is no particular reason to fall back to interpolating the parameters into the SQL string yourself.
If you want to use binary mode transfers, you must instead ensure the integer is the correct size for the target field, is in network byte order, and that you have specified the type OID. Use htonl (for uint32_t) or htons (for uint16_t) for that. It's fine to cast away signedness since you're just re-ordering the bytes.
So:
You cannot ignore the OID field if you're planning to use binary transfer
Use htonl, don't brew your own byte-order conversion
Your values array construction is wrong. You're putting char**s into an array of char* and casting away the wrong type. You want &val1[0] or (equivalent in most/all real-world C implementations, but not technically the same per the spec) just val1, instead of (char*)&val1
You cannot assume that the on-wire format of integer[] is the same as C's int32_t[]. You must pass the type OID INT4ARRAYOID (see include/catalog/pg_type.h or select oid from pg_type where typname = '_int4' - the internal type name of an array is _ in front of its base type) and must construct a PostgreSQL array value compatible with the typreceive function in pg_type for that type (which is array_recv) if you intend to send in binary mode. In particular, binary-format arrays have a header. You cannot just leave out the header.
In other words, the code is broken in multiple exciting ways and cannot possibly work as written.
Really, there is rarely any benefit in sending integers in binary mode. Sending in text-mode is often actually faster because it's often more compact on the wire (small values). If you're going to use binary mode, you will need to understand how C represents integers, how network vs host byte order works, etc.
Especially when working with arrays, text format is easier.
libpq could make this a lot easier than it presently does by offering good array construct / deconstruct functions for both text and binary arrays. Patches are, as always, welcome. Right now, 3rd party libraries like libpqtypes largely fill this role.

Conversion of entire array from int to double in order to do some aritmetic operations

I have this bit of code:
var arrayIntegers : [Int] = []
arrayIntegers += 0...33
var arrayDecimal : [Int] = []
arrayDecimal += 0...999
The problem is I can´t convert the values of both arrays to Double. What I want to do is to get a new array (called arrayDoubleComposed) with composite values, taking a value of arrayIntegers as the integer part and then taking another value of arrayDecimal as the floating part.
When I try to typecast this:
var arrayDoubleComposed : [Double] = []
arrayDoubleComposed = Double (arrayIntegers[] + (arrayDecimal[])/1000)
I´ve got an error. The same if I suppress the [].
I´m a little bit newcomer, I know...
Converting one kind of array into another is a job for map, which applies a function to each element of an array, returning the results as a new array of the type that function returns. In this case, you want a function that converts the Ints to a Double.
Try something like this:
let integers = Array(0...33)
let fractions = Array(0...999)
let arrayDoubleComposed = map(Zip2(integers, fractions)) {
(i, f) in
Double(i) + Double(f)/1_000
}
Zip2 takes two sequences and pairs them up – first elements together, second elements together etc. Then this passes that into map which combines the two elements.
(note also you can just initialize the arrays from the ranges rather than declaring them then adding the values)
It’s not clear what you mean to do, as the integer and fractional arrays are going to be different length. The way Zip2 handles this is to stop when the first sequence runs out, but this may not be what you want.
P.S. casts like the one you tried, which convert the contents of an array en-mass, only work in special cases when converting from Objective-C types to native Swift types, when the Swift compiler sprinkles some magic.

Resources