A damn mess, but now things work, I think.
[yaz-moved-to-github.git] / odr / ber_int.c
1 /*
2  * Copyright (C) 1994, Index Data I/S 
3  * All rights reserved.
4  * Sebastian Hammer, Adam Dickmeiss
5  *
6  * $Log: ber_int.c,v $
7  * Revision 1.2  1995-02-07 17:52:58  quinn
8  * A damn mess, but now things work, I think.
9  *
10  * Revision 1.1  1995/02/02  16:21:52  quinn
11  * First kick.
12  *
13  */
14
15 #include <odr.h>
16 #include <netinet/in.h>
17 #include <string.h>
18
19 static int ber_encinteger(unsigned char *buf, int val, int maxlen);
20 static int ber_decinteger(unsigned char *buf, int *val);
21
22 int ber_integer(ODR o, int *val)
23 {
24     int res;
25
26     switch (o->direction)
27     {
28         case ODR_DECODE:
29             if ((res = ber_decinteger(o->bp, val)) <= 0)
30                 return 0;
31             o->bp += res;
32             o->left -= res;
33             return 1;
34         case ODR_ENCODE:
35             if ((res = ber_encinteger(o->bp, *val, o->left)) <= 0)
36                 return 0;
37             o->bp += res;
38             o->left -= res;
39             return 1;
40         case ODR_PRINT: return 1;
41         default:  return 0;
42     }
43 }
44
45 /*
46  * Returns: number of bytes written or -1 for error (out of bounds).
47  */
48 int ber_encinteger(unsigned char *buf, int val, int maxlen)
49 {
50     unsigned char *b = buf, *lenpos;
51     int a, len;
52     union { int i; unsigned char c[sizeof(int)]; } tmp;
53
54     lenpos = b;
55     maxlen--;
56     b++;
57
58     tmp.i = htonl(val);   /* ensure that that we're big-endian */
59     for (a = 0; a < sizeof(int) - 1; a++)  /* skip superfluous octets */
60         if (!((tmp.c[a] == 0 && !(tmp.c[a+1] & 0X80)) ||
61             (tmp.c[a] == 0XFF && (tmp.c[a+1] & 0X80))))
62             break;
63     if ((len = sizeof(int) - a) > maxlen)
64         return -1;
65     memcpy(b, tmp.c + a, len);
66     b += len;
67     if (ber_enclen(lenpos, len, 1, 1) != 1)
68         return -1;
69     fprintf(stderr, "[val=%d]", val);
70     return b - buf;
71 }
72
73 /*
74  * Returns: Number of bytes read or 0 if no match, -1 if error.
75  */
76 int ber_decinteger(unsigned char *buf, int *val)
77 {
78     unsigned char *b = buf, fill;
79     int res, len, remains;
80     union { int i; unsigned char c[sizeof(int)]; } tmp;
81
82     if ((res = ber_declen(b, &len)) < 0)
83         return -1;
84     if (len > sizeof(int))    /* let's be reasonable, here */
85         return -1;
86     b+= res;
87
88     remains = sizeof(int) - len;
89     memcpy(tmp.c + remains, b, len);
90     if (*b & 0X80)
91         fill = 0XFF;
92     else
93         fill = 0X00;
94     memset(tmp.c, fill, remains);
95     *val = ntohl(tmp.i);
96
97     b += len;
98     fprintf(stderr, "[val=%d]", *val);
99     return b - buf;
100 }