Adding initial code jy.oak@samsung.com
[ric-app/kpimon.git] / asn1c_defs / all-defs / ber_tlv_tag.c
1 /*-\r
2  * Copyright (c) 2003, 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.\r
3  * Redistribution and modifications are permitted subject to BSD license.\r
4  */\r
5 #include <asn_internal.h>\r
6 #include <ber_tlv_tag.h>\r
7 #include <errno.h>\r
8 \r
9 ssize_t\r
10 ber_fetch_tag(const void *ptr, size_t size, ber_tlv_tag_t *tag_r) {\r
11         ber_tlv_tag_t val;\r
12         ber_tlv_tag_t tclass;\r
13         size_t skipped;\r
14 \r
15         if(size == 0)\r
16                 return 0;\r
17 \r
18         val = *(const uint8_t *)ptr;\r
19         tclass = (val >> 6);\r
20         if((val &= 0x1F) != 0x1F) {\r
21                 /*\r
22                  * Simple form: everything encoded in a single octet.\r
23                  * Tag Class is encoded using two least significant bits.\r
24                  */\r
25                 *tag_r = (val << 2) | tclass;\r
26                 return 1;\r
27         }\r
28 \r
29         /*\r
30          * Each octet contains 7 bits of useful information.\r
31          * The MSB is 0 if it is the last octet of the tag.\r
32          */\r
33         for(val = 0, ptr = ((const char *)ptr) + 1, skipped = 2;\r
34                         skipped <= size;\r
35                                 ptr = ((const char *)ptr) + 1, skipped++) {\r
36                 unsigned int oct = *(const uint8_t *)ptr;\r
37                 if(oct & 0x80) {\r
38                         val = (val << 7) | (oct & 0x7F);\r
39                         /*\r
40                          * Make sure there are at least 9 bits spare\r
41                          * at the MS side of a value.\r
42                          */\r
43                         if(val >> ((8 * sizeof(val)) - 9)) {\r
44                                 /*\r
45                                  * We would not be able to accomodate\r
46                                  * any more tag bits.\r
47                                  */\r
48                                 return -1;\r
49                         }\r
50                 } else {\r
51                         val = (val << 7) | oct;\r
52                         *tag_r = (val << 2) | tclass;\r
53                         return skipped;\r
54                 }\r
55         }\r
56 \r
57         return 0;       /* Want more */\r
58 }\r
59 \r
60 \r
61 ssize_t\r
62 ber_tlv_tag_fwrite(ber_tlv_tag_t tag, FILE *f) {\r
63         char buf[sizeof("[APPLICATION ]") + 32];\r
64         ssize_t ret;\r
65 \r
66         ret = ber_tlv_tag_snprint(tag, buf, sizeof(buf));\r
67         if(ret >= (ssize_t)sizeof(buf) || ret < 2) {\r
68                 errno = EPERM;\r
69                 return -1;\r
70         }\r
71 \r
72         return fwrite(buf, 1, ret, f);\r
73 }\r
74 \r
75 ssize_t\r
76 ber_tlv_tag_snprint(ber_tlv_tag_t tag, char *buf, size_t size) {\r
77         const char *type = 0;\r
78         int ret;\r
79 \r
80         switch(tag & 0x3) {\r
81         case ASN_TAG_CLASS_UNIVERSAL:   type = "UNIVERSAL ";    break;\r
82         case ASN_TAG_CLASS_APPLICATION: type = "APPLICATION ";  break;\r
83         case ASN_TAG_CLASS_CONTEXT:     type = "";              break;\r
84         case ASN_TAG_CLASS_PRIVATE:     type = "PRIVATE ";      break;\r
85         }\r
86 \r
87         ret = snprintf(buf, size, "[%s%u]", type, ((unsigned)tag) >> 2);\r
88         if(ret <= 0 && size) buf[0] = '\0';     /* against broken libc's */\r
89 \r
90         return ret;\r
91 }\r
92 \r
93 char *\r
94 ber_tlv_tag_string(ber_tlv_tag_t tag) {\r
95         static char buf[sizeof("[APPLICATION ]") + 32];\r
96 \r
97         (void)ber_tlv_tag_snprint(tag, buf, sizeof(buf));\r
98 \r
99         return buf;\r
100 }\r
101 \r
102 \r
103 size_t\r
104 ber_tlv_tag_serialize(ber_tlv_tag_t tag, void *bufp, size_t size) {\r
105         int tclass = BER_TAG_CLASS(tag);\r
106         ber_tlv_tag_t tval = BER_TAG_VALUE(tag);\r
107         uint8_t *buf = (uint8_t *)bufp;\r
108         uint8_t *end;\r
109         size_t required_size;\r
110         size_t i;\r
111 \r
112         if(tval <= 30) {\r
113                 /* Encoded in 1 octet */\r
114                 if(size) buf[0] = (tclass << 6) | tval;\r
115                 return 1;\r
116         } else if(size) {\r
117                 *buf++ = (tclass << 6) | 0x1F;\r
118                 size--;\r
119         }\r
120 \r
121         /*\r
122          * Compute the size of the subsequent bytes.\r
123          */\r
124         for(required_size = 1, i = 7; i < 8 * sizeof(tval); i += 7) {\r
125                 if(tval >> i)\r
126                         required_size++;\r
127                 else\r
128                         break;\r
129         }\r
130 \r
131         if(size < required_size)\r
132                 return required_size + 1;\r
133 \r
134         /*\r
135          * Fill in the buffer, space permitting.\r
136          */\r
137         end = buf + required_size - 1;\r
138         for(i -= 7; buf < end; i -= 7, buf++)\r
139                 *buf = 0x80 | ((tval >> i) & 0x7F);\r
140         *buf = (tval & 0x7F);   /* Last octet without high bit */\r
141 \r
142         return required_size + 1;\r
143 }\r
144 \r