`std::optional`: How to reduce redundant copies with rvalue reference and std::move() - c++17

In this code,
How many times would the generated string be copied for each case(case 1, case 2)?
Could anyone confirm my answers in the code body?
If so, can I tell case 2 is more efficient than case 1?
Or any other suggestions?
#include <optional>
#include <string>
std::optional<std::string> GenerateString() {
std::string s = "very long string";
return s;
}
class Message {
public:
Message(const std::string &s) : payload_{s} {}
Message(std::string &&s) : payload_{std::move(s)} {}
private:
std::string payload_;
};
int main() {
// case 1
const std::optional<std::string> &opt1 = GenerateString(); // no copy
const std::string &s1 = *opt1; // no copy
Message msg1{s1}; // copy: s1 -> payload_
// case 2
std::optional<std::string> &&opt2 = GenerateString(); // no copy
std::string &&s2 = std::move(*opt2); // no copy
Message msg2{std::move(s2)}; // no copy
return 0;
}

Related

Using fgets and strtok to read in data and create linked list

Need some help with reading in lines of data from a text file using the fgets and string tokenization commands, which will then be used to create a linked list. I've followed some examples I've found on Stack Overflow and other tutorial websites, but still cannot get the read function below to work properly in my program, it just causes it to crash. The data file has lines like this:
Zucchini, Squash, pound, 2.19, 45
Yellow, Squash, pound, 1.79, 15
Based on everything I've read, I believe I have the necessary code, but obviously I'm missing something. Also, I commented out one of the fields (the one for float price) as I'm not sure what to use to copy the float value from the data, as I cannot treat it as a string (the integer value right below it seems to let me get away with it in my compiler).
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// Struct for linked list node
struct produceItem
{
char produce[20];
char type[20];
char soldBy[20];
float price;
int quantityInStock;
struct produceItem *next;
};
// Function to read in data from file to
void read(struct produceItem **head)
{
struct produceItem *temp = NULL;
struct produceItem *right = NULL;
//char ch[3];
char line[50];
char *value;
FILE *data = fopen("RecitationFiveInput.txt", "r");
printf("Trying to open file RecitationFiveInput.txt\n");
if (data == NULL)
{
printf("Could not open file RecitationFiveInput.txt\n");
}
else
{
while(fgets(line, sizeof(line), data))
{
value = strtok(line, ", ");
strcpy(temp->produce, strdup(value));
value = strtok(NULL, ", ");
strcpy(temp->type, strdup(value));
value = strtok(NULL, ", ");
strcpy(temp->soldBy, strdup(value));
//value = strtok(NULL, ", ");
//strcpy(temp->price, strdup(value));
value = strtok(NULL, " \n");
strcpy(temp->quantityInStock, strdup(value));
temp->next = NULL;
if (*head == NULL)
{
*head = temp;
}
else
{
right = *head;
while(right->next != NULL)
{
right = right->next;
}
right->next = temp;
}
}
printf("Successfully opened file RecitationFiveInput.txt\n");
}
fclose(data);
return;
}
// Function to display the nodes of the linked list that contains the data from the data file
void display(struct produceItem *head)
{
int value = 1;
struct produceItem *temp = NULL;
temp = head;
printf("=============================================================================\n");
printf(" Item # Produce Type Sold By Price In Stock\n");
printf("=============================================================================\n");
if(temp == NULL)
{
return;
}
else
{
while(temp != NULL)
{
printf(" %d %s %s %s %lf %d\n", value, temp->produce, temp->type, temp->soldBy, temp->price, temp->quantityInStock);
value++;
temp = temp->next;
if(temp == NULL)
{
break;
}
}
}
return;
}
//Main function
int main()
{
int input = 0;
struct produceItem *head = NULL;
while(1)
{
printf("\nList Operations\n");
printf("=================\n");
printf("1. Stock Produce Department\n");
printf("2. Display Produce Inventory\n");
printf("3. Reverse Order of Produce Inventory\n");
printf("4. Export Produce Inventory\n");
printf("5. Exit Program\n");
printf("Enter your choice: ");
if(scanf("%d", &input) <= 0)
{
printf("Enter only an integer.\n");
exit(0);
}
else
{
switch(input)
{
case 1:
read(&head);
break;
case 2:
display(head);
break;
case 3:
//function
break;
case 4:
//function
break;
case 5:
printf("You have exited the program, Goodbye!\n");
return 0;
break;
default:
printf("Invalid option.\n");
}
}
}
return 0;
}
Never mind everyone, found the issue. The crashes were due to me not allocating memory for the temp pointer in the read me function.

