c++ libconfig and lists - c++

it seems I am unable to find any source telling me how to use lists with libconfig.
Let's say my config file looks like this:
Layer1 = {
Layer2 = {
SomeOption = "MyValue";
Options = (
{
Option = "Full Screen";
Value = "No";
},
{
Option = "Title";
Value = "Test";
}
);
};
};
How can I read Options with libconfig++ ? I can only find methods for reading single values.

OK, I have found the answer:
using namespace libconfig;
// ...
Config *pConfig = new Config();
// ...
Setting& settings = pConfig->lookup("Layer1.Layer2.Options");
const char* op0 = settings[0]["Option"];
// ...

Related

How to parse and modify LUA file when it contains INCLUDE definition with C++?

I'm trying to parse and modify LUA files which relate to cartographer by C++. I'm a newbie in LUA, can't handle the lua file with complicate structures. Here's the example of the file:
//test.lua
include "map_builder.lua"
include "trajectory_builder.lua"
options = {
map_builder = MAP_BUILDER,
trajectory_builder = TRAJECTORY_BUILDER,
map_frame = "map",
tracking_fame = "base_link",
published_frame = "base_link",
...
submap_publish_period_sec = 0.3,
...
}
--MAP_BUILDER
MAP_BUILDER.use_trajectory_builder_3d = true
MAP_BUILDER.num_background_threads = 7
--POSE_GRAPH
POSE_GRAPH.optimize_every_n_nodes = 640
...
--TRAJECTORY_BUILDER_3D
TRAJECTORY_BUILDER_3D.max_range = 50.
...
return options
and next,
//map_builder.lua
include "pose_graph.lua"
MAP_BUILDER = {
use_trajectory_builder_2d = false,
use_trajectory_builder_3d = false,
num_background_threads = 4,
pose_graph = POSE_GRAPH,
...
}
pose_graph.lua:
//pose_graph.lua
POSE_GRAPH = {
optimize_every_n_nodes = 20,
constraint_builder = {
smapling_ratio = 0.03,
...
},
...
}
trajectory_builder.lua:
//trajectory_builder.lua
include "trajectory_builder_2d.lua"
include "trajectory_builder_3d.lua"
TRAJECTORY_BUILDER = {
trajectory_builder_2d = TRAJECTORY_BUILDER_2D,
trajectory_builder_3d = TRAJECTORY_BUILDER_3D,
collate_fixed_frame = true,
...
}
trajectory_builder_2d.lua:
//trajectory_builder_2d.lua
TRAJECTORY_BUILDER_2D = {
...
}
trjectory_builder_3d.lua:
//trajectory_builder_3d.lua
MAX_3D_RANGE = 100.
...
TRAJECTORY_BUILDER_3D = {
...
}
And finally, this is my test code:
I had re-edit my code like this, it seems like I should handle MAP_BUILDER etc. in luaInclude() before loading the file. And so, what's the correct way to handle them before load the test.lua file?
int luaInclude(lua_State *L) {
printf("include file: %s\n", lua_tostring(L, -1));
// get include lua file name and handle it here
// how to handle MAP_BUILDER etc.?
}
int main() {
lua_State *L = luaL_newstate();
luaL_openlibs(L);
lua_register(L, "include", luaInclude);
if(luaL_dofile(L, "test.lua")) {
printf("read file failed: %s", lua_tostring(L, -1));
return;
}
lua_getglobal(L, "options");
int size = lua_gettop(L);
lua_pushnil(L);
// here to do sth.
// like modify "submap_publish_period_sec" from 0.3 to 0.6
lua_close(L);
return 0;
}
But, I got error:
test.lua: attempt to index global 'MAP_BUILDER'(a nil value)!
So, how to handle something like "MAP_BUILDER"、"POSE_GRAPH" and "TRAJECTORY_BUILDER_3D" in test.lua? Help!

TDLib: how to send bold text in the message? (С++)

