1// © 2016 and later: Unicode, Inc. and others.
2// License & terms of use: http://www.unicode.org/copyright.html
3/********************************************************************
4 * COPYRIGHT:
5 * Copyright (c) 2002-2006, International Business Machines Corporation and
6 * others. All Rights Reserved.
7 ********************************************************************/
8
9/* Created by weiv 05/09/2002 */
10
11#include "unicode/datamap.h"
12#include "unicode/resbund.h"
13#include "unicode/unistr.h"
14#include "hash.h"
15#include <stdlib.h>
16
17DataMap::~DataMap() {}
18DataMap::DataMap() {}
19
20int32_t
21DataMap::utoi(const UnicodeString &s) const
22{
23  char ch[256];
24  const UChar *u = toUCharPtr(s.getBuffer());
25  int32_t len = s.length();
26  u_UCharsToChars(u, ch, len);
27  ch[len] = 0; /* include terminating \0 */
28  return atoi(ch);
29}
30
31U_CDECL_BEGIN
32void U_CALLCONV
33deleteResBund(void *obj) {
34  delete (ResourceBundle *)obj;
35}
36U_CDECL_END
37
38
39RBDataMap::~RBDataMap()
40{
41  delete fData;
42}
43
44RBDataMap::RBDataMap()
45{
46  UErrorCode status = U_ZERO_ERROR;
47  fData = new Hashtable(TRUE, status);
48  fData->setValueDeleter(deleteResBund);
49}
50
51// init from table resource
52// will put stuff in hashtable according to
53// keys.
54RBDataMap::RBDataMap(UResourceBundle *data, UErrorCode &status)
55{
56  fData = new Hashtable(TRUE, status);
57  fData->setValueDeleter(deleteResBund);
58  init(data, status);
59}
60
61// init from headers and resource
62// with checking the whether the size of resource matches
63// header size
64RBDataMap::RBDataMap(UResourceBundle *headers, UResourceBundle *data, UErrorCode &status)
65{
66  fData = new Hashtable(TRUE, status);
67  fData->setValueDeleter(deleteResBund);
68  init(headers, data, status);
69}
70
71
72void RBDataMap::init(UResourceBundle *data, UErrorCode &status) {
73  int32_t i = 0;
74  fData->removeAll();
75  UResourceBundle *t = NULL;
76  for(i = 0; i < ures_getSize(data); i++) {
77    t = ures_getByIndex(data, i, t, &status);
78    fData->put(UnicodeString(ures_getKey(t), -1, US_INV), new ResourceBundle(t, status), status);
79  }
80  ures_close(t);
81}
82
83void RBDataMap::init(UResourceBundle *headers, UResourceBundle *data, UErrorCode &status)
84{
85  int32_t i = 0;
86  fData->removeAll();
87  UResourceBundle *t = NULL;
88  const UChar *key = NULL;
89  int32_t keyLen = 0;
90  if(ures_getSize(headers) == ures_getSize(data)) {
91    for(i = 0; i < ures_getSize(data); i++) {
92      t = ures_getByIndex(data, i, t, &status);
93      key = ures_getStringByIndex(headers, i, &keyLen, &status);
94      fData->put(UnicodeString(key, keyLen), new ResourceBundle(t, status), status);
95    }
96  } else {
97    // error
98    status = U_INVALID_FORMAT_ERROR;
99  }
100  ures_close(t);
101}
102
103const ResourceBundle *RBDataMap::getItem(const char* key, UErrorCode &status) const
104{
105  if(U_FAILURE(status)) {
106    return NULL;
107  }
108
109  UnicodeString hashKey(key, -1, US_INV);
110  const ResourceBundle *r = (ResourceBundle *)fData->get(hashKey);
111  if(r != NULL) {
112    return r;
113  } else {
114    status = U_MISSING_RESOURCE_ERROR;
115    return NULL;
116  }
117}
118
119const UnicodeString RBDataMap::getString(const char* key, UErrorCode &status) const
120{
121  const ResourceBundle *r = getItem(key, status);
122  if(U_SUCCESS(status)) {
123    return r->getString(status);
124  } else {
125    return UnicodeString();
126  }
127}
128
129int32_t
130RBDataMap::getInt28(const char* key, UErrorCode &status) const
131{
132  const ResourceBundle *r = getItem(key, status);
133  if(U_SUCCESS(status)) {
134    return r->getInt(status);
135  } else {
136    return 0;
137  }
138}
139
140uint32_t
141RBDataMap::getUInt28(const char* key, UErrorCode &status) const
142{
143  const ResourceBundle *r = getItem(key, status);
144  if(U_SUCCESS(status)) {
145    return r->getUInt(status);
146  } else {
147    return 0;
148  }
149}
150
151const int32_t *
152RBDataMap::getIntVector(int32_t &length, const char *key, UErrorCode &status) const {
153  const ResourceBundle *r = getItem(key, status);
154  if(U_SUCCESS(status)) {
155    return r->getIntVector(length, status);
156  } else {
157    return NULL;
158  }
159}
160
161const uint8_t *
162RBDataMap::getBinary(int32_t &length, const char *key, UErrorCode &status) const {
163  const ResourceBundle *r = getItem(key, status);
164  if(U_SUCCESS(status)) {
165    return r->getBinary(length, status);
166  } else {
167    return NULL;
168  }
169}
170
171int32_t RBDataMap::getInt(const char* key, UErrorCode &status) const
172{
173  UnicodeString r = this->getString(key, status);
174  if(U_SUCCESS(status)) {
175    return utoi(r);
176  } else {
177    return 0;
178  }
179}
180
181const UnicodeString* RBDataMap::getStringArray(int32_t& count, const char* key, UErrorCode &status) const
182{
183  const ResourceBundle *r = getItem(key, status);
184  if(U_SUCCESS(status)) {
185    int32_t i = 0;
186
187    count = r->getSize();
188    if(count <= 0) {
189      return NULL;
190    }
191
192    UnicodeString *result = new UnicodeString[count];
193    for(i = 0; i<count; i++) {
194      result[i] = r->getStringEx(i, status);
195    }
196    return result;
197  } else {
198    return NULL;
199  }
200}
201
202const int32_t* RBDataMap::getIntArray(int32_t& count, const char* key, UErrorCode &status) const
203{
204  const ResourceBundle *r = getItem(key, status);
205  if(U_SUCCESS(status)) {
206    int32_t i = 0;
207
208    count = r->getSize();
209    if(count <= 0) {
210      return NULL;
211    }
212
213    int32_t *result = new int32_t[count];
214    UnicodeString stringRes;
215    for(i = 0; i<count; i++) {
216      stringRes = r->getStringEx(i, status);
217      result[i] = utoi(stringRes);
218    }
219    return result;
220  } else {
221    return NULL;
222  }
223}
224
225