vfs: check userland buffers before reading them.
[haiku.git] / src / kits / locale / TimeZone.cpp
blobd4860c64632aa39f61110054909ca6c04eedf834
1 /*
2 * Copyright (c) 2010, Haiku, Inc.
3 * Distributed under the terms of the MIT license.
5 * Authors:
6 * Adrien Destugues <pulkomandy@pulkomandy.ath.cx>
7 * Oliver Tappe <zooey@hirschkaefer.de>
8 */
11 #include <unicode/uversion.h>
12 #include <TimeZone.h>
14 #include <new>
16 #include <unicode/locid.h>
17 #include <unicode/timezone.h>
18 #include <ICUWrapper.h>
20 #include <Language.h>
23 const char* BTimeZone::kNameOfGmtZone = "GMT";
26 static const BString skEmptyString;
29 static const uint32 skNameField = 1U << 0;
30 static const uint32 skDaylightSavingNameField = 1U << 1;
31 static const uint32 skShortNameField = 1U << 2;
32 static const uint32 skShortDaylightSavingNameField = 1U << 3;
33 static const uint32 skLongGenericNameField = 1U << 4;
34 static const uint32 skGenericLocationNameField = 1U << 5;
35 static const uint32 skShortCommonlyUsedNameField = 1U << 6;
36 static const uint32 skSupportsDaylightSavingField = 1U << 7;
37 static const uint32 skOffsetFromGMTField = 1U << 8;
40 BTimeZone::BTimeZone(const char* zoneID, const BLanguage* language)
42 fICUTimeZone(NULL),
43 fICULocale(NULL),
44 fInitStatus(B_NO_INIT),
45 fInitializedFields(0)
47 SetTo(zoneID, language);
51 BTimeZone::BTimeZone(const BTimeZone& other)
53 fICUTimeZone(other.fICUTimeZone == NULL
54 ? NULL
55 : other.fICUTimeZone->clone()),
56 fICULocale(other.fICULocale == NULL
57 ? NULL
58 : other.fICULocale->clone()),
59 fInitStatus(other.fInitStatus),
60 fInitializedFields(other.fInitializedFields),
61 fZoneID(other.fZoneID),
62 fName(other.fName),
63 fDaylightSavingName(other.fDaylightSavingName),
64 fShortName(other.fShortName),
65 fShortDaylightSavingName(other.fShortDaylightSavingName),
66 fOffsetFromGMT(other.fOffsetFromGMT),
67 fSupportsDaylightSaving(other.fSupportsDaylightSaving)
72 BTimeZone::~BTimeZone()
74 delete fICULocale;
75 delete fICUTimeZone;
79 BTimeZone& BTimeZone::operator=(const BTimeZone& source)
81 delete fICUTimeZone;
82 fICUTimeZone = source.fICUTimeZone == NULL
83 ? NULL
84 : source.fICUTimeZone->clone();
85 fICULocale = source.fICULocale == NULL
86 ? NULL
87 : source.fICULocale->clone();
88 fInitStatus = source.fInitStatus;
89 fInitializedFields = source.fInitializedFields;
90 fZoneID = source.fZoneID;
91 fName = source.fName;
92 fDaylightSavingName = source.fDaylightSavingName;
93 fShortName = source.fShortName;
94 fShortDaylightSavingName = source.fShortDaylightSavingName;
95 fOffsetFromGMT = source.fOffsetFromGMT;
96 fSupportsDaylightSaving = source.fSupportsDaylightSaving;
98 return *this;
102 const BString&
103 BTimeZone::ID() const
105 return fZoneID;
109 const BString&
110 BTimeZone::Name() const
112 if ((fInitializedFields & skNameField) == 0) {
113 UnicodeString unicodeString;
114 if (fICULocale != NULL) {
115 fICUTimeZone->getDisplayName(false, TimeZone::GENERIC_LOCATION,
116 *fICULocale, unicodeString);
117 } else {
118 fICUTimeZone->getDisplayName(false, TimeZone::GENERIC_LOCATION,
119 unicodeString);
121 BStringByteSink sink(&fName);
122 unicodeString.toUTF8(sink);
123 fInitializedFields |= skNameField;
126 return fName;
130 const BString&
131 BTimeZone::DaylightSavingName() const
133 if ((fInitializedFields & skDaylightSavingNameField) == 0) {
134 UnicodeString unicodeString;
135 if (fICULocale != NULL) {
136 fICUTimeZone->getDisplayName(true, TimeZone::GENERIC_LOCATION,
137 *fICULocale, unicodeString);
138 } else {
139 fICUTimeZone->getDisplayName(true, TimeZone::GENERIC_LOCATION,
140 unicodeString);
142 BStringByteSink sink(&fDaylightSavingName);
143 unicodeString.toUTF8(sink);
144 fInitializedFields |= skDaylightSavingNameField;
147 return fDaylightSavingName;
151 const BString&
152 BTimeZone::ShortName() const
154 if ((fInitializedFields & skShortNameField) == 0) {
155 UnicodeString unicodeString;
156 if (fICULocale != NULL) {
157 fICUTimeZone->getDisplayName(false, TimeZone::SHORT, *fICULocale,
158 unicodeString);
159 } else {
160 fICUTimeZone->getDisplayName(false, TimeZone::SHORT, unicodeString);
162 BStringByteSink sink(&fShortName);
163 unicodeString.toUTF8(sink);
164 fInitializedFields |= skShortNameField;
167 return fShortName;
171 const BString&
172 BTimeZone::ShortDaylightSavingName() const
174 if ((fInitializedFields & skShortDaylightSavingNameField) == 0) {
175 UnicodeString unicodeString;
176 if (fICULocale != NULL) {
177 fICUTimeZone->getDisplayName(true, TimeZone::SHORT, *fICULocale,
178 unicodeString);
179 } else {
180 fICUTimeZone->getDisplayName(true, TimeZone::SHORT, unicodeString);
182 BStringByteSink sink(&fShortDaylightSavingName);
183 unicodeString.toUTF8(sink);
184 fInitializedFields |= skShortDaylightSavingNameField;
187 return fShortDaylightSavingName;
192 BTimeZone::OffsetFromGMT() const
194 if ((fInitializedFields & skOffsetFromGMTField) == 0) {
195 int32_t rawOffset;
196 int32_t dstOffset;
197 UDate nowMillis = 1000 * (double)time(NULL);
199 UErrorCode error = U_ZERO_ERROR;
200 fICUTimeZone->getOffset(nowMillis, FALSE, rawOffset, dstOffset, error);
201 if (!U_SUCCESS(error))
202 fOffsetFromGMT = 0;
203 else {
204 fOffsetFromGMT = (rawOffset + dstOffset) / 1000;
205 // we want seconds, not ms (which ICU gives us)
207 fInitializedFields |= skOffsetFromGMTField;
210 return fOffsetFromGMT;
214 bool
215 BTimeZone::SupportsDaylightSaving() const
217 if ((fInitializedFields & skSupportsDaylightSavingField) == 0) {
218 fSupportsDaylightSaving = fICUTimeZone->useDaylightTime();
219 fInitializedFields |= skSupportsDaylightSavingField;
222 return fSupportsDaylightSaving;
226 status_t
227 BTimeZone::InitCheck() const
229 return fInitStatus;
233 status_t
234 BTimeZone::SetLanguage(const BLanguage* language)
236 return SetTo(fZoneID, language);
240 status_t
241 BTimeZone::SetTo(const char* zoneID, const BLanguage* language)
243 delete fICULocale;
244 fICULocale = NULL;
245 delete fICUTimeZone;
246 fInitializedFields = 0;
248 if (zoneID == NULL || zoneID[0] == '\0')
249 fICUTimeZone = TimeZone::createDefault();
250 else
251 fICUTimeZone = TimeZone::createTimeZone(zoneID);
253 if (fICUTimeZone == NULL) {
254 fInitStatus = B_NAME_NOT_FOUND;
255 return fInitStatus;
258 if (language != NULL) {
259 fICULocale = new Locale(language->Code());
260 if (fICULocale == NULL) {
261 fInitStatus = B_NO_MEMORY;
262 return fInitStatus;
266 UnicodeString unicodeString;
267 fICUTimeZone->getID(unicodeString);
268 BStringByteSink sink(&fZoneID);
269 unicodeString.toUTF8(sink);
271 fInitStatus = B_OK;
273 return fInitStatus;