Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added is_type policy function #5691

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
120 changes: 95 additions & 25 deletions libpromises/evalfunction.c
Original file line number Diff line number Diff line change
Expand Up @@ -5276,38 +5276,21 @@ static FnCallResult FnCallFold(EvalContext *ctx,

/*********************************************************************/

static FnCallResult FnCallDatatype(EvalContext *ctx, ARG_UNUSED const Policy *policy, const FnCall *fp, const Rlist *finalargs)
static const char * DataTypeStringFromVarName(EvalContext *ctx, const char *var_name, bool detail)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

const char * commonly means / implies a string owned by something else, or in other words a string you don't need to free.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
static const char * DataTypeStringFromVarName(EvalContext *ctx, const char *var_name, bool detail)
static char * DataTypeStringFromVarName(EvalContext *ctx, const char *var_name, bool detail)

{
assert(fp != NULL);
assert(fp->name != NULL);

if (finalargs == NULL)
{
Log(LOG_LEVEL_ERR,
"Function %s requires variable identifier as first argument",
fp->name);
return FnFailure();
}
const char* const var_name = RlistScalarValue(finalargs);
assert(var_name != NULL);

VarRef* const var_ref = VarRefParse(var_name);
DataType type;
const void *value = EvalContextVariableGet(ctx, var_ref, &type);
VarRefDestroy(var_ref);

/* detail argument defaults to false */
bool detail = false;
if (finalargs->next != NULL)
{
detail = BooleanFromString(RlistScalarValue(finalargs->next));
}

const char *const type_str =
(type == CF_DATA_TYPE_NONE) ? "none" : DataTypeToString(type);

if (!detail)
{
return FnReturn(type_str);
return type_str;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
return type_str;
return StringDuplicate(type_str);

}

if (type == CF_DATA_TYPE_CONTAINER)
Expand Down Expand Up @@ -5339,15 +5322,93 @@ static FnCallResult FnCallDatatype(EvalContext *ctx, ARG_UNUSED const Policy *po
subtype_str = "null";
break;
default:
Log(LOG_LEVEL_ERR,
"Function %s failed to get subtype of type data", fp->name);
return FnFailure();
return NULL;
}

return FnReturnF("%s %s", type_str, subtype_str);
return StringConcatenate(3, type_str, " ", subtype_str);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Never freed.

}
return StringConcatenate(2, "policy ", type_str);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Never freed.

}

static FnCallResult FnCallDatatype(EvalContext *ctx, ARG_UNUSED const Policy *policy, const FnCall *fp, const Rlist *finalargs)
{
assert(fp != NULL);
assert(fp->name != NULL);

return FnReturnF("policy %s", type_str);
if (finalargs == NULL)
{
Log(LOG_LEVEL_ERR,
"Function %s requires variable identifier as first argument",
fp->name);
return FnFailure();
}
const char* const var_name = RlistScalarValue(finalargs);

/* detail argument defaults to false */
bool detail = false;
if (finalargs->next != NULL)
{
detail = BooleanFromString(RlistScalarValue(finalargs->next));
}
const char * const ouptput_string = DataTypeStringFromVarName(ctx, var_name, detail);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Never freed.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
const char * const ouptput_string = DataTypeStringFromVarName(ctx, var_name, detail);
char * const ouptput_string = DataTypeStringFromVarName(ctx, var_name, detail);


if (ouptput_string == NULL)
{
Log(LOG_LEVEL_ERR, "Function %s could not parse var type",
fp->name);
return FnFailure();
}

return FnReturnF("%s", ouptput_string);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is how you can "give" it to the caller, and it's their job to free it.

Suggested change
return FnReturnF("%s", ouptput_string);
return FnReturnNoCopy(output_string);

}

/*********************************************************************/

static FnCallResult FnCallIsDatatype(EvalContext *ctx, ARG_UNUSED const Policy *policy, const FnCall *fp, const Rlist *finalargs)
{
assert(fp != NULL);
assert(fp->name != NULL);

// checks args
const Rlist *const var_arg = finalargs;
if (var_arg == NULL)
{
Log(LOG_LEVEL_ERR, "Function %s requires a variable as first argument",
fp->name);
return FnFailure();
}

assert(finalargs != NULL); // assumes finalargs is already checked by var_arg
const Rlist *const type_arg = finalargs->next;
Fixed Show fixed Hide fixed
victormlg marked this conversation as resolved.
Show resolved Hide resolved
if (type_arg == NULL)
{
Log(LOG_LEVEL_ERR, "Function %s requires a type as second argument",
fp->name);
return FnFailure();
}

const char* const var_name = RlistScalarValue(var_arg);
const char* const type_name = RlistScalarValue(type_arg);
bool detail = false;

const char *p = type_name;
for (char c = *p; c != '\0'; c = *++p)
{
if (c == ' ')
{
detail = true;
}
}
const char * const type_string = DataTypeStringFromVarName(ctx, var_name, detail);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Never freed.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
const char * const type_string = DataTypeStringFromVarName(ctx, var_name, detail);
char * const type_string = DataTypeStringFromVarName(ctx, var_name, detail);


if (type_string == NULL)
{
Log(LOG_LEVEL_ERR, "Function %s could not parse var type",
fp->name);
return FnFailure();
}

return FnReturnContext(StringEqual(type_name, type_string));
Comment on lines +5410 to +5411
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
return FnReturnContext(StringEqual(type_name, type_string));
const bool matching = StringEqual(type_name, type_string);
free(type_string);
return FnReturnContext(matching);

}

/*********************************************************************/
Expand Down Expand Up @@ -10303,6 +10364,13 @@ static const FnCallArg DATATYPE_ARGS[] =
{CF_BOOL, CF_DATA_TYPE_OPTION, "Enable detailed type decription"},
{NULL, CF_DATA_TYPE_NONE, NULL}
};
static const FnCallArg IS_DATATYPE_ARGS[] =
{
{CF_ANYSTRING, CF_DATA_TYPE_STRING, "Variable identifier"},
{CF_ANYSTRING, CF_DATA_TYPE_STRING, "Type"},
{CF_BOOL, CF_DATA_TYPE_OPTION, "Enable detailed type decription"},
{NULL, CF_DATA_TYPE_NONE, NULL}
};


/*********************************************************/
Expand Down Expand Up @@ -10715,6 +10783,8 @@ const FnCallType CF_FNCALL_TYPES[] =
// Datatype functions
FnCallTypeNew("type", CF_DATA_TYPE_STRING, DATATYPE_ARGS, &FnCallDatatype, "Get type description as string",
FNCALL_OPTION_VARARG, FNCALL_CATEGORY_DATA, SYNTAX_STATUS_NORMAL),
FnCallTypeNew("is_type", CF_DATA_TYPE_STRING, IS_DATATYPE_ARGS, &FnCallIsDatatype, "Compare type of variable with type",
FNCALL_OPTION_VARARG, FNCALL_CATEGORY_DATA, SYNTAX_STATUS_NORMAL),

FnCallTypeNewNull()
};
Expand Down
Loading