~ubuntu-branches/ubuntu/dapper/asn1c/dapper

« back to all changes in this revision

Viewing changes to skeletons/NativeInteger.c

  • Committer: Bazaar Package Importer
  • Author(s): W. Borgert
  • Date: 2005-05-28 12:36:42 UTC
  • Revision ID: james.westby@ubuntu.com-20050528123642-3h6kstws5u0xcovl
Tags: upstream-0.9.14
ImportĀ upstreamĀ versionĀ 0.9.14

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*-
 
2
 * Copyright (c) 2004, 2005 Lev Walkin <vlm@lionet.info>. All rights reserved.
 
3
 * Redistribution and modifications are permitted subject to BSD license.
 
4
 */
 
5
/*
 
6
 * Please read the NativeInteger.h for the explanation wrt. differences between
 
7
 * INTEGER and NativeInteger.
 
8
 * Basically, both are decoders and encoders of ASN.1 INTEGER type, but this
 
9
 * implementation deals with the standard (machine-specific) representation
 
10
 * of them instead of using the platform-independent buffer.
 
11
 */
 
12
#include <asn_internal.h>
 
13
#include <NativeInteger.h>
 
14
 
 
15
/*
 
16
 * NativeInteger basic type description.
 
17
 */
 
18
static ber_tlv_tag_t asn_DEF_NativeInteger_tags[] = {
 
19
        (ASN_TAG_CLASS_UNIVERSAL | (2 << 2))
 
20
};
 
21
asn_TYPE_descriptor_t asn_DEF_NativeInteger = {
 
22
        "INTEGER",                      /* The ASN.1 type is still INTEGER */
 
23
        "INTEGER",
 
24
        NativeInteger_free,
 
25
        NativeInteger_print,
 
26
        asn_generic_no_constraint,
 
27
        NativeInteger_decode_ber,
 
28
        NativeInteger_encode_der,
 
29
        NativeInteger_decode_xer,
 
30
        NativeInteger_encode_xer,
 
31
        0, /* Use generic outmost tag fetcher */
 
32
        asn_DEF_NativeInteger_tags,
 
33
        sizeof(asn_DEF_NativeInteger_tags) / sizeof(asn_DEF_NativeInteger_tags[0]),
 
34
        asn_DEF_NativeInteger_tags,     /* Same as above */
 
35
        sizeof(asn_DEF_NativeInteger_tags) / sizeof(asn_DEF_NativeInteger_tags[0]),
 
36
        0, 0,   /* No members */
 
37
        0       /* No specifics */
 
38
};
 
39
 
 
40
/*
 
41
 * Decode INTEGER type.
 
42
 */
 
43
asn_dec_rval_t
 