Interfacing readline into Rust

I try to do this tutorial in rust, so far I have a lot of problems interfacing the C library into Rust.
C equivalent code:
#include <stdio.h>
#include <stdlib.h>
#include <editline/readline.h>
#include <editline/history.h>
int main(int argc, char** argv) {
/* Print Version and Exit Information */
puts("Lispy Version 0.0.0.0.1");
puts("Press Ctrl+c to Exit\n");
/* In a never ending loop */
while (1) {
/* Output our prompt and get input */
char* input = readline("lispy> ");
/* Add input to history */
add_history(input);
/* Echo input back to user */
printf("No you're a %s\n", input);
/* Free retrived input */
free(input);
}
return 0;
}
So far i got this:
extern crate libc;
use std::c_str;
#[link(name = "readline")]
extern {
fn readline (p: *const libc::c_char) -> *const libc::c_char;
}
fn rust_readline (prompt: &str) -> Option<Box<str>> {
let cprmt = prompt.to_c_str();
cprmt.with_ref(|c_buf| {
unsafe {
let ret = c_str::CString::new (readline (c_buf), true);
ret.as_str().map(|ret| ret.to_owned())
}
})
}
fn main() {
println!("Lispy Version 0.0.1");
println!("Press Ctrl+c to Exit.\n");
// I want to have "history" in Linux of this:
//
// loop {
// print!("lispy> ");
// let input = io::stdin().read_line().unwrap();
// print!("No you're a {}", input);
// }
loop {
let val = rust_readline ("lispy> ");
match val {
None => { break }
_ => {
let input = val.unwrap();
println!("No you're a {}", input);
}
}
}
}
Especifically, I'm having issues with rust_readline function, i don't understand very well what's doing inside.
Edit Cargo.toml, put this:
[dependencies.readline]
git = "https://github.com/shaleh/rust-readline"
Code corrected:
extern crate readline;
fn main() {
println!("Lispy Version 0.0.1");
println!("Press Ctrl+c to Exit.\n");
loop {
let input = readline::readline("lispy> ").unwrap();
readline::add_history(input.as_str());
println!("No you're a {}", input);
}
}
Happy Lisping :-) .
Funny thing is, that I found this question reading the very same book, but not including any book specific information in my search query.
There is now a crate for this. Facon's solution worked for me, but the prompt string always printed as garbage using that library, so I looked for another crate and found one working nicely. Here is an updated example:
cargo.toml:
[dependencies]
# https://crates.io/crates/rustyline
rustyline = "3.0.0"
main.rs:
extern crate rustyline;
use rustyline::error::ReadlineError;
use rustyline::Editor;
const HISTORY_FILENAME: &str = "history.txt";
fn main() {
println!("Lispy Version 0.0.1");
println!("Press Ctrl+c to Exit.\n");
// We create an editor for the readline history.
let mut readline_editor = Editor::<()>::new();
// And then load the history, if it exists.
if readline_editor.load_history(HISTORY_FILENAME).is_err() {
println!("No previous history.");
}
loop {
// We read some input from CLI.
let readline = readline_editor.readline("LISPY>> ");
// The reading of the input could fail, if a user uses special
// key combinations. So we match against the readline Result
// type. Result can either be some `Ok` or an some `Err`.
match readline {
Ok(line) => {
readline_editor.add_history_entry(line.as_ref());
println!("No, you are {}", line);
},
Err(ReadlineError::Interrupted) => {
println!("CTRL-C");
break
},
Err(ReadlineError::Eof) => {
println!("CTRL-D");
break
},
Err(err) => {
println!("Error: {:?}", err);
break
}
}
readline_editor.save_history(HISTORY_FILENAME).expect("Could not save to readline history.");
}
}

