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