Using the official TDLib C++ example, I'm trying to send a message with formatted markdown text.
Here's my code:
auto send_message = td_api::make_object<td_api::sendMessage>();
send_message->chat_id_ = -1001424068198;
auto message_content = td_api::make_object<td_api::inputMessageText>();
std::string text = "Hello! **how are u?**";
message_content->text_ = td_api::make_object<td_api::formattedText>();
message_content->text_->text_ = std::move(text);
send_message->input_message_content_ = std::move(message_content);
send_query(std::move(send_message), {});
I expect to see "Hello! how are u?" but the message comes as it is written in the code, without markdown formatting applied.
I spent hours on google trying to figure out how to force TDLib to parse it.
UPDATE: SOLVED!
Thanks Azeem for help!
Using this example, the following code should send the parsed message (tested in VS 2019)
void sendMsg(INT64 chatID, INT64 ReplyTo, const char* textMsg) {
const std::string text = textMsg;
auto textParseMarkdown = td_api::make_object<td_api::textParseModeMarkdown>(2);
auto parseTextEntities = td_api::make_object<td_api::parseTextEntities>(text, std::move(textParseMarkdown));
td::Client::Request parseRequest{ 123, std::move(parseTextEntities) };
auto parseResponse = td::Client::execute(std::move(parseRequest));
if (parseResponse.object->get_id() == td_api::formattedText::ID) {
auto formattedText = td_api::make_object<td_api::formattedText>();
formattedText = td_api::move_object_as<td_api::formattedText>(parseResponse.object);
auto send_message = td_api::make_object<td_api::sendMessage>();
send_message->chat_id_ = chatID;
auto message_content = td_api::make_object<td_api::inputMessageText>();
message_content->text_ = std::move(formattedText);
send_message->input_message_content_ = std::move(message_content);
send_message->reply_to_message_id_ = ReplyTo;
send_query(std::move(send_message), {});
}
}
You can use td_api::textParseModeMarkdown, td_api::parseTextEntities and td::Client::execute() like this:
using namespace td;
const std::string text = "*bold* _italic_ `code`";
auto textParseMarkdown = td_api::make_object<td_api::textParseModeMarkdown>( 2 );
auto parseTextEntities = td_api::make_object<td_api::parseTextEntities>( text, std::move( textParseMarkdown ) );
td::Client::Request parseRequest { 123, std::move( parseTextEntities ) };
auto parseResponse = td::Client::execute( std::move( parseRequest ) );
auto formattedText = td_api::make_object<td_api::formattedText>();
if ( parseResponse.object->get_id() == td_api::formattedText::ID )
{
formattedText = td_api::move_object_as<td_api::formattedText>( parseResponse.object );
}
else
{
std::vector<td_api::object_ptr<td_api::textEntity>> entities;
formattedText = td_api::make_object<td_api::formattedText>( text, std::move(entities) );
}
std::cout << td_api::to_string( formattedText ) << '\n';
For debugging purposes, you can use td_api::to_string() to dump the contents of an object. For example, dumping parseTextEntities like this:
std::cout << td_api::to_string( parseTextEntities ) << '\n';
would give this:
parseTextEntities {
text = "*bold* _italic_ `code`"
parse_mode = textParseModeMarkdown {
version = 2
}
}

Convert a string into closure in ColdFusion

I have a very basic question. Is it possible to convert a string into a closure? I tried evaluate() but it didn't work.
evaluate( "myFunction = function(val){ return dollarFormat( val ); }" );
What I have in mind is to save custom functions in the database as string and then run it as needed.
Thank you!
Edit: Just to clarify: I want to be able to save "function(val){ return dollarFormat( val ); }" as a string in database and be able to convert it into a functioning closure.
I would go with user2943775 answer:
<cfscript>
FileWrite("/ram/UDFs.cfm", "<cfset myFunction = function(val){ return dollarFormat( val ); }>")
include template="/ram/UDFs.cfm";
writedump(myFunction(10));
</cfscript>
And in your Application.cfc
component {
this.mappings["/ram"] = "ram://";
...
}
I came across a similar solution, though I was unable to use the in-memory filesystem due to security restrictions. In my Application.cfc, I added the following mapping:
this.mappings = {
"/models" = "#APP_ROOT_PATH#cfcs/models",
"/utils" = "#APP_ROOT_PATH#cfcs/utils",
"/modules" = "#APP_ROOT_PATH#_modules",
"/components" = "#APP_ROOT_PATH#cfcs",
"/udfs" = "#APP_ROOT_PATH#includes/udfs" // path for global (and temporary) UDFs
};
The UDF I created is as follows:
/**
* Takes a string representation of a function and returns it as a Closure
* #output false
* #return Closure
*/
private any function toClosure (required string closure) {
local.id = replace(createUUID(), "-", "", "all");
local.udfpath = "/udfs/udf#id#.cfm";
local.script = "<cfscript>local.fn#id# = #closure#;</cfscript>";
try {
fileWrite(expandPath(udfPath), script);
include udfpath;
} catch (any e) {
} finally {
try {
fileDelete(expandPath(udfPath));
} catch (any e) {}
}
if (!structkeyExists(local, "fn#id#") || !isClosure(local["fn#id#"])) {
throw (message="Unable to compile closure");
}
// return the closure
return local["fn#id#"];
}
And the result:
myFn = toClosure("function (num) { return num + 1; }");
myFn(1); // returns 2

How to pass an array of integers as a property value in the Configuration object for MapReduce?