Lua 'require' but files are only in memory

Setting: I'm using Lua from a C/C++ environment.
I have several lua files on disk. Those are read into memory and some more memory-only lua files become available during runtime. Think e.g. of an editor, with additional unsaved lua files.
So, I have a list<identifier, lua_file_content> in memory. Some of these files have require statements in them. When I try to load all these files to a lua instance (currently via lua_dostring) I get attempt to call global require (a nil value).
Is there a possibility to provide a require function, which replaces the old one and just uses the provided in memory files (those files are on the C side)?
Is there another way of allowing require in these files without having the required files on disk?
An example would be to load the lua stdlib from memory only without altering it. (This is actually my test case.)
Instead of replacing require, why not add a function to package.loaders? The code is nearly the same.
int my_loader(lua_State* state) {
// get the module name
const char* name = lua_tostring(state);
// find if you have such module loaded
if (mymodules.find(name) != mymodules.end())
{
luaL_loadbuffer(state, buffer, size, name);
// the chunk is now at the top of the stack
return 1;
}
// didn't find anything
return 0;
}
// When you load the lua state, insert this into package.loaders
http://www.lua.org/manual/5.1/manual.html#pdf-package.loaders
A pretty straightforward C++ function that would mimic require could be: (pseudocode)
int my_require(lua_State* state) {
// get the module name
const char* name = lua_tostring(state);
// find if you have such module loaded
if (mymodules.find(name) != mymodules.end())
luaL_loadbuffer(state, buffer, size, name);
// the chunk is now at the top of the stack
lua_call(state)
return 1;
}
Expose this function to Lua as require and you're good to go.
I'd also like to add that to completely mimic require's behaviour, you'd probably need to take care of package.loaded, to avoid the code to be loaded twice.
There is no package.loaders in lua 5.2
It called package.searchers now.
#include <stdio.h>
#include <string>
#include <lua.hpp>
std::string module_script;
int MyLoader(lua_State *L)
{
const char *name = luaL_checkstring(L, 1); // Module name
// std::string result = SearchScript(name); // Search your database.
std::string result = module_script; // Just for demo.
if( luaL_loadbuffer(L, result.c_str(), result.size(), name) )
{
printf("%s", lua_tostring(L, -1));
lua_pop(L, 1);
}
return 1;
}
void SetLoader(lua_State* L)
{
lua_register(L, "my_loader", MyLoader);
std::string str;
// str += "table.insert(package.loaders, 2, my_loader) \n"; // Older than lua v5.2
str += "table.insert(package.searchers, 2, my_loader) \n";
luaL_dostring(L, str.c_str());
}
void SetModule()
{
std::string str;
str += "print([[It is add.lua]]) \n";
str += "return { func = function() print([[message from add.lua]]) end } \n";
module_script=str;
}
void LoadMainScript(lua_State* L)
{
std::string str;
str += "dev = require [[add]] \n";
str += "print([[It is main.lua]]) \n";
str += "dev.func() \n";
if ( luaL_loadbuffer(L, str.c_str(), str.size(), "main") )
{
printf("%s", lua_tostring(L, -1));
lua_pop(L, 1);
return;
}
}
int main()
{
lua_State* L = luaL_newstate();
luaL_openlibs(L);
SetModule(L); // Write down module in memory. Lua not load it yet.
SetLoader(L);
LoadMainScript(L);
lua_pcall(L,0,0,0);
lua_close(L);
return 0;
}

pointers and linked list with shared memory

