Fixed bug #830: pkg-config support. YAZ installs yaz.pc for Debian
[yaz-moved-to-github.git] / src / ber_int.c
1 /*
2  * Copyright (C) 1995-2007, Index Data ApS
3  * See the file LICENSE for details.
4  *
5  * $Id: ber_int.c,v 1.7 2007-01-03 08:42:15 adam Exp $
6  */
7
8 /** 
9  * \file ber_int.c
10  * \brief Implements BER INTEGER encoding and decoding.
11  *
12  * This source file implements BER encoding and decoding of
13  * the INTEGER type.
14  */
15
16 #if HAVE_CONFIG_H
17 #include <config.h>
18 #endif
19
20 #include <string.h>
21
22 #if HAVE_SYS_TYPES_H
23 #include <sys/types.h>
24 #endif
25
26 #ifdef WIN32
27 #include <winsock.h>
28 #else
29 #include <netinet/in.h>
30 #endif
31
32 #include "odr-priv.h"
33
34 static int ber_encinteger(ODR o, int val);
35 static int ber_decinteger(const unsigned char *buf, int *val, int max);
36
37 int ber_integer(ODR o, int *val)
38 {
39     int res;
40
41     switch (o->direction)
42     {
43     case ODR_DECODE:
44         if ((res = ber_decinteger(o->bp, val, odr_max(o))) <= 0)
45         {
46             odr_seterror(o, OPROTO, 50);
47             return 0;
48         }
49         o->bp += res;
50         return 1;
51     case ODR_ENCODE:
52         if ((res = ber_encinteger(o, *val)) < 0)
53             return 0;
54         return 1;
55     case ODR_PRINT:
56         return 1;
57     default:
58         odr_seterror(o, OOTHER, 51);  return 0;
59     }
60 }
61
62 /*
63  * Returns: number of bytes written or -1 for error (out of bounds).
64  */
65 int ber_encinteger(ODR o, int val)
66 {
67     int a, len;
68     union { int i; unsigned char c[sizeof(int)]; } tmp;
69
70     tmp.i = htonl(val);   /* ensure that that we're big-endian */
71     for (a = 0; a < (int) sizeof(int) - 1; a++)  /* skip superfluous octets */
72         if (!((tmp.c[a] == 0 && !(tmp.c[a+1] & 0X80)) ||
73             (tmp.c[a] == 0XFF && (tmp.c[a+1] & 0X80))))
74             break;
75     len = sizeof(int) - a;
76     if (ber_enclen(o, len, 1, 1) != 1)
77         return -1;
78     if (odr_write(o, (unsigned char*) tmp.c + a, len) < 0)
79         return -1;
80     return 0;
81 }
82
83 /*
84  * Returns: Number of bytes read or 0 if no match, -1 if error.
85  */
86 int ber_decinteger(const unsigned char *buf, int *val, int max)
87 {
88     const unsigned char *b = buf;
89     unsigned char fill;
90     int res, len, remains;
91     union { int i; unsigned char c[sizeof(int)]; } tmp;
92
93     if ((res = ber_declen(b, &len, max)) < 0)
94         return -1;
95     if (len+res > max || len < 0) /* out of bounds or indefinite encoding */
96         return -1;  
97     if (len > (int) sizeof(int))  /* let's be reasonable, here */
98         return -1;
99     b+= res;
100
101     remains = sizeof(int) - len;
102     memcpy(tmp.c + remains, b, len);
103     if (*b & 0X80)
104         fill = 0XFF;
105     else
106         fill = 0X00;
107     memset(tmp.c, fill, remains);
108     *val = ntohl(tmp.i);
109
110     b += len;
111     return b - buf;
112 }
113 /*
114  * Local variables:
115  * c-basic-offset: 4
116  * indent-tabs-mode: nil
117  * End:
118  * vim: shiftwidth=4 tabstop=8 expandtab
119  */
120