I am working with protocol buffers in C++. My message has only one extension range. And I want to access all the extension fields without knowing their name, using only their numbers. How can I do this??
message Base {
optional int32 id = 1;
extensions 1000 to 1999;
}
extend Base{
optional int32 id2 = 1000;
}
Up till now, I have obtained ExtensionRange.
const google::protobuf::Descriptor::ExtensionRange* rng = desc->extension_range(0);
std::cerr << "rng " << rng->start << " " << rng->end << std::endl;
But I donot know to to get the Fielddescriptor* of the extensions.
There is one weird thing and that is extension_count() is returning 0. Although I have used extension in my .proto file. Similarly FindExtensionBy[Name/number] are not working as expected?
I found a solution using reflection.
const Reflection* ref = message_.GetReflection();
const FieldDescriptor* cfield = ref->FindKnownExtensionByNumber(33);
std::cerr << "cfield->name() " << cfield->name() << std::endl;
Now my existing solution will be to loop for all the numbers in extension range and get the required Fielddescriptors of the extensions.
I am still waiting for any better/different solution, you guys.
To cite from the official descriptor.h documentation:
To get a FieldDescriptor for an extension, do one of the following:
Get the Descriptor or FileDescriptor for its containing scope, then
call Descriptor::FindExtensionByName() or
FileDescriptor::FindExtensionByName().
Given a DescriptorPool, call
DescriptorPool::FindExtensionByNumber().
Given a Reflection for a
message object, call Reflection::FindKnownExtensionByName() or
Reflection::FindKnownExtensionByNumber(). Use DescriptorPool to
construct your own descriptors.
The reason why extension_count() is returning 0 is that it tells you the number of nested extension declarations (for other message types).
I am trying to write a program that navigates your local disc in Unreal Engine for a small application. I have put together a REST server using Gradle, and long story short, I am given a JSON with a machines directories. I want to pull out the specific directories names, to be returned as string (FText specifically, but that not too important here) array.
I found a library created by nLohmann on github (https://github.com/nlohmann/json) which seems to be the best way to handle a JSON in c++. For the life of me, however, I can't figure out how to pull the directory names out. I've tried an iterator and a straightforward .value() call.
The code and a JSON example are below, any insight would be greatly appreciated.
char buffer[1024];
FILE *lsofFile_p = _popen("py C:\\Users\\jinx5\\CWorkspace\\sysCalls\\PullRoots.py", "r");
fgets(buffer, sizeof(buffer), lsofFile_p);
_pclose(lsofFile_p);
std::string rootsJson(buffer);
string s = rootsJson.substr(1);
s = ReplaceAll(s, "'", "");
//here my string s will contain: [{"description":"Local Disk","name":"C:\\"},{"description":"Local Disk","name":"D:\\"},{"description":"CD Drive","name":"E:\\"}]
//These are two syntax examples I found un nlohmann's docs, neither seems to work
auto j = json::parse(s);
string descr = j.value("description", "err");
I think your problem comes from number of \ in your literal string. You need 5 \ for C:\\ : C:\\\\\.
Here is a working example :
#include "json.hpp"
#include <string>
using namespace std;
using json = nlohmann::json;
int main(){
json j = json::parse("[{\"description\":\"Local Disk\",\"name\":\"C:\\\\\"},{\"description\":\"Local Disk\",\"name\":\"D:\\\\\"},{\"description\":\"CD Drive\",\"name\":\"E:\\\\\"}]");
cout << j.is_array() << endl;
for (auto& element : j) {
std::cout << "description : " << element["description"] << " | " << " name : " << element["name"] << '\n';
}
return 0;
}
cgicc can process form elements quite well , but how can i know whether the data is generated from get_method or post_method?
the piece of code i used:
cout << "Content-type:text/html\r\n\r\n";
try {
Cgicc cgi;
const_form_iterator iter;
for(iter = cgi.getElements().begin();
iter != cgi.getElements().end();
++iter){
cout <<
"<table><tr>" <<
"<td>" << iter->getName() << "</td>" <<
"<td>" << iter->getValue() << "</td>" <<
"</tr></table>" << endl;
}
}catch(exception& e) {
cout << e.what() << endl;
}
update:
i find this from the cgicc official page: "Parses both GET and POST form data transparently." (http://www.gnu.org/software/cgicc/)
it seems that cgicc don't want to separate get and post by design?
You can find the HTTP method (ì.e. GET, POST, etc...) of a request using cgicc::CgiEnvironment::getRequestMethod
I think the only way to solve it is by checking whether there is a variable name in the GET method query string that's the same name of the one in the POST method. This means that the variable name must be mentioned ONLY ONCE either of the two methods. In other words, if you combine the variables of the GET method with the variables of the POST in a single set, the variable name must be mentioned once in this set.
Consider the following string content:
string content = "{'name':'Fantastic gloves','description':'Theese gloves will fit any time period.','current':{'trend':'high','price':'47.1000'}";
I have never used regex_search and I have been searching around for ways to use it - I still do not quite get it. From that random string (it's from an API) how could I grab two things:
1) the price - in this example it is 47.1000
2) the name - in this example Fantastic gloves
From what I have read, regex_search would be the best approach here. I plan on using the price as an integer value, I will use regex_replace in order to remove the "." from the string before converting it. I have only used regex_replace and I found it easy to work with, I don't know why I am struggling so much with regex_search.
Keynotes:
Content is contained inside ' '
Content id and value is separated by :
Conent/value are separated by ,
Value of id's name and price will vary.
My first though was to locate for instance price and then move 3 characters ahead (':') and gather everything until the next ' - however I am not sure if I am completely off-track here or not.
Any help is appreciated.
boost::regex would not be needed. Regular expressions are used for more general pattern matching, whereas your example is very specific. One way to handle your problem is to break the string up into individual tokens. Here is an example using boost::tokenizer:
#include <iostream>
#include <string>
#include <boost/tokenizer.hpp>
#include <map>
int main()
{
std::map<std::string, std::string> m;
std::string content = "{'name':'Fantastic gloves','description':'Theese gloves will fit any time period.','current':{'trend':'high','price':'47.1000'}";
boost::char_separator<char> sep("{},':");
boost::tokenizer<boost::char_separator<char>> tokenizer(content, sep);
std::string id;
for (auto tok = tokenizer.begin(); tok != tokenizer.end(); ++tok)
{
// Since "current" is a special case I added code to handle that
if (*tok != "current")
{
id = *tok++;
m[id] = *tok;
}
else
{
id = *++tok;
m[id] = *++tok; // trend
id = *++tok;
m[id] = *++tok; // price
}
}
std::cout << "Name: " << m["name"] << std::endl;
std::cout << "Price: " << m["price"] << std::endl;
}
Link to live code.
As the string you are attempting to parse appears to be JSON (JavaScript Object Notation), consider using a specialized JSON parser.
You can find a comprehensive list of JSON parsers in many languages including C++ at http://json.org/. Also, I found a discussion on the merits of several JSON parsers for C++ in response to this SO question.
I'm building a graph generator using Boost Graph and Program Options. There are, for example, two types of components C and W, each with 1 source, 1 sink and some additional parameters to specify topology in between. I'd like to be able to stitch them together in the sequence provided by the order of the command line arguments.
For example:
./bin/make_graph -c4,5,1 -w3,3 -c3,1,2
Should create a graph resembling the following:
C -- W -- C
But:
./bin/make_graph -c4,5,1 -c3,1,2 -w3,3
Should create a graph resembling the following:
C -- C -- W
Using boost::program_options, I was unable to determine how to extract the exact order since it "composes" the options of the same string_key into a map with value_type == vector< string > (in my case).
By iterating over the map, the order is lost. Is there a way to not duplicate the parsing, but have a function called (perhaps a callback) every time an option is parsed? I couldn't find documentation in this direction. Any other suggestions?
To convince you that I'm not making this up, here's what I have so far:
namespace bpo = boost::program_options;
std::vector<std::string> args_cat, args_grid, args_web;
bpo::options_description desc("Program options:");
desc.add_options()
.operator ()("help,h","Displays this help message.")
.operator ()("caterpillar,c",bpo::value< std::vector<std::string> >(&args_cat)->default_value( std::vector<std::string>(1,"4,7,2"), "4,7,2" ),"Caterpillar tree with 3 parameters")
.operator ()("grid,g",bpo::value< std::vector<std::string> >(&args_grid)->default_value( std::vector<std::string>(1,"3,4"), "3,4" ),"Rectangular grid with 2 parameters")
.operator ()("web,w",bpo::value< std::vector<std::string> >(&args_web)->default_value( std::vector<std::string>(1,"3,4"), "3,4" ),"Web with 2 parameters")
;
bpo::variables_map ops;
bpo::store(bpo::parse_command_line(argc,argv,desc),ops);
bpo::notify(ops);
if((argc < 2) || (ops.count("help"))) {
std::cout << desc << std::endl;
return;
}
//TODO: remove the following scope block after testing
{
typedef bpo::variables_map::iterator OptionsIterator;
OptionsIterator it = ops.options.begin(), it_end = ops.options.end();
while(it != it_end) {
std::cout << it->first << ": ";
BOOST_FOREACH(std::string value, it->second) {
std::cout << value << " ";
}
std::cout << std::endl;
++it;
}
return;
}
I realize that I could also include the type as a parameter and solve this problem trivially, e.g.:
./bin/make_graph --component c,4,5,1 --component w,3,3 --component c,3,1,2
but that's moving in the direction of writing a parser/validator myself (maybe even without using Boost Program Options):
./bin/make_graph --custom c,4,5,1,w,3,3,c,3,1,2
./bin/make_graph c,4,5,1,w,3,3,c,3,1,2
How would you guys recommend I do this in an elegant way?
Thanks in advance!
PS: I've searched on SO for "[boost] +sequence program options" and "[boost-program-options] +order" (and their variants) before posting this, so I apologize in advance if this turns out to be a duplicate.
Since posting the question, I did some digging and have a "hack" that works with the existing examples I had above.
bpo::parsed_options p_ops = bpo::parse_command_line(argc,argv,desc);
typedef std::vector< bpo::basic_option<char> >::iterator OptionsIterator;
OptionsIterator it = p_ops.options.begin(), it_end = p_ops.options.end();
while(it != it_end) {
std::cout << it->string_key << ": ";
BOOST_FOREACH(std::string value, it->value) {
std::cout << value << " ";
}
std::cout << std::endl;
++it;
}
The reason I call it a hack is because it accesses all arguments as strings, and one would have to extract the types from it much like bpo::variables_map does with the .as<T>() member function. EDIT: It also accesses a member of the options struct directly.
How about this:
./bin/make_graph c,4,5,1 c,3,1,2 w,3,3
Where "c,4,5,1", "c,3,1,2" and "w,3,3" are positional arguments which are stored (in order) in a std::vector<std::string> (just like --input-file in this tutorial) . Then use Boost.Tokenizer or boost::algorithm::split to extract the subtokens from each argument string.
If the graphs can be complex, you should consider making it possible for the user to specify an input file that contains the graph parameters. Boost.Program_Options can parse a user config file that uses the same syntax as the command line options.