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