using rapidjson, how can i encode a number to json format? i have 123.321, i want to convert it to "123.321", then save it in a file. later using json convert it back to 123.321.
i don't want to use Document which saves as like "{"tag":"value"}", i want it to be saved as just a "value", then be converted back.
i have the following code to convert number to "number":
Value v(123);
StringBuffer mybuffer;
Writer<StringBuffer> mywriter(mybuffer);
v.Accept(mywriter);
const char* myjson = mybuffer.GetString();
how to convert it back? is the following a solution? i don't want to use handler!
Reader reader;
StringStream ss(myjson);
reader.Parse(ss, handler);
thanks for the upcoming helps.
I just found the answer after digging into google:
to encode a number to json using rapidjson:
Value v(123.321);
StringBuffer mybuffer;
Writer<StringBuffer> mywriter(mybuffer);
v.Accept(mywriter);
const char* myjson = mybuffer.GetString();
now myjson has "123.321" as its value.
then to decode myjson to a number:
Document d;
d.Parse(myjson); // myjson is "123.321"
assert(d.IsNumber());
value = d.GetDouble(); // now the value is 123.321
as simple as it gets.
Related
We have a file which is present in a data store (S3) which contains data in the form of byte[] (uploaded using Java language).
Now when i download the file, the data i get is in the form of std::basic_streambuf (Ideally it should also be having bytes). Now i want to send this data to another API which takes uint8_t* as the input.
What is the way to do so? Is it making any sense to even do that?
I tried this:
// Assume streambuf is:
std::streambuf *buf;
std::stringstream ss;
ss << buf;
// Solution1
const std::string output1 = ss.str();
cout<<output1;
// This prints the whole data with some weird characters (i think weird characters are valid because data is in byte form). Upon converting output1 to uint8_t*, the final data contains only 20 characters/bytes.
// Solution2
uint8_t* finalString;
ss >> finalString;
cout<<finalString;
// This prints only initial 20 characters/bytes and the remaining part is skipped.
So with both Solution1 and Solution2, ultimate goal of getting uint8_t* of full data could not be achieved. What is the suggested way to do so?
You have to read your data out of the buffer (since the buffer itself can be streaming the data in as it's available). One possible implementation is something like this:
vector<uint8_t> bytes;
do {
bytes.push_back(buf->sgetc());
} while(buf->snextc() != EOF);
// your data is in bytes.data() of type uint8_t*
Of course if you know the number of bytes from the beginning instead of having to read the buffer to find out, simply pre-allocate the vector beforehand.
I am lost with decoding the following base64 string
nVJPb4IwFL/7KUjvAgUM8CIuZiabicsSNR68deXhWKBteGVx336FbJnz4MG+U997/f1L5yTaxsBGn3Rvt0hGK0LPO7eNIhhnBes7BVpQTaBEiwRWwm75soHID8F02mqpGzZZrwpGScZjkUgpMolpFCfRLH/DPKlmaZXGMkqrMq/CMi6Zd8COaq0K5lCYtybqca3ICmVdK+TZlIfTONxzDtEMeHZk3grJ1krY8dW7tQaCgEepH7rikLoTEHaf2AWNPtXqodUlFonDVr++9rpgH1jq82BsusT8eWPa1yd9RLHdf7HFZD4MYBTTXWRwOwJBjnZQxRaDKnKy6tL4RFrWnWzQl7qdBxfIPzwGdlbYnu4I+wrh0Tm9A8U7iKbH28s0EsCulxKJBuLgmvm693f//6sW3w==
It should be valid base64 data representing deflate data of original XML. When I try online decoder here: https://www.samltool.com/decode.php it gives me the proper XML.
I am doing these two steps:
string text = MyClass::decode_base64(input);
text = MyClass::stringDeflateDecode(text);
First I decode the base64 string:
string MyClass::decode_base64(string str)
{
using namespace boost::archive::iterators;
typedef transform_width<binary_from_base64<remove_whitespace<string::const_iterator> >, 8, 6> ItBinaryT;
try {
boost::erase_all(str, "\r");
boost::erase_all(str, "\n");
// If the input isn't a multiple of 4, pad with =
size_t num_pad_chars((4 - str.size() % 4) % 4);
str.append(num_pad_chars, '=');
size_t pad_chars(std::count(str.begin(), str.end(), '='));
std::replace(str.begin(), str.end(), '=', 'A'); // replace '=' by base64 encoding of '\0'
string output(ItBinaryT(str.begin()), ItBinaryT(str.end()));
output.erase(output.end() - pad_chars, output.end());
return output;
} catch (...) {
return string("");
}
}
The code is basically from here Decode Base64 String Using Boost and it was working fine for text-only base64 decoding (no binary deflate data).
Then I would like to decode the deflate:
string MyClass::stringDeflateDecode(const std::string& data)
{
stringstream compressed(data);
stringstream decompressed;
boost::iostreams::filtering_streambuf<boost::iostreams::input> in;
in.push(boost::iostreams::zlib_decompressor());
in.push(compressed);
boost::iostreams::copy(in, decompressed);
return decompressed.str();
}
but ::copy operation throws an exception: zlib error: iostream error
Thanks for any hints!
That is Base-64 encoded raw deflate data. That means compressed data in the deflate format, but no zlib nor gzip wrapper around that deflate data. It looks like zlib_decompressor has a noheader option that you should set to true.
Wikipedia specifies:
SAML requests or responses transmitted via HTTP Redirect have a SAMLRequest or SAMLResponse query string parameter, respectively. Before it's sent, the message is deflated (without header and checksum), base64-encoded, and URL-encoded, in that order. Upon receipt, the process is reversed to recover the original message.
The problem here is the absense of the header and checksum. I don't think boost has the library functions you need.
I use rapid json to serialize a dict, the key is uint32 and the value is a long string. The code is:
rapidjson::StringBuffer buffer();
rapidjson::Write<< rapidjson::StringBuffer>> writer(buffer);
root.Accept(writer);
const char* json_str = buffer.GetString();
But, I found the final json_str is truncated. Does any one known how to avoid truncation?
If assume that the truncation has place due to zero character inside your long string then you can avoid it by stop using char * and use std::string instead.
rapidjson::StringBuffer buffer();
rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
root.Accept(writer);
std::string json_str = std::string(buffer.GetString(), buffer.GetSize());
I'm writing the websocket server on C++ and having a problem with calculating the Sec-WebSocket-Accept key. I've tested sha1 and it generates the right value (I've taken the string from wikipedia example and got the same hash) and I also found the online base64 converter to test the second part, and it seems working right. But as I can see from other issues, my string is too long.
std::string secKey = readHeader(buffer,n,"Sec-WebSocket-Key");
std::string magic = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
secKey.append(magic);
unsigned char hash[20];
char hexstring[41];
sha1::calc(secKey.c_str(),secKey.length(),hash);
sha1::toHexString(hash,hexstring);
std::string encoded = base64_encode(reinterpret_cast<const unsigned char*>(hexstring) ,strlen(hexstring));
For secKey = "4aRdFZG5uYrEUw8dsNLW6g==" I get encoded value "YTYwZWRlMjQ4NWFhNzJiYmRjZTQ5ODI4NjUwMWNjNjE1YTM0MzZkNg=="
I think you can skip the toHexString line and base64 encode the 20 byte hash instead.
sha1::calc(secKey.c_str(),secKey.length(),hash);
std::string encoded = base64_encode(reinterpret_cast<const unsigned char*>(hash), 20);
That's what my C++ server does and handshakes complete successfully.
I'm attempting to use TinyXML to read and save from memory, instead of only reading and saving files to disk.
It seems that the documnent's parse function can load a char *. But then I need to save the document to a char * when I'm done with it. Does anyone know about this?
Edit: The printing & streaming functions aren't what I'm looking for. They output in a viewable format, I need the actual xml content.
Edit: Printing is cool.
Here's some sample code I am using, adapted from the TiXMLPrinter documentation:
TiXmlDocument doc;
// populate document here ...
TiXmlPrinter printer;
printer.SetIndent( " " );
doc.Accept( &printer );
std::string xmltext = printer.CStr();
A simple and elegant solution in TinyXml for printing a TiXmlDocument to a std::string.
I have made this little example
// Create a TiXmlDocument
TiXmlDocument *pDoc =new TiXmlDocument("my_doc_name");
// Add some content to the document, you might fill in something else ;-)
TiXmlComment* comment = new TiXmlComment("hello world" );
pDoc->LinkEndChild( comment );
// Declare a printer
TiXmlPrinter printer;
// attach it to the document you want to convert in to a std::string
pDoc->Accept(&printer);
// Create a std::string and copy your document data in to the string
std::string str = printer.CStr();
I'm not familiar with TinyXML, but from the documentation it seems that by using operator << to a C++ stream (so you can use C++ string streams) or a TiXMLPrinter class you can get an STL string without using a file. See TinyXML documentation (look for the "Printing" section)
Don't quite get what you are saying; your question is not clear. I'm guessing you are wanting to load a file into memory so that you can pass it to the document parse function. In that case, the following code should work.
#include <stdio.h>
The following code reads a file into memory and stores it in a buffer
FILE* fd = fopen("filename.xml", "rb"); // Read-only mode
int fsize = fseek(fd, 0, SEEK_END); // Get file size
rewind(fd);
char* buffer = (char*)calloc(fsize + 1, sizeof(char));
fread(buffer, fsize, 1, fd);
fclose(fd);
The file is now in the variable "buffer" and can be passed to whatever function required you to provide a char* buffer of the file to it.