Second (and last) part of fixing #7226:

* fix most obvious problems in parseQuotedChars()
* drop separate HashMapCatalog in tools-folder, which isn't much 
  different from the original one (we now just use that one instead)


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@40527 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Oliver Tappe 2011-02-16 10:53:46 +00:00
parent 8a990d5228
commit efccf04aaf
3 changed files with 36 additions and 281 deletions

View File

@ -11,6 +11,9 @@
#include <stdlib.h>
namespace BPrivate {
/*
* This is the standard implementation of a localization catalog, using a hash
* map. This class is abstract, you need to inherit it and provide methodes for
@ -86,7 +89,8 @@ CatKey::GetStringParts(BString* str, BString* ctx, BString* cmt) const
}
uint32 CatKey::HashFun(const char* s, int startValue) {
uint32
CatKey::HashFun(const char* s, int startValue) {
unsigned long h = startValue;
for ( ; *s; ++s)
h = 5 * h + *s;
@ -97,7 +101,7 @@ uint32 CatKey::HashFun(const char* s, int startValue) {
return size_t(h);
}
// (end CatKey)
// BHashMapCatalog
@ -143,15 +147,17 @@ BHashMapCatalog::GetString(const CatKey& key)
}
void
static status_t
parseQuotedChars(BString& stringToParse)
{
char* in = stringToParse.LockBuffer(0);
if (in == NULL)
return B_ERROR;
char* out = in;
int newLength = 0;
bool quoted = false;
while (*in != 0 || quoted) {
while (*in != 0) {
if (quoted) {
if (*in == 'n')
*out = '\n';
@ -160,17 +166,19 @@ parseQuotedChars(BString& stringToParse)
else if (*in == '"')
*out = '"';
else if (*in == 'x') {
if (in[1] == '\0' || in[2] == '\0')
break;
// Parse the 2-digit hex integer that follows
char tmp[3];
tmp[0] = *(in+1);
tmp[1] = *(in+2);
tmp[0] = in[1];
tmp[1] = in[2];
tmp[2] = '\0';
unsigned int hexchar = strtoul(tmp, NULL, 16);
*out = hexchar;
// skip the number
in += 2;
} else {
// dump quote from unknown quoting-sequence:
// drop quote from unknown quoting-sequence:
*out = *in ;
}
quoted = false;
@ -187,7 +195,9 @@ parseQuotedChars(BString& stringToParse)
in++;
}
*out = '\0';
stringToParse.UnlockBuffer();
stringToParse.UnlockBuffer(newLength);
return B_OK;
}
@ -197,12 +207,14 @@ BHashMapCatalog::SetString(const char *string, const char *translated,
{
BString stringCopy(string);
BString translatedCopy(translated);
parseQuotedChars(stringCopy);
parseQuotedChars(translatedCopy);
status_t result = parseQuotedChars(stringCopy);
if (result != B_OK)
return result;
if ((result = parseQuotedChars(translatedCopy)) != B_OK)
return result;
CatKey key(stringCopy.String(), context, comment);
fCatMap.Put(key, translatedCopy.String());
return fCatMap.Put(key, translatedCopy.String());
// overwrite existing element
return B_OK;
}
@ -210,11 +222,12 @@ status_t
BHashMapCatalog::SetString(int32 id, const char *translated)
{
BString translatedCopy(translated);
parseQuotedChars(translatedCopy);
status_t result = parseQuotedChars(translatedCopy);
if (result != B_OK)
return result;
CatKey key(id);
fCatMap.Put(key, translatedCopy.String());
return fCatMap.Put(key, translatedCopy.String());
// overwrite existing element
return B_OK;
}
@ -222,10 +235,11 @@ status_t
BHashMapCatalog::SetString(const CatKey& key, const char *translated)
{
BString translatedCopy(translated);
parseQuotedChars(translatedCopy);
fCatMap.Put(key, translatedCopy.String());
status_t result = parseQuotedChars(translatedCopy);
if (result != B_OK)
return result;
return fCatMap.Put(key, translatedCopy.String());
// overwrite existing element
return B_OK;
}
@ -260,3 +274,6 @@ BHashMapCatalog::UpdateFingerprint()
{
fFingerprint = ComputeFingerprint();
}
} // namespace BPrivate

View File

@ -1,263 +0,0 @@
/*
* Copyright 2009, Adrien Destugues, pulkomandy@gmail.com. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#include <HashMapCatalog.h>
#include <ByteOrder.h>
#include <stdlib.h>
/*
* This is the standard implementation of a localization catalog, using a hash
* map. This class is abstract, you need to inherit it and provide methodes for
* reading and writing the catalog to a file. Classes doing that are
* HashMapCatalog and PlainTextCatalog.
* If you ever need to create a catalog not built around an hash map, inherit
* BCatalogAddOn instead. Note that in this case you will not be able to use our
* development tools anymore.
*/
extern "C" uint32 adler32(uint32 adler, const uint8 *buf, uint32 len);
// definition lives in adler32.c
CatKey::CatKey(const char *str, const char *ctx, const char *cmt)
:
fString(str),
fContext(ctx),
fComment(cmt),
fFlags(0)
{
fHashVal = HashFun(fString.String(),0);
fHashVal = HashFun(fContext.String(),fHashVal);
fHashVal = HashFun(fComment.String(),fHashVal);
}
CatKey::CatKey(uint32 id)
:
fHashVal(id),
fFlags(0)
{
}
CatKey::CatKey()
:
fHashVal(0),
fFlags(0)
{
}
bool
CatKey::operator== (const CatKey& right) const
{
// Two keys are equal if their hashval and key (string,context,comment)
// are equal (testing only the hash would not filter out collisions):
return fHashVal == right.fHashVal
&& fString == right.fString
&& fContext == right.fContext
&& fComment == right.fComment;
}
bool
CatKey::operator!= (const CatKey& right) const
{
// Two keys are equal if their hashval and key (string,context,comment)
// are equal (testing only the hash would not filter out collisions):
return fHashVal != right.fHashVal
|| fString != right.fString
|| fContext != right.fContext
|| fComment != right.fComment;
}
status_t
CatKey::GetStringParts(BString* str, BString* ctx, BString* cmt) const
{
if (str) *str = fString;
if (ctx) *ctx = fContext;
if (cmt) *cmt = fComment;
return B_OK;
}
uint32 CatKey::HashFun(const char* s, int startValue) {
unsigned long h = startValue;
for ( ; *s; ++s)
h = 5 * h + *s;
// Add 1 to differenciate ("ab","cd","ef") from ("abcd","e","f")
h = 5 * h + 1;
return size_t(h);
}
// (end CatKey)
// BHashMapCatalog
void
BHashMapCatalog::MakeEmpty()
{
fCatMap.Clear();
}
int32
BHashMapCatalog::CountItems() const
{
return fCatMap.Size();
}
const char *
BHashMapCatalog::GetString(const char *string, const char *context,
const char *comment)
{
CatKey key(string, context, comment);
return GetString(key);
}
const char *
BHashMapCatalog::GetString(uint32 id)
{
CatKey key(id);
return GetString(key);
}
const char *
BHashMapCatalog::GetString(const CatKey& key)
{
BString value = fCatMap.Get(key);
if (value.Length() == 0)
return NULL;
else
return value.String();
}
void
parseQuotedChars(BString& stringToParse)
{
char* in = stringToParse.LockBuffer(0);
char* out = in;
int newLength = 0;
bool quoted = false;
while (*in != 0 || quoted) {
if (quoted) {
if (*in == 'n')
*out = '\n';
else if (*in == 't')
*out = '\t';
else if (*in == '"')
*out = '"';
else if (*in == 'x') {
// Parse the 2-digit hex integer that follows
char tmp[3];
tmp[0] = *(in+1);
tmp[1] = *(in+2);
tmp[2] = '\0';
unsigned int hexchar = strtoul(tmp, NULL, 16);
*out = hexchar;
// skip the number
in += 2;
} else {
// dump quote from unknown quoting-sequence:
*out = *in ;
}
quoted = false;
out++;
newLength++;
} else {
quoted = (*in == '\\');
if (!quoted) {
*out = *in;
out++;
newLength++;
}
}
in++;
}
*out = '\0';
stringToParse.UnlockBuffer();
}
status_t
BHashMapCatalog::SetString(const char *string, const char *translated,
const char *context, const char *comment)
{
BString stringCopy(string);
BString translatedCopy(translated);
parseQuotedChars(stringCopy);
parseQuotedChars(translatedCopy);
CatKey key(stringCopy.String(), context, comment);
return fCatMap.Put(key, translatedCopy.String());
// overwrite existing element
}
status_t
BHashMapCatalog::SetString(int32 id, const char *translated)
{
BString translatedCopy(translated);
parseQuotedChars(translatedCopy);
CatKey key(id);
return fCatMap.Put(key, translatedCopy.String());
// overwrite existing element
}
status_t
BHashMapCatalog::SetString(const CatKey& key, const char *translated)
{
BString translatedCopy(translated);
parseQuotedChars(translatedCopy);
return fCatMap.Put(key, translatedCopy.String());
// overwrite existing element
}
/*
* computes a checksum (we call it fingerprint) on all the catalog-keys. We do
* not include the values, since we want catalogs for different languages of the
* same app to have the same fingerprint, since we use it to separate different
* catalog-versions. We use a simple sum because there is no well known
* checksum algorithm that gives the same result if the string are sorted in the
* wrong order, and this does happen, as an hash map is an unsorted container.
*/
uint32
BHashMapCatalog::ComputeFingerprint() const
{
uint32 checksum = 0;
int32 hash;
CatMap::Iterator iter = fCatMap.GetIterator();
CatMap::Entry entry;
while (iter.HasNext())
{
entry = iter.Next();
hash = entry.key.fHashVal;
checksum += hash;
}
return checksum;
}
void
BHashMapCatalog::UpdateFingerprint()
{
fFingerprint = ComputeFingerprint();
}

View File

@ -4,6 +4,7 @@ UsePublicHeaders locale ;
UsePrivateHeaders locale ;
UsePrivateHeaders shared ;
SEARCH_SOURCE += [ FDirName $(HAIKU_TOP) src kits locale ] ;
SEARCH_SOURCE += [ FDirName $(HAIKU_TOP) src kits tracker ] ;
local localetools =