Minor fix.
[yaz-moved-to-github.git] / odr / ber_len.c
1 /*
2  * Copyright (C) 1995, Index Data.
3  * See the file LICENSE for details.
4  * Sebastian Hammer, Adam Dickmeiss
5  *
6  * $Log: ber_len.c,v $
7  * Revision 1.6  1995-09-29 17:12:17  quinn
8  * Smallish
9  *
10  * Revision 1.5  1995/09/27  15:02:55  quinn
11  * Modified function heads & prototypes.
12  *
13  * Revision 1.4  1995/05/16  08:50:45  quinn
14  * License, documentation, and memory fixes
15  *
16  *
17  */
18
19 #include <stdio.h>
20 #include <odr.h>
21
22 /*
23  * Encode BER length octets. If exact, lenlen is the exact desired
24  * encoding size, else, lenlen is the max available space. Len < 0 =
25  * Indefinite encoding.
26  * Returns: >0   success, number of bytes encoded.
27  * Returns: =0   success, indefinite start-marker set. 1 byte encoded.
28  * Returns: -1   failure, out of bounds.
29  */
30 int ber_enclen(ODR o, int len, int lenlen, int exact)
31 {
32     unsigned char octs[sizeof(int)];
33     int n = 0;
34     int lenpos, end;
35
36 #ifdef ODR_DEBUG
37     fprintf(stderr, "[len=%d]", len);
38 #endif
39     if (len < 0)      /* Indefinite */
40     {
41         if (odr_putc(o, 0x80) < 0)
42             return 0;
43 #ifdef ODR_DEBUG
44         fprintf(stderr, "[indefinite]");
45 #endif
46         return 0;
47     }
48     if (len <= 127 && (lenlen == 1 || !exact)) /* definite short form */
49     {
50         if (odr_putc(o, (unsigned char) len) < 0)
51             return 0;
52         return 1;
53     }
54     if (lenlen == 1)
55     {
56         if (odr_putc(o, 0x80) < 0)
57             return 0;
58         return 0;
59     }
60     /* definite long form */
61     do
62     {
63         octs[n++] = len;
64         len >>= 8;
65     }
66     while (len);
67     if (n >= lenlen)
68         return -1;
69     lenpos = odr_tell(o); /* remember length-of-length position */
70     if (odr_putc(o, 0) < 0)  /* dummy */
71         return 0;
72     if (exact)
73         while (n < --lenlen)        /* pad length octets */
74             if (odr_putc(o, 0) < 0)
75                 return 0;
76     while (n--)
77         if (odr_putc(o, octs[n]) < 0)
78             return 0;
79     /* set length of length */
80     end = odr_tell(o);
81     odr_seek(o, ODR_S_SET, lenpos);
82     if (odr_putc(o, (end - lenpos - 1) | 0X80) < 0)
83         return 0;
84     odr_seek(o, ODR_S_END, 0);
85     return odr_tell(o) - lenpos;
86 }
87
88 /*
89  * Decode BER length octets. Returns number of bytes read or -1 for error.
90  * After return:
91  * len = -1   indefinite.
92  * len >= 0    Length.
93  */
94 int ber_declen(unsigned char *buf, int *len)
95 {
96     unsigned char *b = buf;
97     int n;
98
99     if (*b == 0X80)     /* Indefinite */
100     {
101         *len = -1;
102 #ifdef ODR_DEBUG
103         fprintf(stderr, "[len=%d]", *len);
104 #endif
105         return 1;
106     }
107     if (!(*b & 0X80))   /* Definite short form */
108     {
109         *len = (int) *b;
110 #ifdef ODR_DEBUG
111         fprintf(stderr, "[len=%d]", *len);
112 #endif
113         return 1;
114     }
115     if (*b == 0XFF)     /* reserved value */
116         return -1;
117     /* indefinite long form */ 
118     n = *b & 0X7F;
119     *len = 0;
120     b++;
121     while (n--)
122     {
123         *len <<= 8;
124         *len |= *(b++);
125     }
126 #ifdef ODR_DEBUG
127     fprintf(stderr, "[len=%d]", *len);
128 #endif
129     return (b - buf);
130 }