We can pass an integer as a Configuration property as below:
Configuration conf = new Configuration();
conf.set("size", 4);
Is there a way to send an array of integers as a property value?
conf.set("list.of.nums", {2, 4, 6, 8}); // one way is to pass them as a String but it doesn't look good
You can serialize the array object into a file and then move the file to HDFS.Then you can add the hdfs file path to Distributed cache using following.
DistributedCache.addCacheFile(new URI(dfsMetaPath + "#"
+ Constants.OBJSYMLINK0), conf);
DistributedCache.createSymlink(conf);
Serialization can be done as follows:-
public static <T> void serializeMetadata(T voObj,
String filePath) throws IOException,NullPointerException {
if(null==voObj){
throw new NullPointerException("NULL object found");
}
ObjectOutputStream oout = null;
FileOutputStream fsout = null;
try {
fsout = new FileOutputStream(filePath);
oout = new ObjectOutputStream(fsout);
oout.writeObject(voObj);
oout.close();
} finally {
if (null != fsout) {
fsout.close();
}
if (null != oout) {
oout.close();
}
}
}
You can use the filepath passed as arguments to the above method.Using this filepath you can move the file to HDFS filepath. Use the HDFS filepath to create the symlink.
To retireve in mapper you can use the following inside setup to get the object back.
File hdfsfilepath = new File(Constants.OBJSYMLINK0);
Integer[] youarray = MetadataSerDeUtils.deserializeMetadata(youarray ,
hdfsfilepath.getAbsolutePath());
For deserialization you can use following code:-
public static <T> T deserializeMetadata(T voObj,
String filePath) throws IOException,NullPointerException, ClassNotFoundException {
FileInputStream fsin = null;
ObjectInputStream oin = null;
try {
fsin = new FileInputStream(filePath);
oin = new ObjectInputStream(fsin);
voObj = (T) oin.readObject();
return voObj;
} finally {
if (null != fsin) {
fsin.close();
}
if (null != oin) {
oin.close();
}
}
}

Transaction Advance Search for Sales Order in NetSuite returning Errors when otherRefNum Operator used

Any idea why the below code would return an error(Failure) for its status?
private SearchResult getTxns()
{
TransactionSearchAdvanced tsa = new TransactionSearchAdvanced();
tsa.columns = new TransactionSearchRow();
tsa.columns.basic = new TransactionSearchRowBasic();
tsa.columns.basic.tranId = new SearchColumnStringField[] { new SearchColumnStringField() };
tsa.criteria = new TransactionSearch();
tsa.criteria.basic = new TransactionSearchBasic();
tsa.criteria.basic.mainLine = new SearchBooleanField();
tsa.criteria.basic.mainLine.searchValue = true;
tsa.criteria.basic.mainLine.searchValueSpecified = true;
tsa.criteria.basic.type = new SearchEnumMultiSelectField();
tsa.criteria.basic.type.#operator = SearchEnumMultiSelectFieldOperator.anyOf;
tsa.criteria.basic.type.operatorSpecified = true;
tsa.criteria.basic.type.searchValue = new string[] { "_salesOrder" };
tsa.criteria.basic.otherRefNum = new SearchTextNumberField();
tsa.criteria.basic.otherRefNum.#operator = SearchTextNumberFieldOperator.equalTo;
tsa.criteria.basic.type.operatorSpecified = true;
tsa.criteria.basic.type.searchValue = new string[] { "BBnB 1001" };
SearchResult sr = _service.search(tsa);
return sr;
}
The following is the error that is returned in the results.
Status Code: INVALID_SEARCH_OPERATOR
Status Message: You need to provide a valid search field operator.
However, this operator appears in the NetSuite UI itself when I do a search. Also, I find it in the NetSuite documentation here.
I am using v2013_1_0 for the webservices version of the wsdl.
SOLUTION
Solution found to be in the last block of code. Was attempting to set otherRefNum and was referencing Type. Here is the corrected code.
private SearchResult getTxns()
{
TransactionSearchAdvanced tsa = new TransactionSearchAdvanced();
tsa.columns = new TransactionSearchRow();
tsa.columns.basic = new TransactionSearchRowBasic();
tsa.columns.basic.tranId = new SearchColumnStringField[] { new SearchColumnStringField() };
tsa.criteria = new TransactionSearch();
tsa.criteria.basic = new TransactionSearchBasic();
tsa.criteria.basic.mainLine = new SearchBooleanField();
tsa.criteria.basic.mainLine.searchValue = true;
tsa.criteria.basic.mainLine.searchValueSpecified = true;
tsa.criteria.basic.type = new SearchEnumMultiSelectField();
tsa.criteria.basic.type.#operator = SearchEnumMultiSelectFieldOperator.anyOf;
tsa.criteria.basic.type.operatorSpecified = true;
tsa.criteria.basic.type.searchValue = new string[] { "_salesOrder" };
tsa.criteria.basic.otherRefNum = new SearchTextNumberField();
tsa.criteria.basic.otherRefNum.#operator = SearchTextNumberFieldOperator.equalTo;
tsa.criteria.basic.otherRefNum.operatorSpecified = true;
tsa.criteria.basic.otherRefNum.searchValue = "BBnB 1001";
SearchResult sr = _service.search(tsa);
return sr;
}
The problem is with your SearchEnumMultiSelectField operator. equalto is not a valid operator for this filter; you will need to use anyOf instead.
-- EDIT - Adapated from original comment --
A SearchTextNumberField does not accept an array of Strings. Instead try tsa.criteria.basic.otherRefNum.searchValue = "BBnB 1001";