C++ Wrapper to GNU Readline - c++

I am trying to write a c++ wrapper for GNU Readline to be able to easily use custom completion but came across a small problem and can't think of a solution(I am still new to c++).
class ReadLine {
public:
ReadLine();
~ReadLine();
std::string exec ();
void enableHistory ();
private:
std::vector<std::string> keywordList;
bool history;
private:
static char** my_completion (const char*, int, int);
void* xmalloc (int);
char* generator (const char*, int);
char* dupstr (std::string);
};
cpp file:
std::string ReadLine::exec(){
rl_attempted_completion_function = my_completion;
std::string buf = "";
buf = readline("Command>>");
//enable auto-complete
rl_bind_key('\t',rl_complete);
if (buf[0]!=0)
add_history(buf.c_str());
return buf;
}
char** ReadLine::my_completion (const char* text, int start, int end) {
char** matches;
matches = NULL;
if (start == 0)
matches = rl_completion_matches(text, my_generator);
return matches;
}
My problem is the line
matches = rl_completion_matches(text, my_generator)
It obviously throws an error: call to non-static member function without an object argument but I don't want to make the generator static and I can't find what arguments it should take, because I won't be able to access class members inside of it (I need keywordlist to generate keywords).
What would you suggest?

It's not easy to solve this one in a good way, since the normal solution is to solve it by having a static wrapper function where you pass the pointer to the class in as an argument.
Someone else may be able to come up with something better, but I think the solution is to have a global variable that is a pointer to the current ReadLine class instance - this could be a stack, so you can push a new one onto it, and then pop it to get back to the old one when that's done.
In the simple case, you'd have something like this:
ReadLine *currenReadLine = 0;
....
std::string ReadLine::exec(){
...
currentReadLine = this;
}
// declared as static in the class.
char ** ReadLine::my_completion(...)
{
return currentReadLine->actual_completion(...);
}
And a similar solution for the my_generator.

Related

String type alternative in C

I currently have a function defined in a header that looks like this
void foo::GetValue(std::string& str);
This function basically assigns a value to str. I need to come up with an alternative to str (basically, nothing that employs the standard library).
The implementation of the above function is like this in the .cpp file:
void foo::GetValue(std::string& str)
{
std::string s = bar.someMethod();
str = s;
}
I want to know what is the best/easiest option for replacing the header?
One approach I had was to replace std::string in the header file with char* so I would have this in the header:
void foo::GetValue(char* str);
And in the implementation I would have this:
void foo::GetValue(char* str)
{
std::string resp = bar.someMethod();
char* c = new char[resp.size() + 1];
std::copy(resp.begin(), resp.end(), c);
c[resp.size()] = '\0';
}
The problem with the above approach is that a lot of files are calling this function and they will need to modify their code. Also, they will need to free the above memory. Two concerns I have with this is that other callers to this function will need to do the following two things
Replace std::string being passed to the function with char*.
Free the char* when done using it.
These two items seem very costly to me to trust other callers to do.
Any suggestions on what I can do to solve this problem? Perhaps change the signature to something else? I would prefer if the caller still passes a string, however string.c_str() is a constant char pointer.
For a given C++ function like this:
std::string foo::GetValue(std::string& str)
{
return bar.someMethod(str);
}
Then your equivalent C code looks like this:
void foo_GetValue(char* str, char* res, size_t size)
{
std::string str_arg = str;
std::string result = bar.someMethod(str_arg);
strncpy(res, result.c_str(), size - 1);
res[size-1] = 0; // Ensure is NUL terminated
}
When calling from C:
void example() {
const BUFFER_LEN = 1024;
char buffer[BUFFER_LEN];
foo_GetValue("example", buffer, BUFFER_LEN);
}

What is the appropriate way to pass given vararg parameter to another function?

