Doxyfile file description. Indentation. No change of code.
[yaz-moved-to-github.git] / src / ber_len.c
1 /*
2  * Copyright (C) 1995-2004, Index Data.
3  * See the file LICENSE for details.
4  *
5  * $Id: ber_len.c,v 1.2 2004-10-15 00:18:59 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 #ifdef ODR_DEBUG
39     fprintf(stderr, "[len=%d]", len);
40 #endif
41     if (len < 0)      /* Indefinite */
42     {
43         if (odr_putc(o, 0x80) < 0)
44             return 0;
45 #ifdef ODR_DEBUG
46         fprintf(stderr, "[indefinite]");
47 #endif
48         return 0;
49     }
50     if (len <= 127 && (lenlen == 1 || !exact)) /* definite short form */
51     {
52         if (odr_putc(o, (unsigned char) len) < 0)
53             return 0;
54         return 1;
55     }
56     if (lenlen == 1)
57     {
58         if (odr_putc(o, 0x80) < 0)
59             return 0;
60         return 0;
61     }
62     /* definite long form */
63     do
64     {
65         octs[n++] = len;
66         len >>= 8;
67     }
68     while (len);
69     if (n >= lenlen)
70         return -1;
71     lenpos = odr_tell(o); /* remember length-of-length position */
72     if (odr_putc(o, 0) < 0)  /* dummy */
73         return 0;
74     if (exact)
75         while (n < --lenlen)        /* pad length octets */
76             if (odr_putc(o, 0) < 0)
77                 return 0;
78     while (n--)
79         if (odr_putc(o, octs[n]) < 0)
80             return 0;
81     /* set length of length */
82     end = odr_tell(o);
83     odr_seek(o, ODR_S_SET, lenpos);
84     if (odr_putc(o, (end - lenpos - 1) | 0X80) < 0)
85         return 0;
86     odr_seek(o, ODR_S_END, 0);
87     return odr_tell(o) - lenpos;
88 }
89
90 /**
91  * ber_declen:
92  * Decode BER length octets. Returns 
93  *  > 0  : number of bytes read 
94  *   -1  : not enough room to read bytes within max bytes
95  *   -2  : other error
96  *
97  * After return:
98  * len = -1   indefinite length.
99  * len >= 0   definite length
100  */
101 int ber_declen(const unsigned char *buf, int *len, int max)
102 {
103     const unsigned char *b = buf;
104     int n;
105
106     if (max < 1)
107         return -1;
108     if (*b == 0X80)     /* Indefinite */
109     {
110         *len = -1;
111 #ifdef ODR_DEBUG
112         fprintf(stderr, "[len=%d]", *len);
113 #endif
114         return 1;
115     }
116     if (!(*b & 0X80))   /* Definite short form */
117     {
118         *len = (int) *b;
119 #ifdef ODR_DEBUG
120         fprintf(stderr, "[len=%d]", *len);
121 #endif
122         return 1;
123     }
124     if (*b == 0XFF)     /* reserved value */
125         return -2;
126     /* indefinite long form */ 
127     n = *b & 0X7F;
128     if (n >= max)
129         return -1;
130     *len = 0;
131     b++;
132     while (--n >= 0)
133     {
134         *len <<= 8;
135         *len |= *(b++);
136     }
137     if (*len < 0)
138         return -2;
139 #ifdef ODR_DEBUG
140     fprintf(stderr, "[len=%d]", *len);
141 #endif
142     return (b - buf);
143 }