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