I want to get 2 programs to communicate, one (server) would store datas, and the other (client) would just access it.
I'll have to use a linked list to store datas because it won't stop storing, and then I was wondering if I could access to the whole linked list if only the first node is shared in memory.
What I mean is… are we allowed to access from the client program to the memory pointed by a shared pointer?
Sorry it seems obvious that we can not, so should I store my linked list into the shared memory, or do you think that would be awkward?
Because if I do so, I'll have to declare a shared memory for every node right?
So, to add shared memory to both programs I need the same keys, but I don't know how many keys there will be, and I can't just store it for both programs, unless I would have had already a linked list…
so I used a very very VERY awkward method that I don't even know if it works right, but I wish you can tell, which is to use ftok that is supposed to take an (url,pid) and return a key. So I assumed it would send the exact same key if I used the same url and pid, using a fake pid starting from 0 that I would increment for every element I add to the linked list… what do you think about it? Any other way to do it which would seem less… crap?
typedef struct s_shared_elem
{
char c;
struct s_shared_elem* next;
struct s_shared_elem* previous;
}shared_elem;
typedef struct s_shared_list
{
s_shared_elem* first;
s_shared_elem* last;
}shared_list;
int forthekey = 0;
char* url="/home/toor/Projet_cgi/";
shared_elem* shared_malloc(int pid, const char* url)
{
shared_elem* shm;
int shmid;
int key=ftok(url,pid);
if((shmid=shmget(key,1,IPC_CREAT | 0666)) < 0)
{
perror("shmget");
exit(1);
}
if ((shm = shmat(shmid,NULL,0)) == (shared_elem*)-1)
{
perror("shmat");
exit(1);
}
return shm;
}
void Init_shared_list(shared_list* liste)
{
liste->first = NULL;
liste->last = NULL;
}
void Add_elem(shared_list* liste)
{
shared_elem* new = shared_malloc(pid,url);
new->next = NULL;
new->previous = liste->last;
if(liste->first == NULL)
{
liste->first = new;
liste->last = new;
}
else
{
liste->last->next = new;
liste->last = new;
}
forthekey++;
}
void shared_free(shared_elem* todelete,int pid, const char* url)
{
shared_elem* shm;
int shmid;
int key=ftok(url,pid);
if((shmid=shmget(key,1,IPC_CREAT | 0666)) < 0)
{
perror("shmget");
exit(1);
}
shmdt(todelete);
shmctl(shmid,IPC_RMID,NULL);
forthekey--;
}
void Delete_list(shared_list* liste)
{
while(liste->last != liste->first)
{
shared_elem* tmp=liste->last;
liste->last=liste->last->previous;
Shared_free(tmp,pid,url);
}
Shared_free(liste->first,pid,url);
}
In share memory you can insert a whole linked list. It is useful in many cases. You do not need to create a linked list of share memory (e.g. using previous key, next key ). All you need to copy each node of linked list to the shared memory.
for example .....
process2.c
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/shm.h>
int main(int argc, char *argv[])
{
int shmid,i;
node *data;
if ((shmid = shmget(10, SHM_SIZE, 0644 | IPC_CREAT)) == -1) {
perror("shmget");
exit(1);
}
data = (node *)shmat(shmid, (void *)0, 0); // node is linked list
for(i=0;i<2;i++)
printf("%d\n",(data++)->item_code);
if (shmdt(data) == -1) {
perror("shmdt");
exit(1);
}
return 0;
}
process1.c
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/shm.h>
int main(int argc, char *argv[])
{
node *SELL=NULL; // node is linked list (structure) SELL is header
insert(&SELL,"Soap",1,12.5,10);
insert(&SELL,"Pen",2,20.75,8);
display(SELL);
int shmid,i;
node *data;
if ((shmid = shmget(10, 2*sizeof(node), 0644 | IPC_CREAT)) == -1) {
perror("shmget");
exit(1);
}
data = (node *) shmat(shmid, (void *)0, 0);
for(i=0;i<2;i++)
{
*(data++)=*SELL;
SELL=SELL->next;
}
getchar();
if (shmdt(data) == -1) {
perror("shmdt");
exit(1);
}
shmctl(shmid, IPC_RMID, NULL);
return 0;
}
Run process1.c 1st then run process2.c

