Teach rpmtd about the raw i18n string (array) type
[platform/upstream/rpm.git] / lib / rpmtd.c
1 #include "system.h"
2
3 #include <rpm/rpmtd.h>
4 #include <rpm/rpmstring.h>
5
6 #include "debug.h"
7
8 rpmtd rpmtdNew(void)
9 {
10     rpmtd td = xmalloc(sizeof(*td));
11     rpmtdReset(td);
12     return td;
13 }
14
15 rpmtd rpmtdFree(rpmtd td)
16 {
17     /* permit free on NULL td */
18     if (td != NULL) {
19         /* XXX should we free data too - a flag maybe? */
20         free(td);
21     }
22     return NULL;
23 }
24
25 void rpmtdReset(rpmtd td)
26 {
27     assert(td != NULL);
28
29     memset(td, 0, sizeof(*td));
30     td->ix = -1;
31 }
32
33 void rpmtdFreeData(rpmtd td)
34 {
35     assert(td != NULL);
36
37     if (td->freeData) {
38         free(td->data);
39     }
40     rpmtdReset(td);
41 }
42
43 rpm_count_t rpmtdCount(rpmtd td)
44 {
45     assert(td != NULL);
46     return td->count;
47 }
48
49 rpmTag rpmtdTag(rpmtd td)
50 {
51     assert(td != NULL);
52     return td->tag;
53 }
54
55 rpmTagType rpmtdType(rpmtd td)
56 {
57     assert(td != NULL);
58     return td->type;
59 }
60
61 int rpmtdInit(rpmtd td)
62 {
63     assert(td != NULL);
64
65     /* XXX check that this is an array type? */
66     td->ix = -1;
67     return 0;
68 }
69
70 int rpmtdNext(rpmtd td)
71 {
72     int i = -1;
73
74     assert(td != NULL);
75     if (++td->ix >= 0) {
76         if (td->ix < td->count) {
77             i = td->ix;
78         } else {
79             td->ix = i;
80         }
81     }
82     return i;
83 }
84
85 uint16_t * rpmtdGetUint16(rpmtd td)
86 {
87     uint16_t *res = NULL;
88
89     assert(td != NULL);
90
91     if (td->type == RPM_INT16_TYPE) {
92         int ix = (td->ix >= 0 ? td->ix : 0);
93         res = (uint16_t *) td->data + ix;
94     } 
95     return res;
96 }
97
98 uint32_t * rpmtdGetUint32(rpmtd td)
99 {
100     uint32_t *res = NULL;
101
102     assert(td != NULL);
103
104     if (td->type == RPM_INT32_TYPE) {
105         int ix = (td->ix >= 0 ? td->ix : 0);
106         res = (uint32_t *) td->data + ix;
107     } 
108     return res;
109 }
110 const char * rpmtdGetString(rpmtd td)
111 {
112     const char *str = NULL;
113
114     assert(td != NULL);
115
116     if (td->type == RPM_STRING_TYPE) {
117         str = (const char *) td->data;
118     } else if (td->type == RPM_STRING_ARRAY_TYPE ||
119                td->type == RPM_I18NSTRING_TYPE) {
120         /* XXX TODO: check for array bounds */
121         int ix = (td->ix >= 0 ? td->ix : 0);
122         str = *((const char**) td->data + ix);
123     } 
124     return str;
125 }
126
127 char *rpmtdToString(rpmtd td)
128 {
129     char *res = NULL;
130
131     switch (td->type) {
132         case RPM_STRING_TYPE:
133         case RPM_I18NSTRING_TYPE:
134         case RPM_STRING_ARRAY_TYPE: {
135             const char *s = rpmtdGetString(td);
136             if (s) {
137                 res = xstrdup(s);
138             }
139             break;
140         }
141         case RPM_INT16_TYPE: {
142             uint16_t *num = rpmtdGetUint16(td);
143             if (num) {
144                 rasprintf(&res, "%hd", *num);
145             }
146             break;
147         }
148         case RPM_INT32_TYPE: {
149             uint32_t *num = rpmtdGetUint32(td);
150             if (num) {
151                 rasprintf(&res, "%d", *num);
152             }
153             break;
154         }
155         case RPM_BIN_TYPE: {
156             /* XXX TODO: convert to hex presentation */
157         }
158         default:
159             break;
160     }
161     return res;
162 }
163
164 int rpmtdFromArgv(rpmtd td, rpmTag tag, ARGV_t argv)
165 {
166     int count = argvCount(argv);
167     rpmTagType type = rpmTagGetType(tag) & RPM_MASK_TYPE;
168
169     if (type != RPM_STRING_ARRAY_TYPE || count < 1)
170         return 0;
171
172     assert(td != NULL);
173     rpmtdReset(td);
174     td->type = type;
175     td->tag = tag;
176     td->count = count;
177     td->data = argv;
178     return 1;
179 }
180
181 int rpmtdFromArgi(rpmtd td, rpmTag tag, ARGI_t argi)
182 {
183     int count = argiCount(argi);
184     rpmTagType type = rpmTagGetType(tag) & RPM_MASK_TYPE;
185     rpmTagReturnType retype = rpmTagGetType(tag) & RPM_MASK_RETURN_TYPE;
186
187     if (type != RPM_INT32_TYPE || retype != RPM_ARRAY_RETURN_TYPE || count < 1)
188         return 0;
189
190     assert(td != NULL);
191     rpmtdReset(td);
192     td->type = type;
193     td->tag = tag;
194     td->count = count;
195     td->data = argiData(argi);
196     return 1;
197 }