1 #include <asn_application.h>
2 #include <asn_internal.h>
3 #include <per_encoder.h>
5 static asn_enc_rval_t
uper_encode_internal(asn_TYPE_descriptor_t
*td
, asn_per_constraints_t
*, void *sptr
, asn_app_consume_bytes_f
*cb
, void *app_key
);
8 uper_encode(asn_TYPE_descriptor_t
*td
, void *sptr
, asn_app_consume_bytes_f
*cb
, void *app_key
) {
9 return uper_encode_internal(td
, 0, sptr
, cb
, app_key
);
13 * Argument type and callback necessary for uper_encode_to_buffer().
15 typedef struct enc_to_buf_arg
{
19 static int encode_to_buffer_cb(const void *buffer
, size_t size
, void *key
) {
20 enc_to_buf_arg
*arg
= (enc_to_buf_arg
*)key
;
23 return -1; /* Data exceeds the available buffer size */
25 memcpy(arg
->buffer
, buffer
, size
);
26 arg
->buffer
= ((char *)arg
->buffer
) + size
;
33 uper_encode_to_buffer(asn_TYPE_descriptor_t
*td
, void *sptr
, void *buffer
, size_t buffer_size
) {
37 key
.left
= buffer_size
;
39 if(td
) ASN_DEBUG("Encoding \"%s\" using UNALIGNED PER", td
->name
);
41 return uper_encode_internal(td
, 0, sptr
, encode_to_buffer_cb
, &key
);
44 typedef struct enc_dyn_arg
{
50 encode_dyn_cb(const void *buffer
, size_t size
, void *key
) {
51 enc_dyn_arg
*arg
= key
;
52 if(arg
->length
+ size
>= arg
->allocated
) {
54 arg
->allocated
= arg
->allocated
? (arg
->allocated
<< 2) : size
;
55 p
= REALLOC(arg
->buffer
, arg
->allocated
);
58 memset(arg
, 0, sizeof(*arg
));
63 memcpy(((char *)arg
->buffer
) + arg
->length
, buffer
, size
);
68 uper_encode_to_new_buffer(asn_TYPE_descriptor_t
*td
, asn_per_constraints_t
*constraints
, void *sptr
, void **buffer_r
) {
72 memset(&key
, 0, sizeof(key
));
74 er
= uper_encode_internal(td
, constraints
, sptr
, encode_dyn_cb
, &key
);
81 key
.buffer
= MALLOC(1);
83 *(char *)key
.buffer
= '\0';
84 *buffer_r
= key
.buffer
;
90 *buffer_r
= key
.buffer
;
91 ASN_DEBUG("Complete encoded in %ld bits", (long)er
.encoded
);
92 return ((er
.encoded
+ 7) >> 3);
97 * Internally useful functions.
100 /* Flush partially filled buffer */
102 _uper_encode_flush_outp(asn_per_outp_t
*po
) {
105 if(po
->nboff
== 0 && po
->buffer
== po
->tmpspace
)
108 buf
= po
->buffer
+ (po
->nboff
>> 3);
109 /* Make sure we account for the last, partially filled */
110 if(po
->nboff
& 0x07) {
111 buf
[0] &= 0xff << (8 - (po
->nboff
& 0x07));
115 return po
->outper(po
->tmpspace
, buf
- po
->tmpspace
, po
->op_key
);
118 static asn_enc_rval_t
119 uper_encode_internal(asn_TYPE_descriptor_t
*td
, asn_per_constraints_t
*constraints
, void *sptr
, asn_app_consume_bytes_f
*cb
, void *app_key
) {
121 asn_enc_rval_t er
= { RC_OK
};
124 * Invoke type-specific encoder.
126 if(!td
|| !td
->uper_encoder
)
127 _ASN_ENCODE_FAILED
; /* PER is not compiled in */
129 po
.buffer
= po
.tmpspace
;
131 po
.nbits
= 8 * sizeof(po
.tmpspace
);
134 po
.flushed_bytes
= 0;
136 er
= td
->uper_encoder(td
, constraints
, sptr
, &po
);
137 if(er
.encoded
!= -1) {
138 size_t bits_to_flush
;
140 bits_to_flush
= ((po
.buffer
- po
.tmpspace
) << 3) + po
.nboff
;
142 /* Set number of bits encoded to a firm value */
143 er
.encoded
= (po
.flushed_bytes
<< 3) + bits_to_flush
;
145 if(_uper_encode_flush_outp(&po
))