LibBSON export to buffer - c

I'm searching for a way to copy a BSON document to a buffer or into a file using the C-library libbson.
I think I'm missing something - any help is appreciated.

bson_as_canonical_extended_json exports BSON into UTF-8 without loss of information.

If you only need buffer data, you can use bson_get_data :
bson_t * bson = bson_new();
///// Fill with data
// Get data buffer
const char * data = reinterpret_cast<const char*>(bson_get_data(bson));
int length = bson->len;

Related

How to allocate memory when using custom reading functions in libpng?

I'm in need of reading base64 encoded PNG image, stored as char array/null terminated string, and I'm stuck. Here is what I have found out for now:
Libpng is capable of changing it's workings, by using png_set_*_fn().
reading functions must have prototype alike this one : void user_read_data(png_structp png_ptr, png_bytep data, size_t length); and must check for EOF errors.
Original read function (which reads from png file directly) calls an fread function and dumps everything to memory pointed by data. I have no idea how libpng knows about image size.
So, here is my implementation of read function
size_t base64_to_PNG(const char *const base64_png, png_bytep out)
{
size_t encoded_size, decoded_count;
size_t decoded_size = base64_decoded_block_size(base64_png, &encoded_size);
decoded_count = base64_decode_block(base64_png, encoded_size, (char*)out);
if(decoded_count != decoded_size)
return 0;
return decoded_size;
}
void my_read_png_from_data_uri(png_structp png_ptr, png_bytep data, size_t length)
{
const char *base64_encoded_png = NULL;
size_t PNG_bytes_len;
if(png_ptr == NULL)
return;
base64_encoded_png = png_get_io_ptr(png_ptr);
PNG_bytes_len = base64_to_PNG(base64_encoded_png, data);
if(PNG_bytes_len != length)
png_error(png_ptr, "Error occured during decoding of the image data");
}
I do believe that information about the decoded image size is lost, and I'm going straight to the segfault with that, as I'll be writing to some random address, but I have no idea how to tell libpng how much memory I need. Can you please help me with that?

AWS IoT - JSON incorrect format

I am trying to send this JSON packet to AWS IoT, but it is not recognized by AWS. I am using the example ESP32 AWS FreeRTOS code, but cannot understand what would be the correct format for the JSON packet with the following code:
#define echoMAX_DATA_LENGTH 20
char cDataBuffer[ echoMAX_DATA_LENGTH ];
(void) snprintf(cDataBuffer, echoMAX_DATA_LENGTH, "{\"state\":{\"reported\":%.*d}, \"clientToken\":\"%d\"}", x, x, x);
/* Setup the publish parameters. */
memset( &( xPublishParameters ), 0x00, sizeof( xPublishParameters ) );
xPublishParameters.pucTopic = echoTOPIC_NAME;
xPublishParameters.pvData = cDataBuffer;
xPublishParameters.usTopicLength = ( uint16_t ) strlen( ( const char * ) echoTOPIC_NAME );
xPublishParameters.ulDataLength = ( uint32_t ) strlen( cDataBuffer );
xPublishParameters.xQoS = eMQTTQoS1;
The AWS test page, cannot display the message and has converted it to UTF-8 (this error message is below)
Increase echoMAX_DATA_LENGTH to be large enough to fit your entire JSON message.
The static part of the JSON in your code (without the values filled in by snprintf()) is 34 characters, so there's no way this could ever work with echoMAX_DATA_LENGTH set to 20 - it would always produce a fragment of JSON instead of an entire JSON object.
Remember that the length that snprintf() uses includes a byte for the C string terminating character '\0', so you'll want to make echoMAX_DATA_LENGTH be one greater than the maximum total JSON message length.
When you increase echoMAX_DATA_LENGTH, try adding a debug message after the snprintf() so that you can see the JSON you're generating. If your code is set up to use Serial already, add:
Serial.println(cDataBuffer);
after the snprintf() so you can confirm that you've generated the JSON properly.

Extracting data from an unknown encoding file

We use testing equipment (1995 year manufacturing) powered by MS DOS. Analog-digital converter records information in the file.
In [picture1] is shown the structure of that file.
In [picture2] is shown the oscillogram that constructed according to the data from the file (program for opening the file on MS DOS).
Below I placed link to this file (google drive).
This file contains the data that need for me - the massive of point of oscillogram. I want have opportunities to keep, analyze and print this chart on Windows or Linux (not MS DOS). So I need to extract data from the file.
But I can't make it. And no program (known to me) can't open this file. I analyzed a few first byte and they point to program 'TRAS v4.99'. This program is on MS DOS.
But I really hope, that it is really to get data without this program.
P.S. If anyone will say it is impossible - it is will well too because I haven't found point of view yet:)
Thank you for your time! Best regards!
LINK TO FILE ON GOOGLE DISK - 00014380.K00
STRUCTURE OF FILE
OPENING FILE VIA PROGRAM IN MS DOS
Here is an idea on how you can tackle this problem. Since the format is relatively well specified in the handbook you can use the Java programming language for example with something like java.io.RandomAccessFile to read arrays of bytes. These arrays of bytes can then be converted to Java primitive types OR to string according to the data type. After this conversion you can the print out the data in a human readable format.
Below you can find some sample code to give you an idea of what you could do with this approach (I have not tested the code, it is not complete, it is just to give you an idea of what you can do):
public static void readBinaryfile() throws IOException {
java.io.RandomAccessFile randomAccessFile = new RandomAccessFile("test.bin", "r");
byte[] addKenStrBytes = new byte[12];
randomAccessFile.read(addKenStrBytes);
String addKenStr = new String(addKenStrBytes, "UTF-8");
// TODO: Do something with addKenStr.
System.out.println(addKenStr);
byte[] kopfSizeBytes = new byte[2];
randomAccessFile.read(kopfSizeBytes);
// TODO: Do something with kopfSizeBytes
System.out.println(convertToInt(kopfSizeBytes));
byte[] addRufNrCounterBytes = new byte[6];
randomAccessFile.read(addRufNrCounterBytes);
long addRufNrCounter = convertToLong(addRufNrCounterBytes);
// TODO: Do something with addRufNrCounter
System.out.println(addRufNrCounter);
byte[] endAdrBytes = new byte[4];
randomAccessFile.read(endAdrBytes);
// TODO: Do something with endAdrBytes
System.out.println(convertToLong(endAdrBytes));
// Continue here and after you reached the end of the record repeat until you reached the end off the file
}
private static int convertToInt(byte[] bytes) {
if(bytes.length > 4) {
throw new IllegalArgumentException();
}
int buffer = 0;
for(byte b : bytes) {
buffer |= b;
buffer = buffer << 8;
}
return buffer;
}
private static long convertToLong(byte[] bytes) {
if(bytes.length > 8) {
throw new IllegalArgumentException();
}
long buffer = 0L;
for(byte b : bytes) {
buffer |= b;
buffer = buffer << 8;
}
return buffer;
}
Note that fields with more than 8 bytes need to be most probably converted to strings. This is not complete code, just an example to give you an idea on how you can tackle this problem.

Parsing XML text on a MSP430F5529LP + CC3100Boost platform

I am working on a IOT project using MSP430F5529LP and CC3100Boost. The hardware is successfully connecting to the cloud and exchanging data. The response to the IOT devices is XML based. I am trying to parse the data. The following printf("\n%.*s\n", pch2-pch1-8, pch1 +8); extracts the data and prints to the console. Now in need to save this data to a variable. Here is my code snippet. The answer might be obvious, unfortunately I am failing to see it.
_i8 * databuffer;
char * pch0;
char * pch1;
char * pch2;
char data[7];
pch0 = strstr((char *)dataBuffer,"textResponse");
pch1 = strstr(pch0,"<text_1>");
pch2 = strstr(pch1,"</text_1>");
printf("\n%.*s\n", pch2-pch1-8, pch1 +8);
References:
Extract data between two delimiters
parsing the value in between two XML tags
MSP430G2121: looking for a xml library to parse xml text
Ensure that the data received is valid and of a length that will fit.
Print it to a string using sprintf() or equivalent function.
Print this string to the console with puts(the_string).

Reading unsingned chars with Qt

Hi fellow stack overflowers,
I'm currently parsing a file which both contains text and binary data. Currently, I'm reading the file in following manner:
QTextStream in(&file);
int index = 0;
while(!in.atEnd()) {
if (index==0) {
QString line = in.readLine(); // parse file here
} else {
QByteArray raw_data(in.readAll().toAscii());
data = new QByteArray(raw_data);
}
index++;
}
where data refers to the binary data I'm looking for. I'm not sure if this is what I want, since the QString is encoded into ascii and I have no idea if some bytes are lost.
I checked the documentation, and it recommends using a QDataStream. How can I combine both approaches, i.e. read lines with an encoding and also read the binary dump, after one line break?
Help is greatly appreciated!
This will do what you want.
QTextStream t(&in);
QString line;
QByteArray raw_data;
if(!in.atEnd()) {line = t.readLine();}
in.reset();
int lineSize = line.toLocal8Bit().size() + 1;
in.seek(lineSize);
if(!in.atEnd())
{
int len = in.size() - lineSize;
QDataStream d(&in);
char *raw = new char[len]();
d.readRawData(raw, len);
raw_data = QByteArray(raw, len);
delete raw;
}
PS: if file format is yours, it will be better to create file with QDataStream and write data with <<, read with >>. This way you can store QByteArray and QString in file without such problems.

Resources