Library for managing CLI flags
Clash Royale CLAN TAG#URR8PPP
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty margin-bottom:0;
up vote
3
down vote
favorite
I'm pretty new to C, started learning it less than a month ago, the only language I had previous experience was Javascript.
Anyways, I wrote a library for dealing with CLI flags. It's not a serious project by any means, I wrote it for practice and fun.
It's composed of a source file and a header file (with declarations etc..). I'll list these functions then I'll try to describe them briefly. I didn't use array subscripting as I'm trying to gain a serious understanding of how pointers work etc...
libflagutil.c
:
#include "../flagutil.h" //make sure definitions match declarations and protos etc..
#include "../butil.h" //terminal text styling
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
bool flag_present(int argc, char **argv, const char *flag)
/* a single flag is defined as present IF:
- an arg that exactly matches the provided `flag` string is found
- an arg that exactly matches the provided `flag` string BUT includes an `=` (and optionally somed data)
after it is found
*/
bool present = false;
for(char **cur_flag = argv; cur_flag < argv + argc; cur_flag++)
return present;
const Flag *flag_get(int argc, char **argv, const char *flag) !(*(flag + 1)))
printf("Invalid flag structure for flag " bold("%s") " passed to get_flag.n", flag);
return NULL;
static Flag internal; //static buffer of last-fetched flag
for(char **cur_flag = argv; cur_flag < argv + argc; cur_flag++)
if(strncmp(flag, *cur_flag, strlen(flag)) == 0)
char *char_after_flag = *cur_flag + strlen(flag);
if(*char_after_flag == '=' && *(char_after_flag + 1) != '')
internal.data = char_after_flag + 1;
internal.location = (const char **) cur_flag;
strncpy(internal.name, flag, strlen(flag) + 1);
else if(cur_flag + 1 && **(cur_flag + 1) != '-')
internal.data = *(cur_flag + 1);
internal.location = (const char **) cur_flag;
strncpy(internal.name, flag, strlen(flag) + 1);
return &internal;
void flag_startswith(int argc, char **argv, const char *start_string, Flag *storage)
/* assumes that storage is large enough to accomodate all valid flags */
//TODO: handle `=` within flag_string, for now function doesn't work with those flags
for(char **flag = argv; flag < argv + argc; flag++)
if(**flag != '-')
continue;
//First char isn't a `-`, skip arg
if(*(*flag + 1) == '-')
if(strncmp(*flag + 2, start_string, strlen(start_string)) == 0)
char flag_string[2 + strlen(*flag + 2) + 1];
strcpy(flag_string, "--");
strcpy(flag_string + 2, *flag + 2);
*storage = *f_get(flag_string);
else
if(strncmp(*flag + 1, start_string, strlen(start_string)) == 0)
char flag_string[1 + strlen(*flag + 1) + 1];
strcpy(flag_string, "-");
strcpy(flag_string + 1, *flag + 1);
*storage = *f_get(flag_string);
storage++;
char *flag_nextarg(signed int argc, char **argv)
//oversimplify fetching args from argv... (kinda useless)
static size_t counter = 0;
return *(argv + (counter++));
flagutil.h
:
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
#include "./butil.h"
#pragma once
/*define these yourself if you'd like to use short version but use non-"standard"
names for main's 2 args
*/
#ifndef FLAGUTIL_ARGC_NAME
#define FLAGUTIL_ARGC_NAME argc
#endif
#ifndef FLAGUTIL_ARGV_NAME
#define FLAGUTIL_ARGV_NAME argv
#endif
/* expose functions as short versions taking less arguments, for easier usage */
#define f_present(s) flag_present(FLAGUTIL_ARGC_NAME, FLAGUTIL_ARGV_NAME, s)
#define f_get(s) flag_get(FLAGUTIL_ARGC_NAME, FLAGUTIL_ARGV_NAME, s)
#define f_startswith(s, g) flag_startswith(FLAGUTIL_ARGC_NAME, FLAGUTIL_ARGV_NAME, s, g);
#define f_nextarg() flag_nextarg(FLAGUTIL_ARGC_NAME, FLAGUTIL_ARGV_NAME)
struct flag
char name[100];
const char *data;
const char **location; //actual pointer within argv
;
typedef struct flag Flag;
//prototypes:
bool flag_present(int, char **, const char *);
const Flag *flag_get(int, char **, const char *);
void flag_startswith(int, char **, const char *, Flag *);
char *flag_easyArg(int, char **);
Currently all of the functions accept argc
and argv
as their first 2 arguments, but flagutil.h
exposes these functions as macros with shorter names taking only the necessary arguments, and automatically feeding argc
and argv
(also defined as macros for compatibility in case of non-standard parameter names inside main
).
All of the functions (except flag_startswith
) take flag names in the form -flagName
or --flagName
.
Data is passed to flags in the form of -flagName=DATA
or -flagName DATA
.
bool flag_present(...)
: Returns true
if provided flag exists within argv
, false otherwise.
const Flag *flag_get(...)
: Returns a pointer to an internal static struct which holds data about a certain flag. The actual struct is defined in flagutil.h
and holds the name of the flag, its data (if it has any) and a pointer to its location inside of argv
.
void flag_startswith(...)
: Stores struct representations of all flags that start with start_string
inside of provided array.
char *flag_nextarg(...)
: Pretty pointless, wrote it for fun.
I realize some of these functions are unsafe, sometimes broken etc.. but so far they get the job done and I'll be looking to improve them further. I'm looking for general advice, best practices, stuff to avoid, etc... I've tested it only with GCC and linux64 and it compiles without any warnings (-Wall, -Wextra
).
Please disregard the use of bil()
and bold()
, they're macros for styling text inside the terminal..
c library
add a comment |Â
up vote
3
down vote
favorite
I'm pretty new to C, started learning it less than a month ago, the only language I had previous experience was Javascript.
Anyways, I wrote a library for dealing with CLI flags. It's not a serious project by any means, I wrote it for practice and fun.
It's composed of a source file and a header file (with declarations etc..). I'll list these functions then I'll try to describe them briefly. I didn't use array subscripting as I'm trying to gain a serious understanding of how pointers work etc...
libflagutil.c
:
#include "../flagutil.h" //make sure definitions match declarations and protos etc..
#include "../butil.h" //terminal text styling
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
bool flag_present(int argc, char **argv, const char *flag)
/* a single flag is defined as present IF:
- an arg that exactly matches the provided `flag` string is found
- an arg that exactly matches the provided `flag` string BUT includes an `=` (and optionally somed data)
after it is found
*/
bool present = false;
for(char **cur_flag = argv; cur_flag < argv + argc; cur_flag++)
return present;
const Flag *flag_get(int argc, char **argv, const char *flag) !(*(flag + 1)))
printf("Invalid flag structure for flag " bold("%s") " passed to get_flag.n", flag);
return NULL;
static Flag internal; //static buffer of last-fetched flag
for(char **cur_flag = argv; cur_flag < argv + argc; cur_flag++)
if(strncmp(flag, *cur_flag, strlen(flag)) == 0)
char *char_after_flag = *cur_flag + strlen(flag);
if(*char_after_flag == '=' && *(char_after_flag + 1) != '')
internal.data = char_after_flag + 1;
internal.location = (const char **) cur_flag;
strncpy(internal.name, flag, strlen(flag) + 1);
else if(cur_flag + 1 && **(cur_flag + 1) != '-')
internal.data = *(cur_flag + 1);
internal.location = (const char **) cur_flag;
strncpy(internal.name, flag, strlen(flag) + 1);
return &internal;
void flag_startswith(int argc, char **argv, const char *start_string, Flag *storage)
/* assumes that storage is large enough to accomodate all valid flags */
//TODO: handle `=` within flag_string, for now function doesn't work with those flags
for(char **flag = argv; flag < argv + argc; flag++)
if(**flag != '-')
continue;
//First char isn't a `-`, skip arg
if(*(*flag + 1) == '-')
if(strncmp(*flag + 2, start_string, strlen(start_string)) == 0)
char flag_string[2 + strlen(*flag + 2) + 1];
strcpy(flag_string, "--");
strcpy(flag_string + 2, *flag + 2);
*storage = *f_get(flag_string);
else
if(strncmp(*flag + 1, start_string, strlen(start_string)) == 0)
char flag_string[1 + strlen(*flag + 1) + 1];
strcpy(flag_string, "-");
strcpy(flag_string + 1, *flag + 1);
*storage = *f_get(flag_string);
storage++;
char *flag_nextarg(signed int argc, char **argv)
//oversimplify fetching args from argv... (kinda useless)
static size_t counter = 0;
return *(argv + (counter++));
flagutil.h
:
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
#include "./butil.h"
#pragma once
/*define these yourself if you'd like to use short version but use non-"standard"
names for main's 2 args
*/
#ifndef FLAGUTIL_ARGC_NAME
#define FLAGUTIL_ARGC_NAME argc
#endif
#ifndef FLAGUTIL_ARGV_NAME
#define FLAGUTIL_ARGV_NAME argv
#endif
/* expose functions as short versions taking less arguments, for easier usage */
#define f_present(s) flag_present(FLAGUTIL_ARGC_NAME, FLAGUTIL_ARGV_NAME, s)
#define f_get(s) flag_get(FLAGUTIL_ARGC_NAME, FLAGUTIL_ARGV_NAME, s)
#define f_startswith(s, g) flag_startswith(FLAGUTIL_ARGC_NAME, FLAGUTIL_ARGV_NAME, s, g);
#define f_nextarg() flag_nextarg(FLAGUTIL_ARGC_NAME, FLAGUTIL_ARGV_NAME)
struct flag
char name[100];
const char *data;
const char **location; //actual pointer within argv
;
typedef struct flag Flag;
//prototypes:
bool flag_present(int, char **, const char *);
const Flag *flag_get(int, char **, const char *);
void flag_startswith(int, char **, const char *, Flag *);
char *flag_easyArg(int, char **);
Currently all of the functions accept argc
and argv
as their first 2 arguments, but flagutil.h
exposes these functions as macros with shorter names taking only the necessary arguments, and automatically feeding argc
and argv
(also defined as macros for compatibility in case of non-standard parameter names inside main
).
All of the functions (except flag_startswith
) take flag names in the form -flagName
or --flagName
.
Data is passed to flags in the form of -flagName=DATA
or -flagName DATA
.
bool flag_present(...)
: Returns true
if provided flag exists within argv
, false otherwise.
const Flag *flag_get(...)
: Returns a pointer to an internal static struct which holds data about a certain flag. The actual struct is defined in flagutil.h
and holds the name of the flag, its data (if it has any) and a pointer to its location inside of argv
.
void flag_startswith(...)
: Stores struct representations of all flags that start with start_string
inside of provided array.
char *flag_nextarg(...)
: Pretty pointless, wrote it for fun.
I realize some of these functions are unsafe, sometimes broken etc.. but so far they get the job done and I'll be looking to improve them further. I'm looking for general advice, best practices, stuff to avoid, etc... I've tested it only with GCC and linux64 and it compiles without any warnings (-Wall, -Wextra
).
Please disregard the use of bil()
and bold()
, they're macros for styling text inside the terminal..
c library
1
Few more things but something eye catching is thatstatic
field. Imagine you're writing acurl
clone and you havestruct flag* method = flag_get(argc, argv, "X"); struct flag* body = flag_get(argc, argv, "d");
Now you want to check if user is trying to do a GET with a body:if (strncmp(method->data, "GET"...) && strlen(body->data))
...it fails because bothmethod
andbody
points to the same data. Here I'd happily accept to return newly allocated memory (leaving the caller with its ownership unless you want to accept astruct flag* flag
parameter).
â Adriano Repetti
Jul 30 at 11:59
@Adriano Repetti Thanks. I usually dereference the pointer returned byflag_get
and store the data in a new struct:const struct flag method = *f_get(...)
. Iniyially I got the idea for using a static buffer from thegmtime
function intime.h
. Don't know if it's good practice tho. Thanks for the advice!
â Bogdan M.
Jul 30 at 12:12
It's not a bad practice but it's error-prone. You force the caller to be aware it has to make a copy and the function is not reentrant nor thread-safe (not that it matters in this case). More than that you're returningflag*
which is notconst
and anyway, even if it was, it's a const pointer to variable data. Unless strongly required (and for a cli parser you shouldn't have any strict performance requirement) it's usually better to be on the safe side (a quick search ofgmtime()
on SO wil give you tons of questions related to this issue...)
â Adriano Repetti
Jul 30 at 12:33
Yeah I posted a question about gmtime on SO which is how I learned about it's behavior in the first place.
â Bogdan M.
Jul 30 at 12:36
add a comment |Â
up vote
3
down vote
favorite
up vote
3
down vote
favorite
I'm pretty new to C, started learning it less than a month ago, the only language I had previous experience was Javascript.
Anyways, I wrote a library for dealing with CLI flags. It's not a serious project by any means, I wrote it for practice and fun.
It's composed of a source file and a header file (with declarations etc..). I'll list these functions then I'll try to describe them briefly. I didn't use array subscripting as I'm trying to gain a serious understanding of how pointers work etc...
libflagutil.c
:
#include "../flagutil.h" //make sure definitions match declarations and protos etc..
#include "../butil.h" //terminal text styling
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
bool flag_present(int argc, char **argv, const char *flag)
/* a single flag is defined as present IF:
- an arg that exactly matches the provided `flag` string is found
- an arg that exactly matches the provided `flag` string BUT includes an `=` (and optionally somed data)
after it is found
*/
bool present = false;
for(char **cur_flag = argv; cur_flag < argv + argc; cur_flag++)
return present;
const Flag *flag_get(int argc, char **argv, const char *flag) !(*(flag + 1)))
printf("Invalid flag structure for flag " bold("%s") " passed to get_flag.n", flag);
return NULL;
static Flag internal; //static buffer of last-fetched flag
for(char **cur_flag = argv; cur_flag < argv + argc; cur_flag++)
if(strncmp(flag, *cur_flag, strlen(flag)) == 0)
char *char_after_flag = *cur_flag + strlen(flag);
if(*char_after_flag == '=' && *(char_after_flag + 1) != '')
internal.data = char_after_flag + 1;
internal.location = (const char **) cur_flag;
strncpy(internal.name, flag, strlen(flag) + 1);
else if(cur_flag + 1 && **(cur_flag + 1) != '-')
internal.data = *(cur_flag + 1);
internal.location = (const char **) cur_flag;
strncpy(internal.name, flag, strlen(flag) + 1);
return &internal;
void flag_startswith(int argc, char **argv, const char *start_string, Flag *storage)
/* assumes that storage is large enough to accomodate all valid flags */
//TODO: handle `=` within flag_string, for now function doesn't work with those flags
for(char **flag = argv; flag < argv + argc; flag++)
if(**flag != '-')
continue;
//First char isn't a `-`, skip arg
if(*(*flag + 1) == '-')
if(strncmp(*flag + 2, start_string, strlen(start_string)) == 0)
char flag_string[2 + strlen(*flag + 2) + 1];
strcpy(flag_string, "--");
strcpy(flag_string + 2, *flag + 2);
*storage = *f_get(flag_string);
else
if(strncmp(*flag + 1, start_string, strlen(start_string)) == 0)
char flag_string[1 + strlen(*flag + 1) + 1];
strcpy(flag_string, "-");
strcpy(flag_string + 1, *flag + 1);
*storage = *f_get(flag_string);
storage++;
char *flag_nextarg(signed int argc, char **argv)
//oversimplify fetching args from argv... (kinda useless)
static size_t counter = 0;
return *(argv + (counter++));
flagutil.h
:
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
#include "./butil.h"
#pragma once
/*define these yourself if you'd like to use short version but use non-"standard"
names for main's 2 args
*/
#ifndef FLAGUTIL_ARGC_NAME
#define FLAGUTIL_ARGC_NAME argc
#endif
#ifndef FLAGUTIL_ARGV_NAME
#define FLAGUTIL_ARGV_NAME argv
#endif
/* expose functions as short versions taking less arguments, for easier usage */
#define f_present(s) flag_present(FLAGUTIL_ARGC_NAME, FLAGUTIL_ARGV_NAME, s)
#define f_get(s) flag_get(FLAGUTIL_ARGC_NAME, FLAGUTIL_ARGV_NAME, s)
#define f_startswith(s, g) flag_startswith(FLAGUTIL_ARGC_NAME, FLAGUTIL_ARGV_NAME, s, g);
#define f_nextarg() flag_nextarg(FLAGUTIL_ARGC_NAME, FLAGUTIL_ARGV_NAME)
struct flag
char name[100];
const char *data;
const char **location; //actual pointer within argv
;
typedef struct flag Flag;
//prototypes:
bool flag_present(int, char **, const char *);
const Flag *flag_get(int, char **, const char *);
void flag_startswith(int, char **, const char *, Flag *);
char *flag_easyArg(int, char **);
Currently all of the functions accept argc
and argv
as their first 2 arguments, but flagutil.h
exposes these functions as macros with shorter names taking only the necessary arguments, and automatically feeding argc
and argv
(also defined as macros for compatibility in case of non-standard parameter names inside main
).
All of the functions (except flag_startswith
) take flag names in the form -flagName
or --flagName
.
Data is passed to flags in the form of -flagName=DATA
or -flagName DATA
.
bool flag_present(...)
: Returns true
if provided flag exists within argv
, false otherwise.
const Flag *flag_get(...)
: Returns a pointer to an internal static struct which holds data about a certain flag. The actual struct is defined in flagutil.h
and holds the name of the flag, its data (if it has any) and a pointer to its location inside of argv
.
void flag_startswith(...)
: Stores struct representations of all flags that start with start_string
inside of provided array.
char *flag_nextarg(...)
: Pretty pointless, wrote it for fun.
I realize some of these functions are unsafe, sometimes broken etc.. but so far they get the job done and I'll be looking to improve them further. I'm looking for general advice, best practices, stuff to avoid, etc... I've tested it only with GCC and linux64 and it compiles without any warnings (-Wall, -Wextra
).
Please disregard the use of bil()
and bold()
, they're macros for styling text inside the terminal..
c library
I'm pretty new to C, started learning it less than a month ago, the only language I had previous experience was Javascript.
Anyways, I wrote a library for dealing with CLI flags. It's not a serious project by any means, I wrote it for practice and fun.
It's composed of a source file and a header file (with declarations etc..). I'll list these functions then I'll try to describe them briefly. I didn't use array subscripting as I'm trying to gain a serious understanding of how pointers work etc...
libflagutil.c
:
#include "../flagutil.h" //make sure definitions match declarations and protos etc..
#include "../butil.h" //terminal text styling
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
bool flag_present(int argc, char **argv, const char *flag)
/* a single flag is defined as present IF:
- an arg that exactly matches the provided `flag` string is found
- an arg that exactly matches the provided `flag` string BUT includes an `=` (and optionally somed data)
after it is found
*/
bool present = false;
for(char **cur_flag = argv; cur_flag < argv + argc; cur_flag++)
return present;
const Flag *flag_get(int argc, char **argv, const char *flag) !(*(flag + 1)))
printf("Invalid flag structure for flag " bold("%s") " passed to get_flag.n", flag);
return NULL;
static Flag internal; //static buffer of last-fetched flag
for(char **cur_flag = argv; cur_flag < argv + argc; cur_flag++)
if(strncmp(flag, *cur_flag, strlen(flag)) == 0)
char *char_after_flag = *cur_flag + strlen(flag);
if(*char_after_flag == '=' && *(char_after_flag + 1) != '')
internal.data = char_after_flag + 1;
internal.location = (const char **) cur_flag;
strncpy(internal.name, flag, strlen(flag) + 1);
else if(cur_flag + 1 && **(cur_flag + 1) != '-')
internal.data = *(cur_flag + 1);
internal.location = (const char **) cur_flag;
strncpy(internal.name, flag, strlen(flag) + 1);
return &internal;
void flag_startswith(int argc, char **argv, const char *start_string, Flag *storage)
/* assumes that storage is large enough to accomodate all valid flags */
//TODO: handle `=` within flag_string, for now function doesn't work with those flags
for(char **flag = argv; flag < argv + argc; flag++)
if(**flag != '-')
continue;
//First char isn't a `-`, skip arg
if(*(*flag + 1) == '-')
if(strncmp(*flag + 2, start_string, strlen(start_string)) == 0)
char flag_string[2 + strlen(*flag + 2) + 1];
strcpy(flag_string, "--");
strcpy(flag_string + 2, *flag + 2);
*storage = *f_get(flag_string);
else
if(strncmp(*flag + 1, start_string, strlen(start_string)) == 0)
char flag_string[1 + strlen(*flag + 1) + 1];
strcpy(flag_string, "-");
strcpy(flag_string + 1, *flag + 1);
*storage = *f_get(flag_string);
storage++;
char *flag_nextarg(signed int argc, char **argv)
//oversimplify fetching args from argv... (kinda useless)
static size_t counter = 0;
return *(argv + (counter++));
flagutil.h
:
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
#include "./butil.h"
#pragma once
/*define these yourself if you'd like to use short version but use non-"standard"
names for main's 2 args
*/
#ifndef FLAGUTIL_ARGC_NAME
#define FLAGUTIL_ARGC_NAME argc
#endif
#ifndef FLAGUTIL_ARGV_NAME
#define FLAGUTIL_ARGV_NAME argv
#endif
/* expose functions as short versions taking less arguments, for easier usage */
#define f_present(s) flag_present(FLAGUTIL_ARGC_NAME, FLAGUTIL_ARGV_NAME, s)
#define f_get(s) flag_get(FLAGUTIL_ARGC_NAME, FLAGUTIL_ARGV_NAME, s)
#define f_startswith(s, g) flag_startswith(FLAGUTIL_ARGC_NAME, FLAGUTIL_ARGV_NAME, s, g);
#define f_nextarg() flag_nextarg(FLAGUTIL_ARGC_NAME, FLAGUTIL_ARGV_NAME)
struct flag
char name[100];
const char *data;
const char **location; //actual pointer within argv
;
typedef struct flag Flag;
//prototypes:
bool flag_present(int, char **, const char *);
const Flag *flag_get(int, char **, const char *);
void flag_startswith(int, char **, const char *, Flag *);
char *flag_easyArg(int, char **);
Currently all of the functions accept argc
and argv
as their first 2 arguments, but flagutil.h
exposes these functions as macros with shorter names taking only the necessary arguments, and automatically feeding argc
and argv
(also defined as macros for compatibility in case of non-standard parameter names inside main
).
All of the functions (except flag_startswith
) take flag names in the form -flagName
or --flagName
.
Data is passed to flags in the form of -flagName=DATA
or -flagName DATA
.
bool flag_present(...)
: Returns true
if provided flag exists within argv
, false otherwise.
const Flag *flag_get(...)
: Returns a pointer to an internal static struct which holds data about a certain flag. The actual struct is defined in flagutil.h
and holds the name of the flag, its data (if it has any) and a pointer to its location inside of argv
.
void flag_startswith(...)
: Stores struct representations of all flags that start with start_string
inside of provided array.
char *flag_nextarg(...)
: Pretty pointless, wrote it for fun.
I realize some of these functions are unsafe, sometimes broken etc.. but so far they get the job done and I'll be looking to improve them further. I'm looking for general advice, best practices, stuff to avoid, etc... I've tested it only with GCC and linux64 and it compiles without any warnings (-Wall, -Wextra
).
Please disregard the use of bil()
and bold()
, they're macros for styling text inside the terminal..
c library
edited Jul 30 at 5:32
200_success
123k14143398
123k14143398
asked Jul 29 at 21:55
Bogdan M.
1425
1425
1
Few more things but something eye catching is thatstatic
field. Imagine you're writing acurl
clone and you havestruct flag* method = flag_get(argc, argv, "X"); struct flag* body = flag_get(argc, argv, "d");
Now you want to check if user is trying to do a GET with a body:if (strncmp(method->data, "GET"...) && strlen(body->data))
...it fails because bothmethod
andbody
points to the same data. Here I'd happily accept to return newly allocated memory (leaving the caller with its ownership unless you want to accept astruct flag* flag
parameter).
â Adriano Repetti
Jul 30 at 11:59
@Adriano Repetti Thanks. I usually dereference the pointer returned byflag_get
and store the data in a new struct:const struct flag method = *f_get(...)
. Iniyially I got the idea for using a static buffer from thegmtime
function intime.h
. Don't know if it's good practice tho. Thanks for the advice!
â Bogdan M.
Jul 30 at 12:12
It's not a bad practice but it's error-prone. You force the caller to be aware it has to make a copy and the function is not reentrant nor thread-safe (not that it matters in this case). More than that you're returningflag*
which is notconst
and anyway, even if it was, it's a const pointer to variable data. Unless strongly required (and for a cli parser you shouldn't have any strict performance requirement) it's usually better to be on the safe side (a quick search ofgmtime()
on SO wil give you tons of questions related to this issue...)
â Adriano Repetti
Jul 30 at 12:33
Yeah I posted a question about gmtime on SO which is how I learned about it's behavior in the first place.
â Bogdan M.
Jul 30 at 12:36
add a comment |Â
1
Few more things but something eye catching is thatstatic
field. Imagine you're writing acurl
clone and you havestruct flag* method = flag_get(argc, argv, "X"); struct flag* body = flag_get(argc, argv, "d");
Now you want to check if user is trying to do a GET with a body:if (strncmp(method->data, "GET"...) && strlen(body->data))
...it fails because bothmethod
andbody
points to the same data. Here I'd happily accept to return newly allocated memory (leaving the caller with its ownership unless you want to accept astruct flag* flag
parameter).
â Adriano Repetti
Jul 30 at 11:59
@Adriano Repetti Thanks. I usually dereference the pointer returned byflag_get
and store the data in a new struct:const struct flag method = *f_get(...)
. Iniyially I got the idea for using a static buffer from thegmtime
function intime.h
. Don't know if it's good practice tho. Thanks for the advice!
â Bogdan M.
Jul 30 at 12:12
It's not a bad practice but it's error-prone. You force the caller to be aware it has to make a copy and the function is not reentrant nor thread-safe (not that it matters in this case). More than that you're returningflag*
which is notconst
and anyway, even if it was, it's a const pointer to variable data. Unless strongly required (and for a cli parser you shouldn't have any strict performance requirement) it's usually better to be on the safe side (a quick search ofgmtime()
on SO wil give you tons of questions related to this issue...)
â Adriano Repetti
Jul 30 at 12:33
Yeah I posted a question about gmtime on SO which is how I learned about it's behavior in the first place.
â Bogdan M.
Jul 30 at 12:36
1
1
Few more things but something eye catching is that
static
field. Imagine you're writing a curl
clone and you have struct flag* method = flag_get(argc, argv, "X"); struct flag* body = flag_get(argc, argv, "d");
Now you want to check if user is trying to do a GET with a body: if (strncmp(method->data, "GET"...) && strlen(body->data))
...it fails because both method
and body
points to the same data. Here I'd happily accept to return newly allocated memory (leaving the caller with its ownership unless you want to accept a struct flag* flag
parameter).â Adriano Repetti
Jul 30 at 11:59
Few more things but something eye catching is that
static
field. Imagine you're writing a curl
clone and you have struct flag* method = flag_get(argc, argv, "X"); struct flag* body = flag_get(argc, argv, "d");
Now you want to check if user is trying to do a GET with a body: if (strncmp(method->data, "GET"...) && strlen(body->data))
...it fails because both method
and body
points to the same data. Here I'd happily accept to return newly allocated memory (leaving the caller with its ownership unless you want to accept a struct flag* flag
parameter).â Adriano Repetti
Jul 30 at 11:59
@Adriano Repetti Thanks. I usually dereference the pointer returned by
flag_get
and store the data in a new struct: const struct flag method = *f_get(...)
. Iniyially I got the idea for using a static buffer from the gmtime
function in time.h
. Don't know if it's good practice tho. Thanks for the advice!â Bogdan M.
Jul 30 at 12:12
@Adriano Repetti Thanks. I usually dereference the pointer returned by
flag_get
and store the data in a new struct: const struct flag method = *f_get(...)
. Iniyially I got the idea for using a static buffer from the gmtime
function in time.h
. Don't know if it's good practice tho. Thanks for the advice!â Bogdan M.
Jul 30 at 12:12
It's not a bad practice but it's error-prone. You force the caller to be aware it has to make a copy and the function is not reentrant nor thread-safe (not that it matters in this case). More than that you're returning
flag*
which is not const
and anyway, even if it was, it's a const pointer to variable data. Unless strongly required (and for a cli parser you shouldn't have any strict performance requirement) it's usually better to be on the safe side (a quick search of gmtime()
on SO wil give you tons of questions related to this issue...)â Adriano Repetti
Jul 30 at 12:33
It's not a bad practice but it's error-prone. You force the caller to be aware it has to make a copy and the function is not reentrant nor thread-safe (not that it matters in this case). More than that you're returning
flag*
which is not const
and anyway, even if it was, it's a const pointer to variable data. Unless strongly required (and for a cli parser you shouldn't have any strict performance requirement) it's usually better to be on the safe side (a quick search of gmtime()
on SO wil give you tons of questions related to this issue...)â Adriano Repetti
Jul 30 at 12:33
Yeah I posted a question about gmtime on SO which is how I learned about it's behavior in the first place.
â Bogdan M.
Jul 30 at 12:36
Yeah I posted a question about gmtime on SO which is how I learned about it's behavior in the first place.
â Bogdan M.
Jul 30 at 12:36
add a comment |Â
active
oldest
votes
active
oldest
votes
active
oldest
votes
active
oldest
votes
active
oldest
votes
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f200556%2flibrary-for-managing-cli-flags%23new-answer', 'question_page');
);
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
1
Few more things but something eye catching is that
static
field. Imagine you're writing acurl
clone and you havestruct flag* method = flag_get(argc, argv, "X"); struct flag* body = flag_get(argc, argv, "d");
Now you want to check if user is trying to do a GET with a body:if (strncmp(method->data, "GET"...) && strlen(body->data))
...it fails because bothmethod
andbody
points to the same data. Here I'd happily accept to return newly allocated memory (leaving the caller with its ownership unless you want to accept astruct flag* flag
parameter).â Adriano Repetti
Jul 30 at 11:59
@Adriano Repetti Thanks. I usually dereference the pointer returned by
flag_get
and store the data in a new struct:const struct flag method = *f_get(...)
. Iniyially I got the idea for using a static buffer from thegmtime
function intime.h
. Don't know if it's good practice tho. Thanks for the advice!â Bogdan M.
Jul 30 at 12:12
It's not a bad practice but it's error-prone. You force the caller to be aware it has to make a copy and the function is not reentrant nor thread-safe (not that it matters in this case). More than that you're returning
flag*
which is notconst
and anyway, even if it was, it's a const pointer to variable data. Unless strongly required (and for a cli parser you shouldn't have any strict performance requirement) it's usually better to be on the safe side (a quick search ofgmtime()
on SO wil give you tons of questions related to this issue...)â Adriano Repetti
Jul 30 at 12:33
Yeah I posted a question about gmtime on SO which is how I learned about it's behavior in the first place.
â Bogdan M.
Jul 30 at 12:36