First kick.
[yaz-moved-to-github.git] / odr / ber_len.c
1 #include <stdio.h>
2 #include <odr.h>
3
4 /*
5  * Encode BER length octets. If exact, lenlen is the exact desired
6  * encoding size, else, lenlen is the max available space. Len < 0 =
7  * Indefinite encoding.
8  * Returns: >0   success, number of bytes encoded.
9  * Returns: =0   success, indefinite start-marker set. 1 byte encoded.
10  * Returns: -1   failure, out of bounds.
11  */
12 int ber_enclen(unsigned char *buf, int len, int lenlen, int exact)
13 {
14     unsigned char *b = buf;
15     unsigned char octs[sizeof(int)];
16     int n = 0;
17
18     fprintf(stderr, "[len=%d]", len);
19     if (len < 0)      /* Indefinite */
20     {
21         *b = 0X80;
22         fprintf(stderr, "[indefinite]");
23         return 0;
24     }
25     if (len <= 127 && (lenlen == 1 || !exact)) /* definite short form */
26     {
27         *b = len;
28         return 1;
29     }
30     if (lenlen == 1)
31     {
32         *b = 0X80;
33         return 0;
34     }
35     /* definite long form */
36     do
37     {
38         octs[n++] = len;
39         len >>= 8;
40     }
41     while (len);
42     if (n >= lenlen)
43         return -1;
44     b++;
45     if (exact)
46         while (n < --lenlen)        /* pad length octets */
47             *(++b) = 0;
48     while (n--)
49         *(b++) = octs[n];
50     *buf = (b - buf - 1) | 0X80;
51     return b - buf;
52 }
53
54 /*
55  * Decode BER length octets. Returns number of bytes read or -1 for error.
56  * After return:
57  * len = -1   indefinite.
58  * len >= 0    Length.
59  */
60 int ber_declen(unsigned char *buf, int *len)
61 {
62     unsigned char *b = buf;
63     int n;
64
65     if (*b == 0X80)     /* Indefinite */
66     {
67         *len = -1;
68         fprintf(stderr, "[len=%d]", *len);
69         return 1;
70     }
71     if (!(*b & 0X80))   /* Definite short form */
72     {
73         *len = (int) *b;
74         fprintf(stderr, "[len=%d]", *len);
75         return 1;
76     }
77     if (*b == 0XFF)     /* reserved value */
78         return -1;
79     /* indefinite long form */ 
80     n = *b & 0X7F;
81     *len = 0;
82     b++;
83     while (n--)
84     {
85         *len <<= 8;
86         *len |= *(b++);
87     }
88     fprintf(stderr, "[len=%d]", *len);
89     return (b - buf);
90 }