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