How does a Lex & Yacc parser output values?

So for a project that I'm working on, I am using Lex and Yacc to parse a FTP configuration file. The configuration files look something like this:
global {
num_daemons = 10
etc = /etc/ftpd
};
host "ftp-1.foobar.com" {
ftproot = /var/ftp/server1
max_out_bandwidth = 20.7
};
host "ftp-2.foobar.com" {
ftproot = /var/ftp/server2
exclude = /var/ftp/server2/private
};
host "ftp-3.foobar.com" {
ftproot = /var/ftp/server3
};
Now, my question is, how do I obtain this information in a usable way? Let's say I wanted to put things like the address after the host token into a struct. How would I do that? Also, how would I simply print out the values that I've parsed to the command line? Also, to run it, do I just cat the config file and pipe in the compiled c program? Thanks in advance for any help!
Here is my code:
%{
// tokens.l
#include <stdio.h>
#include <stdlib.h>
#include "y.tab.h"
int yyparse();
%}
%option noyywrap
%x OPTION
%x OPTID
%%
<INITIAL>global { return GLOBAL; }
<INITIAL>host { return HOST; }
<INITIAL>"[a-zA-z1-9./-]+" { return NAME; }
<INITIAL>\{ { return CURLY_OPEN; BEGIN OPTION; }
<INITIAL>\n { return EOLN; }
<INITIAL><<EOF>> { return EOFTOK; }
<OPTION>[a-zA-z1-9./-_]+ { return ID_NAME; BEGIN OPTID; }
<OPTION>[\t] {}
<OPTION>[\};] { return OPTION_CLOSE; BEGIN INITIAL;}
<OPTID>[a-zA-z1-9./-]+ { return ID_STRING; BEGIN OPTION; }
<OPTID>[0-9.]+ { return ID_NUM; BEGIN OPTION; }
<OPTID>[\n] { return EOLN; }
%%
int main(int argc, char **argv) {
// Where I am confused..
}
and my yacc file:
%{
// parse.y
#include <stdio.h>
#include <stdlib.h>
int yyerror(char *);
int yylex(void);
%}
%token ERROR EOLN EOFTOK
%token OPTION_CLOSE GLOBAL HOST NAME ID_NAME ID_STRING ID_NUM CURLY_OPEN
%%
input
: lines EOFTOK { YYACCEPT; }
;
lines
:
| lines line
;
line
: option
| opident
| OPTION_CLOSE
;
option
: GLOBAL CURLY_OPEN
| HOST NAME CURLY_OPEN
;
opident
: ID_NAME '=' ID_STRING
| ID_NAME '=' ID_NUM
;
%%
int yyerror(char *msg) {}
You would generally have variables which were accessible and set up before calling the parser, like a linked list of key/value pairs:
typedef struct sNode {
char *key;
char *val;
struct sNode *next;
} tNode;
tNode *lookupHead = NULL;
Then, in your Yacc code, something like:
opident
: ID_NAME '=' ID_STRING { addLookupStr (lookupHead, $1, $3); }
| ID_NAME '=' ID_NUM { other function call here }
;
This would basically execute that code as the rules are found (replacing the $ variables with the item in the rule, $1 is the value for the ID_NAME token, $2 is the =, and so on).
The function would be something like:
void addLookupStr (char *newkey, char *newval) {
// Check for duplicate keys, then attempt to add. All premature returns
// should also be logging errors and setting error flags as needed.
tNode *curr = lookupHead;
while (curr != NULL) {
if (strcmp (curr->key, newkey) == 0)
return;
curr = curr->next;
}
if ((curr = malloc (sizeof (tNode))) == NULL)
return;
if ((curr->key = strdup (newkey)) == NULL) {
free (curr);
return;
}
if ((curr->val = strdup (newval)) == NULL) {
free (curr->newkey);
free (curr);
return;
}
// All possibly-failing ops complete, insert at head of list.
curr->next = lookupHead;
lookupHead = curr;
}

Resources