44
NativeInteger_decode_ber(asn_codec_ctx_t *opt_codec_ctx,
 
45
        asn_TYPE_descriptor_t *td,
 
46
        void **nint_ptr, const void *buf_ptr, size_t size, int tag_mode) {
 
47
        long *native = (long *)*nint_ptr;
 
48
        asn_dec_rval_t rval;
 
49
        ber_tlv_len_t length;
 
50
 
 
51
        /*
 
52
         * If the structure is not there, allocate it.
 
53
         */
 
54
        if(native == NULL) {
 
55
                native = (long *)(*nint_ptr = CALLOC(1, sizeof(*native)));
 
56
                if(native == NULL) {
 
57
                        rval.code = RC_FAIL;
 
58
                        rval.consumed = 0;
 
59
                        return rval;
 
60
                }
 
61
        }
 
62
 
 
63
        ASN_DEBUG("Decoding %s as INTEGER (tm=%d)",
 
64
                td->name, tag_mode);
 
65
 
 
66
        /*
 
67
         * Check tags.
 
68
         */
 
69
        rval = ber_check_tags(opt_codec_ctx, td, 0, buf_ptr, size,
 
70
                        tag_mode, 0, &length, 0);
 
71
        if(rval.code != RC_OK)
 
72
                return rval;
 
73
 
 
74
        ASN_DEBUG("%s length is %d bytes", td->name, (int)length);
 
75
 
 
76
        /*
 
77
         * Make sure we have this length.
 
78
         */
 
79
        buf_ptr = ((const char *)buf_ptr) + rval.consumed;
 
80
        size -= rval.consumed;
 
81
        if(length > (ber_tlv_len_t)size) {
 
82
                rval.code = RC_WMORE;
 
83
                rval.consumed = 0;
 
84
                return rval;
 
85
        }
 
86
 
 
87
        /*
 
88
         * ASN.1 encoded INTEGER: buf_ptr, length
 
89
         * Fill the native, at the same time checking for overflow.
 
90
         * If overflow occured, return with RC_FAIL.
 
91
         */
 
92
        {
 
93
                INTEGER_t tmp;
 
94
                long l;
 
95
                (const uint8_t *)tmp.buf = (const uint8_t *)buf_ptr;
 
96
                tmp.size = length;
 
97
 
 
98
                if(asn_INTEGER2long(&tmp, &l)) {
 
99
                        rval.code = RC_FAIL;
 
100
                        rval.consumed = 0;
 
101
                        return rval;
 
102
                }
 
103
 
 
104
                *native = l;
 
105
 
 
106
                /*
 
107
                 * Note that native integer size might be other than long.
 
108
                 * This expression hopefully will be optimized away
 
109
                 * by compiler.
 
110
                 */
 
111
                if(sizeof(*native) != sizeof(long) && ((long)*native != l)) {
 
112
                        *native = 0;    /* Safe value */
 
113
                        rval.code = RC_FAIL;
 
114
                        rval.consumed = 0;
 
115
                        return rval;
 
116
                }
 
117
        }
 
118
 
 
119
        rval.code = RC_OK;
 
120
        rval.consumed += length;
 
121
 
 
122
        ASN_DEBUG("Took %ld/%ld bytes to encode %s (%ld)",
 
123
                (long)rval.consumed, (long)length, td->name, (long)*native);
 
124
 
 
125
        return rval;
 
126
}
 
127
 
 
128
/*
 
129
 * Encode the NativeInteger using the standard INTEGER type DER encoder.
 
130
 */
 
131
asn_enc_rval_t
 
132
NativeInteger_encode_der(asn_TYPE_descriptor_t *sd, void *ptr,
 
133
        int tag_mode, ber_tlv_tag_t tag,
 
134
        asn_app_consume_bytes_f *cb, void *app_key) {
 
135
        unsigned long native = *(unsigned long *)ptr;   /* Disable sign ext. */
 
136
        asn_enc_rval_t erval;
 
137
        INTEGER_t tmp;
 
138
 
 
139
#ifdef  WORDS_BIGENDIAN         /* Opportunistic optimization */
 
140
 
 
141
        tmp.buf = (uint8_t *)&native;
 
142
        tmp.size = sizeof(native);
 
143
 
 
144
#else   /* Works even if WORDS_BIGENDIAN is not set where should've been */
 
145
        uint8_t buf[sizeof(native)];
 
146
        uint8_t *p;
 
147
 
 
148
        /* Prepare a fake INTEGER */
 
149
        for(p = buf + sizeof(buf) - 1; p >= buf; p--, native >>= 8)
 
150
                *p = native;
 
151
 
 
152
        tmp.buf = buf;
 
153
        tmp.size = sizeof(buf);
 
154
#endif  /* WORDS_BIGENDIAN */
 
155
        
 
156
        /* Encode fake INTEGER */
 
157
        erval = INTEGER_encode_der(sd, &tmp, tag_mode, tag, cb, app_key);
 
158
        if(erval.encoded == -1) {
 
159
                assert(erval.structure_ptr == &tmp);
 
160
                erval.structure_ptr = ptr;
 
161
        }
 
162
        return erval;
 
163
}
 
164
 
 
165
/*
 
166
 * Decode the chunk of XML text encoding INTEGER.
 
167
 */
 
168
asn_dec_rval_t
 
