Commit 8d99d7b5 authored by Lev Walkin's avatar Lev Walkin

introduced ASN_STRUCT_RESET; preferred over ASN_STRUCT_FREE_CONTENTS_ONLY

parent 56d59b46
......@@ -304,14 +304,14 @@ structure:
\begin{codesample}
Rectangle_t *rect = ...;
asn_DEF_Rectangle.free_struct(&asn_DEF_Rectangle, rect, 0);
ASN_STRUCT_FREE(asn_DEF_Rectangle, rect);
\end{codesample}
This code defines a \emph{rect} pointer which points to the Rectangle\_t
structure which needs to be freed. The second line invokes the generic
\emph{free\_struct()} routine created specifically for this Rectangle\_t
structure. The \emph{asn\_DEF\_Rectangle} is the type descriptor,
which holds a collection of routines to deal with the Rectangle\_t
structure.
structure which needs to be freed. The second line uses the generic
ASN\_STRUCT\_FREE() macro which invokes the memory deallocation routine
created specifically for this Rectangle\_t structure.
The \emph{asn\_DEF\_Rectangle} is the type descriptor which holds
a collection of routines and operations defined for the Rectangle\_t structure.
The following member functions of the asn\_DEF\_Rectangle type descriptor
are of interest:
......@@ -400,7 +400,7 @@ simple_deserializer(const void *buffer, size_t buf_size) {
return rect; /* Decoding succeeded */
} else {
/* Free partially decoded rect */
asn_DEF_Rectangle.free_struct(&asn_DEF_Rectangle, rect, 0);
ASN_STRUCT_FREE(asn_DEF_Rectangle, rect);
return 0;
}
}
......@@ -554,7 +554,7 @@ XML_to_Rectangle(const void *buffer, size_t buf_size) {
return rect; /* Decoding succeeded */
} else {
/* Free partially decoded rect */
asn_DEF_Rectangle.free_struct(&asn_DEF_Rectangle, rect, 0);
ASN_STRUCT_FREE(asn_DEF_Rectangle, rect);
return 0;
}
}
......@@ -626,7 +626,7 @@ struct my_figure { /* The custom structure */
/* other members of the structure */
};
\end{codesample}
In this example, the application programmer defined a custom structure
In this example, the application programmer defines a custom structure
with one ASN.1-derived member (rect). This member is not a reference
to the Rectangle\_t, but an in-place inclusion of the Rectangle\_t
structure. If the freeing is necessary, the usual procedure of freeing
......@@ -635,11 +635,9 @@ it does not point to the memory block directly allocated by the memory
allocation routine, but instead lies within a block allocated for
the my\_figure structure.
To solve this problem, the free\_struct routine has the additional
argument (besides the obvious type descriptor and target structure
pointers), which is the flag specifying whether the outer pointer
itself must be freed (0, default) or it should be left intact (non-zero
value).
To solve this problem, in addition to ASN\_STRUCT\_FREE macro, the asn1c
skeletons define the ASN\_STRUCT\_RESET macro which doesn't free the passed
pointer and instead resets the structure into the clean and safe state.
\begin{codesample}
/* %\textbf{1. Rectangle\_t is defined within my\_figure}% */
struct my_figure {
......@@ -649,8 +647,7 @@ struct my_figure {
* Freeing the Rectangle_t
* without freeing the mf->rect area.
*/
asn_DEF_Rectangle.free_struct(
&asn_DEF_Rectangle, &mf->rect, %\textbf{1 /* !free */}%);
ASN_STRUCT_RESET(asn_DEF_Rectangle, &mf->rect);
/* %\textbf{2. Rectangle\_t is a stand-alone pointer}% */
Rectangle_t *rect = ...;
......@@ -658,20 +655,10 @@ Rectangle_t *rect = ...;
* Freeing the Rectangle_t
* and freeing the rect pointer.
*/
asn_DEF_Rectangle.free_struct(
&asn_DEF_Rectangle, rect, %\textbf{0 /* free the pointer too */}%);
ASN_STRUCT_FREE(asn_DEF_Rectangle, &mf->rect);
\end{codesample}
It is safe to invoke the \emph{free\_struct} function with the target
structure pointer set to 0 (NULL), the function will do nothing.
For the programmer's convenience, the following macros are available:
\begin{codesample}
ASN_STRUCT_FREE(asn_DEF, ptr);
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF, ptr);
\end{codesample}
These macros bear the same semantics as the \emph{free\_struct} function
invocation, discussed above.
It is safe to invoke both macros with the target structure pointer
set to 0 (NULL). In this case, the function will do nothing.
\chapter{\label{cha:Step-by-step-examples}Step by step examples}
......
......@@ -246,10 +246,20 @@ BOOLEAN_print(asn_TYPE_descriptor_t *td, const void *sptr, int ilevel,
}
void
BOOLEAN_free(const asn_TYPE_descriptor_t *td, void *ptr, int contents_only) {
if(td && ptr && !contents_only) {
FREEMEM(ptr);
}
BOOLEAN_free(const asn_TYPE_descriptor_t *td, void *ptr,
enum asn_struct_free_method method) {
if(td && ptr) {
switch(method) {
case ASFM_FREE_EVERYTHING:
FREEMEM(ptr);
break;
case ASFM_FREE_UNDERLYING:
break;
case ASFM_FREE_UNDERLYING_AND_RESET:
memset(ptr, 0, sizeof(BOOLEAN_t));
break;
}
}
}
asn_dec_rval_t
......
......@@ -347,16 +347,23 @@ NativeInteger_print(asn_TYPE_descriptor_t *td, const void *sptr, int ilevel,
void
NativeInteger_free(const asn_TYPE_descriptor_t *td, void *ptr,
int contents_only) {
enum asn_struct_free_method method) {
if(!td || !ptr)
return;
ASN_DEBUG("Freeing %s as INTEGER (%d, %p, Native)",
td->name, contents_only, ptr);
if(!contents_only) {
FREEMEM(ptr);
}
td->name, method, ptr);
switch(method) {
case ASFM_FREE_EVERYTHING:
FREEMEM(ptr);
break;
case ASFM_FREE_UNDERLYING:
break;
case ASFM_FREE_UNDERLYING_AND_RESET:
memset(ptr, 0, sizeof(long));
break;
}
}
int
......
......@@ -385,15 +385,23 @@ NativeReal_compare(const asn_TYPE_descriptor_t *td, const void *aptr,
}
void
NativeReal_free(const asn_TYPE_descriptor_t *td, void *ptr, int contents_only) {
NativeReal_free(const asn_TYPE_descriptor_t *td, void *ptr,
enum asn_struct_free_method method) {
if(!td || !ptr)
return;
ASN_DEBUG("Freeing %s as REAL (%d, %p, Native)",
td->name, contents_only, ptr);
if(!contents_only) {
FREEMEM(ptr);
}
td->name, method, ptr);
switch(method) {
case ASFM_FREE_EVERYTHING:
FREEMEM(ptr);
break;
case ASFM_FREE_UNDERLYING:
break;
case ASFM_FREE_UNDERLYING_AND_RESET:
memset(ptr, 0, sizeof(double));
break;
}
}
......@@ -1731,8 +1731,8 @@ OCTET_STRING_print_utf8(asn_TYPE_descriptor_t *td, const void *sptr,
void
OCTET_STRING_free(const asn_TYPE_descriptor_t *td, void *sptr,
int contents_only) {
OCTET_STRING_t *st = (OCTET_STRING_t *)sptr;
enum asn_struct_free_method method) {
OCTET_STRING_t *st = (OCTET_STRING_t *)sptr;
asn_OCTET_STRING_specifics_t *specs;
asn_struct_ctx_t *ctx;
struct _stack *stck;
......@@ -1765,9 +1765,17 @@ OCTET_STRING_free(const asn_TYPE_descriptor_t *td, void *sptr,
FREEMEM(stck);
}
if(!contents_only) {
FREEMEM(st);
}
switch(method) {
case ASFM_FREE_EVERYTHING:
FREEMEM(sptr);
break;
case ASFM_FREE_UNDERLYING:
break;
case ASFM_FREE_UNDERLYING_AND_RESET:
memset(sptr, 0,
((asn_OCTET_STRING_specifics_t *)(td->specifics))->struct_size);
break;
}
}
/*
......
......@@ -97,6 +97,7 @@ OPEN_TYPE_oer_get(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
asn_type_selector_result_t selected;
void *memb_ptr; /* Pointer to the member */
void **memb_ptr2; /* Pointer to that pointer */
void *inner_value;
asn_dec_rval_t rv;
size_t ot_ret;
......@@ -124,8 +125,12 @@ OPEN_TYPE_oer_get(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
}
}
inner_value =
(char *)*memb_ptr2
+ elm->type->elements[selected.presence_index - 1].memb_offset;
ot_ret = oer_open_type_get(opt_codec_ctx, selected.type_descriptor, NULL,
memb_ptr2, ptr, size);
&inner_value, ptr, size);
switch(ot_ret) {
default:
if(CHOICE_variant_set_presence(selected.type_descriptor, *memb_ptr2,
......@@ -151,11 +156,11 @@ OPEN_TYPE_oer_get(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
if(*memb_ptr2) {
asn_CHOICE_specifics_t *specs = selected.type_descriptor->specifics;
if(elm->flags & ATF_POINTER) {
ASN_STRUCT_FREE(*selected.type_descriptor, *memb_ptr2);
ASN_STRUCT_FREE(*selected.type_descriptor, inner_value);
*memb_ptr2 = NULL;
} else {
ASN_STRUCT_FREE_CONTENTS_ONLY(*selected.type_descriptor,
*memb_ptr2);
inner_value);
memset(*memb_ptr2, 0, specs->struct_size);
}
}
......
......@@ -116,7 +116,7 @@ der_encode_primitive(asn_TYPE_descriptor_t *td, void *sptr,
void
ASN__PRIMITIVE_TYPE_free(const asn_TYPE_descriptor_t *td, void *sptr,
int contents_only) {
enum asn_struct_free_method method) {
ASN__PRIMITIVE_TYPE_t *st = (ASN__PRIMITIVE_TYPE_t *)sptr;
if(!td || !sptr)
......@@ -127,8 +127,16 @@ ASN__PRIMITIVE_TYPE_free(const asn_TYPE_descriptor_t *td, void *sptr,
if(st->buf)
FREEMEM(st->buf);
if(!contents_only)
FREEMEM(st);
switch(method) {
case ASFM_FREE_EVERYTHING:
FREEMEM(sptr);
break;
case ASFM_FREE_UNDERLYING:
break;
case ASFM_FREE_UNDERLYING_AND_RESET:
memset(sptr, 0, sizeof(ASN__PRIMITIVE_TYPE_t));
break;
}
}
......
......@@ -1037,7 +1037,8 @@ CHOICE_print(asn_TYPE_descriptor_t *td, const void *sptr, int ilevel,
}
void
CHOICE_free(const asn_TYPE_descriptor_t *td, void *ptr, int contents_only) {
CHOICE_free(const asn_TYPE_descriptor_t *td, void *ptr,
enum asn_struct_free_method method) {
asn_CHOICE_specifics_t *specs = (asn_CHOICE_specifics_t *)td->specifics;
unsigned present;
......@@ -1068,9 +1069,16 @@ CHOICE_free(const asn_TYPE_descriptor_t *td, void *ptr, int contents_only) {
}
}
if(!contents_only) {
FREEMEM(ptr);
}
switch(method) {
case ASFM_FREE_EVERYTHING:
FREEMEM(ptr);
break;
case ASFM_FREE_UNDERLYING:
break;
case ASFM_FREE_UNDERLYING_AND_RESET:
memset(ptr, 0, specs->struct_size);
break;
}
}
......@@ -1223,8 +1231,7 @@ CHOICE_variant_set_presence(const asn_TYPE_descriptor_t *td, void *sptr,
if(old_present != 0) {
assert(old_present <= td->elements_count);
ASN_STRUCT_FREE_CONTENTS_ONLY(*td, sptr);
memset(sptr, 0, specs->struct_size);
ASN_STRUCT_RESET(*td, sptr);
}
_set_present_idx(sptr, specs->pres_offset, specs->pres_size, present);
......
......@@ -949,7 +949,8 @@ SEQUENCE_print(asn_TYPE_descriptor_t *td, const void *sptr, int ilevel,
}
void
SEQUENCE_free(const asn_TYPE_descriptor_t *td, void *sptr, int contents_only) {
SEQUENCE_free(const asn_TYPE_descriptor_t *td, void *sptr,
enum asn_struct_free_method method) {
size_t edx;
if(!td || !sptr)
......@@ -970,9 +971,17 @@ SEQUENCE_free(const asn_TYPE_descriptor_t *td, void *sptr, int contents_only) {
}
}
if(!contents_only) {
FREEMEM(sptr);
}
switch(method) {
case ASFM_FREE_EVERYTHING:
FREEMEM(sptr);
break;
case ASFM_FREE_UNDERLYING:
break;
case ASFM_FREE_UNDERLYING_AND_RESET:
memset(sptr, 0,
((asn_SEQUENCE_specifics_t *)(td->specifics))->struct_size);
break;
}
}
int
......
......@@ -910,8 +910,9 @@ SET_print(asn_TYPE_descriptor_t *td, const void *sptr, int ilevel,
}
void
SET_free(const asn_TYPE_descriptor_t *td, void *ptr, int contents_only) {
size_t edx;
SET_free(const asn_TYPE_descriptor_t *td, void *ptr,
enum asn_struct_free_method method) {
size_t edx;
if(!td || !ptr)
return;
......@@ -931,9 +932,16 @@ SET_free(const asn_TYPE_descriptor_t *td, void *ptr, int contents_only) {
}
}
if(!contents_only) {
FREEMEM(ptr);
}
switch(method) {
case ASFM_FREE_EVERYTHING:
FREEMEM(ptr);
break;
case ASFM_FREE_UNDERLYING:
break;
case ASFM_FREE_UNDERLYING_AND_RESET:
memset(ptr, 0, ((asn_SET_specifics_t *)(td->specifics))->struct_size);
break;
}
}
int
......
......@@ -788,8 +788,9 @@ SET_OF_print(asn_TYPE_descriptor_t *td, const void *sptr, int ilevel,
}
void
SET_OF_free(const asn_TYPE_descriptor_t *td, void *ptr, int contents_only) {
if(td && ptr) {
SET_OF_free(const asn_TYPE_descriptor_t *td, void *ptr,
enum asn_struct_free_method method) {
if(td && ptr) {
asn_SET_OF_specifics_t *specs;
asn_TYPE_member_t *elm = td->elements;
asn_anonymous_set_ *list = _A_SET_FROM_VOID(ptr);
......@@ -816,10 +817,17 @@ SET_OF_free(const asn_TYPE_descriptor_t *td, void *ptr, int contents_only) {
ctx->ptr = 0;
}
if(!contents_only) {
FREEMEM(ptr);
}
}
switch(method) {
case ASFM_FREE_EVERYTHING:
FREEMEM(ptr);
break;
case ASFM_FREE_UNDERLYING:
break;
case ASFM_FREE_UNDERLYING_AND_RESET:
memset(ptr, 0, specs->struct_size);
break;
}
}
}
int
......
......@@ -47,17 +47,44 @@ typedef struct asn_struct_ctx_s {
/*
* Free the structure according to its specification.
* If (free_contents_only) is set, the wrapper structure itself (struct_ptr)
* will not be freed. (It may be useful in case the structure is allocated
* statically or arranged on the stack, yet its elements are allocated
* dynamically.)
* Use one of ASN_STRUCT_{FREE,RESET,CONTENTS_ONLY} macros instead.
* Do not use directly.
*/
enum asn_struct_free_method {
ASFM_FREE_EVERYTHING, /* free(struct_ptr) and underlying members */
ASFM_FREE_UNDERLYING, /* free underlying members */
ASFM_FREE_UNDERLYING_AND_RESET /* FREE_UNDERLYING + memset(0) */
};
typedef void (asn_struct_free_f)(
const struct asn_TYPE_descriptor_s *type_descriptor,
void *struct_ptr, int free_contents_only);
#define ASN_STRUCT_FREE(asn_DEF, ptr) (asn_DEF).op->free_struct(&(asn_DEF),ptr,0)
#define ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF, ptr) \
(asn_DEF).op->free_struct(&(asn_DEF),ptr,1)
void *struct_ptr, enum asn_struct_free_method);
/*
* Free the structure including freeing the memory pointed to by ptr itself.
*/
#define ASN_STRUCT_FREE(asn_DEF, ptr) \
(asn_DEF).op->free_struct(&(asn_DEF), (ptr), ASFM_FREE_EVERYTHING)
/*
* Free the memory used by the members of the structure without freeing the
* the structure pointer itself.
* ZERO-OUT the structure to the safe clean state.
* (Retaining the pointer may be useful in case the structure is allocated
* statically or arranged on the stack, yet its elements are dynamic.)
*/
#define ASN_STRUCT_RESET(asn_DEF, ptr) \
(asn_DEF).op->free_struct(&(asn_DEF), (ptr), ASFM_FREE_UNDERLYING_AND_RESET)
/*
* Free memory used by the members of the structure without freeing
* the structure pointer itself.
* (Retaining the pointer may be useful in case the structure is allocated
* statically or arranged on the stack, yet its elements are dynamic.)
* AVOID using it in the application code;
* Use a safer ASN_STRUCT_RESET() instead.
*/
#define ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF, ptr) \
(asn_DEF).op->free_struct(&(asn_DEF), (ptr), ASFM_FREE_UNDERLYING)
/*
* Print the structure according to its specification.
......
......@@ -136,7 +136,7 @@ check(int is_ok, uint8_t *buf, size_t size, size_t consumed) {
assert(rval.consumed <= consumed);
}
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_T, &t);
ASN_STRUCT_RESET(asn_DEF_T, &t);
}
static void
......@@ -237,7 +237,7 @@ partial_read(uint8_t *buf, size_t size) {
assert(rval.code == RC_OK);
assert(rval.consumed == size3);
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_T, &t);
ASN_STRUCT_RESET(asn_DEF_T, &t);
}
}
}
......
......@@ -138,7 +138,7 @@ check(int is_ok, uint8_t *buf, size_t size, size_t consumed) {
asn_fprint(stderr, &asn_DEF_Forest, &t);
xer_fprint(stderr, &asn_DEF_Forest, &t);
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_Forest, &t);
ASN_STRUCT_RESET(asn_DEF_Forest, &t);
}
static char xer_buf[512];
......
......@@ -265,7 +265,7 @@ partial_read(uint8_t *data, size_t size) {
assert(rval.code == RC_OK);
assert(rval.consumed == size3);
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_T, &t);
ASN_STRUCT_RESET(asn_DEF_T, &t);
}
}
}
......@@ -315,12 +315,12 @@ main(int ac, char **av) {
check(&t, buf1, sizeof(buf1) + 10, sizeof(buf1));
compare(&t, buf1_reconstr, sizeof(buf1_reconstr));
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_T, &t);
ASN_STRUCT_RESET(asn_DEF_T, &t);
check_xer(buf1, sizeof(buf1), "<T><c><false/></c><b><b2>z</b2></b><a>=&lt;&amp;&gt;</a><d><r-oid>85.79</r-oid></d></T>");
check(&t, buf2, sizeof(buf2) + 10, sizeof(buf2));
compare(&t, buf2_reconstr, sizeof(buf2_reconstr));
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_T, &t);
ASN_STRUCT_RESET(asn_DEF_T, &t);
check_xer(buf2, sizeof(buf2), "<T><c><true/></c><b><b1>z</b1></b><a>=&lt;&amp;&gt;</a><d><oid>2.1</oid></d></T>");
/* Split the buffer in parts and check decoder restartability */
......
......@@ -281,7 +281,7 @@ partial_read(uint8_t *data, size_t size) {
assert(rval.code == RC_OK);
assert(rval.consumed == size3);
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_T, &t);
ASN_STRUCT_RESET(asn_DEF_T, &t);
}
}
}
......@@ -293,27 +293,27 @@ main() {
/* Check exact buf0 */
check(&t, buf0, sizeof(buf0), sizeof(buf0));
compare(&t, buf0_reconstr, sizeof(buf0_reconstr));
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_T, &t);
ASN_STRUCT_RESET(asn_DEF_T, &t);
/* Check exact buf1 */
check(&t, buf1, sizeof(buf1), sizeof(buf1));
compare(&t, buf1_reconstr, sizeof(buf1_reconstr));
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_T, &t);
ASN_STRUCT_RESET(asn_DEF_T, &t);
/* Check slightly more than buf1 */
check(&t, buf1, sizeof(buf1) + 10, sizeof(buf1));
compare(&t, buf1_reconstr, sizeof(buf1_reconstr));
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_T, &t);
ASN_STRUCT_RESET(asn_DEF_T, &t);
/* Check exact buf2 */
check(&t, buf2, sizeof(buf2), sizeof(buf2));
compare(&t, buf2_reconstr, sizeof(buf2_reconstr));
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_T, &t);
ASN_STRUCT_RESET(asn_DEF_T, &t);
/* Check slightly more than buf2 */
check(&t, buf2, sizeof(buf2) + 10, sizeof(buf2));
compare(&t, buf2_reconstr, sizeof(buf2_reconstr));
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_T, &t);
ASN_STRUCT_RESET(asn_DEF_T, &t);
/* Split the buffer in parts and check decoder restartability */
partial_read(buf0, sizeof(buf0));
......
......@@ -188,7 +188,7 @@ partial_read(uint8_t *buf_0, size_t size) {
assert(rval.code == RC_OK);
assert(rval.consumed == size3);
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_T, &t);
ASN_STRUCT_RESET(asn_DEF_T, &t);
}
}
}
......@@ -204,13 +204,13 @@ main(int ac, char **av) {
check(&t, buf1, sizeof(buf1), sizeof(buf1));
compare(&t, buf1_reconstr, sizeof(buf1_reconstr));
asn_fprint(stderr, &asn_DEF_T, &t);
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_T, &t);
ASN_STRUCT_RESET(asn_DEF_T, &t);
/* Check slightly more than buf1 */
check(&t, buf1, sizeof(buf1) + 10, sizeof(buf1));
compare(&t, buf1_reconstr, sizeof(buf1_reconstr));
asn_fprint(stderr, &asn_DEF_T, &t);
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_T, &t);
ASN_STRUCT_RESET(asn_DEF_T, &t);
/* Split the buffer in parts and check decoder restartability */
partial_read(buf1, sizeof(buf1));
......
......@@ -66,7 +66,7 @@ check(LogLine_t *tp, uint8_t *ptr, size_t size, size_t consumed) {
assert(rval.code == RC_OK);
assert(rval.consumed == consumed);
asn_fprint(stderr, &asn_DEF_LogLine, tp);
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_LogLine, tp);
ASN_STRUCT_RESET(asn_DEF_LogLine, tp);
}
uint8_t *buf;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment