root/headers/private/locale/HashMapCatalog.h
/*
 * Copyright 2009, Adrien Destugues, pulkomandy@gmail.com.
 * Distributed under the terms of the MIT License.
 */
/*
 * This file declares all the things we need to add to a catalog add-on to be
 * able to use it in the developper tools (linkcatkeys, dumpcatalog, and the
 * catalog editor, when we will have one.
 */


#ifndef _HASH_MAP_CATALOG_H_
#define _HASH_MAP_CATALOG_H_


#include <assert.h>

#include <CatalogData.h>
#include <HashMap.h>
#include <String.h>


namespace BPrivate {

/*
 * The key-type for the hash_map which maps native strings or IDs to
 * the corresponding translated string.
 * The key-type should be efficient to use if it is just created by an ID
 * but it should also support being created from up to three strings,
 * which as a whole specify the key to the translated string.
 */
class CatKey {
        public:
                BString fString;
                        // The native string
                BString fContext;
                        // The context of the string's usage
                BString fComment;
                        // A comment that can be used to separate strings that
                        // are identical otherwise in the native language, but different in
                        // the translation (useful for the translator)
                uint32 fHashVal;
                        // the hash-value of the key, computed from the three strings
                uint32 fFlags;
                        // with respect to the catalog-editor, each translation can be
                        // in different states (empty, unchecked, checked, etc.). This
                        // state (and potential other flags) lives in the fFlags member.

        public:
                CatKey(const char *str, const char *ctx, const char *cmt);
                CatKey(uint32 id);
                CatKey();

                bool operator== (const CatKey& right) const;
                bool operator!= (const CatKey& right) const;
                status_t GetStringParts(BString* str, BString* ctx, BString* cmt) const;
                static uint32 HashFun(const char* s, int startvalue = 0);
                        // The hash function is called 3 times, cumulating the 3 strings to
                        // calculate the key
                uint32 GetHashCode() const { return fHashVal; }
};


class HashMapCatalog: public BCatalogData {
        protected:
                uint32 ComputeFingerprint() const;
                typedef HashMap<CatKey, BString> CatMap;
                CatMap                          fCatMap;

        public:
                HashMapCatalog(const char* signature, const char* language,
                        uint32 fingerprint);
                        // Constructor for normal use
                        //
                // overrides of BCatalogData:
                const char *GetString(const char *string, const char *context = NULL,
                                                const char *comment = NULL);
                const char *GetString(uint32 id);
                const char *GetString(const CatKey& key);
                //
                status_t SetString(const char *string, const char *translated,
                                        const char *context = NULL, const char *comment = NULL);
                status_t SetString(int32 id, const char *translated);
                status_t SetString(const CatKey& key, const char *translated);

                // implementation for editor-interface
                virtual status_t ReadFromFile(const char *path = NULL)
                        {return B_NOT_SUPPORTED;}
                virtual status_t ReadFromAttribute(const entry_ref &appOrAddOnRef)
                        {return B_NOT_SUPPORTED;}
                virtual status_t ReadFromResource(const entry_ref &appOrAddOnRef)
                        {return B_NOT_SUPPORTED;}
                virtual status_t WriteToFile(const char *path = NULL)
                        {return B_NOT_SUPPORTED;}
                virtual status_t WriteToAttribute(const entry_ref &appOrAddOnRef)
                        {return B_NOT_SUPPORTED;}
                virtual status_t WriteToResource(const entry_ref &appOrAddOnRef)
                        {return B_NOT_SUPPORTED;}

                void UpdateFingerprint();
                //
                void MakeEmpty();
                int32 CountItems() const;

                /*
                 * CatWalker allows to walk trough all the strings stored in the
                 * catalog. We need that for dumpcatalog, linkcatkeys (to extract the
                 * data from the plaintext catalog) and in the catalog editor (to
                 * display the list of strings in a given catalog).
                 */
                class CatWalker {
                        public:
                                //CatWalker() {}; // if you use this there is no way to set fPos
                                // properly.
                                CatWalker(HashMapCatalog* catalog);
                                bool AtEnd() const;
                                const CatKey& GetKey() const;
                                const char *GetValue() const;
                                void Next();
                        private:
                                CatMap::Iterator fPos;
                                CatMap::Entry current;
                                bool atEnd;
                };
                friend class CatWalker;
                status_t GetWalker(CatWalker *walker);


};


inline HashMapCatalog::HashMapCatalog(const char* signature,
        const char* language, uint32 fingerprint)
        :
        BCatalogData(signature, language, fingerprint)
{
}


inline
HashMapCatalog::CatWalker::CatWalker(HashMapCatalog* catalog)
        :
        fPos(catalog->fCatMap.GetIterator())
{
        if (fPos.HasNext()) {
                current = fPos.Next();
                atEnd = false;
        } else
                atEnd = true;
}


inline bool
HashMapCatalog::CatWalker::AtEnd() const
{
        return atEnd;
}


inline const CatKey &
HashMapCatalog::CatWalker::GetKey() const
{
        assert(!atEnd);
        return current.key;
}


inline const char *
HashMapCatalog::CatWalker::GetValue() const
{
        assert(!atEnd);
        return current.value.String();
}


inline void
HashMapCatalog::CatWalker::Next()
{
        if (fPos.HasNext()) {
                current = fPos.Next();
                atEnd = false;
        } else
                atEnd = true;
}


inline status_t
HashMapCatalog::GetWalker(CatWalker *walker)
{
        if (!walker)
                return B_BAD_VALUE;
        *walker = CatWalker(this);
        return B_OK;
}


} // namespace BPrivate

#endif // _HASH_MAP_CATALOG_H_