I've begun works on a hook/event system in C++. This system is supposed to handle all sorts of events as notified by other parts of the application.
The issue I've faced is with the way I want it to run.
Generally, I want it to be so that you call a specific function with all arguments you wish to pass on, and then that function handles calling all registered hooks of that specific event, passing them on the arguments, retrieving their result values and returning it to the original caller.
Generally, this is how it was supposed to look:
CHookReturn* bInitializationStatus = Hook::Run("Initialize", gGame);
CHookReturn* bThinkSuccessful = Hook::Run("Think");
However, I ran into one issue.
I set it up in such way that the Run function in the Hook namespace, calling the Run function of the CHookData_t structure, needs to pass on varargs. I couldn't find any other way. This is how it ended up:
union CHookReturn
{
const char* m_pszValue;
int m_iValue;
float m_flValue;
double m_dlValue;
bool m_bValue;
};
struct CHookData_t
{
virtual void Run(CHookReturn* ret, ...) = 0;
};
namespace Hook
{
std::unordered_map<const char*, std::unordered_map<const char*, CHookData_t*>> umHookList;
bool Add(const char*, const char*, CHookData_t*);
bool Exists(const char*, const char*);
bool Remove(const char*, const char*);
int Count(const char*);
CHookReturn* Run(const char*, ...);
};
CPP file segment of the Hook::Run function:
CHookReturn* Hook::Run(const char* eventName, ...)
{
// FIXME: Look into alternative execution.
// This code seems more like a workaround
// than what I originally wanted it to be.
int count = Hook::Count(eventName);
CHookReturn* returnValues = new CHookReturn[count];
int c = 0;
unordered_map<const char*, CHookData_t*>::iterator itr;
unordered_map<const char*, CHookData_t*> res;
res = umHookList.at(eventName);
va_list valist;
void* args;
va_copy(args, valist);
for (itr = res.begin(); itr != res.end(); itr++)
{
CHookReturn returnData;
itr->second->Run(&returnData, args);
returnValues[c] = returnData;
++c;
}
return returnValues;
}
The above code brings up two warnings which make me question if it is a good idea to execute it in this way, as well as whether there are any alternatives I should look into.
The warnings I received were:
Warning C6001 Using uninitialized memory 'valist'.
Warning C6386 Buffer overrun while writing to 'returnValues': the writable size is 'count*8' bytes, but '16' bytes might be written.
Is there a better way to do this?
Fixing your code using va_list:
struct CHookData_t
{
virtual ~CHookData_t() {}
virtual void Run(CHookReturn* ret, va_list arg) = 0;
};
namespace Hook
{
using HooksList = std::unordered_map<
std::string,
std::unordered_map<std::string, std::unique_ptr<CHookData_t>>;
HooksList umHookList;
...
}
std::vector<CHookReturn> Hook::Run(const std::string& eventName, ....)
{
va_list valist;
va_start(valist, eventName);
auto result = Hook::RunVarg(eventName, valist);
va_end(valist);
return result;
}
std::vector<CHookReturn> Hook::RunVarg(const std::string& eventName, va_list arg)
{
int count = Hook::Count(eventName);
std::vector<CHookReturn> returnValues(count);
size_t c = 0;
for (auto& item : umHookList.at(eventName))
{
va_list arg_copy;
va_copy(arg_copy, arg);
item.second->Run(&returnValues[c], arg_copy);
va_end(arg_copy);
++c;
}
return returnValues;
}
I have no idea what are arguments of Hook::Run what va_list points to, so I can't you provide nice C++ solution.
Note that va_copy is needed inside of loop, since some compilers (don't remembered which, possibly msvc) va_list behaves like a pointer and reading arguments from it will have impact on each iteration. On other compilers va_list behaves like a value and va_copy do not change anything.
offtopic: your code is to much C, you shouldn't use const char* but std::string or std::string_view if you are using C++17, instead va_args it would be better to use variadic template or std::initializer_list, avoid raw pointers in favor of std::unique_ptr and std::shared_ptr. I've tweaked your code a bit to cover that.
Also Hook should not be a namespace, by the look of functions and variables it contains it should be a class, so you should fix it too.

C++ Passing a function that's in a class to another function

I'm trying to use lua_pushcfunction (Using lua 5.2). I have the struct
class readFunctions {
private:
std::ifstream file;
public:
static int readAll(lua_State*);
};
int readFunctions::readAll(lua_State *L){
std::string line;
std::string nam;
while (std::getline(file, line)) {
nam = nam + line;
}
std::cout << nam;
return 1;
}
readFunctions hand;
I use lua_pushcfunction(lua_state, hand.readAll) and get error: argument of type 'int (readFunctions::)(lua_State*)' does not match 'lua_CFunction {aka int (*)(lua_State*)}'|
How would I pass a method from a class to a function?
Try
lua_pushcfunction(lua_state, & readFunctions::readAll);
readAll is static so you dont need an instance; and you need its address not just the function (a function is like a value, so you need to give pushcfunction its address). However I can't remember if compiler will accept int (readFunctions::*)(lua_State*) as a int (*)(lua_State*), I have a feeling it might not but can't test it right now.
If you don't want a static method but a regular method: the method is part of an object (class instance), so to call it you need a this pointer; that won't work. But what might work is to use your static readFunctions::readAll, but when you call that function, the first parameter can be a light user data that is the readFunctions instance that you want to call.

C++11 Function That Only Accepts String Literals?

I want to write a C++11 function that will only accept string literals as a parameter:
void f(const char* s) { static_assert(s is a string literal); ... }
That is:
f("foo"); // OK
char c = ...;
f(&c); // ERROR: Doesn't compile
string s = ...;
f(s.c_str()); // ERROR: Doesn't compile
etc
Is there anyway to implement this? The signature of the function is open to changes, as is adding the use of macros or any other language feature.
If this is not possible what is the closest approximation? (Can user-defined literals help in anyway?)
If not is there a platform specific way in GCC 4.7 / Linux ?
I think the closest you are going to get is this
template<int N>
void f(const char (&str)[N]){
...
}
It will compile with literals and arrays but not pointers.
An alternative might be to make a GCC extension to check at compile time that your particular function is only called with a literal string.
You could use MELT to extend GCC. MELT is a high-level domain specific language to extend the GCC compiler, and is very well suited for the kind of check you want.
Basically, you would add a new pass inside GCC and code that pass in MELT which would find every gimple which is a call to your function and check that the argument is indeed a literal string. The ex06 example on melt-examples should inspire you. Then subscribe to gcc-melt#googlegroups.com and ask your MELT specific questions there.
Of course, this is not a foolproof approach: the function could be called indirectly thru pointers, and it could e.g. have a partial literal string, e.g. f("hello world I am here"+(i%4)) is conceptually a call with some literal string (e.g. in .rodata segment), but not in the generated code nor in the gimple.
I use this :
// these are used to force constant, literal strings in sqfish binding names
// which allows to store/copy just the pointer without having to manage
// allocations and memory copies
struct _literalstring
{
// these functions are just for easy usage... not needed
// the struct can be empty
bool equal(_literalstring const *other) { return !strcmp((const char *)this, (const char *)other); }
bool equal(const char *other) { return !strcmp((const char *)this, other); }
const char *str(void) { return (const char *)this; }
bool empty(void) { return *(const char *)this == 0; }
};
typedef _literalstring *LITSTR;
constexpr LITSTR operator "" _LIT(const char *s, size_t) {
return (LITSTR)s;
}
Then you just declare your function like this :
void myFunc(LITSTR str)
{
printf("%s\n", str->str());
printf("%s\n", (const char *)str);
const char *aVar = str->str();
const char *another = (const char *)str;
}
And you call it like this:
myFunc("some text"_LIT);
If you do something like this:
myFunc("some text");
myFunc(aTextVariable);
you get a compiler error.

How to pass lua string(binary) to c++ using tolua++

I hava a class likeļ¼š
class SomeClass
{
void initFromBuffer(void* buffer,int length);
void initFromString(const std::string& str);
}
Using tolua++, got the binding like:
static int SomeClass_initFromBuffer00(lua_State* tolua_S)
{
SomeClass* self = (SomeClass*) tolua_tousertype(tolua_S,1,0);
void* buffer = ((void*) tolua_touserdata(tolua_S,2,0));
int length = ((int) tolua_tonumber(tolua_S,3,0));
self->initFromBuffer(buffer,length);
}
and:
static int SomeClass_initFromString00(lua_State* tolua_S)
{
SomeClass* self = (SomeClass*) tolua_tousertype(tolua_S,1,0);
const std::string str = ((const std::string) tolua_tocppstring(tolua_S,2,0));
self->initFromString(str);
tolua_pushcppstring(tolua_S,(const char*)str);
}
Now,i want to pass binary data from lua to c++,the binary has '\0' in it,so if i use initFromString to pass it, the binary data will be trimed. But if i use initFromBuffer to pass it, i got bad ptr at `void* buffer = ((void*) tolua_touserdata(tolua_S,2,0));, the pointer is null.
So, how could i pass binary string from lua to c++?
Maybe you should stop using Tolua's bad APIs and use plain Lua's actually good APIs. Both std::string and Lua strings are capable of storing embedded null characters. The only reason tolua_tocppstring causes truncation is because the function name is a lie. It doesn't convert it to a C++ string; it converts it to a C string, a const char*.
The correct answer is to use the proper API function:
std::string fromLuaStack(lua_State *lua, int stackIx)
{
size_t len;
const char *str = lua_tolstring(lua, stackIx, &len);
return std::string(str, len);
}
Similarly, you can use lua_pushlstring to push a std::string onto the stack.
It's unfortunate that Tolua doesn't have better documentation, as there may be a function to do this all directly. If there is, I couldn't find it.