169
NativeInteger_decode_xer(asn_codec_ctx_t *opt_codec_ctx,
 
170
        asn_TYPE_descriptor_t *td, void **sptr, const char *opt_mname,
 
171
                const void *buf_ptr, size_t size) {
 
172
        asn_dec_rval_t rval;
 
173
        INTEGER_t *st = 0;
 
174
        void *st_ptr = (void *)&st;
 
175
        long *native = (long *)*sptr;
 
176
 
 
177
        if(!native) {
 
178
                *sptr = CALLOC(1, sizeof(int));
 
179
                native = (long *)*sptr;
 
180
                if(!native) {
 
181
                        rval.code = RC_FAIL;
 
182
                        rval.consumed = 0;
 
183
                        return rval;
 
184
                }
 
185
        }
 
186
 
 
187
        rval = INTEGER_decode_xer(opt_codec_ctx, td, (void **)st_ptr, 
 
188
                opt_mname, buf_ptr, size);
 
189
        if(rval.code == RC_OK) {
 
190
                long l;
 
191
                if(asn_INTEGER2long(st, &l)) {
 
192
                        rval.code = RC_FAIL;
 
193
                        rval.consumed = 0;
 
194
                } else {
 
195
                        *native = l;
 
196
 
 
197
                        /* Native type might be shorter than long */
 
198
                        if(sizeof(*native) != sizeof(long)
 
199
                                        && ((long)*native != l)) {
 
200
                                *native = 0;    /* Safe value */
 
201
                                rval.code = RC_FAIL;
 
202
                                rval.consumed = 0;
 
203
                                return rval;
 
204
                        }
 
205
                }
 
206
        } else {
 
207
                /*
 
208
                 * Cannot restart from the middle;
 
209
                 * there is no place to save state in the native type.
 
210
                 * Request a continuation from the very beginning.
 
211
                 */
 
212
                rval.consumed = 0;
 
213
        }
 
214
        asn_DEF_INTEGER.free_struct(&asn_DEF_INTEGER, st, 0);
 
215
        return rval;
 
216
}
 
217
 
 
218
 
 
219
asn_enc_rval_t
 
220
NativeInteger_encode_xer(asn_TYPE_descriptor_t *td, void *sptr,
 
221
        int ilevel, enum xer_encoder_flags_e flags,
 
222
                asn_app_consume_bytes_f *cb, void *app_key) {
 
223
        char scratch[32];       /* Enough for 64-bit int */
 
224
        asn_enc_rval_t er;
 
225
        const long *native = (const long *)sptr;
 
226
 
 
227
        (void)ilevel;
 
228
        (void)flags;
 
229
 
 
230
        if(!native) _ASN_ENCODE_FAILED;
 
231
 
 
232
        er.encoded = snprintf(scratch, sizeof(scratch), "%ld", *native);
 
233
        if(er.encoded <= 0 || (size_t)er.encoded >= sizeof(scratch)
 
234
                || cb(scratch, er.encoded, app_key) < 0)
 
235
                _ASN_ENCODE_FAILED;
 
236
 
 
237
        return er;
 
238
}
 
239
 
 
240
/*
 
241
 * INTEGER specific human-readable output.
 
242
 */
 
243
int
 
244
NativeInteger_print(asn_TYPE_descriptor_t *td, const void *sptr, int ilevel,
 
245
        asn_app_consume_bytes_f *cb, void *app_key) {
 
246
        const long *native = (const long *)sptr;
 
247
        char scratch[32];       /* Enough for 64-bit int */
 
248
        int ret;
 
249
 
 
250
        (void)td;       /* Unused argument */
 
251
        (void)ilevel;   /* Unused argument */
 
252
 
 
253
        if(native) {
 
254
                ret = snprintf(scratch, sizeof(scratch), "%ld", *native);
 
255
                assert(ret > 0 && (size_t)ret < sizeof(scratch));
 
256
                return (cb(scratch, ret, app_key) < 0) ? -1 : 0;
 
257
        } else {
 
258
                return (cb("<absent>", 8, app_key) < 0) ? -1 : 0;
 
259
        }
 
260
}
 
261
 
 
262
void
 
263
NativeInteger_free(asn_TYPE_descriptor_t *td, void *ptr, int contents_only) {
 
264
 
 
265
        if(!td || !ptr)
 
266
                return;
 
267
 
 
268
        ASN_DEBUG("Freeing %s as INTEGER (%d, %p, Native)",
 
269
                td->name, contents_only, ptr);
 
270
 
 
271
        if(!contents_only) {
 
272
                FREEMEM(ptr);
 
273
        }
 
274
}
 
275