2 * Copyright 2009, Adrien Destugues, pulkomandy@gmail.com. All rights reserved.
3 * Distributed under the terms of the MIT License.
7 #include <HashMapCatalog.h>
18 * This is the standard implementation of a localization catalog, using a hash
19 * map. This class is abstract, you need to inherit it and provide methodes for
20 * reading and writing the catalog to a file. Classes doing that are
21 * HashMapCatalog and PlainTextCatalog.
22 * If you ever need to create a catalog not built around an hash map, inherit
23 * BCatalogData instead. Note that in this case you will not be able to use our
24 * development tools anymore.
28 CatKey::CatKey(const char *str
, const char *ctx
, const char *cmt
)
35 fHashVal
= HashFun(fString
.String(),0);
36 fHashVal
= HashFun(fContext
.String(),fHashVal
);
37 fHashVal
= HashFun(fComment
.String(),fHashVal
);
41 CatKey::CatKey(uint32 id
)
58 CatKey::operator== (const CatKey
& right
) const
60 // Two keys are equal if their hashval and key (string,context,comment)
61 // are equal (testing only the hash would not filter out collisions):
62 return fHashVal
== right
.fHashVal
63 && fString
== right
.fString
64 && fContext
== right
.fContext
65 && fComment
== right
.fComment
;
70 CatKey::operator!= (const CatKey
& right
) const
72 // Two keys are equal if their hashval and key (string,context,comment)
73 // are equal (testing only the hash would not filter out collisions):
74 return fHashVal
!= right
.fHashVal
75 || fString
!= right
.fString
76 || fContext
!= right
.fContext
77 || fComment
!= right
.fComment
;
82 CatKey::GetStringParts(BString
* str
, BString
* ctx
, BString
* cmt
) const
84 if (str
) *str
= fString
;
85 if (ctx
) *ctx
= fContext
;
86 if (cmt
) *cmt
= fComment
;
93 CatKey::HashFun(const char* s
, int startValue
) {
94 unsigned long h
= startValue
;
98 // Add 1 to differenciate ("ab","cd","ef") from ("abcd","e","f")
109 HashMapCatalog::MakeEmpty()
116 HashMapCatalog::CountItems() const
118 return fCatMap
.Size();
123 HashMapCatalog::GetString(const char *string
, const char *context
,
126 CatKey
key(string
, context
, comment
);
127 return GetString(key
);
132 HashMapCatalog::GetString(uint32 id
)
135 return GetString(key
);
140 HashMapCatalog::GetString(const CatKey
& key
)
142 BString value
= fCatMap
.Get(key
);
143 if (value
.Length() == 0)
146 return value
.String();
151 parseQuotedChars(BString
& stringToParse
)
153 char* in
= stringToParse
.LockBuffer(0);
168 else if (*in
== 'x') {
169 if (in
[1] == '\0' || in
[2] == '\0')
171 // Parse the 2-digit hex integer that follows
176 unsigned int hexchar
= strtoul(tmp
, NULL
, 16);
181 // drop quote from unknown quoting-sequence:
188 quoted
= (*in
== '\\');
198 stringToParse
.UnlockBuffer(newLength
);
205 HashMapCatalog::SetString(const char *string
, const char *translated
,
206 const char *context
, const char *comment
)
208 BString
stringCopy(string
);
209 status_t result
= parseQuotedChars(stringCopy
);
213 BString
translatedCopy(translated
);
214 if ((result
= parseQuotedChars(translatedCopy
)) != B_OK
)
217 BString
commentCopy(comment
);
218 if ((result
= parseQuotedChars(commentCopy
)) != B_OK
)
221 CatKey
key(stringCopy
.String(), context
, commentCopy
.String());
222 return fCatMap
.Put(key
, translatedCopy
.String());
223 // overwrite existing element
228 HashMapCatalog::SetString(int32 id
, const char *translated
)
230 BString
translatedCopy(translated
);
231 status_t result
= parseQuotedChars(translatedCopy
);
235 return fCatMap
.Put(key
, translatedCopy
.String());
236 // overwrite existing element
241 HashMapCatalog::SetString(const CatKey
& key
, const char *translated
)
243 BString
translatedCopy(translated
);
244 status_t result
= parseQuotedChars(translatedCopy
);
247 return fCatMap
.Put(key
, translatedCopy
.String());
248 // overwrite existing element
253 * computes a checksum (we call it fingerprint) on all the catalog-keys. We do
254 * not include the values, since we want catalogs for different languages of the
255 * same app to have the same fingerprint, since we use it to separate different
256 * catalog-versions. We use a simple sum because there is no well known
257 * checksum algorithm that gives the same result if the string are sorted in the
258 * wrong order, and this does happen, as an hash map is an unsorted container.
261 HashMapCatalog::ComputeFingerprint() const
266 CatMap::Iterator iter
= fCatMap
.GetIterator();
268 while (iter
.HasNext())
271 hash
= B_HOST_TO_LENDIAN_INT32(entry
.key
.fHashVal
);
279 HashMapCatalog::UpdateFingerprint()
281 fFingerprint
= ComputeFingerprint();
285 } // namespace BPrivate