Ticket #3829: localekit_base.patch

File localekit_base.patch, 311.5 KB (added by pulkomandy, 15 years ago)

*fixed* patch adding the localekit to the Haiku tree.

  • build/jam/HaikuImage

     
    4747    uptime urlwrapper useradd uudecode uuencode
    4848    vdir version vim vmstat waitfor wc wget whoami xargs xres yes
    4949    zdiff zforce zgrep zip zipcloak <bin>zipgrep zipnote zipsplit zmore znew
     50    collectcatkeys linkcatkeys dumpcatalog genprops
    5051;
    5152
    5253SYSTEM_APPS = AboutSystem ActivityMonitor CharacterMap CodyCam DeskCalc DiskProbe
     
    5657    StyledEdit Terminal TextSearch TV Workspaces
    5758;
    5859SYSTEM_PREFERENCES = Appearance Backgrounds CPUFrequency DataTranslations E-mail
    59     FileTypes Fonts Keyboard Keymap Media Menu Mouse Network Printers Screen
     60    FileTypes Fonts Keyboard Keymap Locale Media Menu Mouse Network Printers Screen
    6061    ScreenSaver Sounds Time Touchpad <preference>Tracker VirtualMemory
    6162;
    6263SYSTEM_DEMOS = BSnow Chart Clock Cortex FontDemo
     
    6869    libmail.so libtextencoding.so libz.so libfreetype.so libpng.so libmidi.so
    6970    libmidi2.so libdevice.so libgame.so libscreensaver.so <revisioned>libroot.so
    7071    libGL.so libfluidsynth.so liblpsolve55.so liblinprog.so libalm.so
    71     libilmimf.so libiconv.so
     72    libilmimf.so libiconv.so liblocale.so
    7273;
    7374SYSTEM_SERVERS = registrar debug_server syslog_daemon media_server
    7475    net_server media_addon_server input_server app_server fake_app_server
     
    273274# TODO/NOTE: Cannot use $(SYSTEM_PREFERENCES) here since there is
    274275# "<preferences>Tracker"...
    275276DESKBAR_PREFERENCES = Appearance Backgrounds CPUFrequency DataTranslations
    276     E-mail FileTypes Fonts Keyboard Keymap Media Menu Mouse Network Printers
     277    E-mail FileTypes Fonts Keyboard Keymap Locale Media Menu Mouse Network Printers
    277278    Screen ScreenSaver Sounds Time Touchpad Tracker VirtualMemory
    278279;
    279280for linkTarget in $(DESKBAR_PREFERENCES) {
     
    328329    = [ FDirName $(HAIKU_TOP) src apps mail ] ;
    329330AddFilesToHaikuImage system etc word_dictionary : $(spellFiles) ;
    330331
     332# Locale kit system-wide catalogs
     333local catalogs = deutsch français ;
     334catalogs = $(catalogs:G=catalogs).language ;
     335SEARCH on $(catalogs)
     336    = [ FDirName $(HAIKU_TOP) data etc locale languages ] ;
     337AddFilesToHaikuImage system etc locale languages : $(catalogs) ;
     338
    331339local etcFiles = bash_completion inputrc profile teapot.data ;
    332340etcFiles = $(etcFiles:G=etc) ;
    333341SEARCH on $(etcFiles) = [ FDirName $(HAIKU_TOP) data etc ] ;
  • src/preferences/locale/Locale.cpp

     
     1/*
     2 * Copyright 2005, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
     3 * Distributed under the terms of the MIT License.
     4 */
     5
     6
     7#include "Locale.h"
     8#include "LocaleWindow.h"
     9
     10#include <Application.h>
     11#include <Alert.h>
     12#include <TextView.h>
     13#include <FindDirectory.h>
     14#include <File.h>
     15#include <Path.h>
     16
     17#include <stdio.h>
     18#include <string.h>
     19
     20
     21const char *kSignature = "application/x-vnd.Haiku-Locale";
     22
     23static const uint32 kMsgLocaleSettings = 'LCst';
     24
     25
     26class Settings {
     27    public:
     28        Settings();
     29        ~Settings();
     30
     31        const BMessage &Message() const { return fMessage; }
     32        void UpdateFrom(BMessage *message);
     33
     34    private:
     35        status_t Open(BFile *file, int32 mode);
     36
     37        BMessage    fMessage;
     38        bool        fUpdated;
     39};
     40
     41
     42class Locale : public BApplication {
     43    public:
     44        Locale();
     45        virtual ~Locale();
     46
     47        virtual void ReadyToRun();
     48        virtual void MessageReceived(BMessage *message);
     49
     50        virtual void AboutRequested();
     51        virtual bool QuitRequested();
     52
     53    private:
     54        Settings    fSettings;
     55        BWindow     *fOpenWindow;
     56        BRect       fWindowFrame;
     57};
     58
     59
     60//-----------------
     61
     62
     63Settings::Settings()
     64    :
     65    fMessage(kMsgLocaleSettings),
     66    fUpdated(false)
     67{
     68    BFile file;
     69    if (Open(&file, B_READ_ONLY) != B_OK
     70        || fMessage.Unflatten(&file) != B_OK) {
     71        // set default prefs
     72        fMessage.AddRect("window_frame", BRect(50, 50, 550, 500));
     73        return;
     74    }
     75}
     76
     77
     78Settings::~Settings()
     79{
     80    // only save the settings if something has changed
     81    if (!fUpdated)
     82        return;
     83
     84    BFile file;
     85    if (Open(&file, B_CREATE_FILE | B_WRITE_ONLY) != B_OK)
     86        return;
     87
     88    fMessage.Flatten(&file);
     89}
     90
     91
     92status_t
     93Settings::Open(BFile *file, int32 mode)
     94{
     95    BPath path;
     96    if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) != B_OK)
     97        return B_ERROR;
     98
     99    path.Append("Locale settings");
     100
     101    return file->SetTo(path.Path(), mode);
     102}
     103
     104
     105void
     106Settings::UpdateFrom(BMessage *message)
     107{
     108    BRect frame;
     109    if (message->FindRect("window_frame", &frame) == B_OK)
     110        fMessage.ReplaceRect("window_frame", frame);
     111
     112    fUpdated = true;
     113}
     114
     115
     116//  #pragma mark -
     117
     118
     119Locale::Locale()
     120    : BApplication(kSignature)
     121{
     122    fWindowFrame = fSettings.Message().FindRect("window_frame");
     123
     124    BWindow* window = new LocaleWindow(fWindowFrame);
     125    window->Show();
     126}
     127
     128
     129Locale::~Locale()
     130{
     131}
     132
     133
     134void
     135Locale::ReadyToRun()
     136{
     137    // are there already windows open?
     138    if (CountWindows() != 1)
     139        return;
     140
     141    // if not, ask the user to open a file
     142    PostMessage(kMsgOpenOpenWindow);
     143}
     144
     145
     146void
     147Locale::MessageReceived(BMessage *message)
     148{
     149    switch (message->what) {
     150        case kMsgSettingsChanged:
     151            fSettings.UpdateFrom(message);
     152            break;
     153
     154        default:
     155            BApplication::MessageReceived(message);
     156            break;
     157    }
     158}
     159
     160
     161void
     162Locale::AboutRequested()
     163{
     164    BAlert *alert = new BAlert("about", "Locale\n"
     165        "\twritten by Axel Dörfler\n"
     166        "\tCopyright 2005, Haiku.\n\n", "Ok");
     167    BTextView *view = alert->TextView();
     168    BFont font;
     169
     170    view->SetStylable(true);
     171
     172    view->GetFont(&font);
     173    font.SetSize(18);
     174    font.SetFace(B_BOLD_FACE);         
     175    view->SetFontAndColor(0, 7, &font);
     176
     177    alert->Go();
     178}
     179
     180
     181bool
     182Locale::QuitRequested()
     183{
     184    return true;
     185}
     186
     187
     188//  #pragma mark -
     189
     190
     191int
     192main(int argc, char **argv)
     193{
     194    Locale app;
     195
     196    app.Run();
     197    return 0;
     198}
  • src/preferences/locale/Locale.h

     
     1/*
     2 * Copyright 2005, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
     3 * Distributed under the terms of the MIT License.
     4 */
     5#ifndef LOCALE_H
     6#define LOCALE_H
     7
     8
     9#include <SupportDefs.h>
     10
     11
     12extern const char *kSignature;
     13
     14static const uint32 kMsgOpenFilePanel = 'opFp';
     15static const uint32 kMsgOpenOpenWindow = 'opOw';
     16static const uint32 kMsgOpenWindowClosed = 'clOw';
     17static const uint32 kMsgWindowClosed = 'WiCl';
     18static const uint32 kMsgSettingsChanged = 'SeCh';
     19
     20static const uint32 kMsgOpenFindWindow = 'OpFw';
     21static const uint32 kMsgFindWindowClosed = 'clFw';
     22static const uint32 kMsgFindTarget = 'FTgt';
     23static const uint32 kMsgFind = 'find';
     24
     25#endif  /* LOCALE_H */
  • src/preferences/locale/Jamfile

    Impossible d'afficher : fichier considéré comme binaire.
    svn:mime-type = application/octet-stream
    
    Modification de propriétés sur src/preferences/locale/Locale.rsrc
    ___________________________________________________________________
    Ajouté : svn:mime-type
       + application/octet-stream
    
     
     1SubDir HAIKU_TOP src preferences locale ;
     2
     3AddResources Locale : Locale.rsrc ;
     4
     5Preference Locale :
     6    Locale.cpp
     7    LocaleWindow.cpp
     8    : be liblocale.so ;
  • src/preferences/locale/LocaleWindow.cpp

     
     1/*
     2 * Copyright 2005, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
     3 * Distributed under the terms of the MIT License.
     4 */
     5
     6
     7#include "Locale.h"
     8#include "LocaleWindow.h"
     9
     10#include <Application.h>
     11#include <Screen.h>
     12#include <TabView.h>
     13#include <ScrollView.h>
     14#include <ListView.h>
     15#include <Button.h>
     16
     17
     18const static uint32 kMsgSelectLanguage = 'slng';
     19const static uint32 kMsgDefaults = 'dflt';
     20const static uint32 kMsgRevert = 'revt';
     21
     22
     23LocaleWindow::LocaleWindow(BRect rect)
     24    : BWindow(rect, "Locale", B_TITLED_WINDOW,
     25        B_NOT_RESIZABLE | B_NOT_ZOOMABLE | B_ASYNCHRONOUS_CONTROLS)
     26{
     27    rect = Bounds();
     28    BView *view = new BView(rect, "view", B_FOLLOW_ALL, 0);
     29    view->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
     30    AddChild(view);
     31
     32    BButton *button = new BButton(rect, "defaults", "Defaults",
     33        new BMessage(kMsgDefaults), B_FOLLOW_NONE);
     34    button->ResizeToPreferred();
     35    button->MoveTo(10, rect.bottom - 10 - button->Bounds().Height());
     36    view->AddChild(button);
     37
     38    fRevertButton = new BButton(rect, "revert", "Revert",
     39        new BMessage(kMsgRevert), B_FOLLOW_NONE);
     40    fRevertButton->ResizeToPreferred();
     41    fRevertButton->MoveTo(20 + button->Bounds().Width(), button->Frame().top);
     42    fRevertButton->SetEnabled(false);
     43    view->AddChild(fRevertButton);
     44
     45    rect.InsetBy(10, 10);
     46    rect.bottom -= 10 + button->Bounds().Height();
     47    BTabView *tabView = new BTabView(rect, "tabview");
     48
     49    rect = tabView->ContainerView()->Bounds();
     50    rect.InsetBy(2, 2);
     51    BView *tab = new BView(rect, "Language", B_FOLLOW_NONE, B_WILL_DRAW);
     52    tab->SetViewColor(tabView->ViewColor());
     53    tabView->AddTab(tab);
     54
     55    {
     56        BRect frame = rect;
     57        frame.InsetBy(12, 12);
     58        frame.right = 100 + B_V_SCROLL_BAR_WIDTH;
     59        frame.bottom = 150;
     60
     61        BListView *listView = new BListView(frame, "preferred", B_SINGLE_SELECTION_LIST,
     62            B_FOLLOW_LEFT_RIGHT | B_FOLLOW_TOP);
     63        listView->SetSelectionMessage(new BMessage(kMsgSelectLanguage));
     64
     65        BScrollView *scrollView = new BScrollView("scroller", listView,
     66            B_FOLLOW_LEFT_RIGHT | B_FOLLOW_TOP, 0, false, true, B_FANCY_BORDER);
     67        tab->AddChild(scrollView);
     68    }
     69
     70    tab = new BView(rect, "Country", B_FOLLOW_NONE, B_WILL_DRAW);
     71    tab->SetViewColor(tabView->ViewColor());
     72    tabView->AddTab(tab);
     73
     74    tab = new BView(rect, "Keyboard", B_FOLLOW_NONE, B_WILL_DRAW);
     75    tab->SetViewColor(tabView->ViewColor());
     76    tabView->AddTab(tab);
     77
     78    view->AddChild(tabView);
     79
     80    // check if the window is on screen
     81
     82    rect = BScreen().Frame();
     83    rect.right -= 20;
     84    rect.bottom -= 20;
     85
     86    BPoint position = Frame().LeftTop();
     87    if (!rect.Contains(position)) {
     88        // center window on screen as it doesn't fit on the saved position
     89        position.x = (rect.Width() - Bounds().Width()) / 2;
     90        position.y = (rect.Height() - Bounds().Height()) / 2;
     91    }
     92    MoveTo(position);
     93}
     94
     95
     96bool
     97LocaleWindow::QuitRequested()
     98{
     99    BMessage update(kMsgSettingsChanged);
     100    update.AddRect("window_frame", Frame());
     101    be_app_messenger.SendMessage(&update);
     102
     103    be_app_messenger.SendMessage(B_QUIT_REQUESTED);
     104    return true;
     105}
     106
     107
     108void
     109LocaleWindow::MessageReceived(BMessage *message)
     110{
     111    switch (message->what) {
     112        case kMsgDefaults:
     113            // reset default settings
     114            break;
     115
     116        case kMsgRevert:
     117            // revert to last settings
     118            break;
     119
     120        default:
     121            BWindow::MessageReceived(message);
     122            break;
     123    }
     124}
     125
  • src/preferences/locale/LocaleWindow.h

     
     1/*
     2 * Copyright 2005, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
     3 * Distributed under the terms of the MIT License.
     4 */
     5#ifndef LOCALE_WINDOW_H
     6#define LOCALE_WINDOW_H
     7
     8
     9#include <Window.h>
     10
     11class BButton;
     12
     13
     14class LocaleWindow : public BWindow {
     15    public:
     16        LocaleWindow(BRect rect);
     17
     18        virtual bool QuitRequested();
     19        virtual void MessageReceived(BMessage *message);
     20
     21    private:
     22        BButton*    fRevertButton;
     23};
     24
     25#endif  /* LOCALE_WINDOW_H */
  • src/preferences/Jamfile

     
    1212SubInclude HAIKU_TOP src preferences joysticks ;
    1313SubInclude HAIKU_TOP src preferences keyboard ;
    1414SubInclude HAIKU_TOP src preferences keymap ;
     15SubInclude HAIKU_TOP src preferences locale ;
    1516SubInclude HAIKU_TOP src preferences mail ;
    1617SubInclude HAIKU_TOP src preferences media ;
    1718SubInclude HAIKU_TOP src preferences menu ;
  • src/bin/locale/RegExp.h

     
     1/*
     2Open Tracker License
     3
     4Terms and Conditions
     5
     6Copyright (c) 1991-2000, Be Incorporated. All rights reserved.
     7
     8Permission is hereby granted, free of charge, to any person obtaining a copy of
     9this software and associated documentation files (the "Software"), to deal in
     10the Software without restriction, including without limitation the rights to
     11use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
     12of the Software, and to permit persons to whom the Software is furnished to do
     13so, subject to the following conditions:
     14
     15The above copyright notice and this permission notice applies to all licensees
     16and shall be included in all copies or substantial portions of the Software.
     17
     18THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     19IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF TITLE, MERCHANTABILITY,
     20FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
     21BE INCORPORATED BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
     22AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF, OR IN CONNECTION
     23WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
     24
     25Except as contained in this notice, the name of Be Incorporated shall not be
     26used in advertising or otherwise to promote the sale, use or other dealings in
     27this Software without prior written authorization from Be Incorporated.
     28
     29Tracker(TM), Be(R), BeOS(R), and BeIA(TM) are trademarks or registered trademarks
     30of Be Incorporated in the United States and other countries. Other brand product
     31names are registered trademarks or trademarks of their respective holders.
     32All rights reserved.
     33*/
     34
     35
     36// This code is based on regexp.c, v.1.3 by Henry Spencer:
     37
     38// @(#)regexp.c 1.3 of 18 April 87
     39//
     40//  Copyright (c) 1986 by University of Toronto.
     41//  Written by Henry Spencer.  Not derived from licensed software.
     42//
     43//  Permission is granted to anyone to use this software for any
     44//  purpose on any computer system, and to redistribute it freely,
     45//  subject to the following restrictions:
     46//
     47//  1. The author is not responsible for the consequences of use of
     48//      this software, no matter how awful, even if they arise
     49//      from defects in it.
     50//
     51//  2. The origin of this software must not be misrepresented, either
     52//      by explicit claim or by omission.
     53//
     54//  3. Altered versions must be plainly marked as such, and must not
     55//      be misrepresented as being the original software.
     56//
     57// Beware that some of this code is subtly aware of the way operator
     58// precedence is structured in regular expressions.  Serious changes in
     59// regular-expression syntax might require a total rethink.
     60//
     61
     62// ALTERED VERSION: Adapted to ANSI C and C++ for the OpenTracker
     63// project (www.opentracker.org), Jul 11, 2000.
     64
     65#ifndef _REG_EXP_H
     66#define _REG_EXP_H
     67
     68#include <String.h>
     69
     70namespace BPrivate {
     71
     72enum {
     73    REGEXP_UNMATCHED_PARENTHESIS = B_ERRORS_END,
     74    REGEXP_TOO_BIG,
     75    REGEXP_TOO_MANY_PARENTHESIS,
     76    REGEXP_JUNK_ON_END,
     77    REGEXP_STAR_PLUS_OPERAND_EMPTY,
     78    REGEXP_NESTED_STAR_QUESTION_PLUS,
     79    REGEXP_INVALID_BRACKET_RANGE,
     80    REGEXP_UNMATCHED_BRACKET,
     81    REGEXP_INTERNAL_ERROR,
     82    REGEXP_QUESTION_PLUS_STAR_FOLLOWS_NOTHING,
     83    REGEXP_TRAILING_BACKSLASH,
     84    REGEXP_CORRUPTED_PROGRAM,
     85    REGEXP_MEMORY_CORRUPTION,
     86    REGEXP_CORRUPTED_POINTERS,
     87    REGEXP_CORRUPTED_OPCODE
     88};
     89
     90const int32 kSubExpressionMax = 10;
     91
     92struct regexp {
     93    const char *startp[kSubExpressionMax];
     94    const char *endp[kSubExpressionMax];
     95    char regstart;      /* Internal use only. See RegExp.cpp for details. */
     96    char reganch;       /* Internal use only. */
     97    const char *regmust;/* Internal use only. */
     98    int regmlen;        /* Internal use only. */
     99    char program[1];    /* Unwarranted chumminess with compiler. */
     100};
     101
     102class RegExp {
     103
     104public:
     105    RegExp();
     106    RegExp(const char *);
     107    RegExp(const BString &);
     108    ~RegExp();
     109   
     110    status_t InitCheck() const;
     111   
     112    status_t SetTo(const char*);
     113    status_t SetTo(const BString &);
     114   
     115    bool Matches(const char *string) const;
     116    bool Matches(const BString &) const;
     117
     118    int32 RunMatcher(regexp *, const char *) const;
     119    regexp *Compile(const char *);
     120    regexp *Expression() const;
     121    const char *ErrorString() const;
     122
     123#ifdef DEBUG
     124    void Dump();
     125#endif
     126
     127private:
     128
     129    void SetError(status_t error) const;
     130
     131    // Working functions for Compile():
     132    char *Reg(int32, int32 *);
     133    char *Branch(int32 *);
     134    char *Piece(int32 *);
     135    char *Atom(int32 *);
     136    char *Node(char);
     137    char *Next(char *);
     138    const char *Next(const char *) const;
     139    void Char(char);
     140    void Insert(char, char *);
     141    void Tail(char *, char *);
     142    void OpTail(char *, char *);
     143
     144    // Working functions for RunMatcher():
     145    int32 Try(regexp *, const char *) const;
     146    int32 Match(const char *) const;
     147    int32 Repeat(const char *) const;
     148
     149    // Utility functions:
     150#ifdef DEBUG
     151    char *Prop(const char *) const;
     152    void RegExpError(const char *) const;
     153#endif
     154    inline int32 UCharAt(const char *p) const;
     155    inline char *Operand(char* p) const;
     156    inline const char *Operand(const char* p) const;
     157    inline bool IsMult(char c) const;
     158
     159// --------- Variables -------------
     160
     161    mutable status_t fError;
     162    regexp *fRegExp;
     163
     164    // Work variables for Compile().
     165
     166    const char *fInputScanPointer;
     167    int32 fParenthesisCount;       
     168    char fDummy;
     169    char *fCodeEmitPointer;     // &fDummy = don't.
     170    long fCodeSize;     
     171
     172    // Work variables for RunMatcher().
     173
     174    mutable const char *fStringInputPointer;
     175    mutable const char *fRegBol;    // Beginning of input, for ^ check.
     176    mutable const char **fStartPArrayPointer;
     177    mutable const char **fEndPArrayPointer;
     178};
     179
     180} // namespace BPrivate
     181
     182using namespace BPrivate;
     183
     184#endif
  • src/bin/locale/dumpcatalog.cpp

     
     1/*
     2** Copyright 2003, Oliver Tappe, zooey@hirschkaefer.de. All rights reserved.
     3** Distributed under the terms of the OpenBeOS License.
     4*/
     5
     6#include <cstdio>
     7#include <cstdlib>
     8
     9#include <Catalog.h>
     10#include <DefaultCatalog.h>
     11#include <File.h>
     12#include <String.h>
     13
     14void
     15usage()
     16{
     17    fprintf(stderr, "usage: dumpcatalog <catalogFiles>\n");
     18    exit(-1);
     19}
     20
     21
     22int
     23main(int argc, char **argv)
     24{
     25    const char *inputFile = NULL;
     26    status_t res;
     27    if (!argv[1] || !strcmp(argv[1], "--help")) {
     28        usage();
     29    } else {
     30        inputFile = argv[1];
     31    }
     32    if (!inputFile || !strlen(inputFile))
     33        usage();
     34   
     35    EditableCatalog inputCatalog("Default", "dummy", "dummy");
     36    if ((res = inputCatalog.InitCheck()) != B_OK) {
     37        fprintf(stderr, "couldn't construct catalog %s - error: %s\n",
     38            inputFile, strerror(res));
     39        exit(-1);
     40    }
     41    if ((res = inputCatalog.ReadFromFile(inputFile)) != B_OK) {
     42        fprintf(stderr, "couldn't load input-catalog %s - error: %s\n",
     43            inputFile, strerror(res));
     44        exit(-1);
     45    }
     46    DefaultCatalog* inputCatImpl
     47        = dynamic_cast<DefaultCatalog*>(inputCatalog.CatalogAddOn());
     48    if (!inputCatImpl) {
     49        fprintf(stderr, "couldn't access impl of input-catalog %s\n",
     50            inputFile);
     51        exit(-1);
     52    }
     53    // now walk over all entries in input-catalog and dump them to
     54    // stdout
     55    DefaultCatalog::CatWalker walker;
     56    if ((res = inputCatImpl->GetWalker(&walker)) != B_OK) {
     57        fprintf(stderr, "couldn't get walker for input-catalog %s - error: %s\n",
     58            inputFile, strerror(res));
     59        exit(-1);
     60    }
     61    BString str, ctx, cmt;
     62    while(!walker.AtEnd()) {
     63        const CatKey &key(walker.GetKey());
     64        key.GetStringParts(&str, &ctx, &cmt);
     65        printf("Hash:\t\t%ld\nKey:\t\t<%s:%s:%s>\nTranslation:\t%s\n-----\n",
     66            key.fHashVal, str.String(), ctx.String(), cmt.String(),
     67            walker.GetValue());
     68        walker.Next();
     69    }
     70    int32 count = inputCatalog.CountItems();
     71    if (count)
     72        fprintf(stderr, "%ld entr%s dumped\n",  count, (count==1 ? "y": "ies"));
     73    else
     74        fprintf(stderr, "no entries found\n");
     75    return res;
     76}
  • src/bin/locale/linkcatkeys.cpp

    Impossible d'afficher : fichier considéré comme binaire.
    svn:mime-type = application/octet-stream
    
    Modification de propriétés sur src/bin/locale/collectcatkeys.rsrc
    ___________________________________________________________________
    Ajouté : svn:mime-type
       + application/octet-stream
    
     
     1/*
     2** Copyright 2003, Oliver Tappe, zooey@hirschkaefer.de. All rights reserved.
     3** Distributed under the terms of the OpenBeOS License.
     4*/
     5
     6#include <cstdio>
     7#include <cstdlib>
     8#include <vector>
     9
     10#include <Catalog.h>
     11#include <DefaultCatalog.h>
     12#include <Entry.h>
     13#include <File.h>
     14#include <String.h>
     15
     16void
     17usage()
     18{
     19    fprintf(stderr,
     20        "usage: linkcatkeys [-v] [-t(a|f|r)] [-o <outfile>] [-l <catalogLang>]\n"
     21        "                   -s <catalogSig> <catalogFiles>\n"
     22        "options:\n"
     23        "  -l <catalogLang>\tlanguage of the target-catalog (default is English)\n"
     24        "  -o <outfile>\t\texplicitly specifies the name of the output-file\n"
     25        "  -s <catalogSig>\tsignature of the target-catalog\n"
     26        "  -t(a|f|r)\t\tspecifies target of resulting catalog (-tf is default)\n"
     27        "           \t\ta => write catalog as an attribute (to output-file)\n"
     28        "           \t\tf => write catalog into the output-file\n"
     29        "           \t\tr => write catalog as a resource (to output-file)\n"
     30        "  -v\t\t\tbe verbose, show summary\n");
     31    exit(-1);
     32}
     33
     34
     35int
     36main(int argc, char **argv)
     37{
     38    bool showSummary = false;
     39    bool showWarnings = false;
     40    vector<const char *> inputFiles;
     41    BString outputFile("default.catalog");
     42    enum TargetType {
     43        TARGET_ATTRIBUTE,
     44        TARGET_FILE,
     45        TARGET_RESOURCE
     46    };
     47    TargetType outputTarget = TARGET_FILE;
     48    const char *catalogSig = NULL;
     49    const char *catalogLang = "English";
     50    status_t res;
     51    while ((++argv)[0]) {
     52        if (argv[0][0] == '-' && argv[0][1] != '-') {
     53            char *arg = argv[0] + 1;
     54            char c;
     55            while ((c = *arg++) != '\0') {
     56                if (c == 's')
     57                    catalogSig = (++argv)[0];
     58                else if (c == 'v')
     59                    showSummary = true;
     60                else if (c == 'w')
     61                    showWarnings = true;
     62                else if (c == 'o') {
     63                    outputFile = (++argv)[0];
     64                    break;
     65                }
     66                else if (c == 't') {
     67                    switch(*arg) {
     68                        case 'a': outputTarget = TARGET_ATTRIBUTE; break;
     69                        case 'f': outputTarget = TARGET_FILE; break;
     70                        case 'r': outputTarget = TARGET_RESOURCE; break;
     71                        default: usage();
     72                    }
     73                }
     74            }
     75        } else if (!strcmp(argv[0], "--help")) {
     76            usage();
     77        } else {
     78            inputFiles.push_back(argv[0]);
     79        }
     80    }
     81    if (inputFiles.empty() || !catalogSig || !outputFile.Length())
     82        usage();
     83   
     84    EditableCatalog targetCatalog("Default", catalogSig, catalogLang);
     85    if ((res = targetCatalog.InitCheck()) != B_OK) {
     86        fprintf(stderr, "couldn't construct target-catalog %s - error: %s\n",
     87            outputFile.String(), strerror(res));
     88        exit(-1);
     89    }
     90    DefaultCatalog* targetCatImpl
     91        = dynamic_cast<DefaultCatalog*>(targetCatalog.CatalogAddOn());
     92    if (!targetCatImpl) {
     93        fprintf(stderr, "couldn't access impl of target-catalog %s\n",
     94            outputFile.String());
     95        exit(-1);
     96    }
     97
     98    uint32 count = inputFiles.size();
     99    for( uint32 i=0; i<count; ++i) {
     100        EditableCatalog inputCatalog("Default", catalogSig, "native");
     101        if ((res = inputCatalog.ReadFromFile(inputFiles[i])) != B_OK) {
     102            fprintf(stderr, "couldn't load target-catalog %s - error: %s\n",
     103                inputFiles[i], strerror(res));
     104            exit(-1);
     105        }
     106        DefaultCatalog* inputCatImpl
     107            = dynamic_cast<DefaultCatalog*>(inputCatalog.CatalogAddOn());
     108        if (!inputCatImpl) {
     109            fprintf(stderr, "couldn't access impl of input-catalog %s\n",
     110                inputFiles[i]);
     111            exit(-1);
     112        }
     113        // now walk over all entries in input-catalog and add them to
     114        // target catalog, unless they already exist there.
     115        // (This could be improved by simply inserting the hashmaps,
     116        // but this should be fast enough).
     117        DefaultCatalog::CatWalker walker;
     118        if ((res = inputCatImpl->GetWalker(&walker)) != B_OK) {
     119            fprintf(stderr, "couldn't get walker for input-catalog %s - error: %s\n",
     120                inputFiles[i], strerror(res));
     121            exit(-1);
     122        }
     123        while(!walker.AtEnd()) {
     124            const CatKey &key(walker.GetKey());
     125            if (!targetCatImpl->GetString(key))
     126                targetCatImpl->SetString(key, walker.GetValue());
     127            walker.Next();
     128        }
     129    }
     130
     131    switch(outputTarget) {
     132        case TARGET_ATTRIBUTE: {
     133            BEntry entry(outputFile.String());
     134            entry_ref eref;
     135            entry.GetRef(&eref);
     136            res = targetCatalog.WriteToAttribute(&eref);
     137            if (res != B_OK) {
     138                fprintf(stderr, "couldn't write target-attribute to %s - error: %s\n",
     139                    outputFile.String(), strerror(res));
     140                exit(-1);
     141            }
     142            break;
     143        }
     144        case TARGET_RESOURCE: {
     145            BEntry entry(outputFile.String());
     146            entry_ref eref;
     147            entry.GetRef(&eref);
     148            res = targetCatalog.WriteToResource(&eref);
     149            if (res != B_OK) {
     150                fprintf(stderr, "couldn't write target-resource to %s - error: %s\n",
     151                    outputFile.String(), strerror(res));
     152                exit(-1);
     153            }
     154        }
     155        default: {
     156            res = targetCatalog.WriteToFile(outputFile.String());
     157            if (res != B_OK) {
     158                fprintf(stderr, "couldn't write target-catalog to %s - error: %s\n",
     159                    outputFile.String(), strerror(res));
     160                exit(-1);
     161            }
     162        }
     163    }
     164    if (showSummary) {
     165        int32 count = targetCatalog.CountItems();
     166        if (count)
     167            fprintf(stderr, "%ld key%s found and written to %s\n",
     168                count, (count==1 ? "": "s"), outputFile.String());
     169        else
     170            fprintf(stderr, "no keys found\n");
     171    }
     172
     173    return res;
     174}
  • src/bin/locale/Jamfile

     
     1SubDir HAIKU_TOP src bin locale ;
     2
     3UseHeaders [ FDirName $(HAIKU_TOP) headers os locale ] : true ;
     4
     5AddResources collectcatkeys : collectcatkeys.rsrc ;
     6Application collectcatkeys : collectcatkeys.cpp RegExp.cpp : be liblocale.so ;
     7
     8AddResources linkcatkeys : linkcatkeys.rsrc ;
     9Application linkcatkeys : linkcatkeys.cpp : be liblocale.so ;
     10
     11AddResources dumpcatalog ;
     12Application dumpcatalog : dumpcatalog.cpp : be liblocale.so ;
  • src/bin/locale/collectcatkeys.cpp

    Impossible d'afficher : fichier considéré comme binaire.
    svn:mime-type = application/octet-stream
    
    Modification de propriétés sur src/bin/locale/dumpcatalog.rsrc
    ___________________________________________________________________
    Ajouté : svn:mime-type
       + application/octet-stream
    
    Impossible d'afficher : fichier considéré comme binaire.
    svn:mime-type = application/octet-stream
    
    Modification de propriétés sur src/bin/locale/linkcatkeys.rsrc
    ___________________________________________________________________
    Ajouté : svn:mime-type
       + application/octet-stream
    
     
     1/*
     2** Copyright 2003, Oliver Tappe, zooey@hirschkaefer.de. All rights reserved.
     3** Distributed under the terms of the OpenBeOS License.
     4*/
     5
     6#include <cctype>
     7#include <cerrno>
     8#include <cstdio>
     9#include <cstdlib>
     10
     11#include <Catalog.h>
     12using namespace BPrivate;
     13#include <Entry.h>
     14#include <File.h>
     15#include "RegExp.h"
     16#include <String.h>
     17
     18bool showKeys = false;
     19bool showSummary = false;
     20bool showWarnings = false;
     21const char *inputFile = NULL;
     22BString outputFile;
     23const char *catalogSig = NULL;
     24const char *catalogLang = "English";
     25BString rxString("be_catalog\\s*->\\s*GetString\\s*");
     26
     27
     28BString str, ctx, cmt;
     29bool haveID;
     30int32 id;
     31
     32
     33EditableCatalog *catalog = NULL;
     34
     35
     36void
     37usage()
     38{
     39    fprintf(stderr,
     40        "usage: collectcatkeys [-pvw] [-r <regex>] [-o <outfile>] [-l <catalogLanguage>]\n"
     41        "                      -s <catalogSig> <prepCppFile>\n"
     42        "options:\n"
     43        "  -l <catalogLang>\tlanguage of the target-catalog (default is English)\n"
     44        "  -o <outfile>\t\texplicitly specifies the name of the output-file\n"
     45        "  -p\t\t\tprint keys as they are found\n"
     46        "  -r <regex>\t\tchanges the regex used by the key-scanner to the one given,\n"
     47        "      \t\t\tthe default is:   be_catalog\\s*->\\s*GetString\\s*\n"
     48        "  -s <catalogSig>\tsignature of the target-catalog\n"
     49        "  -v\t\t\tbe verbose, show summary\n"
     50        "  -w\t\t\tshow warnings about catalog-accesses that couldn't be resolved completely\n");
     51    exit(-1);
     52}
     53
     54
     55bool
     56fetchStr(const char *&in, BString &str, bool lookForID)
     57{
     58    int parLevel = 0;
     59    while(isspace(*in) || *in == '(') {
     60        if (*in == '(')
     61            parLevel++;
     62        in++;
     63    }
     64    if (*in == '"') {
     65        in++;
     66        bool quoted = false;
     67        while (*in != '"' || quoted) {
     68            if (quoted) {
     69                if (*in == 'n')
     70                    str.Append("\n",1);
     71                else if (*in == 't')
     72                    str.Append("\t",1);
     73                else if (*in == '"')
     74                    str.Append("\"",1);
     75                else
     76                    // dump quote from unknown quoting-sequence:
     77                    str.Append(in,1);
     78                quoted = false;
     79            } else {
     80                quoted = (*in == '\\');
     81                if (!quoted)
     82                    str.Append(in,1);
     83            }
     84            in++;
     85        }
     86        in++;
     87    } else if (!memcmp(in, "__null", 6)) {
     88        // NULL is preprocessed into __null, which we parse as ""
     89        in += 6;
     90    } else if (lookForID && (isdigit(*in) || *in == '-' || *in == '+')) {
     91        // try to parse an ID (a long):
     92        errno = 0;
     93        char *next;
     94        id = strtol(in, &next, 10);
     95        if (id != 0 || errno == 0) {
     96            haveID = true;
     97            in = next;
     98        }
     99    } else
     100        return false;
     101    while(isspace(*in) || *in == ')') {
     102        if (*in == ')') {
     103            if (!parLevel)
     104                return true;
     105            parLevel--;
     106        }
     107        in++;
     108    }
     109    return true;
     110}
     111
     112
     113bool
     114fetchKey(const char *&in)
     115{
     116    str = ctx = cmt = "";
     117    haveID = false;
     118    // fetch native string or id:
     119    if (!fetchStr(in, str, true))
     120        return false;
     121    if (*in == ',') {
     122        in++;
     123        // fetch context:
     124        if (!fetchStr(in, ctx, false))
     125            return false;
     126        if (*in == ',') {
     127            in++;
     128            // fetch comment:
     129            if (!fetchStr(in, cmt, false))
     130                return false;
     131        }
     132    }
     133    return true;
     134}
     135
     136
     137void
     138collectAllCatalogKeys(BString& inputStr)
     139{
     140    RegExp rx;
     141    struct regexp *rxprg = rx.Compile(rxString.String());
     142    if (rx.InitCheck() != B_OK) {
     143        fprintf(stderr, "regex-compilation error %s\n", rx.ErrorString());
     144        return;
     145    }
     146    status_t res;
     147    const char *in = inputStr.String();
     148    while(rx.RunMatcher(rxprg, in)) {
     149        const char *start = rxprg->startp[0];
     150        in = rxprg->endp[0];
     151        if (fetchKey(in)) {
     152            if (haveID) {
     153                if (showKeys)
     154                    printf("CatKey(%ld)\n", id);
     155                res = catalog->SetString(id, "");
     156                if (res != B_OK) {
     157                    fprintf(stderr, "couldn't add key %ld - error: %s\n",
     158                        id, strerror(res));
     159                    exit(-1);
     160                }
     161            } else {
     162                if (showKeys)
     163                    printf("CatKey(\"%s\", \"%s\", \"%s\")\n", str.String(),
     164                        ctx.String(), cmt.String());
     165                res = catalog->SetString(str.String(), str.String(), ctx.String(), cmt.String());
     166                if (res != B_OK) {
     167                    fprintf(stderr, "couldn't add key %s,%s,%s - error: %s\n",
     168                        str.String(), ctx.String(), cmt.String(), strerror(res));
     169                    exit(-1);
     170                }
     171            }
     172        } else if (showWarnings) {
     173            const char *end = strchr(in, ';');
     174            BString match;
     175            if (end)
     176                match.SetTo(start, end-start+1);
     177            else
     178                // can't determine end of statement, we output next 40 characters
     179                match.SetTo(start, 40);
     180            fprintf(stderr, "Warning: couldn't resolve catalog-access:\n\t%s\n",
     181                match.String());
     182        }
     183    }
     184}
     185
     186
     187int
     188main(int argc, char **argv)
     189{
     190    while ((++argv)[0]) {
     191        if (argv[0][0] == '-' && argv[0][1] != '-') {
     192            char *arg = argv[0] + 1;
     193            char c;
     194            while ((c = *arg++) != '\0') {
     195                if (c == 'p')
     196                    showKeys = true;
     197                else if (c == 'l')
     198                    catalogLang = (++argv)[0];
     199                else if (c == 's')
     200                    catalogSig = (++argv)[0];
     201                else if (c == 'v')
     202                    showSummary = true;
     203                else if (c == 'w')
     204                    showWarnings = true;
     205                else if (c == 'o') {
     206                    outputFile = (++argv)[0];
     207                    break;
     208                }
     209                else if (c == 'r') {
     210                    rxString = (++argv)[0];
     211                    break;
     212                }
     213            }
     214        } else if (!strcmp(argv[0], "--help")) {
     215            usage();
     216        } else {
     217            if (!inputFile)
     218                inputFile = argv[0];
     219            else
     220                usage();
     221        }
     222    }
     223    if (!outputFile.Length() && inputFile) {
     224        // generate default output-file from input-file by replacing
     225        // the extension with '.catkeys':
     226        outputFile = inputFile;
     227        int32 dot = outputFile.FindLast('.');
     228        if (dot >= B_OK)
     229            outputFile.Truncate(dot);
     230        outputFile << ".catkeys";
     231    }
     232    if (!inputFile || !catalogSig || !outputFile.Length() || !catalogLang)
     233        usage();
     234   
     235    BFile inFile;
     236    status_t res = inFile.SetTo(inputFile, B_READ_ONLY);
     237    if (res != B_OK) {
     238        fprintf(stderr, "unable to open inputfile %s - error: %s\n", inputFile,
     239            strerror(res));
     240        exit(-1);
     241    }
     242    off_t sz;
     243    inFile.GetSize(&sz);
     244    if (sz > 0) {
     245        BString inputStr;
     246        char *buf = inputStr.LockBuffer(sz);
     247        off_t rsz = inFile.Read(buf, sz);
     248        if (rsz < sz) {
     249            fprintf(stderr, "couldn't read %Ld bytes from %s (got only %Ld)\n",
     250                sz, inputFile, rsz);
     251            exit(-1);
     252        }
     253        inputStr.UnlockBuffer(rsz);
     254        catalog = new EditableCatalog("Default", catalogSig, catalogLang);
     255        collectAllCatalogKeys(inputStr);
     256        res = catalog->WriteToFile(outputFile.String());
     257        if (res != B_OK) {
     258            fprintf(stderr, "couldn't write catalog to %s - error: %s\n",
     259                outputFile.String(), strerror(res));
     260            exit(-1);
     261        }
     262        if (showSummary) {
     263            int32 count = catalog->CountItems();
     264            if (count)
     265                fprintf(stderr, "%ld key%s found and written to %s\n",
     266                    count, (count==1 ? "": "s"), outputFile.String());
     267            else
     268                fprintf(stderr, "no keys found\n");
     269        }
     270        delete catalog;
     271    }
     272
     273//  BEntry inEntry(inputFile);
     274//  inEntry.Remove();
     275   
     276    return res;
     277}
  • src/bin/locale/RegExp.cpp

     
     1/*
     2Open Tracker License
     3
     4Terms and Conditions
     5
     6Copyright (c) 1991-2000, Be Incorporated. All rights reserved.
     7
     8Permission is hereby granted, free of charge, to any person obtaining a copy of
     9this software and associated documentation files (the "Software"), to deal in
     10the Software without restriction, including without limitation the rights to
     11use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
     12of the Software, and to permit persons to whom the Software is furnished to do
     13so, subject to the following conditions:
     14
     15The above copyright notice and this permission notice applies to all licensees
     16and shall be included in all copies or substantial portions of the Software.
     17
     18THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     19IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF TITLE, MERCHANTABILITY,
     20FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
     21BE INCORPORATED BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
     22AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF, OR IN CONNECTION
     23WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
     24
     25Except as contained in this notice, the name of Be Incorporated shall not be
     26used in advertising or otherwise to promote the sale, use or other dealings in
     27this Software without prior written authorization from Be Incorporated.
     28
     29Tracker(TM), Be(R), BeOS(R), and BeIA(TM) are trademarks or registered trademarks
     30of Be Incorporated in the United States and other countries. Other brand product
     31names are registered trademarks or trademarks of their respective holders.
     32All rights reserved.
     33*/
     34
     35// This code is based on regexp.c, v.1.3 by Henry Spencer:
     36
     37// @(#)regexp.c 1.3 of 18 April 87
     38//
     39//  Copyright (c) 1986 by University of Toronto.
     40//  Written by Henry Spencer.  Not derived from licensed software.
     41//
     42//  Permission is granted to anyone to use this software for any
     43//  purpose on any computer system, and to redistribute it freely,
     44//  subject to the following restrictions:
     45//
     46//  1. The author is not responsible for the consequences of use of
     47//      this software, no matter how awful, even if they arise
     48//      from defects in it.
     49//
     50//  2. The origin of this software must not be misrepresented, either
     51//      by explicit claim or by omission.
     52//
     53//  3. Altered versions must be plainly marked as such, and must not
     54//      be misrepresented as being the original software.
     55//
     56// Beware that some of this code is subtly aware of the way operator
     57// precedence is structured in regular expressions.  Serious changes in
     58// regular-expression syntax might require a total rethink.
     59//
     60
     61// ALTERED VERSION: Adapted to ANSI C and C++ for the OpenTracker
     62// project (www.opentracker.org), Jul 11, 2000.
     63
     64#include <malloc.h>
     65#include <stdio.h>
     66#include <string.h>
     67
     68#include <Errors.h>
     69
     70#include "RegExp.h"
     71
     72// The first byte of the regexp internal "program" is actually this magic
     73// number; the start node begins in the second byte.
     74
     75const uint8 kRegExpMagic = 0234;
     76
     77// The "internal use only" fields in RegExp.h are present to pass info from
     78// compile to execute that permits the execute phase to run lots faster on
     79// simple cases.  They are:
     80//
     81// regstart char that must begin a match; '\0' if none obvious
     82// reganch  is the match anchored (at beginning-of-line only)?
     83// regmust  string (pointer into program) that match must include, or NULL
     84// regmlen  length of regmust string
     85//
     86// Regstart and reganch permit very fast decisions on suitable starting points
     87// for a match, cutting down the work a lot.  Regmust permits fast rejection
     88// of lines that cannot possibly match.  The regmust tests are costly enough
     89// that Compile() supplies a regmust only if the r.e. contains something
     90// potentially expensive (at present, the only such thing detected is * or +
     91// at the start of the r.e., which can involve a lot of backup).  Regmlen is
     92// supplied because the test in RunMatcher() needs it and Compile() is computing
     93// it anyway.
     94//
     95//
     96//
     97// Structure for regexp "program".  This is essentially a linear encoding
     98// of a nondeterministic finite-state machine (aka syntax charts or
     99// "railroad normal form" in parsing technology).  Each node is an opcode
     100// plus a "next" pointer, possibly plus an operand.  "Next" pointers of
     101// all nodes except kRegExpBranch implement concatenation; a "next" pointer with
     102// a kRegExpBranch on both ends of it is connecting two alternatives.  (Here we
     103// have one of the subtle syntax dependencies:  an individual kRegExpBranch (as
     104// opposed to a collection of them) is never concatenated with anything
     105// because of operator precedence.)  The operand of some types of node is
     106// a literal string; for others, it is a node leading into a sub-FSM.  In
     107// particular, the operand of a kRegExpBranch node is the first node of the branch.
     108// (NB this is *not* a tree structure:  the tail of the branch connects
     109// to the thing following the set of kRegExpBranches.)  The opcodes are:
     110//
     111
     112// definition   number  opnd?   meaning
     113enum {
     114    kRegExpEnd = 0,     // no   End of program.
     115    kRegExpBol = 1,     // no   Match "" at beginning of line.
     116    kRegExpEol = 2,     // no   Match "" at end of line.
     117    kRegExpAny = 3,     // no   Match any one character.
     118    kRegExpAnyOf = 4,   // str  Match any character in this string.
     119    kRegExpAnyBut = 5,  // str  Match any character not in this string.
     120    kRegExpBranch = 6,  // node Match this alternative, or the next...
     121    kRegExpBack = 7,    // no   Match "", "next" ptr points backward.
     122    kRegExpExactly = 8, // str  Match this string.
     123    kRegExpNothing = 9, // no   Match empty string.
     124    kRegExpStar = 10,   // node Match this (simple) thing 0 or more times.
     125    kRegExpPlus = 11,   // node Match this (simple) thing 1 or more times.
     126    kRegExpOpen = 20,   // no   Mark this point in input as start of #n.
     127                            //  kRegExpOpen + 1 is number 1, etc.
     128    kRegExpClose = 30   // no   Analogous to kRegExpOpen.
     129};
     130
     131//
     132// Opcode notes:
     133//
     134// kRegExpBranch    The set of branches constituting a single choice are hooked
     135//      together with their "next" pointers, since precedence prevents
     136//      anything being concatenated to any individual branch.  The
     137//      "next" pointer of the last kRegExpBranch in a choice points to the
     138//      thing following the whole choice.  This is also where the
     139//      final "next" pointer of each individual branch points; each
     140//      branch starts with the operand node of a kRegExpBranch node.
     141//
     142// kRegExpBack      Normal "next" pointers all implicitly point forward; kRegExpBack
     143//      exists to make loop structures possible.
     144//
     145// kRegExpStar,kRegExpPlus  '?', and complex '*' and '+', are implemented as circular
     146//      kRegExpBranch structures using kRegExpBack.  Simple cases (one character
     147//      per match) are implemented with kRegExpStar and kRegExpPlus for speed
     148//      and to minimize recursive plunges.
     149//
     150// kRegExpOpen,kRegExpClose ...are numbered at compile time.
     151//
     152//
     153//
     154// A node is one char of opcode followed by two chars of "next" pointer.
     155// "Next" pointers are stored as two 8-bit pieces, high order first.  The
     156// value is a positive offset from the opcode of the node containing it.
     157// An operand, if any, simply follows the node.  (Note that much of the
     158// code generation knows about this implicit relationship.)
     159//
     160// Using two bytes for the "next" pointer is vast overkill for most things,
     161// but allows patterns to get big without disasters.
     162//
     163
     164const char *kMeta = "^$.[()|?+*\\";
     165const int32 kMaxSize = 32767L;      // Probably could be 65535L.
     166
     167// Flags to be passed up and down:
     168enum {
     169    kHasWidth = 01, // Known never to match null string.
     170    kSimple = 02,   // Simple enough to be kRegExpStar/kRegExpPlus operand.
     171    kSPStart = 04,  // Starts with * or +.
     172    kWorst = 0  // Worst case.
     173};
     174
     175const char *kRegExpErrorStringArray[] = {
     176    "Unmatched parenthesis.",
     177    "Expression too long.",
     178    "Too many parenthesis.",
     179    "Junk on end.",
     180    "*+? operand may be empty.",
     181    "Nested *?+.",
     182    "Invalid bracket range.",
     183    "Unmatched brackets.",
     184    "Internal error.",
     185    "?+* follows nothing.",
     186    "Trailing \\.",
     187    "Corrupted expression.",
     188    "Memory corruption.",
     189    "Corrupted pointers.",
     190    "Corrupted opcode."
     191};
     192
     193#ifdef DEBUG
     194int32 regnarrate = 0;
     195#endif
     196
     197RegExp::RegExp()
     198    :   fError(B_OK),
     199        fRegExp(NULL)
     200{
     201}
     202
     203RegExp::RegExp(const char *pattern)
     204    :   fError(B_OK),
     205        fRegExp(NULL)
     206{
     207    fRegExp = Compile(pattern);
     208}
     209
     210RegExp::RegExp(const BString &pattern)
     211    :   fError(B_OK),
     212        fRegExp(NULL)
     213{
     214    fRegExp = Compile(pattern.String());
     215}
     216
     217RegExp::~RegExp()
     218{
     219    free(fRegExp);
     220}
     221
     222
     223
     224status_t
     225RegExp::InitCheck() const
     226{
     227    return fError;
     228}
     229
     230status_t
     231RegExp::SetTo(const char *pattern)
     232{
     233    fError = B_OK;
     234    free(fRegExp);
     235    fRegExp = Compile(pattern);
     236    return fError;
     237}
     238
     239status_t
     240RegExp::SetTo(const BString &pattern)
     241{
     242    fError = B_OK;
     243    free(fRegExp);
     244    fRegExp = Compile(pattern.String());
     245    return fError;
     246}
     247
     248bool
     249RegExp::Matches(const char *string) const
     250{
     251    if (!fRegExp || !string)
     252        return false;
     253       
     254    return RunMatcher(fRegExp, string) == 1;
     255}
     256
     257bool
     258RegExp::Matches(const BString &string) const
     259{
     260    if (!fRegExp)
     261        return false;
     262
     263    return RunMatcher(fRegExp, string.String()) == 1;
     264}
     265
     266
     267//
     268// - Compile - compile a regular expression into internal code
     269//
     270// We can't allocate space until we know how big the compiled form will be,
     271// but we can't compile it (and thus know how big it is) until we've got a
     272// place to put the code.  So we cheat:  we compile it twice, once with code
     273// generation turned off and size counting turned on, and once "for real".
     274// This also means that we don't allocate space until we are sure that the
     275// thing really will compile successfully, and we never have to move the
     276// code and thus invalidate pointers into it.  (Note that it has to be in
     277// one piece because free() must be able to free it all.)
     278//
     279// Beware that the optimization-preparation code in here knows about some
     280// of the structure of the compiled regexp.
     281
     282regexp *
     283RegExp::Compile(const char *exp)
     284{
     285    regexp *r;
     286    const char *scan;
     287    const char *longest;
     288    int32 len;
     289    int32 flags;
     290
     291    if (exp == NULL) {
     292        SetError(B_BAD_VALUE);
     293        return NULL;
     294    }
     295
     296    // First pass: determine size, legality.
     297    fInputScanPointer = exp;
     298    fParenthesisCount = 1;
     299    fCodeSize = 0L;
     300    fCodeEmitPointer = &fDummy;
     301    Char(kRegExpMagic);
     302    if (Reg(0, &flags) == NULL)
     303        return NULL;
     304
     305    // Small enough for pointer-storage convention?
     306    if (fCodeSize >= kMaxSize) {
     307        SetError(REGEXP_TOO_BIG);
     308        return NULL;
     309    }
     310
     311    // Allocate space.
     312    r = (regexp *)malloc(sizeof(regexp) + fCodeSize);
     313
     314    if (!r) {
     315        SetError(B_NO_MEMORY);
     316        return NULL;
     317    }
     318
     319    // Second pass: emit code.
     320    fInputScanPointer = exp;
     321    fParenthesisCount = 1;
     322    fCodeEmitPointer = r->program;
     323    Char(kRegExpMagic);
     324    if (Reg(0, &flags) == NULL) {
     325        free(r);
     326        return NULL;
     327    }
     328   
     329    // Dig out information for optimizations.
     330    r->regstart = '\0'; // Worst-case defaults.
     331    r->reganch = 0;
     332    r->regmust = NULL;
     333    r->regmlen = 0;
     334    scan = r->program + 1;          // First kRegExpBranch.
     335    if (*Next((char *)scan) == kRegExpEnd) {        // Only one top-level choice.
     336        scan = Operand(scan);
     337
     338        // Starting-point info.
     339        if (*scan == kRegExpExactly)
     340            r->regstart = *Operand(scan);
     341        else if (*scan == kRegExpBol)
     342            r->reganch++;
     343
     344        //
     345        // If there's something expensive in the r.e., find the
     346        // longest literal string that must appear and make it the
     347        // regmust.  Resolve ties in favor of later strings, since
     348        // the regstart check works with the beginning of the r.e.
     349        // and avoiding duplication strengthens checking.  Not a
     350        // strong reason, but sufficient in the absence of others.
     351        //
     352        if (flags&kSPStart) {
     353            longest = NULL;
     354            len = 0;
     355            for (; scan != NULL; scan = Next((char *)scan))
     356                if (*scan == kRegExpExactly && (int32)strlen(Operand(scan)) >= len) {
     357                    longest = Operand(scan);
     358                    len = (int32)strlen(Operand(scan));
     359                }
     360            r->regmust = longest;
     361            r->regmlen = len;
     362        }
     363    }
     364
     365    return r;
     366}
     367
     368regexp *
     369RegExp::Expression() const
     370{
     371    return fRegExp;
     372}
     373
     374const char *
     375RegExp::ErrorString() const
     376{
     377    if (fError >= REGEXP_UNMATCHED_PARENTHESIS
     378        && fError <= REGEXP_CORRUPTED_OPCODE)
     379        return kRegExpErrorStringArray[fError - B_ERRORS_END];
     380
     381    return strerror(fError);
     382}
     383
     384
     385void
     386RegExp::SetError(status_t error) const
     387{
     388    fError = error;
     389}
     390
     391
     392//
     393// - Reg - regular expression, i.e. main body or parenthesized thing
     394//
     395// Caller must absorb opening parenthesis.
     396//
     397// Combining parenthesis handling with the base level of regular expression
     398// is a trifle forced, but the need to tie the tails of the branches to what
     399// follows makes it hard to avoid.
     400//
     401char *
     402RegExp::Reg(int32 paren, int32 *flagp)
     403{
     404    char *ret;
     405    char *br;
     406    char *ender;
     407    int32 parno = 0;
     408    int32 flags;
     409
     410    *flagp = kHasWidth; // Tentatively.
     411
     412    // Make an kRegExpOpen node, if parenthesized.
     413    if (paren) {
     414        if (fParenthesisCount >= kSubExpressionMax) {
     415            SetError(REGEXP_TOO_MANY_PARENTHESIS);
     416            return NULL;
     417        }
     418        parno = fParenthesisCount;
     419        fParenthesisCount++;
     420        ret = Node((char)(kRegExpOpen + parno));
     421    } else
     422        ret = NULL;
     423
     424    // Pick up the branches, linking them together.
     425    br = Branch(&flags);
     426    if (br == NULL)
     427        return NULL;
     428    if (ret != NULL)
     429        Tail(ret, br);  // kRegExpOpen -> first
     430    else
     431        ret = br;
     432    if (!(flags & kHasWidth))
     433        *flagp &= ~kHasWidth;
     434    *flagp |= flags&kSPStart;
     435    while (*fInputScanPointer == '|') {
     436        fInputScanPointer++;
     437        br = Branch(&flags);
     438        if (br == NULL)
     439            return NULL;
     440        Tail(ret, br);  // kRegExpBranch -> kRegExpBranch.
     441        if (!(flags & kHasWidth))
     442            *flagp &= ~kHasWidth;
     443        *flagp |= flags&kSPStart;
     444    }
     445
     446    // Make a closing node, and hook it on the end.
     447    ender = Node(paren ? (char)(kRegExpClose + parno) : (char)kRegExpEnd); 
     448    Tail(ret, ender);
     449
     450    // Hook the tails of the branches to the closing node.
     451    for (br = ret; br != NULL; br = Next(br))
     452        OpTail(br, ender);
     453
     454    // Check for proper termination.
     455    if (paren && *fInputScanPointer++ != ')') {
     456        SetError(REGEXP_UNMATCHED_PARENTHESIS);
     457        return NULL;
     458    } else if (!paren && *fInputScanPointer != '\0') {
     459        if (*fInputScanPointer == ')') {
     460            SetError(REGEXP_UNMATCHED_PARENTHESIS);
     461            return NULL;
     462        } else {
     463            SetError(REGEXP_JUNK_ON_END);
     464            return NULL;    //  "Can't happen".
     465        }
     466        // NOTREACHED
     467    }
     468
     469    return ret;
     470}
     471
     472//
     473// - Branch - one alternative of an | operator
     474//
     475// Implements the concatenation operator.
     476//
     477char *
     478RegExp::Branch(int32 *flagp)
     479{
     480    char *ret;
     481    char *chain;
     482    char *latest;
     483    int32 flags;
     484
     485    *flagp = kWorst;        // Tentatively.
     486
     487    ret = Node(kRegExpBranch);
     488    chain = NULL;
     489    while (*fInputScanPointer != '\0'
     490        && *fInputScanPointer != '|'
     491        && *fInputScanPointer != ')') {
     492        latest = Piece(&flags);
     493        if (latest == NULL)
     494            return NULL;
     495        *flagp |= flags & kHasWidth;
     496        if (chain == NULL)  // First piece.
     497            *flagp |= flags & kSPStart;
     498        else
     499            Tail(chain, latest);
     500        chain = latest;
     501    }
     502    if (chain == NULL)  // Loop ran zero times.
     503        Node(kRegExpNothing);
     504
     505    return ret;
     506}
     507
     508//
     509// - Piece - something followed by possible [*+?]
     510//
     511// Note that the branching code sequences used for ? and the general cases
     512// of * and + are somewhat optimized:  they use the same kRegExpNothing node as
     513// both the endmarker for their branch list and the body of the last branch.
     514// It might seem that this node could be dispensed with entirely, but the
     515// endmarker role is not redundant.
     516//
     517char *
     518RegExp::Piece(int32 *flagp)
     519{
     520    char *ret;
     521    char op;
     522    char *next;
     523    int32 flags;
     524
     525    ret = Atom(&flags);
     526    if (ret == NULL)
     527        return NULL;
     528
     529    op = *fInputScanPointer;
     530    if (!IsMult(op)) {
     531        *flagp = flags;
     532        return ret;
     533    }
     534
     535    if (!(flags & kHasWidth) && op != '?') {
     536        SetError(REGEXP_STAR_PLUS_OPERAND_EMPTY);
     537        return NULL;
     538    }
     539    *flagp = op != '+' ? kWorst | kSPStart :  kWorst | kHasWidth;
     540
     541    if (op == '*' && (flags & kSimple))
     542        Insert(kRegExpStar, ret);
     543    else if (op == '*') {
     544        // Emit x* as (x&|), where & means "self".
     545        Insert(kRegExpBranch, ret);             // Either x
     546        OpTail(ret, Node(kRegExpBack));     // and loop
     547        OpTail(ret, ret);               // back
     548        Tail(ret, Node(kRegExpBranch));     // or
     549        Tail(ret, Node(kRegExpNothing));        // null.
     550    } else if (op == '+' && (flags & kSimple))
     551        Insert(kRegExpPlus, ret);
     552    else if (op == '+') {
     553        // Emit x+ as x(&|), where & means "self".
     554        next = Node(kRegExpBranch);             // Either
     555        Tail(ret, next);
     556        Tail(Node(kRegExpBack), ret);       // loop back
     557        Tail(next, Node(kRegExpBranch));        // or
     558        Tail(ret, Node(kRegExpNothing));        // null.
     559    } else if (op == '?') {
     560        // Emit x? as (x|)
     561        Insert(kRegExpBranch, ret);         // Either x
     562        Tail(ret, Node(kRegExpBranch)); // or
     563        next = Node(kRegExpNothing);        // null.
     564        Tail(ret, next);
     565        OpTail(ret, next);
     566    }
     567    fInputScanPointer++;
     568    if (IsMult(*fInputScanPointer)) {
     569        SetError(REGEXP_NESTED_STAR_QUESTION_PLUS);
     570        return NULL;
     571    }
     572    return ret;
     573}
     574
     575//
     576// - Atom - the lowest level
     577//
     578// Optimization:  gobbles an entire sequence of ordinary characters so that
     579// it can turn them into a single node, which is smaller to store and
     580// faster to run.  Backslashed characters are exceptions, each becoming a
     581// separate node; the code is simpler that way and it's not worth fixing.
     582//
     583char *
     584RegExp::Atom(int32 *flagp)
     585{
     586    char *ret;
     587    int32 flags;
     588
     589    *flagp = kWorst;        // Tentatively.
     590
     591    switch (*fInputScanPointer++) {
     592        case '^':
     593            ret = Node(kRegExpBol);
     594            break;
     595        case '$':
     596            ret = Node(kRegExpEol);
     597            break;
     598        case '.':
     599            ret = Node(kRegExpAny);
     600            *flagp |= kHasWidth|kSimple;
     601            break;
     602        case '[':
     603            {
     604                int32 cclass;
     605                int32 classend;
     606   
     607                if (*fInputScanPointer == '^') {    // Complement of range.
     608                    ret = Node(kRegExpAnyBut);
     609                    fInputScanPointer++;
     610                } else
     611                    ret = Node(kRegExpAnyOf);
     612                if (*fInputScanPointer == ']' || *fInputScanPointer == '-')
     613                    Char(*fInputScanPointer++);
     614                while (*fInputScanPointer != '\0' && *fInputScanPointer != ']') {
     615                    if (*fInputScanPointer == '-') {
     616                        fInputScanPointer++;
     617                        if (*fInputScanPointer == ']' || *fInputScanPointer == '\0')
     618                            Char('-');
     619                        else {
     620                            cclass = UCharAt(fInputScanPointer - 2) + 1;
     621                            classend = UCharAt(fInputScanPointer);
     622                            if (cclass > classend + 1) {
     623                                SetError(REGEXP_INVALID_BRACKET_RANGE);
     624                                return NULL;
     625                            }
     626                            for (; cclass <= classend; cclass++)
     627                                Char((char)cclass);
     628                            fInputScanPointer++;
     629                        }
     630                    } else
     631                        Char(*fInputScanPointer++);
     632                }
     633                Char('\0');
     634                if (*fInputScanPointer != ']') {
     635                    SetError(REGEXP_UNMATCHED_BRACKET);
     636                    return NULL;
     637                }
     638                fInputScanPointer++;
     639                *flagp |= kHasWidth | kSimple;
     640            }
     641            break;
     642        case '(':
     643            ret = Reg(1, &flags);
     644            if (ret == NULL)
     645                return NULL;
     646            *flagp |= flags & (kHasWidth | kSPStart);
     647            break;
     648        case '\0':
     649        case '|':
     650        case ')':
     651            SetError(REGEXP_INTERNAL_ERROR);
     652            return NULL; //  Supposed to be caught earlier.
     653        case '?':
     654        case '+':
     655        case '*':
     656            SetError(REGEXP_QUESTION_PLUS_STAR_FOLLOWS_NOTHING);
     657            return NULL;
     658        case '\\':
     659            if (*fInputScanPointer == '\0') {
     660                SetError(REGEXP_TRAILING_BACKSLASH);
     661                return NULL;
     662            }
     663            ret = Node(kRegExpExactly);
     664            Char(*fInputScanPointer++);
     665            Char('\0');
     666            *flagp |= kHasWidth|kSimple;
     667            break;
     668        default:
     669            {
     670                int32 len;
     671                char ender;
     672   
     673                fInputScanPointer--;
     674                len = (int32)strcspn(fInputScanPointer, kMeta);
     675                if (len <= 0) {
     676                    SetError(REGEXP_INTERNAL_ERROR);
     677                    return NULL;
     678                }
     679                ender = *(fInputScanPointer + len);
     680                if (len > 1 && IsMult(ender))
     681                    len--;      // Back off clear of ?+* operand.
     682                *flagp |= kHasWidth;
     683                if (len == 1)
     684                    *flagp |= kSimple;
     685                ret = Node(kRegExpExactly);
     686                while (len > 0) {
     687                    Char(*fInputScanPointer++);
     688                    len--;
     689                }
     690                Char('\0');
     691            }
     692            break;
     693    }
     694
     695    return ret;
     696}
     697
     698//
     699// - Node - emit a node
     700//
     701char *          // Location.
     702RegExp::Node(char op)
     703{
     704    char *ret;
     705    char *ptr;
     706
     707    ret = fCodeEmitPointer;
     708    if (ret == &fDummy) {
     709        fCodeSize += 3;
     710        return ret;
     711    }
     712
     713    ptr = ret;
     714    *ptr++ = op;
     715    *ptr++ = '\0';      // Null "next" pointer.
     716    *ptr++ = '\0';
     717    fCodeEmitPointer = ptr;
     718
     719    return ret;
     720}
     721
     722//
     723// - Char - emit (if appropriate) a byte of code
     724//
     725void
     726RegExp::Char(char b)
     727{
     728    if (fCodeEmitPointer != &fDummy)
     729        *fCodeEmitPointer++ = b;
     730    else
     731        fCodeSize++;
     732}
     733
     734//
     735// - Insert - insert an operator in front of already-emitted operand
     736//
     737// Means relocating the operand.
     738//
     739void
     740RegExp::Insert(char op, char *opnd)
     741{
     742    char *src;
     743    char *dst;
     744    char *place;
     745
     746    if (fCodeEmitPointer == &fDummy) {
     747        fCodeSize += 3;
     748        return;
     749    }
     750
     751    src = fCodeEmitPointer;
     752    fCodeEmitPointer += 3;
     753    dst = fCodeEmitPointer;
     754    while (src > opnd)
     755        *--dst = *--src;
     756
     757    place = opnd;       // Op node, where operand used to be.
     758    *place++ = op;
     759    *place++ = '\0';
     760    *place++ = '\0';
     761}
     762
     763//
     764// - Tail - set the next-pointer at the end of a node chain
     765//
     766void
     767RegExp::Tail(char *p, char *val)
     768{
     769    char *scan;
     770    char *temp;
     771    int32 offset;
     772
     773    if (p == &fDummy)
     774        return;
     775
     776    // Find last node.
     777    scan = p;
     778    for (;;) {
     779        temp = Next(scan);
     780        if (temp == NULL)
     781            break;
     782        scan = temp;
     783    }
     784
     785    if (scan[0] == kRegExpBack)
     786        offset = scan - val;
     787    else
     788        offset = val - scan;
     789
     790    scan[1] = (char)((offset >> 8) & 0377);
     791    scan[2] = (char)(offset & 0377);
     792}
     793
     794//
     795// - OpTail - Tail on operand of first argument; nop if operandless
     796//
     797void
     798RegExp::OpTail(char *p, char *val)
     799{
     800    // "Operandless" and "op != kRegExpBranch" are synonymous in practice.
     801    if (p == NULL || p == &fDummy || *p != kRegExpBranch)
     802        return;
     803    Tail(Operand(p), val);
     804}
     805
     806//
     807// RunMatcher and friends
     808//
     809
     810//
     811// - RunMatcher - match a regexp against a string
     812//
     813int32
     814RegExp::RunMatcher(regexp *prog, const char *string) const
     815{
     816    const char *s;
     817
     818    // Be paranoid...
     819    if (prog == NULL || string == NULL) {
     820        SetError(B_BAD_VALUE);
     821        return 0;
     822    }
     823
     824    // Check validity of program.
     825    if (UCharAt(prog->program) != kRegExpMagic) {
     826        SetError(REGEXP_CORRUPTED_PROGRAM);
     827        return 0;
     828    }
     829
     830    // If there is a "must appear" string, look for it.
     831    if (prog->regmust != NULL) {
     832        s = string;
     833        while ((s = strchr(s, prog->regmust[0])) != NULL) {
     834            if (strncmp(s, prog->regmust, (size_t)prog->regmlen) == 0)
     835                break;  // Found it.
     836            s++;
     837        }
     838        if (s == NULL)  // Not present.
     839            return 0;
     840    }
     841
     842    // Mark beginning of line for ^ .
     843    fRegBol = string;
     844
     845    // Simplest case:  anchored match need be tried only once.
     846    if (prog->reganch)
     847        return Try(prog, (char*)string);
     848
     849    // Messy cases:  unanchored match.
     850    s = string;
     851    if (prog->regstart != '\0')
     852        // We know what char it must start with.
     853        while ((s = strchr(s, prog->regstart)) != NULL) {
     854            if (Try(prog, (char*)s))
     855                return 1;
     856            s++;
     857        }
     858    else
     859        // We don't -- general case.
     860        do {
     861            if (Try(prog, (char*)s))
     862                return 1;
     863        } while (*s++ != '\0');
     864
     865    // Failure.
     866    return 0;
     867}
     868
     869//
     870// - Try - try match at specific point
     871//
     872int32           // 0 failure, 1 success
     873RegExp::Try(regexp *prog, const char *string) const
     874{
     875    int32 i;
     876    const char **sp;
     877    const char **ep;
     878
     879    fStringInputPointer = string;
     880    fStartPArrayPointer = prog->startp;
     881    fEndPArrayPointer = prog->endp;
     882
     883    sp = prog->startp;
     884    ep = prog->endp;
     885    for (i = kSubExpressionMax; i > 0; i--) {
     886        *sp++ = NULL;
     887        *ep++ = NULL;
     888    }
     889    if (Match(prog->program + 1)) {
     890        prog->startp[0] = string;
     891        prog->endp[0] = fStringInputPointer;
     892        return 1;
     893    } else
     894        return 0;
     895}
     896
     897//
     898// - Match - main matching routine
     899//
     900// Conceptually the strategy is simple:  check to see whether the current
     901// node matches, call self recursively to see whether the rest matches,
     902// and then act accordingly.  In practice we make some effort to avoid
     903// recursion, in particular by going through "ordinary" nodes (that don't
     904// need to know whether the rest of the match failed) by a loop instead of
     905// by recursion.
     906///
     907int32           // 0 failure, 1 success
     908RegExp::Match(const char *prog) const
     909{
     910    const char *scan;   // Current node.
     911    const char *next;       // Next node.
     912
     913    scan = prog;
     914#ifdef DEBUG
     915    if (scan != NULL && regnarrate)
     916        fprintf(stderr, "%s(\n", Prop(scan));
     917#endif
     918    while (scan != NULL) {
     919#ifdef DEBUG
     920        if (regnarrate)
     921            fprintf(stderr, "%s...\n", Prop(scan));
     922#endif
     923        next = Next(scan);
     924
     925        switch (*scan) {
     926            case kRegExpBol:
     927                if (fStringInputPointer != fRegBol)
     928                    return 0;
     929                break;
     930            case kRegExpEol:
     931                if (*fStringInputPointer != '\0')
     932                    return 0;
     933                break;
     934            case kRegExpAny:
     935                if (*fStringInputPointer == '\0')
     936                    return 0;
     937                fStringInputPointer++;
     938                break;
     939            case kRegExpExactly:
     940                {
     941                    const char *opnd = Operand(scan);
     942                    // Inline the first character, for speed.
     943                    if (*opnd != *fStringInputPointer)
     944                        return 0;
     945
     946                    uint32 len = strlen(opnd);
     947                    if (len > 1 && strncmp(opnd, fStringInputPointer, len) != 0)
     948                        return 0;
     949
     950                    fStringInputPointer += len;
     951                }
     952                break;
     953            case kRegExpAnyOf:
     954                if (*fStringInputPointer == '\0'
     955                    || strchr(Operand(scan), *fStringInputPointer) == NULL)
     956                    return 0;
     957                fStringInputPointer++;
     958                break;
     959            case kRegExpAnyBut:
     960                if (*fStringInputPointer == '\0'
     961                    || strchr(Operand(scan), *fStringInputPointer) != NULL)
     962                    return 0;
     963                fStringInputPointer++;
     964                break;
     965            case kRegExpNothing:
     966                break;
     967            case kRegExpBack:
     968                break;
     969            case kRegExpOpen + 1:
     970            case kRegExpOpen + 2:
     971            case kRegExpOpen + 3:
     972            case kRegExpOpen + 4:
     973            case kRegExpOpen + 5:
     974            case kRegExpOpen + 6:
     975            case kRegExpOpen + 7:
     976            case kRegExpOpen + 8:
     977            case kRegExpOpen + 9:
     978                {
     979                    int32 no;
     980                    const char *save;
     981   
     982                    no = *scan - kRegExpOpen;
     983                    save = fStringInputPointer;
     984   
     985                    if (Match(next)) {
     986                        //
     987                        // Don't set startp if some later
     988                        // invocation of the same parentheses
     989                        // already has.
     990                        //
     991                        if (fStartPArrayPointer[no] == NULL)
     992                            fStartPArrayPointer[no] = save;
     993                        return 1;
     994                    } else
     995                        return 0;
     996                }
     997                break;
     998            case kRegExpClose + 1:
     999            case kRegExpClose + 2:
     1000            case kRegExpClose + 3:
     1001            case kRegExpClose + 4:
     1002            case kRegExpClose + 5:
     1003            case kRegExpClose + 6:
     1004            case kRegExpClose + 7:
     1005            case kRegExpClose + 8:
     1006            case kRegExpClose + 9:
     1007                {
     1008                    int32 no;
     1009                    const char *save;
     1010   
     1011                    no = *scan - kRegExpClose;
     1012                    save = fStringInputPointer;
     1013   
     1014                    if (Match(next)) {
     1015                        //
     1016                        // Don't set endp if some later
     1017                        // invocation of the same parentheses
     1018                        // already has.
     1019                        //
     1020                        if (fEndPArrayPointer[no] == NULL)
     1021                            fEndPArrayPointer[no] = save;
     1022                        return 1;
     1023                    } else
     1024                        return 0;
     1025                }
     1026                break;
     1027            case kRegExpBranch:
     1028                {
     1029                    const char *save;
     1030   
     1031                    if (*next != kRegExpBranch)     // No choice.
     1032                        next = Operand(scan);   // Avoid recursion.
     1033                    else {
     1034                        do {
     1035                            save = fStringInputPointer;
     1036                            if (Match(Operand(scan)))
     1037                                return 1;
     1038                            fStringInputPointer = save;
     1039                            scan = Next(scan);
     1040                        } while (scan != NULL && *scan == kRegExpBranch);
     1041                        return 0;
     1042                        // NOTREACHED/
     1043                    }
     1044                }
     1045                break;
     1046            case kRegExpStar:
     1047            case kRegExpPlus:
     1048                {
     1049                    char nextch;
     1050                    int32 no;
     1051                    const char *save;
     1052                    int32 min;
     1053   
     1054                    //
     1055                    //Lookahead to avoid useless match attempts
     1056                    // when we know what character comes next.
     1057                    //
     1058                    nextch = '\0';
     1059                    if (*next == kRegExpExactly)
     1060                        nextch = *Operand(next);
     1061                    min = (*scan == kRegExpStar) ? 0 : 1;
     1062                    save = fStringInputPointer;
     1063                    no = Repeat(Operand(scan));
     1064                    while (no >= min) {
     1065                        // If it could work, try it.
     1066                        if (nextch == '\0' || *fStringInputPointer == nextch)
     1067                            if (Match(next))
     1068                                return 1;
     1069                        // Couldn't or didn't -- back up.
     1070                        no--;
     1071                        fStringInputPointer = save + no;
     1072                    }
     1073                    return 0;
     1074                }
     1075                break;
     1076            case kRegExpEnd:
     1077                return 1;   // Success!
     1078
     1079            default:
     1080                SetError(REGEXP_MEMORY_CORRUPTION);
     1081                return 0;
     1082            }
     1083
     1084        scan = next;
     1085    }
     1086
     1087    //
     1088    // We get here only if there's trouble -- normally "case kRegExpEnd" is
     1089    // the terminating point.
     1090    //
     1091    SetError(REGEXP_CORRUPTED_POINTERS);
     1092    return 0;
     1093}
     1094
     1095//
     1096// - Repeat - repeatedly match something simple, report how many
     1097//
     1098int32
     1099RegExp::Repeat(const char *p) const
     1100{
     1101    int32 count = 0;
     1102    const char *scan;
     1103    const char *opnd;
     1104
     1105    scan = fStringInputPointer;
     1106    opnd = Operand(p);
     1107    switch (*p) {
     1108        case kRegExpAny:
     1109            count = (int32)strlen(scan);
     1110            scan += count;
     1111            break;
     1112
     1113        case kRegExpExactly:
     1114            while (*opnd == *scan) {
     1115                count++;
     1116                scan++;
     1117            }
     1118            break;
     1119
     1120        case kRegExpAnyOf:
     1121            while (*scan != '\0' && strchr(opnd, *scan) != NULL) {
     1122                count++;
     1123                scan++;
     1124            }
     1125            break;
     1126
     1127        case kRegExpAnyBut:
     1128            while (*scan != '\0' && strchr(opnd, *scan) == NULL) {
     1129                count++;
     1130                scan++;
     1131            }
     1132            break;
     1133
     1134        default:        // Oh dear.  Called inappropriately.
     1135            SetError(REGEXP_INTERNAL_ERROR);
     1136            count = 0;  // Best compromise.
     1137            break;
     1138    }
     1139    fStringInputPointer = scan;
     1140
     1141    return count;
     1142}
     1143
     1144//
     1145// - Next - dig the "next" pointer out of a node
     1146//
     1147char *
     1148RegExp::Next(char *p)
     1149{
     1150    int32 offset;
     1151
     1152    if (p == &fDummy)
     1153        return NULL;
     1154
     1155    offset = ((*(p + 1) & 0377) << 8) + (*(p + 2) & 0377);
     1156    if (offset == 0)
     1157        return NULL;
     1158
     1159    if (*p == kRegExpBack)
     1160        return p - offset;
     1161    else
     1162        return p + offset;
     1163}
     1164
     1165const char *
     1166RegExp::Next(const char *p) const
     1167{
     1168    int32 offset;
     1169
     1170    if (p == &fDummy)
     1171        return NULL;
     1172
     1173    offset = ((*(p + 1) & 0377) << 8) + (*(p + 2) & 0377);
     1174    if (offset == 0)
     1175        return NULL;
     1176
     1177    if (*p == kRegExpBack)
     1178        return p - offset;
     1179    else
     1180        return p + offset;
     1181}
     1182
     1183inline int32
     1184RegExp::UCharAt(const char *p) const
     1185{
     1186    return (int32)*(unsigned char *)p;
     1187}
     1188
     1189inline char *
     1190RegExp::Operand(char* p) const
     1191{
     1192    return p + 3;
     1193}
     1194
     1195inline const char *
     1196RegExp::Operand(const char* p) const
     1197{
     1198    return p + 3;
     1199}
     1200
     1201inline bool
     1202RegExp::IsMult(char c) const
     1203{
     1204    return c == '*' || c == '+' || c == '?';
     1205}
     1206
     1207
     1208#ifdef DEBUG
     1209
     1210//
     1211// - Dump - dump a regexp onto stdout in vaguely comprehensible form
     1212//
     1213void
     1214RegExp::Dump()
     1215{
     1216    char *s;
     1217    char op = kRegExpExactly;   // Arbitrary non-kRegExpEnd op.
     1218    char *next;
     1219
     1220    s = fRegExp->program + 1;
     1221    while (op != kRegExpEnd) {  // While that wasn't kRegExpEnd last time...
     1222        op = *s;
     1223        printf("%2ld%s", s - fRegExp->program, Prop(s));    // Where, what.
     1224        next = this->Next(s);
     1225        if (next == NULL)       // Next ptr.
     1226            printf("(0)");
     1227        else
     1228            printf("(%ld)", (s - fRegExp->program) + (next - s));
     1229        s += 3;
     1230        if (op == kRegExpAnyOf || op == kRegExpAnyBut || op == kRegExpExactly) {
     1231            // Literal string, where present.
     1232            while (*s != '\0') {
     1233                putchar(*s);
     1234                s++;
     1235            }
     1236            s++;
     1237        }
     1238        putchar('\n');
     1239    }
     1240
     1241    // Header fields of interest.
     1242    if (fRegExp->regstart != '\0')
     1243        printf("start `%c' ", fRegExp->regstart);
     1244    if (fRegExp->reganch)
     1245        printf("anchored ");
     1246    if (fRegExp->regmust != NULL)
     1247        printf("must have \"%s\"", fRegExp->regmust);
     1248    printf("\n");
     1249}
     1250
     1251//
     1252// - Prop - printable representation of opcode
     1253//
     1254char *
     1255RegExp::Prop(const char *op) const
     1256{
     1257    char *p = NULL;
     1258    static char buf[50];
     1259
     1260    (void) strcpy(buf, ":");
     1261
     1262    switch (*op) {
     1263        case kRegExpBol:
     1264            p = "kRegExpBol";
     1265            break;
     1266        case kRegExpEol:
     1267            p = "kRegExpEol";
     1268            break;
     1269        case kRegExpAny:
     1270            p = "kRegExpAny";
     1271            break;
     1272        case kRegExpAnyOf:
     1273            p = "kRegExpAnyOf";
     1274            break;
     1275        case kRegExpAnyBut:
     1276            p = "kRegExpAnyBut";
     1277            break;
     1278        case kRegExpBranch:
     1279            p = "kRegExpBranch";
     1280            break;
     1281        case kRegExpExactly:
     1282            p = "kRegExpExactly";
     1283            break;
     1284        case kRegExpNothing:
     1285            p = "kRegExpNothing";
     1286            break;
     1287        case kRegExpBack:
     1288            p = "kRegExpBack";
     1289            break;
     1290        case kRegExpEnd:
     1291            p = "kRegExpEnd";
     1292            break;
     1293        case kRegExpOpen + 1:
     1294        case kRegExpOpen + 2:
     1295        case kRegExpOpen + 3:
     1296        case kRegExpOpen + 4:
     1297        case kRegExpOpen + 5:
     1298        case kRegExpOpen + 6:
     1299        case kRegExpOpen + 7:
     1300        case kRegExpOpen + 8:
     1301        case kRegExpOpen + 9:
     1302            sprintf(buf + strlen(buf), "kRegExpOpen%d", *op - kRegExpOpen);
     1303            p = NULL;
     1304            break;
     1305        case kRegExpClose + 1:
     1306        case kRegExpClose + 2:
     1307        case kRegExpClose + 3:
     1308        case kRegExpClose + 4:
     1309        case kRegExpClose + 5:
     1310        case kRegExpClose + 6:
     1311        case kRegExpClose + 7:
     1312        case kRegExpClose + 8:
     1313        case kRegExpClose + 9:
     1314            sprintf(buf + strlen(buf), "kRegExpClose%d", *op - kRegExpClose);
     1315            p = NULL;
     1316            break;
     1317        case kRegExpStar:
     1318            p = "kRegExpStar";
     1319            break;
     1320        case kRegExpPlus:
     1321            p = "kRegExpPlus";
     1322            break;
     1323        default:
     1324            RegExpError("corrupted opcode");
     1325            break;
     1326    }
     1327
     1328    if (p != NULL)
     1329        strcat(buf, p);
     1330
     1331    return buf;
     1332}
     1333
     1334void
     1335RegExp::RegExpError(const char *) const
     1336{
     1337    // does nothing now, perhaps it should printf?
     1338}
     1339
     1340#endif
  • src/bin/Jamfile

     
    222222# Network command line tools
    223223SubInclude HAIKU_TOP src bin network ;
    224224
     225# Locale kit tools
     226SubInclude HAIKU_TOP src bin locale ;
     227
    225228# Compression command line tools
    226229SubInclude HAIKU_TOP src bin unzip ;
    227230SubInclude HAIKU_TOP src bin zip ;
  • src/kits/locale/GenericNumberFormat.cpp

     
     1#include <algorithm>
     2#include <float.h>
     3#include <math.h>
     4#include <new>
     5#include <stdlib.h>
     6
     7#include <GenericNumberFormat.h>
     8#include <String.h>
     9#include <UnicodeChar.h>
     10
     11// constants (more below the helper classes)
     12
     13static const int kMaxIntDigitCount = 20;    // int64: 19 + sign, uint64: 20
     14static const int kMaxFloatDigitCount = DBL_DIG + 2;
     15    // double: mantissa precision + 2
     16
     17
     18// Symbol
     19
     20// constructor
     21BGenericNumberFormat::Symbol::Symbol(const char *symbol)
     22    : symbol(NULL),
     23      length(0),
     24      char_count(0)
     25{
     26    SetTo(symbol);
     27}
     28
     29// destructor
     30BGenericNumberFormat::Symbol::~Symbol()
     31{
     32    Unset();
     33}
     34
     35// SetTo
     36status_t
     37BGenericNumberFormat::Symbol::SetTo(const char *symbol)
     38{
     39    // unset old
     40    if (this->symbol) {
     41        free(this->symbol);
     42        length = 0;
     43        char_count = 0;
     44    }
     45    // set new
     46    if (symbol) {
     47        this->symbol = strdup(symbol);
     48        if (!this->symbol)
     49            return B_NO_MEMORY;
     50        length = strlen(this->symbol);
     51        char_count = BUnicodeChar::UTF8StringLength(this->symbol);
     52    }
     53    return B_OK;
     54}
     55
     56
     57// SpecialNumberSymbols
     58struct BGenericNumberFormat::SpecialNumberSymbols {
     59    const Symbol    *nan;
     60    const Symbol    *infinity;
     61    const Symbol    *negative_infinity;
     62};
     63
     64
     65// GroupingInfo
     66class BGenericNumberFormat::GroupingInfo {
     67    public:
     68        GroupingInfo()
     69            : fSeparators(NULL),
     70              fSeparatorCount(0),
     71              fSizes(NULL),
     72              fSizeCount(0),
     73              fSumSizes(NULL),
     74              fSumSeparators(NULL)
     75        {
     76        }
     77
     78        GroupingInfo(const char **separators, int32 separatorCount,
     79                     const size_t *sizes, int32 sizeCount)
     80            : fSeparators(NULL),
     81              fSeparatorCount(0),
     82              fSizes(NULL),
     83              fSizeCount(0),
     84              fSumSizes(NULL),
     85              fSumSeparators(NULL)
     86        {
     87            SetTo(separators, separatorCount, sizes, sizeCount);
     88        }
     89
     90        ~GroupingInfo()
     91        {
     92            Unset();
     93        }
     94
     95        status_t SetTo(const char **separators, int32 separatorCount,
     96                       const size_t *sizes, int32 sizeCount)
     97        {
     98            // unset old
     99            Unset();
     100            // set new
     101            if (!separators && separatorCount <= 0 || !sizes && sizeCount <= 0)
     102                return B_OK;
     103            // allocate arrays
     104            fSeparators = new(std::nothrow) Symbol[separatorCount];
     105            fSizes = new(std::nothrow) int32[sizeCount];
     106            fSumSizes = new(std::nothrow) int32[sizeCount];
     107            fSumSeparators = new(std::nothrow) Symbol*[separatorCount];
     108            if (!fSeparators || !fSizes || !fSumSizes || !fSumSeparators) {
     109                Unset();
     110                return B_NO_MEMORY;
     111            }
     112            fSeparatorCount = separatorCount;
     113            fSizeCount = sizeCount;
     114            // separators
     115            for (int i = 0; i < separatorCount; i++) {
     116                status_t error = fSeparators[i].SetTo(separators[i]);
     117                if (error != B_OK) {
     118                    Unset();
     119                    return error;
     120                }
     121            }
     122            // sizes and sum arrays
     123            int32 sumSize = -1;
     124            for (int32 i = 0; i < sizeCount; i++) {
     125                fSizes[i] = (int32)sizes[i];
     126                sumSize += fSizes[i];
     127                fSumSizes[i] = sumSize;
     128                fSumSeparators[i] = &fSeparators[std::min(i, fSeparatorCount)];
     129            }
     130            return B_OK;
     131        }
     132
     133        void Unset()
     134        {
     135            if (fSeparators) {
     136                delete[] fSeparators;
     137                fSeparators = NULL;
     138            }
     139            fSeparatorCount = 0;
     140            if (fSizes) {
     141                delete[] fSizes;
     142                fSizes = NULL;
     143            }
     144            fSizeCount = 0;
     145            if (fSumSizes) {
     146                delete[] fSumSizes;
     147                fSumSizes = NULL;
     148            }
     149            if (fSumSeparators) {
     150                delete[] fSumSeparators;
     151                fSumSeparators = NULL;
     152            }
     153        }
     154
     155        const Symbol *SeparatorForDigit(int32 position) const
     156        {
     157            for (int i = fSizeCount - 1; i >= 0; i--) {
     158                if (fSumSizes[i] <= position) {
     159                    if (fSumSizes[i] == position
     160                        || i == fSizeCount - 1
     161                           && (position - fSumSizes[i]) % fSizes[i] == 0) {
     162                        return fSumSeparators[i];
     163                    }
     164                    return NULL;
     165                }
     166            }
     167            return NULL;
     168        }
     169
     170    private:
     171        Symbol  *fSeparators;
     172        int32   fSeparatorCount;
     173        int32   *fSizes;
     174        int32   fSizeCount;
     175        int32   *fSumSizes;
     176        Symbol  **fSumSeparators;
     177};
     178
     179
     180// SignSymbols
     181class BGenericNumberFormat::SignSymbols {
     182    public:
     183        SignSymbols()
     184            : fPlusPrefix(),
     185              fMinusPrefix(),
     186              fPadPlusPrefix(),
     187              fNoForcePlusPrefix(),
     188              fPlusSuffix(),
     189              fMinusSuffix(),
     190              fPadPlusSuffix(),
     191              fNoForcePlusSuffix()
     192        {
     193        }
     194
     195        SignSymbols(const char *plusPrefix, const char *minusPrefix,
     196            const char *padPlusPrefix, const char *noForcePlusPrefix,
     197            const char *plusSuffix, const char *minusSuffix,
     198            const char *padPlusSuffix, const char *noForcePlusSuffix)
     199            : fPlusPrefix(plusPrefix),
     200              fMinusPrefix(minusPrefix),
     201              fPadPlusPrefix(padPlusPrefix),
     202              fNoForcePlusPrefix(noForcePlusPrefix),
     203              fPlusSuffix(plusSuffix),
     204              fMinusSuffix(minusSuffix),
     205              fPadPlusSuffix(padPlusSuffix),
     206              fNoForcePlusSuffix(noForcePlusSuffix)
     207        {
     208        }
     209
     210        ~SignSymbols()
     211        {
     212        }
     213
     214        status_t SetTo(const char *plusPrefix, const char *minusPrefix,
     215            const char *padPlusPrefix, const char *noForcePlusPrefix,
     216            const char *plusSuffix, const char *minusSuffix,
     217            const char *padPlusSuffix, const char *noForcePlusSuffix)
     218        {
     219            status_t error = B_OK;
     220            if (error == B_OK)
     221                error = fPlusPrefix.SetTo(plusPrefix);
     222            if (error == B_OK)
     223                error = fMinusPrefix.SetTo(minusPrefix);
     224            if (error == B_OK)
     225                error = fPadPlusPrefix.SetTo(noForcePlusPrefix);
     226            if (error == B_OK)
     227                error = fNoForcePlusPrefix.SetTo(noForcePlusPrefix);
     228            if (error == B_OK)
     229                error = fPlusSuffix.SetTo(plusSuffix);
     230            if (error == B_OK)
     231                error = fMinusSuffix.SetTo(minusSuffix);
     232            if (error == B_OK)
     233                error = fPadPlusSuffix.SetTo(noForcePlusSuffix);
     234            if (error == B_OK)
     235                error = fNoForcePlusSuffix.SetTo(noForcePlusSuffix);
     236            if (error != B_OK)
     237                Unset();
     238            return error;
     239        }
     240
     241        void Unset()
     242        {
     243            fPlusPrefix.Unset();
     244            fMinusPrefix.Unset();
     245            fNoForcePlusPrefix.Unset();
     246            fPadPlusPrefix.Unset();
     247            fPlusSuffix.Unset();
     248            fMinusSuffix.Unset();
     249            fNoForcePlusSuffix.Unset();
     250            fPadPlusSuffix.Unset();
     251        }
     252
     253        const Symbol *PlusPrefix() const
     254        {
     255            return &fPlusPrefix;
     256        }
     257
     258        const Symbol *MinusPrefix() const
     259        {
     260            return &fMinusPrefix;
     261        }
     262
     263        const Symbol *PadPlusPrefix() const
     264        {
     265            return &fPadPlusPrefix;
     266        }
     267
     268        const Symbol *NoForcePlusPrefix() const
     269        {
     270            return &fNoForcePlusPrefix;
     271        }
     272
     273        const Symbol *PlusSuffix() const
     274        {
     275            return &fPlusSuffix;
     276        }
     277
     278        const Symbol *MinusSuffix() const
     279        {
     280            return &fMinusSuffix;
     281        }
     282
     283        const Symbol *PadPlusSuffix() const
     284        {
     285            return &fPadPlusSuffix;
     286        }
     287
     288        const Symbol *NoForcePlusSuffix() const
     289        {
     290            return &fNoForcePlusSuffix;
     291        }
     292
     293    private:
     294        Symbol  fPlusPrefix;
     295        Symbol  fMinusPrefix;
     296        Symbol  fPadPlusPrefix;
     297        Symbol  fNoForcePlusPrefix;
     298        Symbol  fPlusSuffix;
     299        Symbol  fMinusSuffix;
     300        Symbol  fPadPlusSuffix;
     301        Symbol  fNoForcePlusSuffix;
     302};
     303
     304
     305// BufferWriter
     306class BGenericNumberFormat::BufferWriter {
     307    public:
     308        BufferWriter(char *buffer = NULL, int32 bufferSize = 0)
     309        {
     310            SetTo(buffer, bufferSize);
     311        }
     312
     313        void SetTo(char *buffer = NULL, int32 bufferSize = 0)
     314        {
     315            fBuffer = buffer;
     316            fBufferSize = bufferSize;
     317            fPosition = 0;
     318            fCharCount = 0;
     319            fDryRun = (!fBuffer || (fBufferSize == 0));
     320            if (!fDryRun)
     321                fBuffer[0] = '\0';
     322        }
     323
     324        int32 StringLength() const
     325        {
     326            return fPosition;
     327        }
     328
     329        int32 CharCount() const
     330        {
     331            return fCharCount;
     332        }
     333
     334        bool IsOverflow() const
     335        {
     336            return (fPosition >= fBufferSize);
     337        }
     338
     339        void Append(const char *bytes, size_t length, size_t charCount)
     340        {
     341            int32 newPosition = fPosition + length;
     342            fDryRun |= (newPosition >= fBufferSize);
     343            if (!fDryRun && length > 0) {
     344                memcpy(fBuffer + fPosition, bytes, length);
     345                fBuffer[newPosition] = '\0';
     346            }
     347            fPosition = newPosition;
     348            fCharCount += charCount;
     349        }
     350
     351        void Append(const Symbol &symbol)
     352        {
     353            Append(symbol.symbol, symbol.length, symbol.char_count);
     354        }
     355
     356        void Append(const Symbol *symbol)
     357        {
     358            if (symbol)
     359                Append(*symbol);
     360        }
     361
     362        void Append(char c, int32 count)    // ASCII 128 chars only!
     363        {
     364            if (count <= 0)
     365                return;
     366            int32 newPosition = fPosition + count;
     367            fDryRun |= (newPosition >= fBufferSize);
     368            if (!fDryRun && count > 0) {
     369                memset(fBuffer + fPosition, c, count);
     370                fBuffer[newPosition] = '\0';
     371            }
     372            fPosition = newPosition;
     373            fCharCount += count;
     374        }
     375
     376        void Append(const Symbol &symbol, int32 count)
     377        {
     378            if (count <= 0)
     379                return;
     380            int32 bytes = count * symbol.length;
     381            int32 newPosition = fPosition + bytes;
     382            fDryRun |= (newPosition >= fBufferSize);
     383            if (!fDryRun && count > 0) {
     384                for (int i = 0; i < count * symbol.length; i++)
     385                    fBuffer[i] = symbol.symbol[i % symbol.length];
     386                fBuffer[newPosition] = '\0';
     387            }
     388            fPosition = newPosition;
     389            fCharCount += count * symbol.char_count;
     390        }
     391
     392        void Append(const Symbol *symbol, int32 count)
     393        {
     394            if (symbol)
     395                Append(*symbol, count);
     396        }
     397
     398    private:
     399        char    *fBuffer;
     400        int32   fBufferSize;
     401        int32   fPosition;
     402        int32   fCharCount;
     403        bool    fDryRun;
     404};
     405
     406
     407// constants
     408
     409// digit symbols
     410static const BGenericNumberFormat::Symbol kDefaultDigitSymbols[] = {
     411    "0", "1", "2", "3", "4", "5", "6", "7", "8", "9"
     412};
     413
     414// decimal separator symbol
     415static const BGenericNumberFormat::Symbol kDefaultFractionSeparator = ".";
     416
     417// grouping separator symbols
     418static const char *kDefaultGroupingSeparators[] = { "," };
     419static const int32 kDefaultGroupingSeparatorCount
     420    = sizeof(kDefaultGroupingSeparators) / sizeof(const char*);
     421static const char *kNoGroupingSeparators[] = { NULL };  // to please mwcc
     422static const int32 kNoGroupingSeparatorCount = 0;
     423
     424// grouping sizes
     425static const size_t kDefaultGroupingSizes[] = { 3 };
     426static const int32 kDefaultGroupingSizeCount
     427    = sizeof(kDefaultGroupingSizes) / sizeof(size_t);
     428static const size_t kNoGroupingSizes[] = { 0 };         // to please mwcc
     429static const int32 kNoGroupingSizeCount = 0;
     430
     431// grouping info
     432static const BGenericNumberFormat::GroupingInfo kDefaultGroupingInfo(
     433    kDefaultGroupingSeparators, kDefaultGroupingSeparatorCount,
     434    kDefaultGroupingSizes, kDefaultGroupingSizeCount
     435);
     436static const BGenericNumberFormat::GroupingInfo kNoGroupingInfo(
     437    kNoGroupingSeparators, kNoGroupingSeparatorCount,
     438    kNoGroupingSizes, kNoGroupingSizeCount
     439);
     440
     441// exponent symbol
     442static const BGenericNumberFormat::Symbol kDefaultExponentSymbol = "e";
     443static const BGenericNumberFormat::Symbol kDefaultUpperCaseExponentSymbol
     444    = "E";
     445
     446// NaN symbol
     447static const BGenericNumberFormat::Symbol kDefaultNaNSymbol = "NaN";
     448static const BGenericNumberFormat::Symbol kDefaultUpperCaseNaNSymbol = "NaN";
     449
     450// infinity symbol
     451static const BGenericNumberFormat::Symbol kDefaultInfinitySymbol
     452    = "infinity";
     453static const BGenericNumberFormat::Symbol kDefaultUpperCaseInfinitySymbol
     454    = "INFINITY";
     455
     456// negative infinity symbol
     457static const BGenericNumberFormat::Symbol kDefaultNegativeInfinitySymbol
     458    = "-infinity";
     459static const BGenericNumberFormat::Symbol
     460    kDefaultUpperCaseNegativeInfinitySymbol = "-INFINITY";
     461
     462// sign symbols
     463static const BGenericNumberFormat::SignSymbols kDefaultSignSymbols(
     464    "+", "-", " ", "",  // prefixes
     465    "", "", "", ""      // suffixes
     466);
     467
     468// mantissa sign symbols
     469static const BGenericNumberFormat::SignSymbols kDefaultMantissaSignSymbols(
     470    "", "", "", "", // prefixes
     471    "", "", "", ""      // suffixes
     472);
     473
     474// exponent sign symbols
     475static const BGenericNumberFormat::SignSymbols kDefaultExponentSignSymbols(
     476    "+", "-", " ", "",  // prefixes
     477    "", "", "", ""      // suffixes
     478);
     479
     480
     481// Integer
     482class BGenericNumberFormat::Integer {
     483    public:
     484        Integer(int64 number)
     485            : fDigitCount(0),
     486              fNegative(number < 0)
     487        {
     488            if (fNegative)
     489                Init(0ULL - (uint64)number);
     490            else
     491                Init(number);
     492        }
     493
     494        Integer(uint64 number)
     495            : fDigitCount(0),
     496              fNegative(false)
     497        {
     498            Init(number);
     499        }
     500
     501        int DigitCount() const
     502        {
     503            return fDigitCount;
     504        }
     505
     506        bool IsNegative() const
     507        {
     508            return fNegative;
     509        }
     510
     511        char *ToString(char *str) const
     512        {
     513            if (fDigitCount == 0) {
     514                str[0] = '0';
     515                str[1] = '\0';
     516            } else if (fNegative) {
     517                str[0] = '-';
     518                for (int i = 0; i < fDigitCount; i++)
     519                    str[i + 1] = '0' + fDigits[fDigitCount - i - 1];
     520                str[fDigitCount + 1] = '\0';
     521            } else {
     522                for (int i = 0; i < fDigitCount; i++)
     523                    str[i] = '0' + fDigits[fDigitCount - i - 1];
     524                str[fDigitCount] = '\0';
     525            }
     526            return str;
     527        }
     528
     529        void Format(BufferWriter &writer, const Symbol *digitSymbols,
     530            const SignSymbols *signSymbols,
     531            number_format_sign_policy signPolicy,
     532            const GroupingInfo *groupingInfo, int32 minDigits)  const
     533        {
     534            const Symbol *suffix = NULL;
     535            // write sign prefix
     536            if (fNegative) {
     537                writer.Append(signSymbols->MinusPrefix());
     538                suffix = signSymbols->MinusSuffix();
     539            } else {
     540                switch (signPolicy) {
     541                    case B_USE_NEGATIVE_SIGN_ONLY:
     542                        writer.Append(signSymbols->NoForcePlusPrefix());
     543                        suffix = signSymbols->NoForcePlusSuffix();
     544                        break;
     545                    case B_USE_SPACE_FOR_POSITIVE_SIGN:
     546                        writer.Append(signSymbols->PadPlusPrefix());
     547                        suffix = signSymbols->PadPlusSuffix();
     548                        break;
     549                    case B_USE_POSITIVE_SIGN:
     550                        writer.Append(signSymbols->PlusPrefix());
     551                        suffix = signSymbols->PlusSuffix();
     552                        break;
     553                }
     554            }
     555            // the digits
     556            if (fDigitCount == 0 && minDigits < 1) {
     557                // special case for zero and less the one minimal digit
     558                writer.Append(digitSymbols[0]);
     559            } else {
     560                // not zero or at least one minimal digit
     561                if (groupingInfo) {
     562                    // use grouping
     563                    // pad with zeros up to minDigits
     564                    int32 digitCount = std::max(fDigitCount, minDigits);
     565                    for (int i = minDigits - 1; i >= fDigitCount; i--) {
     566                        if (i != digitCount - 1)
     567                            writer.Append(groupingInfo->SeparatorForDigit(i));
     568                        writer.Append(digitSymbols[0]);
     569                    }
     570                    // write digits
     571                    for (int i = fDigitCount - 1; i >= 0; i--) {
     572                        if (i != digitCount - 1)
     573                            writer.Append(groupingInfo->SeparatorForDigit(i));
     574                        writer.Append(digitSymbols[fDigits[i]]);
     575                    }
     576                } else {
     577                    // no grouping
     578                    // pad with zeros up to minDigits
     579                    if (fDigitCount < minDigits)
     580                        writer.Append(digitSymbols, minDigits - fDigitCount);
     581                    // write digits
     582                    for (int i = fDigitCount - 1; i >= 0; i--)
     583                        writer.Append(digitSymbols[fDigits[i]]);
     584                }
     585            }
     586            // append suffix
     587            writer.Append(suffix);
     588        }
     589
     590    private:
     591        void Init(uint64 number)
     592        {
     593            fDigitCount = 0;
     594            while (number) {
     595                fDigits[fDigitCount] = number % 10;
     596                number /= 10;
     597                fDigitCount++;
     598            }
     599        }
     600
     601    private:
     602        uchar   fDigits[kMaxIntDigitCount];
     603        int32   fDigitCount;
     604        bool    fNegative;
     605};
     606
     607
     608// Float
     609class BGenericNumberFormat::Float {
     610    public:
     611        Float(double number)
     612            : fNegative(signbit(number)),
     613              fClass(fpclassify(number)),
     614              fExponent(0),
     615              fDigitCount(0)
     616        {
     617            // filter special cases
     618            switch (fClass) {
     619                case FP_NAN:
     620                case FP_INFINITE:
     621                    return;
     622                case FP_ZERO:
     623                    fDigits[0] = 0;
     624                    fDigitCount = 1;
     625                    return;
     626                case FP_NORMAL:
     627                case FP_SUBNORMAL:
     628                    break;
     629            }
     630            if (fNegative)
     631                number = -number;
     632            // We start with an exponent great enough to make
     633            // number / 10^fExponent < 10. It may even be < 1 or 0.1.
     634            // We simply cut those digits later.
     635            fExponent = (int)ceil(log10(number));
     636            int shiftBy = kMaxFloatDigitCount - fExponent - 1;
     637            // We don't multiply with 10^shiftBy not in one go, since for
     638            // subnormal numbers 10^shiftBy will not be representable. Maybe
     639            // also for normal numbers close to the limit -- so don't risk
     640            // anything, for the time being. TODO: Optimize later.
     641            double mantissa = number * pow(10, shiftBy / 2);
     642            mantissa *= pow(10, shiftBy - shiftBy / 2);
     643            // get the mantissa's digits -- we drop trailing zeros
     644            int32 firstNonNull = -1;
     645            for (int i = 0; i < kMaxFloatDigitCount; i++) {
     646                char digit = (char)fmod(mantissa, 10);
     647                if (firstNonNull < 0 && digit > 0)
     648                    firstNonNull = i;
     649                if (firstNonNull >= 0)
     650                    fDigits[i - firstNonNull] = digit;
     651                mantissa /= 10;
     652            }
     653            if (firstNonNull >= 0)
     654                fDigitCount = kMaxFloatDigitCount - firstNonNull;
     655            else
     656                fDigitCount = 0;
     657            // drop leading zeros
     658            while (fDigitCount > 0 && fDigits[fDigitCount - 1] == 0) {
     659                fDigitCount--;
     660                fExponent--;
     661            }
     662            // due to rounding effects we may end up with zero: switch to its
     663            // canaonical representation then
     664            if (fDigitCount == 0) {
     665                fExponent = 0;
     666                fDigits[0] = 0;
     667                fDigitCount = 1;
     668            }
     669        }
     670
     671        void Format(BufferWriter &writer, const Symbol *digitSymbols,
     672            const SpecialNumberSymbols *specialNumbers,
     673            const Symbol *fractionSeparator,
     674            const Symbol *exponentSymbol,
     675            const SignSymbols *signSymbols,
     676            const SignSymbols *mantissaSignSymbols,
     677            const SignSymbols *exponentSignSymbols,
     678            float_format_type formatType,
     679            number_format_sign_policy signPolicy,
     680            const GroupingInfo *groupingInfo,
     681            int32 minIntegerDigits, int32 minFractionDigits,
     682            int32 maxFractionDigits, bool forceFractionSeparator,
     683            bool keepTrailingFractionZeros) const
     684        {
     685            // deal with special numbers
     686            switch (fClass) {
     687                case FP_NAN:
     688                    writer.Append(specialNumbers->nan);
     689                    return;
     690                case FP_INFINITE:
     691                    if (fNegative)
     692                        writer.Append(specialNumbers->negative_infinity);
     693                    else
     694                        writer.Append(specialNumbers->infinity);
     695                    return;
     696                case FP_ZERO:
     697                case FP_NORMAL:
     698                case FP_SUBNORMAL:
     699                    break;
     700            }
     701            // format according to the specified format type
     702            bool scientific = false;
     703            switch (formatType) {
     704                case B_FIXED_POINT_FLOAT_FORMAT:
     705                    break;
     706                case B_SCIENTIFIC_FLOAT_FORMAT:
     707                    scientific = true;
     708                    break;
     709                case B_AUTO_FLOAT_FORMAT:
     710                    // the criterion printf() uses:
     711                    scientific = (fExponent >= maxFractionDigits
     712                                  || fExponent < -4);
     713                    break;
     714            }
     715            // finally invoke the respective method that does the formatting
     716            if (scientific) {
     717                FormatScientific(writer, digitSymbols, fractionSeparator,
     718                    exponentSymbol, signSymbols, mantissaSignSymbols,
     719                    exponentSignSymbols, signPolicy, minIntegerDigits,
     720                    minFractionDigits, maxFractionDigits,
     721                    forceFractionSeparator, keepTrailingFractionZeros);
     722            } else {
     723                FormatFixedPoint(writer, digitSymbols, fractionSeparator,
     724                    signSymbols, mantissaSignSymbols, signPolicy, groupingInfo,
     725                    minIntegerDigits, minFractionDigits, maxFractionDigits,
     726                    forceFractionSeparator, keepTrailingFractionZeros);
     727            }
     728        }
     729
     730        void FormatScientific(BufferWriter &writer, const Symbol *digitSymbols,
     731            const Symbol *fractionSeparator,
     732            const Symbol *exponentSymbol,
     733            const SignSymbols *signSymbols,
     734            const SignSymbols *mantissaSignSymbols,
     735            const SignSymbols *exponentSignSymbols,
     736            number_format_sign_policy signPolicy,
     737            int32 minIntegerDigits, int32 minFractionDigits,
     738            int32 maxFractionDigits, bool forceFractionSeparator,
     739            bool keepTrailingFractionZeros) const
     740        {
     741            const Symbol *suffix = NULL;
     742            const Symbol *mantissaSuffix = NULL;
     743            // write sign prefix
     744            if (fNegative) {
     745                writer.Append(signSymbols->MinusPrefix());
     746                writer.Append(mantissaSignSymbols->MinusPrefix());
     747                suffix = signSymbols->MinusSuffix();
     748                mantissaSuffix = mantissaSignSymbols->MinusSuffix();
     749            } else {
     750                switch (signPolicy) {
     751                    case B_USE_NEGATIVE_SIGN_ONLY:
     752                        writer.Append(signSymbols->NoForcePlusPrefix());
     753                        writer.Append(mantissaSignSymbols->NoForcePlusPrefix());
     754                        suffix = signSymbols->NoForcePlusSuffix();
     755                        mantissaSuffix
     756                            = mantissaSignSymbols->NoForcePlusSuffix();
     757                        break;
     758                    case B_USE_SPACE_FOR_POSITIVE_SIGN:
     759                        writer.Append(signSymbols->PadPlusPrefix());
     760                        writer.Append(mantissaSignSymbols->PadPlusPrefix());
     761                        suffix = signSymbols->PadPlusSuffix();
     762                        mantissaSuffix = mantissaSignSymbols->PadPlusSuffix();
     763                        break;
     764                    case B_USE_POSITIVE_SIGN:
     765                        writer.Append(signSymbols->PlusPrefix());
     766                        writer.Append(mantissaSignSymbols->PlusPrefix());
     767                        suffix = signSymbols->PlusSuffix();
     768                        mantissaSuffix = mantissaSignSymbols->PlusSuffix();
     769                        break;
     770                }
     771            }
     772            // round
     773            int32 exponent = fExponent;
     774            char digits[kMaxFloatDigitCount];
     775            int32 integerDigits = std::max(minIntegerDigits, 1L);
     776            int32 fractionDigits
     777                = std::max(fDigitCount - integerDigits, minFractionDigits);
     778            fractionDigits = std::min(fractionDigits, maxFractionDigits);
     779            int32 digitCount
     780                = _Round(digits, integerDigits + fractionDigits, exponent);
     781            fractionDigits = digitCount - integerDigits;
     782            if (keepTrailingFractionZeros)
     783                fractionDigits = std::max(fractionDigits, minFractionDigits);
     784            fractionDigits = std::min(fractionDigits, maxFractionDigits);
     785            // the mantissa
     786            // integer part
     787            int32 existingIntegerDigits = std::min(integerDigits, digitCount);
     788            for (int i = 0; i < existingIntegerDigits; i++)
     789                writer.Append(digitSymbols[digits[digitCount - i - 1]]);
     790            // pad with zeros to get the desired number of integer digits
     791            if (existingIntegerDigits < integerDigits) {
     792                writer.Append(digitSymbols,
     793                              integerDigits - existingIntegerDigits);
     794            }
     795            // unless the number is 0, adjust the exponent
     796            if (!_IsZero(digits, digitCount))
     797                exponent -= integerDigits - 1;
     798            // fraction part
     799            if (fractionDigits > 0 || forceFractionSeparator)
     800                writer.Append(fractionSeparator);
     801            int32 existingFractionDigits
     802                = std::min(digitCount - integerDigits, fractionDigits);
     803            for (int i = existingFractionDigits - 1; i >= 0; i--)
     804                writer.Append(digitSymbols[digits[i]]);
     805            // pad with zeros to get the desired number of fraction digits
     806            if (fractionDigits > existingFractionDigits) {
     807                writer.Append(digitSymbols,
     808                              fractionDigits - existingFractionDigits);
     809            }
     810            writer.Append(mantissaSuffix);
     811            // the exponent
     812            writer.Append(exponentSymbol);
     813
     814            Integer(static_cast<int64>(exponent)).Format(writer, digitSymbols,
     815                exponentSignSymbols, B_USE_POSITIVE_SIGN, &kNoGroupingInfo, 2);
     816            // sign suffix
     817            writer.Append(suffix);
     818        }
     819
     820        void FormatFixedPoint(BufferWriter &writer, const Symbol *digitSymbols,
     821            const Symbol *fractionSeparator,
     822            const SignSymbols *signSymbols,
     823            const SignSymbols *mantissaSignSymbols,
     824            number_format_sign_policy signPolicy,
     825            const GroupingInfo *groupingInfo,
     826            int32 minIntegerDigits, int32 minFractionDigits,
     827            int32 maxFractionDigits, bool forceFractionSeparator,
     828            bool keepTrailingFractionZeros) const
     829        {
     830            const Symbol *suffix = NULL;
     831            const Symbol *mantissaSuffix = NULL;
     832            // write sign prefix
     833            if (fNegative) {
     834                writer.Append(signSymbols->MinusPrefix());
     835                writer.Append(mantissaSignSymbols->MinusPrefix());
     836                suffix = signSymbols->MinusSuffix();
     837                mantissaSuffix = mantissaSignSymbols->MinusSuffix();
     838            } else {
     839                switch (signPolicy) {
     840                    case B_USE_NEGATIVE_SIGN_ONLY:
     841                        writer.Append(signSymbols->NoForcePlusPrefix());
     842                        writer.Append(mantissaSignSymbols->NoForcePlusPrefix());
     843                        suffix = signSymbols->NoForcePlusSuffix();
     844                        mantissaSuffix
     845                            = mantissaSignSymbols->NoForcePlusSuffix();
     846                        break;
     847                    case B_USE_SPACE_FOR_POSITIVE_SIGN:
     848                        writer.Append(signSymbols->PadPlusPrefix());
     849                        writer.Append(mantissaSignSymbols->PadPlusPrefix());
     850                        suffix = signSymbols->PadPlusSuffix();
     851                        mantissaSuffix = mantissaSignSymbols->PadPlusSuffix();
     852                        break;
     853                    case B_USE_POSITIVE_SIGN:
     854                        writer.Append(signSymbols->PlusPrefix());
     855                        writer.Append(mantissaSignSymbols->PlusPrefix());
     856                        suffix = signSymbols->PlusSuffix();
     857                        mantissaSuffix = mantissaSignSymbols->PlusSuffix();
     858                        break;
     859                }
     860            }
     861            // round
     862            int32 exponent = fExponent;
     863            char digits[kMaxFloatDigitCount];
     864            int32 integerDigits = std::max(minIntegerDigits, exponent + 1L);
     865            int32 fractionDigits
     866                = std::max(fDigitCount - integerDigits, minFractionDigits);
     867            fractionDigits = std::min(fractionDigits, maxFractionDigits);
     868            int32 digitCount
     869                = _Round(digits, integerDigits + fractionDigits, exponent);
     870            fractionDigits = digitCount - integerDigits;
     871            if (keepTrailingFractionZeros)
     872                fractionDigits = std::max(fractionDigits, minFractionDigits);
     873            fractionDigits = std::min(fractionDigits, maxFractionDigits);
     874            // integer part
     875            int32 existingIntegerDigits = std::min(integerDigits, exponent + 1);
     876            existingIntegerDigits = std::max(existingIntegerDigits, 0L);
     877            if (groupingInfo) {
     878                // use grouping
     879                // pad with zeros up to minDigits
     880                for (int i = integerDigits - 1;
     881                     i >= existingIntegerDigits;
     882                     i--) {
     883                    if (i != integerDigits - 1)
     884                        writer.Append(groupingInfo->SeparatorForDigit(i));
     885                    writer.Append(digitSymbols[0]);
     886                }
     887                // write digits
     888                for (int i = existingIntegerDigits - 1; i >= 0; i--) {
     889                    if (i != integerDigits - 1)
     890                        writer.Append(groupingInfo->SeparatorForDigit(i));
     891                    writer.Append(digitSymbols[digits[
     892                        digitCount - existingIntegerDigits + i]]);
     893                }
     894            } else {
     895                // no grouping
     896                // pad with zeros to get the desired number of integer digits
     897                if (existingIntegerDigits < integerDigits) {
     898                    writer.Append(digitSymbols[0],
     899                                  integerDigits - existingIntegerDigits);
     900                }
     901                // write digits
     902                for (int i = 0; i < existingIntegerDigits; i++)
     903                    writer.Append(digitSymbols[digits[digitCount - i - 1]]);
     904            }
     905            // fraction part
     906            if (fractionDigits > 0 || forceFractionSeparator)
     907                writer.Append(fractionSeparator);
     908            int32 existingFractionDigits
     909                = std::min(digitCount - existingIntegerDigits, fractionDigits);
     910            for (int i = existingFractionDigits - 1; i >= 0; i--)
     911                writer.Append(digitSymbols[digits[i]]);
     912            // pad with zeros to get the desired number of fraction digits
     913            if (fractionDigits > existingFractionDigits) {
     914                writer.Append(digitSymbols,
     915                              fractionDigits - existingFractionDigits);
     916            }
     917            // sign suffixes
     918            writer.Append(mantissaSuffix);
     919            writer.Append(suffix);
     920        }
     921
     922    private:
     923        int32 _Round(char *digits, int32 count, int32 &exponent) const
     924        {
     925            if (count > fDigitCount)
     926                count = fDigitCount;
     927            int firstNonNull = -1;
     928// TODO: Non-hardcoded base-independent rounding.
     929            bool carry = false;
     930            if (count < fDigitCount)
     931                carry = (fDigits[fDigitCount - count - 1] >= 5);
     932            for (int i = 0; i < count; i++) {
     933                char digit =  fDigits[fDigitCount - count + i];
     934                if (carry) {
     935                    digit++;
     936                    if (digit == 10)    // == base
     937                        digit = 0;
     938                    else
     939                        carry = false;
     940                }
     941                if (firstNonNull < 0 && digit > 0)
     942                    firstNonNull = i;
     943                if (firstNonNull >= 0)
     944                    digits[i - firstNonNull] = digit;
     945            }
     946            if (firstNonNull < 0) {
     947                if (carry) {
     948                    // 9.999999... -> 10
     949                    digits[0] = 1;
     950                    exponent++;
     951                } else {
     952                    // 0.0000...1 -> 0
     953                    exponent = 0;
     954                    digits[0] = 0;
     955                }
     956                count = 1;
     957            } else
     958                count -= firstNonNull;
     959            return count;
     960        }
     961
     962        static bool _IsZero(const char *digits, int32 digitCount)
     963        {
     964            return (digitCount == 1 && digits[0] == 0);
     965        }
     966
     967    private:
     968        bool    fNegative;
     969        int     fClass;
     970        int32   fExponent;
     971        char    fDigits[kMaxFloatDigitCount];
     972        int32   fDigitCount;
     973};
     974
     975
     976// constructor
     977BGenericNumberFormat::BGenericNumberFormat()
     978    : fIntegerParameters(),
     979      fFloatParameters(),
     980      fDigitSymbols(NULL),
     981      fFractionSeparator(NULL),
     982      fGroupingInfo(NULL),
     983      fExponentSymbol(NULL),
     984      fUpperCaseExponentSymbol(NULL),
     985      fNaNSymbol(NULL),
     986      fUpperCaseNaNSymbol(NULL),
     987      fInfinitySymbol(NULL),
     988      fUpperCaseInfinitySymbol(NULL),
     989      fNegativeInfinitySymbol(NULL),
     990      fUpperCaseNegativeInfinitySymbol(NULL),
     991      fSignSymbols(NULL),
     992      fMantissaSignSymbols(NULL),
     993      fExponentSignSymbols(NULL)
     994{
     995}
     996
     997// destructor
     998BGenericNumberFormat::~BGenericNumberFormat()
     999{
     1000}
     1001
     1002// FormatInteger
     1003status_t
     1004BGenericNumberFormat::FormatInteger(
     1005    const BIntegerFormatParameters *parameters, int64 number, BString *buffer,
     1006    format_field_position *positions, int32 positionCount, int32 *fieldCount,
     1007    bool allFieldPositions) const
     1008{
     1009    if (!buffer)
     1010        return B_BAD_VALUE;
     1011    char localBuffer[1024];
     1012    status_t error = FormatInteger(parameters, number, localBuffer,
     1013        sizeof(localBuffer), positions, positionCount, fieldCount,
     1014        allFieldPositions);
     1015    if (error == B_OK) {
     1016        buffer->Append(localBuffer);
     1017        // TODO: Check, if the allocation succeeded.
     1018    }
     1019    return error;
     1020}
     1021
     1022// FormatInteger
     1023status_t
     1024BGenericNumberFormat::FormatInteger(
     1025    const BIntegerFormatParameters *parameters, uint64 number, BString *buffer,
     1026    format_field_position *positions, int32 positionCount, int32 *fieldCount,
     1027    bool allFieldPositions) const
     1028{
     1029    if (!buffer)
     1030        return B_BAD_VALUE;
     1031    char localBuffer[1024];
     1032    status_t error = FormatInteger(parameters, number, localBuffer,
     1033        sizeof(localBuffer), positions, positionCount, fieldCount,
     1034        allFieldPositions);
     1035    if (error == B_OK) {
     1036        buffer->Append(localBuffer);
     1037        // TODO: Check, if the allocation succeeded.
     1038    }
     1039    return error;
     1040}
     1041
     1042// FormatInteger
     1043status_t
     1044BGenericNumberFormat::FormatInteger(
     1045    const BIntegerFormatParameters *parameters, int64 number, char *buffer,
     1046    size_t bufferSize, format_field_position *positions, int32 positionCount,
     1047    int32 *fieldCount, bool allFieldPositions) const
     1048{
     1049    Integer integer(number);
     1050    return FormatInteger(parameters, integer, buffer, bufferSize, positions,
     1051                         positionCount, fieldCount, allFieldPositions);
     1052}
     1053
     1054// FormatInteger
     1055status_t
     1056BGenericNumberFormat::FormatInteger(
     1057    const BIntegerFormatParameters *parameters, uint64 number, char *buffer,
     1058    size_t bufferSize, format_field_position *positions, int32 positionCount,
     1059    int32 *fieldCount, bool allFieldPositions) const
     1060{
     1061    Integer integer(number);
     1062    return FormatInteger(parameters, integer, buffer, bufferSize, positions,
     1063                         positionCount, fieldCount, allFieldPositions);
     1064}
     1065
     1066// FormatFloat
     1067status_t
     1068BGenericNumberFormat::FormatFloat(const BFloatFormatParameters *parameters,
     1069    double number, BString *buffer, format_field_position *positions,
     1070    int32 positionCount, int32 *fieldCount, bool allFieldPositions) const
     1071{
     1072    if (!buffer)
     1073        return B_BAD_VALUE;
     1074    // TODO: How to ensure that this is enough?
     1075    char localBuffer[1024];
     1076    status_t error = FormatFloat(parameters, number, localBuffer,
     1077        sizeof(localBuffer), positions, positionCount, fieldCount,
     1078        allFieldPositions);
     1079    if (error == B_OK) {
     1080        buffer->Append(localBuffer);
     1081        // TODO: Check, if the allocation succeeded.
     1082    }
     1083    return error;
     1084}
     1085
     1086// FormatFloat
     1087status_t
     1088BGenericNumberFormat::FormatFloat(const BFloatFormatParameters *parameters,
     1089    double number, char *buffer, size_t bufferSize,
     1090    format_field_position *positions, int32 positionCount, int32 *fieldCount,
     1091    bool allFieldPositions) const
     1092{
     1093    // TODO: Check parameters.
     1094    if (!parameters)
     1095        parameters = DefaultFloatFormatParameters();
     1096    if (bufferSize <= parameters->FormatWidth())
     1097        return EOVERFLOW;
     1098    Float floatNumber(number);
     1099    // prepare some parameters
     1100    const GroupingInfo *groupingInfo = NULL;
     1101    if (parameters->UseGrouping())
     1102        groupingInfo = GetGroupingInfo();
     1103    bool upperCase = parameters->UseUpperCase();
     1104    SpecialNumberSymbols specialSymbols;
     1105    GetSpecialNumberSymbols(upperCase, &specialSymbols);
     1106    // compute the length of the formatted string
     1107    BufferWriter writer;
     1108    floatNumber.Format(writer, DigitSymbols(), &specialSymbols,
     1109        FractionSeparator(), ExponentSymbol(), GetSignSymbols(),
     1110        MantissaSignSymbols(), ExponentSignSymbols(),
     1111        parameters->FloatFormatType(), parameters->SignPolicy(), groupingInfo,
     1112        parameters->MinimalIntegerDigits(), parameters->MinimalFractionDigits(),
     1113        parameters->MaximalFractionDigits(),
     1114        parameters->AlwaysUseFractionSeparator(),
     1115        parameters->KeepTrailingFractionZeros());
     1116    int32 stringLength = writer.StringLength();
     1117    int32 charCount = writer.CharCount();
     1118    // consider alignment and check the available space in the buffer
     1119    int32 padding = std::max(0L, (int32)parameters->FormatWidth() - charCount);
     1120// TODO: Padding with zeros.
     1121    if ((int32)bufferSize <= stringLength + padding)
     1122        return EOVERFLOW;
     1123    // prepare for writing
     1124    writer.SetTo(buffer, bufferSize);
     1125    // write padding for right field alignment
     1126    if (parameters->Alignment() == B_ALIGN_FORMAT_RIGHT && padding > 0)
     1127        writer.Append(' ', padding);
     1128    // write the number
     1129    floatNumber.Format(writer,  DigitSymbols(), &specialSymbols,
     1130        FractionSeparator(), ExponentSymbol(), GetSignSymbols(),
     1131        MantissaSignSymbols(), ExponentSignSymbols(),
     1132        parameters->FloatFormatType(), parameters->SignPolicy(), groupingInfo,
     1133        parameters->MinimalIntegerDigits(), parameters->MinimalFractionDigits(),
     1134        parameters->MaximalFractionDigits(),
     1135        parameters->AlwaysUseFractionSeparator(),
     1136        parameters->KeepTrailingFractionZeros());
     1137    // write padding for left field alignment
     1138    if (parameters->Alignment() == B_ALIGN_FORMAT_LEFT && padding > 0)
     1139        writer.Append(' ', padding);
     1140    return B_OK;
     1141}
     1142
     1143// SetDefaultIntegerFormatParameters
     1144status_t
     1145BGenericNumberFormat::SetDefaultIntegerFormatParameters(
     1146    const BIntegerFormatParameters *parameters)
     1147{
     1148    if (!parameters)
     1149        return B_BAD_VALUE;
     1150    fIntegerParameters = *parameters;
     1151    return B_OK;
     1152}
     1153
     1154// DefaultIntegerFormatParameters
     1155BIntegerFormatParameters *
     1156BGenericNumberFormat::DefaultIntegerFormatParameters()
     1157{
     1158    return &fIntegerParameters;
     1159}
     1160
     1161// DefaultIntegerFormatParameters
     1162const BIntegerFormatParameters *
     1163BGenericNumberFormat::DefaultIntegerFormatParameters() const
     1164{
     1165    return &fIntegerParameters;
     1166}
     1167
     1168// SetDefaultFloatFormatParameters
     1169status_t
     1170BGenericNumberFormat::SetDefaultFloatFormatParameters(
     1171    const BFloatFormatParameters *parameters)
     1172{
     1173    if (!parameters)
     1174        return B_BAD_VALUE;
     1175    fFloatParameters = *parameters;
     1176    return B_OK;
     1177}
     1178
     1179// DefaultFloatFormatParameters
     1180BFloatFormatParameters *
     1181BGenericNumberFormat::DefaultFloatFormatParameters()
     1182{
     1183    return &fFloatParameters;
     1184}
     1185
     1186// DefaultFloatFormatParameters
     1187const BFloatFormatParameters *
     1188BGenericNumberFormat::DefaultFloatFormatParameters() const
     1189{
     1190    return &fFloatParameters;
     1191}
     1192
     1193// SetDigitSymbols
     1194status_t
     1195BGenericNumberFormat::SetDigitSymbols(const char **digits)
     1196{
     1197    // check parameters
     1198    if (digits) {
     1199        for (int i = 0; i < 10; i++) {
     1200            if (!digits[i])
     1201                return B_BAD_VALUE;
     1202        }
     1203    }
     1204    // unset old
     1205    if (fDigitSymbols) {
     1206        delete[] fDigitSymbols;
     1207        fDigitSymbols = NULL;
     1208    }
     1209    // set new
     1210    if (digits) {
     1211        fDigitSymbols = new(std::nothrow) Symbol[10];
     1212        if (!fDigitSymbols)
     1213            return B_NO_MEMORY;
     1214        for (int i = 0; i < 10; i++) {
     1215            status_t error = fDigitSymbols[i].SetTo(digits[i]);
     1216            if (error != B_OK) {
     1217                SetDigitSymbols(NULL);
     1218                return error;
     1219            }
     1220        }
     1221    }
     1222    return B_OK;
     1223}
     1224
     1225// SetFractionSeparator
     1226status_t
     1227BGenericNumberFormat::SetFractionSeparator(const char *decimalSeparator)
     1228{
     1229    return _SetSymbol(&fFractionSeparator, decimalSeparator);
     1230}
     1231
     1232// SetGroupingInfo
     1233status_t
     1234BGenericNumberFormat::SetGroupingInfo(const char **groupingSeparators,
     1235    size_t separatorCount, size_t *groupingSizes, size_t sizeCount)
     1236{
     1237    // check parameters
     1238    if (groupingSeparators && separatorCount > 0 && groupingSizes
     1239        && sizeCount) {
     1240        for (int i = 0; i < (int)separatorCount; i++) {
     1241            if (!groupingSeparators[i])
     1242                return B_BAD_VALUE;
     1243        }
     1244    }
     1245    // unset old
     1246    if (fGroupingInfo) {
     1247        delete fGroupingInfo;
     1248        fGroupingInfo = NULL;
     1249    }
     1250    // set new
     1251    if (groupingSeparators && separatorCount > 0 && groupingSizes
     1252        && sizeCount) {
     1253        fGroupingInfo = new GroupingInfo;
     1254        if (!fGroupingInfo)
     1255            return B_NO_MEMORY;
     1256        status_t error = fGroupingInfo->SetTo(groupingSeparators,
     1257            separatorCount, groupingSizes, sizeCount);
     1258        if (error != B_OK) {
     1259            delete fGroupingInfo;
     1260            fGroupingInfo = NULL;
     1261            return error;
     1262        }
     1263    }
     1264    return B_OK;
     1265}
     1266
     1267// SetExponentSymbol
     1268status_t
     1269BGenericNumberFormat::SetExponentSymbol(const char *exponentSymbol,
     1270    const char *upperCaseExponentSymbol)
     1271{
     1272    status_t error = _SetSymbol(&fExponentSymbol, exponentSymbol);
     1273    if (error == B_OK)
     1274        error = _SetSymbol(&fUpperCaseExponentSymbol, upperCaseExponentSymbol);
     1275    if (error != B_OK)
     1276        SetExponentSymbol(NULL, NULL);
     1277    return error;
     1278}
     1279
     1280// SetSpecialNumberSymbols
     1281status_t
     1282BGenericNumberFormat::SetSpecialNumberSymbols(const char *nan,
     1283    const char *infinity, const char *negativeInfinity,
     1284    const char *upperCaseNaN, const char *upperCaseInfinity,
     1285    const char *upperCaseNegativeInfinity)
     1286{
     1287    status_t error = _SetSymbol(&fNaNSymbol, nan);
     1288    if (error == B_OK)
     1289        error = _SetSymbol(&fInfinitySymbol, infinity);
     1290    if (error == B_OK)
     1291        error = _SetSymbol(&fNegativeInfinitySymbol, negativeInfinity);
     1292    if (error == B_OK)
     1293        error = _SetSymbol(&fUpperCaseNaNSymbol, upperCaseNaN);
     1294    if (error == B_OK)
     1295        error = _SetSymbol(&fUpperCaseInfinitySymbol, upperCaseInfinity);
     1296    if (error == B_OK) {
     1297        error = _SetSymbol(&fUpperCaseNegativeInfinitySymbol,
     1298            upperCaseNegativeInfinity);
     1299    }
     1300    if (error != B_OK)
     1301        SetSpecialNumberSymbols(NULL, NULL, NULL, NULL, NULL, NULL);
     1302    return error;
     1303}
     1304
     1305// SetSignSymbols
     1306status_t
     1307BGenericNumberFormat::SetSignSymbols(const char *plusPrefix,
     1308    const char *minusPrefix, const char *padPlusPrefix,
     1309    const char *noForcePlusPrefix, const char *plusSuffix,
     1310    const char *minusSuffix, const char *padPlusSuffix,
     1311    const char *noForcePlusSuffix)
     1312{
     1313    if (!fSignSymbols) {
     1314        fSignSymbols = new(std::nothrow) SignSymbols;
     1315        if (!fSignSymbols)
     1316            return B_NO_MEMORY;
     1317    }
     1318    return fSignSymbols->SetTo(plusPrefix, minusPrefix, padPlusPrefix,
     1319        noForcePlusPrefix, plusSuffix, minusSuffix, padPlusSuffix,
     1320        noForcePlusSuffix);
     1321}
     1322
     1323// SetMantissaSignSymbols
     1324status_t
     1325BGenericNumberFormat::SetMantissaSignSymbols(const char *plusPrefix,
     1326    const char *minusPrefix, const char *padPlusPrefix,
     1327    const char *noForcePlusPrefix, const char *plusSuffix,
     1328    const char *minusSuffix, const char *padPlusSuffix,
     1329    const char *noForcePlusSuffix)
     1330{
     1331    if (!fMantissaSignSymbols) {
     1332        fMantissaSignSymbols = new(std::nothrow) SignSymbols;
     1333        if (!fMantissaSignSymbols)
     1334            return B_NO_MEMORY;
     1335    }
     1336    return fMantissaSignSymbols->SetTo(plusPrefix, minusPrefix, padPlusPrefix,
     1337        noForcePlusPrefix, plusSuffix, minusSuffix, padPlusSuffix,
     1338        noForcePlusSuffix);
     1339}
     1340
     1341// SetExponentSignSymbols
     1342status_t
     1343BGenericNumberFormat::SetExponentSignSymbols(const char *plusPrefix,
     1344    const char *minusPrefix, const char *plusSuffix, const char *minusSuffix)
     1345{
     1346    if (!fExponentSignSymbols) {
     1347        fExponentSignSymbols = new(std::nothrow) SignSymbols;
     1348        if (!fExponentSignSymbols)
     1349            return B_NO_MEMORY;
     1350    }
     1351    return fExponentSignSymbols->SetTo(plusPrefix, minusPrefix, plusPrefix,
     1352        plusPrefix, plusSuffix, minusSuffix, plusSuffix, plusSuffix);
     1353}
     1354
     1355// FormatInteger
     1356status_t
     1357BGenericNumberFormat::FormatInteger(
     1358    const BIntegerFormatParameters *parameters, const Integer &integer,
     1359    char *buffer, size_t bufferSize, format_field_position *positions,
     1360    int32 positionCount, int32 *fieldCount, bool allFieldPositions) const
     1361{
     1362    // TODO: Check parameters.
     1363    if (!parameters)
     1364        parameters = DefaultIntegerFormatParameters();
     1365    if (bufferSize <= parameters->FormatWidth())
     1366        return EOVERFLOW;
     1367    // prepare some parameters
     1368    const GroupingInfo *groupingInfo = NULL;
     1369    if (parameters->UseGrouping())
     1370        groupingInfo = GetGroupingInfo();
     1371    // compute the length of the formatted string
     1372    BufferWriter writer;
     1373    integer.Format(writer, DigitSymbols(),
     1374        GetSignSymbols(), parameters->SignPolicy(), groupingInfo,
     1375        parameters->MinimalIntegerDigits());
     1376    int32 stringLength = writer.StringLength();
     1377    int32 charCount = writer.CharCount();
     1378    // consider alignment and check the available space in the buffer
     1379    int32 padding = std::max(0L, (int32)parameters->FormatWidth() - charCount);
     1380// TODO: Padding with zeros.
     1381    if ((int32)bufferSize <= stringLength + padding)
     1382        return EOVERFLOW;
     1383    // prepare for writing
     1384    writer.SetTo(buffer, bufferSize);
     1385    // write padding for right field alignment
     1386    if (parameters->Alignment() == B_ALIGN_FORMAT_RIGHT && padding > 0)
     1387        writer.Append(' ', padding);
     1388    // write the number
     1389    integer.Format(writer, DigitSymbols(),
     1390        GetSignSymbols(), parameters->SignPolicy(), groupingInfo,
     1391        parameters->MinimalIntegerDigits());
     1392    // write padding for left field alignment
     1393    if (parameters->Alignment() == B_ALIGN_FORMAT_LEFT && padding > 0)
     1394        writer.Append(' ', padding);
     1395    return B_OK;
     1396}
     1397
     1398// DigitSymbols
     1399const BGenericNumberFormat::Symbol *
     1400BGenericNumberFormat::DigitSymbols() const
     1401{
     1402    return (fDigitSymbols ? fDigitSymbols : kDefaultDigitSymbols);
     1403}
     1404
     1405// FractionSeparator
     1406const BGenericNumberFormat::Symbol *
     1407BGenericNumberFormat::FractionSeparator() const
     1408{
     1409    return (fFractionSeparator ? fFractionSeparator
     1410                               : &kDefaultFractionSeparator);
     1411}
     1412
     1413// GetGroupingInfo
     1414const BGenericNumberFormat::GroupingInfo *
     1415BGenericNumberFormat::GetGroupingInfo() const
     1416{
     1417    return (fGroupingInfo ? fGroupingInfo : &kDefaultGroupingInfo);
     1418}
     1419
     1420// ExponentSymbol
     1421const BGenericNumberFormat::Symbol *
     1422BGenericNumberFormat::ExponentSymbol(bool upperCase) const
     1423{
     1424    if (fExponentSymbol) {
     1425        return (upperCase && fUpperCaseExponentSymbol ? fUpperCaseExponentSymbol
     1426                                                      : fExponentSymbol);
     1427    }
     1428    return (upperCase ? &kDefaultUpperCaseExponentSymbol
     1429                      : &kDefaultExponentSymbol);
     1430}
     1431
     1432// NaNSymbol
     1433const BGenericNumberFormat::Symbol *
     1434BGenericNumberFormat::NaNSymbol(bool upperCase) const
     1435{
     1436    if (fNaNSymbol) {
     1437        return (upperCase && fUpperCaseNaNSymbol ? fUpperCaseNaNSymbol
     1438                                                 : fNaNSymbol);
     1439    }
     1440    return (upperCase ? &kDefaultUpperCaseNaNSymbol
     1441                      : &kDefaultNaNSymbol);
     1442}
     1443
     1444// InfinitySymbol
     1445const BGenericNumberFormat::Symbol *
     1446BGenericNumberFormat::InfinitySymbol(bool upperCase) const
     1447{
     1448    if (fInfinitySymbol) {
     1449        return (upperCase && fUpperCaseInfinitySymbol ? fUpperCaseInfinitySymbol
     1450                                                      : fInfinitySymbol);
     1451    }
     1452    return (upperCase ? &kDefaultUpperCaseInfinitySymbol
     1453                      : &kDefaultInfinitySymbol);
     1454}
     1455
     1456// NegativeInfinitySymbol
     1457const BGenericNumberFormat::Symbol *
     1458BGenericNumberFormat::NegativeInfinitySymbol(bool upperCase) const
     1459{
     1460    if (fNegativeInfinitySymbol) {
     1461        return (upperCase && fUpperCaseNegativeInfinitySymbol
     1462            ? fUpperCaseNegativeInfinitySymbol : fNegativeInfinitySymbol);
     1463    }
     1464    return (upperCase ? &kDefaultUpperCaseNegativeInfinitySymbol
     1465                      : &kDefaultNegativeInfinitySymbol);
     1466}
     1467
     1468// GetSpecialNumberSymbols
     1469void
     1470BGenericNumberFormat::GetSpecialNumberSymbols(bool upperCase,
     1471    SpecialNumberSymbols *symbols) const
     1472{
     1473    symbols->nan = NaNSymbol(upperCase);
     1474    symbols->infinity = InfinitySymbol(upperCase);
     1475    symbols->negative_infinity = NegativeInfinitySymbol(upperCase);
     1476}
     1477
     1478// GetSignSymbols
     1479const BGenericNumberFormat::SignSymbols *
     1480BGenericNumberFormat::GetSignSymbols() const
     1481{
     1482    return (fSignSymbols ? fSignSymbols : &kDefaultSignSymbols);
     1483}
     1484
     1485// MantissaSignSymbols
     1486const BGenericNumberFormat::SignSymbols *
     1487BGenericNumberFormat::MantissaSignSymbols() const
     1488{
     1489    return (fMantissaSignSymbols ? fMantissaSignSymbols
     1490                                 : &kDefaultMantissaSignSymbols);
     1491}
     1492
     1493// ExponentSignSymbols
     1494const BGenericNumberFormat::SignSymbols *
     1495BGenericNumberFormat::ExponentSignSymbols() const
     1496{
     1497    return (fExponentSignSymbols ? fExponentSignSymbols
     1498                                 : &kDefaultExponentSignSymbols);
     1499}
     1500
     1501// _SetSymbol
     1502status_t
     1503BGenericNumberFormat::_SetSymbol(Symbol **symbol, const char *str)
     1504{
     1505    if (!str) {
     1506        // no symbol -- unset old
     1507        if (*symbol) {
     1508            delete *symbol;
     1509            symbol = NULL;
     1510        }
     1511    } else {
     1512        // allocate if not existing
     1513        if (!*symbol) {
     1514            *symbol = new(std::nothrow) Symbol;
     1515            if (!*symbol)
     1516                return B_NO_MEMORY;
     1517        }
     1518        // set symbol
     1519        status_t error = (*symbol)->SetTo(str);
     1520        if (error != B_OK) {
     1521            delete *symbol;
     1522            *symbol = NULL;
     1523            return B_NO_MEMORY;
     1524        }
     1525    }
     1526    return B_OK;
     1527}
     1528
  • src/kits/locale/FloatFormatImpl.cpp

     
     1#include <FloatFormatImpl.h>
     2#include <FloatFormatParameters.h>
     3
     4// constructor
     5BFloatFormatImpl::BFloatFormatImpl()
     6    : BNumberFormatImpl()
     7{
     8}
     9
     10// destructor
     11BFloatFormatImpl::~BFloatFormatImpl()
     12{
     13}
     14
     15// DefaultNumberFormatParameters
     16BNumberFormatParameters *
     17BFloatFormatImpl::DefaultNumberFormatParameters()
     18{
     19    return DefaultFloatFormatParameters();
     20}
     21
     22// DefaultNumberFormatParameters
     23const BNumberFormatParameters *
     24BFloatFormatImpl::DefaultNumberFormatParameters() const
     25{
     26    return DefaultFloatFormatParameters();
     27}
     28
  • src/kits/locale/FloatFormatParameters.cpp

     
     1#include <FloatFormatParameters.h>
     2
     3// defaults
     4static const size_t kDefaultMinimalFractionDigits = 0;
     5static const size_t kDefaultMaximalFractionDigits = 6;
     6static const bool kDefaultUseUpperCase = false;
     7static const float_format_type kDefaultFloatFormatType = B_AUTO_FLOAT_FORMAT;
     8static const bool kDefaultAlwaysUseFractionSeparator = false;
     9static const bool kDefaultKeepTrailingFractionZeros = false;
     10
     11
     12// flags
     13enum {
     14    MINIMAL_FRACTION_DIGITS_SET         = 0x01,
     15    MAXIMAL_FRACTION_DIGITS_SET         = 0x02,
     16    USE_UPPER_CASE_SET                  = 0x04,
     17    FLOAT_FORMAT_TYPE_SET               = 0x08,
     18    ALWAYS_USE_FRACTION_SEPARATOR_SET   = 0x10,
     19    KEEP_TRAILING_FRACTION_ZEROS_SET    = 0x20,
     20};
     21
     22// constructor
     23BFloatFormatParameters::BFloatFormatParameters(
     24    const BFloatFormatParameters *parent)
     25    : BNumberFormatParameters(parent),
     26      fParent(parent),
     27      fFlags(0)
     28{
     29}
     30
     31// copy constructor
     32BFloatFormatParameters::BFloatFormatParameters(
     33    const BFloatFormatParameters &other)
     34    : BNumberFormatParameters(other),
     35      fParent(other.fParent),
     36      fMinimalFractionDigits(other.fMinimalFractionDigits),
     37      fMaximalFractionDigits(other.fMaximalFractionDigits),
     38      fUseUpperCase(other.fUseUpperCase),
     39      fFloatFormatType(other.fFloatFormatType),
     40      fAlwaysUseFractionSeparator(other.fAlwaysUseFractionSeparator),
     41      fKeepTrailingFractionZeros(other.fKeepTrailingFractionZeros),
     42      fFlags(other.fFlags)
     43{
     44}
     45
     46// destructor
     47BFloatFormatParameters::~BFloatFormatParameters()
     48{
     49}
     50
     51// SetMinimalFractionDigits
     52void
     53BFloatFormatParameters::SetMinimalFractionDigits(size_t minFractionDigits)
     54{
     55    fMinimalFractionDigits = minFractionDigits;
     56    fFlags |= MINIMAL_FRACTION_DIGITS_SET;
     57}
     58
     59// MinimalFractionDigits
     60size_t
     61BFloatFormatParameters::MinimalFractionDigits() const
     62{
     63    if (fFlags & MINIMAL_FRACTION_DIGITS_SET)
     64        return fMinimalFractionDigits;
     65    if (fParent)
     66        return fParent->MinimalFractionDigits();
     67    return kDefaultMinimalFractionDigits;
     68}
     69
     70// SetMaximalFractionDigits
     71void
     72BFloatFormatParameters::SetMaximalFractionDigits(size_t maxFractionDigits)
     73{
     74    fMaximalFractionDigits = maxFractionDigits;
     75    fFlags |= MAXIMAL_FRACTION_DIGITS_SET;
     76}
     77
     78// MaximalFractionDigits
     79size_t
     80BFloatFormatParameters::MaximalFractionDigits() const
     81{
     82    if (fFlags & MAXIMAL_FRACTION_DIGITS_SET)
     83        return fMaximalFractionDigits;
     84    if (fParent)
     85        return fParent->MaximalFractionDigits();
     86    return kDefaultMaximalFractionDigits;
     87}
     88
     89// SetUseUpperCase
     90void
     91BFloatFormatParameters::SetUseUpperCase(bool useCapitals)
     92{
     93    fUseUpperCase = useCapitals;
     94    fFlags |= USE_UPPER_CASE_SET;
     95}
     96
     97// UseUpperCase
     98bool
     99BFloatFormatParameters::UseUpperCase() const
     100{
     101    if (fFlags & USE_UPPER_CASE_SET)
     102        return fUseUpperCase;
     103    if (fParent)
     104        return fParent->UseUpperCase();
     105    return kDefaultUseUpperCase;
     106}
     107
     108// SetFloatFormatType
     109void
     110BFloatFormatParameters::SetFloatFormatType(float_format_type type)
     111{
     112    fFloatFormatType = type;
     113    fFlags |= FLOAT_FORMAT_TYPE_SET;
     114}
     115
     116// FloatFormatType
     117float_format_type
     118BFloatFormatParameters::FloatFormatType() const
     119{
     120    if (fFlags & FLOAT_FORMAT_TYPE_SET)
     121        return fFloatFormatType;
     122    if (fParent)
     123        return fParent->FloatFormatType();
     124    return kDefaultFloatFormatType;
     125}
     126
     127// SetAlwaysUseFractionSeparator
     128void
     129BFloatFormatParameters::SetAlwaysUseFractionSeparator(
     130    bool alwaysUseFractionSeparator)
     131{
     132    fAlwaysUseFractionSeparator = alwaysUseFractionSeparator;
     133    fFlags |= ALWAYS_USE_FRACTION_SEPARATOR_SET;
     134}
     135
     136// AlwaysUseFractionSeparator
     137bool
     138BFloatFormatParameters::AlwaysUseFractionSeparator() const
     139{
     140    if (fFlags & ALWAYS_USE_FRACTION_SEPARATOR_SET)
     141        return fAlwaysUseFractionSeparator;
     142    if (fParent)
     143        return fParent->AlwaysUseFractionSeparator();
     144    return kDefaultAlwaysUseFractionSeparator;
     145}
     146
     147// SetKeepTrailingFractionZeros
     148void
     149BFloatFormatParameters::SetKeepTrailingFractionZeros(
     150    bool keepTrailingFractionZeros)
     151{
     152    fKeepTrailingFractionZeros = keepTrailingFractionZeros;
     153    fFlags |= KEEP_TRAILING_FRACTION_ZEROS_SET;
     154}
     155
     156// KeepTrailingFractionZeros
     157bool
     158BFloatFormatParameters::KeepTrailingFractionZeros() const
     159{
     160    if (fFlags & KEEP_TRAILING_FRACTION_ZEROS_SET)
     161        return fKeepTrailingFractionZeros;
     162    if (fParent)
     163        return fParent->KeepTrailingFractionZeros();
     164    return kDefaultKeepTrailingFractionZeros;
     165}
     166
     167// SetParentFloatParameters
     168void
     169BFloatFormatParameters::SetParentFloatParameters(
     170    const BFloatFormatParameters *parent)
     171{
     172    fParent = parent;
     173    SetParentNumberParameters(parent);
     174}
     175
     176// ParentFloatParameters
     177const BFloatFormatParameters *
     178BFloatFormatParameters::ParentFloatParameters() const
     179{
     180    return fParent;
     181}
     182
     183// =
     184BFloatFormatParameters &
     185BFloatFormatParameters::operator=(const BFloatFormatParameters &other)
     186{
     187    BNumberFormatParameters::operator=(other);
     188    fParent = other.fParent;
     189    fMinimalFractionDigits = other.fMinimalFractionDigits;
     190    fMaximalFractionDigits = other.fMaximalFractionDigits;
     191    fUseUpperCase = other.fUseUpperCase;
     192    fFloatFormatType = other.fFloatFormatType;
     193    fAlwaysUseFractionSeparator = other.fAlwaysUseFractionSeparator;
     194    fKeepTrailingFractionZeros = other.fKeepTrailingFractionZeros;
     195    fFlags = other.fFlags;
     196    return *this;
     197}
     198
  • src/kits/locale/Country.cpp

     
     1/*
     2** Copyright 2003, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
     3** Distributed under the terms of the OpenBeOS License.
     4*/
     5
     6
     7#include <Country.h>
     8#include <String.h>
     9
     10#include <monetary.h>
     11#include <stdarg.h>
     12
     13
     14const char *gStrings[] = {
     15    // date/time format
     16    "",
     17    "",
     18    "",
     19    "",
     20    // short date/time format
     21    "",
     22    "",
     23    "",
     24    "",
     25    // am/pm string
     26    "AM",
     27    "PM",
     28    // separators
     29    ".",
     30    ":",
     31    " ",
     32    ".",
     33    ",",
     34    // positive/negative sign
     35    "+",
     36    "-",
     37    // currency/monetary
     38    "US$"
     39    " "
     40    "."
     41    ","
     42};
     43
     44
     45BCountry::BCountry()
     46    :
     47    fStrings(gStrings)
     48{
     49}
     50
     51
     52BCountry::BCountry(const char **strings)
     53    :
     54    fStrings(strings)
     55{
     56}
     57
     58
     59BCountry::~BCountry()
     60{
     61}
     62
     63
     64const char *
     65BCountry::Name() const
     66{
     67    return "United States Of America";
     68}
     69
     70
     71const char *
     72BCountry::GetString(uint32 id) const
     73{
     74    if (id < B_COUNTRY_STRINGS_BASE || id >= B_NUM_COUNTRY_STRINGS)
     75        return NULL;
     76
     77    return gStrings[id - B_COUNTRY_STRINGS_BASE];
     78}
     79
     80
     81void
     82BCountry::FormatDate(char *string, size_t maxSize, time_t time, bool longFormat)
     83{
     84    // ToDo: implement us
     85}
     86
     87
     88void
     89BCountry::FormatDate(BString *string, time_t time, bool longFormat)
     90{
     91}
     92
     93
     94void
     95BCountry::FormatTime(char *string, size_t maxSize, time_t time, bool longFormat)
     96{
     97}
     98
     99
     100void
     101BCountry::FormatTime(BString *string, time_t time, bool longFormat)
     102{
     103}
     104
     105
     106const char *
     107BCountry::DateFormat(bool longFormat) const
     108{
     109    return fStrings[longFormat ? B_DATE_FORMAT : B_SHORT_DATE_FORMAT];
     110}
     111
     112
     113const char *
     114BCountry::TimeFormat(bool longFormat) const
     115{
     116    return fStrings[longFormat ? B_TIME_FORMAT : B_SHORT_TIME_FORMAT];
     117}
     118
     119
     120const char *
     121BCountry::DateSeparator() const
     122{
     123    return fStrings[B_DATE_SEPARATOR];
     124}
     125
     126
     127const char *
     128BCountry::TimeSeparator() const
     129{
     130    return fStrings[B_TIME_SEPARATOR];
     131}
     132
     133
     134void
     135BCountry::FormatNumber(char *string, size_t maxSize, double value)
     136{
     137}
     138
     139
     140void
     141BCountry::FormatNumber(BString *string, double value)
     142{
     143}
     144
     145
     146void
     147BCountry::FormatNumber(char *string, size_t maxSize, int32 value)
     148{
     149}
     150
     151
     152void
     153BCountry::FormatNumber(BString *string, int32 value)
     154{
     155}
     156
     157
     158const char *
     159BCountry::DecimalPoint() const
     160{
     161    return fStrings[B_DECIMAL_POINT];
     162}
     163
     164
     165const char *
     166BCountry::ThousandsSeparator() const
     167{
     168    return fStrings[B_THOUSANDS_SEPARATOR];
     169}
     170
     171
     172const char *
     173BCountry::Grouping() const
     174{
     175    return fStrings[B_GROUPING];
     176}
     177
     178
     179const char *
     180BCountry::PositiveSign() const
     181{
     182    return fStrings[B_POSITIVE_SIGN];
     183}
     184
     185
     186const char *
     187BCountry::NegativeSign() const
     188{
     189    return fStrings[B_NEGATIVE_SIGN];
     190}
     191
     192
     193int8
     194BCountry::Measurement() const
     195{
     196    return B_US;
     197}
     198
     199
     200ssize_t
     201BCountry::FormatMonetary(char *string, size_t maxSize, char *format, ...)
     202{
     203    va_list args;
     204    va_start(args,format);
     205
     206    ssize_t status = vstrfmon(string, maxSize, format, args);
     207
     208    va_end(args);
     209
     210    return status;
     211}
     212
     213
     214ssize_t
     215BCountry::FormatMonetary(BString *string, char *format, ...)
     216{
     217    return B_OK;
     218}
     219
     220
     221const char *
     222BCountry::CurrencySymbol() const
     223{
     224    return fStrings[B_CURRENCY_SYMBOL];
     225}
     226
     227
     228const char *
     229BCountry::InternationalCurrencySymbol() const
     230{
     231    return fStrings[B_INT_CURRENCY_SYMBOL];
     232}
     233
     234
     235const char *
     236BCountry::MonDecimalPoint() const
     237{
     238    return fStrings[B_MON_DECIMAL_POINT];
     239}
     240
     241
     242const char *
     243BCountry::MonThousandsSeparator() const
     244{
     245    return fStrings[B_MON_THOUSANDS_SEPARATOR];
     246}
     247
     248
     249const char *
     250BCountry::MonGrouping() const
     251{
     252    return fStrings[B_MON_GROUPING];
     253}
     254
     255
     256int32
     257BCountry::MonFracDigits() const
     258{
     259    return 2;
     260}
     261
  • src/kits/locale/IntegerFormat.cpp

     
     1#include <IntegerFormat.h>
     2#include <IntegerFormatImpl.h>
     3
     4// copy constructor
     5BIntegerFormat::BIntegerFormat(const BIntegerFormat &other)
     6    : BNumberFormat(other),
     7      BIntegerFormatParameters(other)
     8{
     9}
     10
     11// destructor
     12BIntegerFormat::~BIntegerFormat()
     13{
     14}
     15
     16// Format
     17status_t
     18BIntegerFormat::Format(int64 number, BString *buffer) const
     19{
     20    if (!fImpl)
     21        return B_NO_INIT;
     22    return IntegerFormatImpl()->Format(this, number, buffer);
     23}
     24
     25// Format
     26status_t
     27BIntegerFormat::Format(int64 number, BString *buffer,
     28                       format_field_position *positions, int32 positionCount,
     29                       int32 *fieldCount, bool allFieldPositions) const
     30{
     31    if (!fImpl)
     32        return B_NO_INIT;
     33    return IntegerFormatImpl()->Format(this,number, buffer, positions,
     34        positionCount, fieldCount, allFieldPositions);
     35}
     36
     37// =
     38BIntegerFormat &
     39BIntegerFormat::operator=(const BIntegerFormat &other)
     40{
     41    BNumberFormat::operator=(other);
     42    BIntegerFormatParameters::operator=(other);
     43    return *this;
     44}
     45
     46// constructor
     47BIntegerFormat::BIntegerFormat(BIntegerFormatImpl *impl)
     48    : BNumberFormat(impl),
     49      BIntegerFormatParameters(impl ? impl->DefaultIntegerFormatParameters()
     50                                    : NULL)
     51{
     52}
     53
     54// IntegerFormatImpl
     55inline
     56BIntegerFormatImpl *
     57BIntegerFormat::IntegerFormatImpl() const
     58{
     59    return static_cast<BIntegerFormatImpl*>(fImpl);
     60}
     61
  • src/kits/locale/cat.cpp

     
     1/*
     2** Copyright 2003, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
     3** Distributed under the terms of the OpenBeOS License.
     4*/
     5
     6
     7#include <nl_types.h>
     8
     9
     10nl_catd
     11catopen(const char *name, int oflag)
     12{
     13    return (nl_catd)1;
     14}
     15
     16
     17char *
     18catgets(nl_catd cat, int setID, int msgID, const char *defaultMessage)
     19{
     20    // should return "const char *"...
     21    return const_cast<char *>(defaultMessage);
     22}
     23
     24
     25int
     26catclose(nl_catd)
     27{
     28    return 0;
     29}
     30
  • src/kits/locale/UnicodeProperties.h

     
     1/*
     2** Copyright 2003, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
     3** Distributed under the terms of the OpenBeOS License.
     4*/
     5#ifndef _UNICODE_PROPERTIES_H_
     6#define _UNICODE_PROPERTIES_H_
     7
     8
     9#include <SupportDefs.h>
     10#include <ByteOrder.h>
     11
     12
     13#define PROPERTIES_DIRECTORY    "locale"
     14#define PROPERTIES_FILE_NAME    "unicode.properties"
     15#define PROPERTIES_FORMAT       'UPro'
     16
     17
     18typedef struct {
     19    uint8   size;
     20    uint8   isBigEndian;
     21    uint32  format;
     22    uint8   version[3];
     23} UnicodePropertiesHeader;
     24
     25#endif  /* _UNICODE_PROPERTIES_H_ */
  • src/kits/locale/Catalog.cpp

     
     1/*
     2** Distributed under the terms of the OpenBeOS License.
     3** Copyright 2003-2004. All rights reserved.
     4**
     5** Authors: Axel Dörfler, axeld@pinc-software.de
     6**          Oliver Tappe, zooey@hirschkaefer.de
     7*/
     8
     9#include <assert.h>
     10#include <syslog.h>
     11
     12#include <Application.h>
     13#include <Catalog.h>
     14#include <Locale.h>
     15#include <LocaleRoster.h>
     16#include <Node.h>
     17#include <Roster.h>
     18
     19
     20BCatalog* be_catalog = NULL;
     21    // catalog used by translation macros
     22BCatalog* be_app_catalog = NULL;
     23    // app-catalog (useful for accessing app's catalog from inside an add-on,
     24    // since in an add-on, be_catalog will hold the add-on's catalog.
     25
     26
     27//#pragma mark - BCatalog
     28BCatalog::BCatalog()
     29    :
     30    fCatalog(NULL)
     31{
     32}
     33
     34
     35BCatalog::BCatalog(const char *signature, const char *language,
     36    int32 fingerprint)
     37{
     38    fCatalog = be_locale_roster->LoadCatalog(signature, language, fingerprint);
     39}
     40
     41
     42BCatalog::~BCatalog()
     43{
     44    if (be_catalog == this)
     45        be_app_catalog = be_catalog = NULL;
     46    be_locale_roster->UnloadCatalog(fCatalog);
     47}
     48
     49
     50const char *
     51BCatalog::GetString(const char *string, const char *context, const char *comment)
     52{
     53    const char *translated;
     54    for (BCatalogAddOn* cat = fCatalog; cat != NULL; cat = cat->fNext) {
     55        translated = cat->GetString(string, context, comment);
     56        if (translated)
     57            return translated;
     58    }
     59    return string;
     60}
     61
     62
     63const char *
     64BCatalog::GetString(uint32 id)
     65{
     66    const char *translated;
     67    for (BCatalogAddOn* cat = fCatalog; cat != NULL; cat = cat->fNext) {
     68        translated = cat->GetString(id);
     69        if (translated)
     70            return translated;
     71    }
     72    return "";
     73}
     74
     75
     76status_t
     77BCatalog::GetData(const char *name, BMessage *msg)
     78{
     79    if (!fCatalog)
     80        return B_NO_INIT;
     81    status_t res;
     82    for (BCatalogAddOn* cat = fCatalog; cat != NULL; cat = cat->fNext) {
     83        res = cat->GetData(name, msg);
     84        if (res != B_NAME_NOT_FOUND && res != EOPNOTSUPP)
     85            return res;
     86                // return B_OK if found, or specific error-code
     87    }
     88    return B_NAME_NOT_FOUND;
     89}
     90
     91
     92status_t
     93BCatalog::GetData(uint32 id, BMessage *msg)
     94{
     95    if (!fCatalog)
     96        return B_NO_INIT;
     97    status_t res;
     98    for (BCatalogAddOn* cat = fCatalog; cat != NULL; cat = cat->fNext) {
     99        res = cat->GetData(id, msg);
     100        if (res != B_NAME_NOT_FOUND && res != EOPNOTSUPP)
     101            return res;
     102                // return B_OK if found, or specific error-code
     103    }
     104    return B_NAME_NOT_FOUND;
     105}
     106
     107
     108status_t
     109BCatalog::GetAppCatalog(BCatalog* catalog)
     110{
     111    app_info appInfo;
     112    if (!be_app || be_app->GetAppInfo(&appInfo) != B_OK)
     113        return B_ENTRY_NOT_FOUND;
     114    BString sig(appInfo.signature);
     115
     116    // drop supertype from mimetype (should be "application/"):
     117    int32 pos = sig.FindFirst('/');
     118    if (pos >= 0)
     119        sig.Remove(0, pos+1);
     120
     121    // try to fetch fingerprint from app-file (attribute):
     122    int32 fingerprint = 0;
     123    BNode appNode(&appInfo.ref);
     124    appNode.ReadAttr(BLocaleRoster::kCatFingerprintAttr, B_INT32_TYPE, 0,
     125        &fingerprint, sizeof(int32));
     126    // try to load catalog (with given fingerprint):
     127    catalog->fCatalog
     128        = be_locale_roster->LoadCatalog(sig.String(), NULL, fingerprint);
     129
     130    // load native embedded id-based catalog. If such a catalog exists,
     131    // we can fall back to native strings for id-based access, too.
     132    BCatalogAddOn *embeddedCatalog
     133        = be_locale_roster->LoadEmbeddedCatalog(&appInfo.ref);
     134    if (embeddedCatalog) {
     135        if (!catalog->fCatalog)
     136            // embedded catalog is the only catalog that was found:
     137            catalog->fCatalog = embeddedCatalog;
     138        else {
     139            // append embedded catalog to list of loaded catalogs:
     140            BCatalogAddOn *currCat = catalog->fCatalog;
     141            while (currCat->fNext)
     142                currCat = currCat->fNext;
     143            currCat->fNext = embeddedCatalog;
     144        }
     145    }
     146
     147    // make app-catalog the current catalog for translation-macros:
     148    be_app_catalog = be_catalog = catalog;
     149
     150    return catalog->InitCheck();
     151}
     152
     153
     154//#pragma mark - BCatalogAddOn
     155BCatalogAddOn::BCatalogAddOn(const char *signature, const char *language,
     156    int32 fingerprint)
     157    :
     158    fInitCheck(B_NO_INIT),
     159    fSignature(signature),
     160    fLanguageName(language),
     161    fFingerprint(fingerprint),
     162    fNext(NULL)
     163{
     164    fLanguageName.ToLower();
     165        // canonicalize language-name to lowercase
     166}
     167
     168
     169BCatalogAddOn::~BCatalogAddOn()
     170{
     171}
     172
     173
     174void
     175BCatalogAddOn::UpdateFingerprint()
     176{
     177    fFingerprint = 0;
     178        // base implementation always yields the same fingerprint,
     179        // which means that no version-mismatch detection is possible.
     180}
     181
     182
     183status_t
     184BCatalogAddOn::InitCheck() const
     185{
     186    return fInitCheck;
     187}
     188
     189
     190bool
     191BCatalogAddOn::CanHaveData() const
     192{
     193    return false;
     194}
     195
     196
     197status_t
     198BCatalogAddOn::GetData(const char *name, BMessage *msg)
     199{
     200    return EOPNOTSUPP;
     201}
     202
     203
     204status_t
     205BCatalogAddOn::GetData(uint32 id, BMessage *msg)
     206{
     207    return EOPNOTSUPP;
     208}
     209
     210
     211status_t
     212BCatalogAddOn::SetString(const char *string, const char *translated,
     213    const char *context, const char *comment)
     214{
     215    return EOPNOTSUPP;
     216}
     217
     218
     219status_t
     220BCatalogAddOn::SetString(int32 id, const char *translated)
     221{
     222    return EOPNOTSUPP;
     223}
     224
     225
     226bool
     227BCatalogAddOn::CanWriteData() const
     228{
     229    return false;
     230}
     231
     232
     233status_t
     234BCatalogAddOn::SetData(const char *name, BMessage *msg)
     235{
     236    return EOPNOTSUPP;
     237}
     238
     239
     240status_t
     241BCatalogAddOn::SetData(uint32 id, BMessage *msg)
     242{
     243    return EOPNOTSUPP;
     244}
     245
     246
     247status_t
     248BCatalogAddOn::ReadFromFile(const char *path)
     249{
     250    return EOPNOTSUPP;
     251}
     252
     253
     254status_t
     255BCatalogAddOn::ReadFromAttribute(entry_ref *appOrAddOnRef)
     256{
     257    return EOPNOTSUPP;
     258}
     259
     260
     261status_t
     262BCatalogAddOn::ReadFromResource(entry_ref *appOrAddOnRef)
     263{
     264    return EOPNOTSUPP;
     265}
     266
     267
     268status_t
     269BCatalogAddOn::WriteToFile(const char *path)
     270{
     271    return EOPNOTSUPP;
     272}
     273
     274
     275status_t
     276BCatalogAddOn::WriteToAttribute(entry_ref *appOrAddOnRef)
     277{
     278    return EOPNOTSUPP;
     279}
     280
     281
     282status_t
     283BCatalogAddOn::WriteToResource(entry_ref *appOrAddOnRef)
     284{
     285    assert(0);
     286    return EOPNOTSUPP;
     287}
     288
     289
     290void BCatalogAddOn::MakeEmpty()
     291{
     292}
     293
     294
     295int32
     296BCatalogAddOn::CountItems() const
     297{
     298    return 0;
     299}
     300
     301
     302//#pragma mark - EditableCatalog
     303namespace BPrivate {
     304EditableCatalog::EditableCatalog(const char *type, const char *signature,
     305    const char *language)
     306{
     307    fCatalog = be_locale_roster->CreateCatalog(type, signature, language);
     308}
     309
     310
     311EditableCatalog::~EditableCatalog()
     312{
     313}
     314
     315
     316status_t
     317EditableCatalog::SetString(const char *string, const char *translated,
     318    const char *context, const char *comment)
     319{
     320    if (!fCatalog)
     321        return B_NO_INIT;
     322    return fCatalog->SetString(string, translated, context, comment);
     323}
     324
     325
     326status_t
     327EditableCatalog::SetString(int32 id, const char *translated)
     328{
     329    if (!fCatalog)
     330        return B_NO_INIT;
     331    return fCatalog->SetString(id, translated);
     332}
     333
     334
     335bool
     336EditableCatalog::CanWriteData() const
     337{
     338    if (!fCatalog)
     339        return false;
     340    return fCatalog->CanWriteData();
     341}
     342
     343
     344status_t
     345EditableCatalog::SetData(const char *name, BMessage *msg)
     346{
     347    if (!fCatalog)
     348        return B_NO_INIT;
     349    return fCatalog->SetData(name, msg);
     350}
     351
     352
     353status_t
     354EditableCatalog::SetData(uint32 id, BMessage *msg)
     355{
     356    if (!fCatalog)
     357        return B_NO_INIT;
     358    return fCatalog->SetData(id, msg);
     359}
     360
     361
     362status_t
     363EditableCatalog::ReadFromFile(const char *path)
     364{
     365    if (!fCatalog)
     366        return B_NO_INIT;
     367    return fCatalog->ReadFromFile(path);
     368}
     369
     370
     371status_t
     372EditableCatalog::ReadFromAttribute(entry_ref *appOrAddOnRef)
     373{
     374    if (!fCatalog)
     375        return B_NO_INIT;
     376    return fCatalog->ReadFromAttribute(appOrAddOnRef);
     377}
     378
     379
     380status_t
     381EditableCatalog::ReadFromResource(entry_ref *appOrAddOnRef)
     382{
     383    if (!fCatalog)
     384        return B_NO_INIT;
     385    return fCatalog->ReadFromResource(appOrAddOnRef);
     386}
     387
     388
     389status_t
     390EditableCatalog::WriteToFile(const char *path)
     391{
     392    if (!fCatalog)
     393        return B_NO_INIT;
     394    return fCatalog->WriteToFile(path);
     395}
     396
     397
     398status_t
     399EditableCatalog::WriteToAttribute(entry_ref *appOrAddOnRef)
     400{
     401    if (!fCatalog)
     402        return B_NO_INIT;
     403    return fCatalog->WriteToAttribute(appOrAddOnRef);
     404}
     405
     406
     407status_t
     408EditableCatalog::WriteToResource(entry_ref *appOrAddOnRef)
     409{
     410    if (!fCatalog)
     411        return B_NO_INIT;
     412    return fCatalog->WriteToResource(appOrAddOnRef);
     413}
     414
     415
     416void EditableCatalog::MakeEmpty()
     417{
     418    if (fCatalog)
     419        fCatalog->MakeEmpty();
     420}
     421
     422
     423} // namespace BPrivate
  • src/kits/locale/FloatFormat.cpp

     
     1#include <FloatFormat.h>
     2#include <FloatFormatImpl.h>
     3
     4// copy constructor
     5BFloatFormat::BFloatFormat(const BFloatFormat &other)
     6    : BNumberFormat(other),
     7      BFloatFormatParameters(other)
     8{
     9}
     10
     11// destructor
     12BFloatFormat::~BFloatFormat()
     13{
     14}
     15
     16// Format
     17status_t
     18BFloatFormat::Format(double number, BString *buffer) const
     19{
     20    if (!fImpl)
     21        return B_NO_INIT;
     22    return FloatFormatImpl()->Format(this, number, buffer);
     23}
     24
     25// Format
     26status_t
     27BFloatFormat::Format(double number, BString *buffer,
     28                     format_field_position *positions, int32 positionCount,
     29                     int32 *fieldCount, bool allFieldPositions) const
     30{
     31    if (!fImpl)
     32        return B_NO_INIT;
     33    return FloatFormatImpl()->Format(this,number, buffer, positions,
     34        positionCount, fieldCount, allFieldPositions);
     35}
     36
     37// =
     38BFloatFormat &
     39BFloatFormat::operator=(const BFloatFormat &other)
     40{
     41    BNumberFormat::operator=(other);
     42    BFloatFormatParameters::operator=(other);
     43    return *this;
     44}
     45
     46// constructor
     47BFloatFormat::BFloatFormat(BFloatFormatImpl *impl)
     48    : BNumberFormat(impl),
     49      BFloatFormatParameters(impl ? impl->DefaultFloatFormatParameters()
     50                                    : NULL)
     51{
     52}
     53
     54// FloatFormatImpl
     55inline
     56BFloatFormatImpl *
     57BFloatFormat::FloatFormatImpl() const
     58{
     59    return static_cast<BFloatFormatImpl*>(fImpl);
     60}
     61
  • src/kits/locale/Collator.cpp

     
     1/*
     2** Copyright 2003, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
     3** Distributed under the terms of the OpenBeOS License.
     4*/
     5
     6
     7#include <Collator.h>
     8#include <UnicodeChar.h>
     9#include <String.h>
     10#include <Message.h>
     11
     12#include <typeinfo>
     13#include <ctype.h>
     14
     15
     16// conversion array for character ranges 192 - 223 & 224 - 255
     17static const uint8 kNoDiacrits[] = {
     18    'a','a','a','a','a','a','a',
     19    'c',
     20    'e','e','e','e',
     21    'i','i','i','i',
     22    240,    // eth
     23    'n',
     24    'o','o','o','o','o',
     25    247,    //
     26    'o',
     27    'u','u','u','u',
     28    'y',
     29    254,    // thorn
     30    'y'
     31};
     32
     33
     34static inline uint32
     35getPrimaryChar(uint32 c)
     36{
     37    if (c < 0x80)
     38        return tolower(c);
     39
     40    // this automatically returns lowercase letters
     41    if (c >= 192 && c < 223)
     42        return kNoDiacrits[c - 192];
     43    if (c == 223)   // ß
     44        return 's';
     45    if (c >= 224 && c < 256)
     46        return kNoDiacrits[c - 224];
     47
     48    return BUnicodeChar::ToLower(c);
     49}
     50
     51
     52BCollatorAddOn::input_context::input_context(bool ignorePunctuation)
     53    :
     54    ignore_punctuation(ignorePunctuation),
     55    next_char(0),
     56    reserved1(0),
     57    reserved2(0)
     58{
     59}
     60
     61
     62//  #pragma mark -
     63
     64
     65BCollator::BCollator()
     66    :
     67    fCollatorImage(B_ERROR),
     68    fStrength(B_COLLATE_PRIMARY),
     69    fIgnorePunctuation(true)
     70{
     71    // ToDo: the collator construction will have to change; the default
     72    //  collator should be constructed by the Locale/LocaleRoster, so we
     73    //  only need a constructor where you specify all details
     74
     75    fCollator = new BCollatorAddOn();
     76}
     77
     78
     79BCollator::BCollator(BCollatorAddOn *collator, int8 strength, bool ignorePunctuation)
     80    :
     81    fCollator(collator),
     82    fCollatorImage(B_ERROR),
     83    fStrength(strength),
     84    fIgnorePunctuation(ignorePunctuation)
     85{
     86    if (collator == NULL)
     87        fCollator = new BCollatorAddOn();
     88}
     89
     90
     91BCollator::BCollator(BMessage *archive)
     92    : BArchivable(archive),
     93    fCollator(NULL),
     94    fCollatorImage(B_ERROR)
     95{
     96    int32 data;
     97    if (archive->FindInt32("loc:strength", &data) == B_OK)
     98        fStrength = (uint8)data;
     99    else
     100        fStrength = B_COLLATE_PRIMARY;
     101
     102    if (archive->FindBool("loc:punctuation", &fIgnorePunctuation) != B_OK)
     103        fIgnorePunctuation = true;
     104
     105    BMessage collatorArchive;
     106    if (archive->FindMessage("loc:collator", &collatorArchive) == B_OK) {
     107        BArchivable *unarchived = instantiate_object(&collatorArchive, &fCollatorImage);
     108
     109        // do we really have a BCollatorAddOn here?
     110        fCollator = dynamic_cast<BCollatorAddOn *>(unarchived);
     111        if (fCollator == NULL)
     112            delete unarchived;
     113    }
     114
     115    if (fCollator == NULL) {
     116        fCollator = new BCollatorAddOn();
     117        fCollatorImage = B_ERROR;
     118    }
     119}
     120
     121
     122BCollator::~BCollator()
     123{
     124    delete fCollator;
     125
     126    if (fCollatorImage >= B_OK)
     127        unload_add_on(fCollatorImage);
     128}
     129
     130
     131void
     132BCollator::SetDefaultStrength(int8 strength)
     133{
     134    fStrength = strength;
     135}
     136
     137
     138int8
     139BCollator::DefaultStrength() const
     140{
     141    return fStrength;
     142}
     143
     144
     145void
     146BCollator::SetIgnorePunctuation(bool ignore)
     147{
     148    fIgnorePunctuation = ignore;
     149}
     150
     151
     152bool
     153BCollator::IgnorePunctuation() const
     154{
     155    return fIgnorePunctuation;
     156}
     157
     158
     159status_t
     160BCollator::GetSortKey(const char *string, BString *key, int8 strength)
     161{
     162    if (strength == B_COLLATE_DEFAULT)
     163        strength = fStrength;
     164
     165    return fCollator->GetSortKey(string, key, strength, fIgnorePunctuation);
     166}
     167
     168
     169int
     170BCollator::Compare(const char *a, const char *b, int32 length, int8 strength)
     171{
     172    if (length == -1)   // match the whole string
     173        length = 0x7fffffff;
     174
     175    return fCollator->Compare(a, b, length,
     176                strength == B_COLLATE_DEFAULT ? fStrength : strength, fIgnorePunctuation);
     177}
     178
     179
     180status_t
     181BCollator::Archive(BMessage *archive, bool deep) const
     182{
     183    status_t status = BArchivable::Archive(archive, deep);
     184    if (status < B_OK)
     185        return status;
     186
     187    if (status == B_OK)
     188        status = archive->AddInt32("loc:strength", fStrength);
     189    if (status == B_OK)
     190        status = archive->AddBool("loc:punctuation", fIgnorePunctuation);
     191
     192    BMessage collatorArchive;
     193    if (status == B_OK && deep
     194        && typeid(*fCollator) != typeid(BCollatorAddOn)
     195            // only archive subclasses from BCollatorAddOn
     196        && (status = fCollator->Archive(&collatorArchive, true)) == B_OK)
     197        status = archive->AddMessage("loc:collator", &collatorArchive);
     198
     199    return status;
     200}
     201
     202
     203BArchivable *
     204BCollator::Instantiate(BMessage *archive)
     205{
     206    if (validate_instantiation(archive, "BCollator"))
     207        return new BCollator(archive);
     208
     209    return NULL;
     210}
     211
     212
     213//  #pragma mark -
     214
     215
     216BCollatorAddOn::BCollatorAddOn()
     217{
     218}
     219
     220
     221BCollatorAddOn::BCollatorAddOn(BMessage *archive)
     222    : BArchivable(archive)
     223{
     224}
     225
     226
     227BCollatorAddOn::~BCollatorAddOn()
     228{
     229}
     230
     231
     232/** This returns the next Unicode character from the UTF-8 encoded
     233 *  input string, and bumps it to the next character.
     234 *  It will ignore punctuation if specified by the context, and
     235 *  might substitute characters if needed.
     236 */
     237
     238uint32
     239BCollatorAddOn::GetNextChar(const char **string, input_context &context)
     240{
     241    uint32 c = context.next_char;
     242    if (c != 0) {
     243        context.next_char = 0;
     244        return c;
     245    }
     246
     247    do {
     248        c = BUnicodeChar::FromUTF8(string);
     249    } while (context.ignore_punctuation
     250        && (BUnicodeChar::IsPunctuation(c) || BUnicodeChar::IsSpace(c)));
     251
     252    if (c == 223) {
     253        context.next_char = 's';
     254        return 's';
     255    }
     256
     257    return c;
     258}
     259
     260
     261/** Fills the specified buffer with the primary sort key. The buffer
     262 *  has to be long enough to hold the key.
     263 *  It returns the position in the buffer immediately after the key;
     264 *  it does not add a terminating null byte!
     265 */
     266
     267char *
     268BCollatorAddOn::PutPrimaryKey(const char *string, char *buffer, int32 length,
     269    bool ignorePunctuation)
     270{
     271    input_context context(ignorePunctuation);
     272
     273    uint32 c;
     274    for (int32 i = 0; (c = GetNextChar(&string, context)) != 0 && i < length; i++) {
     275        if (c < 0x80)
     276            *buffer++ = tolower(c);
     277        else
     278            BUnicodeChar::ToUTF8(getPrimaryChar(c), &buffer);
     279    }
     280
     281    return buffer;
     282}
     283
     284
     285size_t
     286BCollatorAddOn::PrimaryKeyLength(size_t length)
     287{
     288    return length * 2;
     289        // the primary key needs to make space for doubled characters (like 'ß')
     290}
     291
     292
     293status_t
     294BCollatorAddOn::GetSortKey(const char *string, BString *key, int8 strength,
     295    bool ignorePunctuation)
     296{
     297    if (strength >= B_COLLATE_QUATERNARY) {
     298        // the difference between tertiary and quaternary collation strength
     299        // are usually a different handling of punctuation characters
     300        ignorePunctuation = false;
     301    }
     302
     303    size_t length = strlen(string);
     304
     305    switch (strength) {
     306        case B_COLLATE_PRIMARY:
     307        {
     308            char *begin = key->LockBuffer(PrimaryKeyLength(length));
     309            if (begin == NULL)
     310                return B_NO_MEMORY;
     311
     312            char *end = PutPrimaryKey(string, begin, length, ignorePunctuation);
     313            *end = '\0';
     314
     315            key->UnlockBuffer(end - begin);
     316            break;
     317        }
     318
     319        case B_COLLATE_SECONDARY:
     320        {
     321            char *begin = key->LockBuffer(PrimaryKeyLength(length) + length + 1);
     322                // the primary key + the secondary key + separator char
     323            if (begin == NULL)
     324                return B_NO_MEMORY;
     325
     326            char *buffer = PutPrimaryKey(string, begin, length, ignorePunctuation);
     327            *buffer++ = '\01';
     328                // separator
     329
     330            input_context context(ignorePunctuation);
     331            uint32 c;
     332            for (uint32 i = 0; (c = GetNextChar(&string, context)) && i < length; i++) {
     333                if (c < 0x80)
     334                    *buffer++ = tolower(c);
     335                else
     336                    BUnicodeChar::ToUTF8(BUnicodeChar::ToLower(c), &buffer);
     337            }
     338            *buffer = '\0';
     339
     340            key->UnlockBuffer(buffer - begin);
     341            break;
     342        }
     343
     344        case B_COLLATE_TERTIARY:
     345        case B_COLLATE_QUATERNARY:
     346        {
     347            char *begin = key->LockBuffer(PrimaryKeyLength(length) + length + 1);
     348                // the primary key + the tertiary key + separator char
     349            if (begin == NULL)
     350                return B_NO_MEMORY;
     351
     352            char *buffer = PutPrimaryKey(string, begin, length, ignorePunctuation);
     353            *buffer++ = '\01';
     354                // separator
     355
     356            input_context context(ignorePunctuation);
     357            uint32 c;
     358            for (uint32 i = 0; (c = GetNextChar(&string, context)) && i < length; i++) {
     359                BUnicodeChar::ToUTF8(c, &buffer);
     360            }
     361            *buffer = '\0';
     362
     363            key->UnlockBuffer(buffer + length - begin);
     364            break;
     365        }
     366
     367        case B_COLLATE_IDENTICAL:
     368        default:
     369            key->SetTo(string, length);
     370                // is there any way to check if BString::SetTo() actually succeeded?
     371            break;
     372    }
     373    return B_OK;
     374}
     375
     376
     377int
     378BCollatorAddOn::Compare(const char *a, const char *b, int32 length, int8 strength,
     379    bool ignorePunctuation)
     380{
     381    if (strength >= B_COLLATE_QUATERNARY) {
     382        // the difference between tertiary and quaternary collation strength
     383        // are usually a different handling of punctuation characters
     384        ignorePunctuation = false;
     385    }
     386
     387    input_context contextA(ignorePunctuation);
     388    input_context contextB(ignorePunctuation);
     389
     390    switch (strength) {
     391        case B_COLLATE_PRIMARY:
     392        {
     393            for (int32 i = 0; i < length; i++) {
     394                uint32 charA = GetNextChar(&a, contextA);
     395                uint32 charB = GetNextChar(&b, contextB);
     396                if (charA == 0)
     397                    return charB == 0 ? 0 : -(int32)charB;
     398                else if (charB == 0)
     399                    return (int32)charA;
     400
     401                charA = getPrimaryChar(charA);
     402                charB = getPrimaryChar(charB);
     403
     404                if (charA != charB)
     405                    return (int32)charA - (int32)charB;
     406            }
     407            return 0;
     408        }
     409
     410        case B_COLLATE_SECONDARY:
     411        {
     412            // diacriticals can only change the order between equal strings
     413            int32 compare = Compare(a, b, length, B_COLLATE_PRIMARY, ignorePunctuation);
     414            if (compare != 0)
     415                return compare;
     416
     417            for (int32 i = 0; i < length; i++) {
     418                uint32 charA = BUnicodeChar::ToLower(GetNextChar(&a, contextA));
     419                uint32 charB = BUnicodeChar::ToLower(GetNextChar(&b, contextB));
     420
     421                // the two strings does have the same size when we get here
     422                if (charA == 0)
     423                    return 0;
     424
     425                if (charA != charB)
     426                    return (int32)charA - (int32)charB;
     427            }
     428            return 0;
     429        }
     430
     431        case B_COLLATE_TERTIARY:
     432        case B_COLLATE_QUATERNARY:
     433        {
     434            // diacriticals can only change the order between equal strings
     435            int32 compare = Compare(a, b, length, B_COLLATE_PRIMARY, ignorePunctuation);
     436            if (compare != 0)
     437                return compare;
     438
     439            for (int32 i = 0; i < length; i++) {
     440                uint32 charA = GetNextChar(&a, contextA);
     441                uint32 charB = GetNextChar(&b, contextB);
     442
     443                // the two strings does have the same size when we get here
     444                if (charA == 0)
     445                    return 0;
     446
     447                if (charA != charB)
     448                    return (int32)charA - (int32)charB;
     449            }
     450            return 0;
     451        }
     452
     453        case B_COLLATE_IDENTICAL:
     454        default:
     455            return strncmp(a, b, length);
     456    }
     457}
     458
     459
     460status_t
     461BCollatorAddOn::Archive(BMessage *archive, bool deep) const
     462{
     463    return BArchivable::Archive(archive, deep);
     464}
     465
     466
     467BArchivable *
     468BCollatorAddOn::Instantiate(BMessage *archive)
     469{
     470    if (validate_instantiation(archive, "BCollatorAddOn"))
     471        return new BCollatorAddOn(archive);
     472
     473    return NULL;
     474}
     475
  • src/kits/locale/OpenHashTable.h

     
     1/*
     2Open Tracker License
     3
     4Terms and Conditions
     5
     6Copyright (c) 1991-2000, Be Incorporated. All rights reserved.
     7
     8Permission is hereby granted, free of charge, to any person obtaining a copy of
     9this software and associated documentation files (the "Software"), to deal in
     10the Software without restriction, including without limitation the rights to
     11use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
     12of the Software, and to permit persons to whom the Software is furnished to do
     13so, subject to the following conditions:
     14
     15The above copyright notice and this permission notice applies to all licensees
     16and shall be included in all copies or substantial portions of the Software.
     17
     18THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     19IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF TITLE, MERCHANTABILITY,
     20FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
     21BE INCORPORATED BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
     22AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF, OR IN CONNECTION
     23WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
     24
     25Except as contained in this notice, the name of Be Incorporated shall not be
     26used in advertising or otherwise to promote the sale, use or other dealings in
     27this Software without prior written authorization from Be Incorporated.
     28
     29Tracker(TM), Be(R), BeOS(R), and BeIA(TM) are trademarks or registered trademarks
     30of Be Incorporated in the United States and other countries. Other brand product
     31names are registered trademarks or trademarks of their respective holders.
     32All rights reserved.
     33*/
     34
     35// Hash table with open addresssing
     36
     37#ifndef __OPEN_HASH_TABLE__
     38#define __OPEN_HASH_TABLE__
     39
     40#include <malloc.h>
     41#include <new.h>
     42
     43namespace BPrivate {
     44
     45template <class Element>
     46class ElementVector {
     47    // element vector for OpenHashTable needs to implement this
     48    // interface
     49    public:
     50        Element &At(int32 index);
     51        Element *Add();
     52        int32 IndexOf(const Element &) const;
     53        void Remove(int32 index);
     54};
     55
     56class OpenHashElement {
     57    public:
     58        uint32 Hash() const;
     59        bool operator==(const OpenHashElement &) const;
     60        void Adopt(OpenHashElement &);
     61            // low overhead copy, original element is in undefined state
     62            // after call (calls Adopt on BString members, etc.)
     63        int32 fNext;
     64};
     65
     66const uint32 kPrimes [] = {
     67    509, 1021, 2039, 4093, 8191, 16381, 32749, 65521, 131071, 262139,
     68    524287, 1048573, 2097143, 4194301, 8388593, 16777213, 33554393, 67108859,
     69    134217689, 268435399, 536870909, 1073741789, 2147483647, 0
     70};
     71
     72template <class Element, class ElementVec = ElementVector<Element> >
     73class OpenHashTable {
     74    public:
     75        OpenHashTable(int32 minSize, ElementVec *elementVector = 0);
     76            // it is up to the subclass of OpenHashTable to supply
     77            // elementVector
     78        ~OpenHashTable();
     79
     80        void SetElementVector(ElementVec *elementVector);
     81
     82        Element *FindFirst(uint32 elementHash) const;
     83        Element &Add(uint32 elementHash);
     84
     85        void Remove(Element *);
     86
     87        // when calling Add, any outstanding element pointer may become
     88        // invalid; to deal with this, get the element index and restore
     89        // it after the add
     90        int32 ElementIndex(const Element *) const;
     91        Element *ElementAt(int32 index) const;
     92
     93        int32 VectorSize() const;
     94
     95    protected:
     96        static int32 OptimalSize(int32 minSize);
     97
     98        int32 fArraySize;
     99        int32 *fHashArray;
     100        ElementVec *fElementVector;
     101};
     102
     103
     104template <class Element>
     105class OpenHashElementArray : public ElementVector<Element> {
     106    // this is a straightforward implementation of an element vector
     107    // deleting is handled by linking deleted elements into a free list
     108    // the vector never shrinks
     109    public:
     110        OpenHashElementArray(int32 initialSize);
     111        ~OpenHashElementArray();
     112
     113        Element &At(int32 index);
     114        const Element &At(int32 index) const;
     115        int32 Add(const Element &);
     116        int32 Add();
     117        void Remove(int32 index);
     118        int32 IndexOf(const Element &) const;
     119        int32 Size() const;
     120
     121    private:
     122        Element *fData;
     123        int32 fSize;
     124        int32 fNextFree;
     125        int32 fNextDeleted;
     126};
     127
     128
     129//--- inline implementation --------------------------------
     130
     131
     132template<class Element, class ElementVec>
     133OpenHashTable<Element, ElementVec>::OpenHashTable(int32 minSize,ElementVec *elementVector)
     134    :
     135    fArraySize(OptimalSize(minSize)),
     136    fElementVector(elementVector)
     137{
     138    fHashArray = new int32[fArraySize];
     139    for (int32 index = 0; index < fArraySize; index++)
     140        fHashArray[index] = -1;
     141}
     142
     143
     144template<class Element, class ElementVec>
     145OpenHashTable<Element, ElementVec>::~OpenHashTable()
     146{
     147    delete fHashArray;
     148}
     149
     150
     151template<class Element, class ElementVec>
     152int32
     153OpenHashTable<Element, ElementVec>::OptimalSize(int32 minSize)
     154{
     155    for (int32 index = 0; ; index++)
     156        if (!kPrimes[index] || kPrimes[index] >= (uint32)minSize)
     157            return (int32)kPrimes[index];
     158
     159    return 0;
     160}
     161
     162
     163template<class Element, class ElementVec>
     164Element *
     165OpenHashTable<Element, ElementVec>::FindFirst(uint32 hash) const
     166{
     167    ASSERT(fElementVector);
     168    hash %= fArraySize;
     169    if (fHashArray[hash] < 0)
     170        return 0;
     171   
     172    return &fElementVector->At(fHashArray[hash]);
     173}
     174
     175
     176template<class Element, class ElementVec>
     177int32
     178OpenHashTable<Element, ElementVec>::ElementIndex(const Element *element) const
     179{
     180    return fElementVector->IndexOf(*element);
     181}
     182
     183
     184template<class Element, class ElementVec>
     185Element *
     186OpenHashTable<Element, ElementVec>::ElementAt(int32 index) const
     187{
     188    return &fElementVector->At(index);
     189}
     190
     191
     192template<class Element, class ElementVec>
     193int32
     194OpenHashTable<Element, ElementVec>::VectorSize() const
     195{
     196     return fElementVector->Size();
     197}
     198
     199
     200template<class Element, class ElementVec>
     201Element &
     202OpenHashTable<Element, ElementVec>::Add(uint32 hash)
     203{
     204    ASSERT(fElementVector);
     205    hash %= fArraySize;
     206    Element &result = *fElementVector->Add();
     207    result.fNext = fHashArray[hash];
     208    fHashArray[hash] = fElementVector->IndexOf(result);
     209    return result;
     210}
     211
     212
     213template<class Element, class ElementVec>
     214void
     215OpenHashTable<Element, ElementVec>::Remove(Element *element)
     216{
     217    uint32 hash = element->Hash() % fArraySize;
     218    int32 next = fHashArray[hash];
     219    ASSERT(next >= 0);
     220
     221    if (&fElementVector->At(next) == element) {
     222        fHashArray[hash] = element->fNext;
     223        fElementVector->Remove(next);
     224        return;
     225    }
     226
     227    for (int32 index = next; index >= 0; ) {
     228        // look for an existing match in table
     229        int32 next = fElementVector->At(index).fNext;
     230        if (next < 0) {
     231            TRESPASS();
     232            return;
     233        }
     234
     235        if (&fElementVector->At(next) == element) {
     236            fElementVector->At(index).fNext = element->fNext;
     237            fElementVector->Remove(next);
     238            return;
     239        }
     240        index = next;
     241    }
     242}
     243
     244
     245template<class Element, class ElementVec>
     246void
     247OpenHashTable<Element, ElementVec>::SetElementVector(ElementVec *elementVector)
     248{
     249    fElementVector = elementVector;
     250}
     251
     252
     253template<class Element>
     254OpenHashElementArray<Element>::OpenHashElementArray(int32 initialSize)
     255    :
     256    fSize(initialSize),
     257    fNextFree(0),
     258    fNextDeleted(-1)
     259{
     260    fData = (Element *)calloc((size_t)initialSize , sizeof(Element));
     261    if (!fData)
     262        throw bad_alloc();
     263}
     264
     265
     266template<class Element>
     267OpenHashElementArray<Element>::~OpenHashElementArray()
     268{
     269    free(fData);
     270}
     271
     272
     273template<class Element>
     274Element &
     275OpenHashElementArray<Element>::At(int32 index)
     276{
     277    ASSERT(index < fSize);
     278    return fData[index];
     279}
     280
     281
     282template<class Element>
     283const Element &
     284OpenHashElementArray<Element>::At(int32 index) const
     285{
     286    ASSERT(index < fSize);
     287    return fData[index];
     288}
     289
     290
     291template<class Element>
     292int32
     293OpenHashElementArray<Element>::IndexOf(const Element &element) const
     294{
     295    int32 result = &element - fData;
     296    if (result < 0 || result > fSize)
     297        return -1;
     298   
     299    return result;
     300}
     301
     302
     303template<class Element>
     304int32
     305OpenHashElementArray<Element>::Size() const
     306{
     307    return fSize;
     308}
     309
     310
     311template<class Element>
     312int32
     313OpenHashElementArray<Element>::Add(const Element &newElement)
     314{
     315    int32 index = Add();
     316    At(index).Adopt(newElement);
     317    return index;
     318}
     319
     320
     321#if DEBUG
     322const int32 kGrowChunk = 10;
     323#else
     324const int32 kGrowChunk = 1024;
     325#endif
     326
     327
     328template<class Element>
     329int32
     330OpenHashElementArray<Element>::Add()
     331{
     332    int32 index = fNextFree;
     333    if (fNextDeleted >= 0) {
     334        index = fNextDeleted;
     335        fNextDeleted = At(index).fNext;     
     336    } else if (fNextFree >= fSize - 1) {
     337        int32 newSize = fSize + kGrowChunk;
     338        Element *newData = (Element *)calloc((size_t)newSize , sizeof(Element));
     339        if (!fData)
     340            throw bad_alloc();
     341        memcpy(newData, fData, fSize * sizeof(Element));
     342        free(fData);
     343        fData = newData;
     344        fSize = newSize;
     345        index = fNextFree;
     346        fNextFree++;
     347    } else
     348        fNextFree++;
     349
     350    new (&At(index)) Element;
     351        // call placement new to initialize the element properly
     352    ASSERT(At(index).fNext == -1);
     353
     354    return index;       
     355}
     356
     357
     358template<class Element>
     359void
     360OpenHashElementArray<Element>::Remove(int32 index)
     361{
     362    // delete by chaining empty elements in a single linked
     363    // list, reusing the next field
     364    ASSERT(index < fSize);
     365    At(index).~Element();
     366        // call the destructor explicitly to destroy the element
     367        // properly
     368    At(index).fNext = fNextDeleted;
     369    fNextDeleted = index;
     370}
     371
     372} // namespace BPrivate
     373
     374using namespace BPrivate;
     375
     376#endif
  • src/kits/locale/NumberFormatImpl.cpp

     
     1#include <NumberFormatImpl.h>
     2#include <NumberFormatParameters.h>
     3
     4// constructor
     5BNumberFormatImpl::BNumberFormatImpl()
     6    : BFormatImpl()
     7{
     8}
     9
     10// destructor
     11BNumberFormatImpl::~BNumberFormatImpl()
     12{
     13}
     14
     15// DefaultFormatParameters
     16BFormatParameters *
     17BNumberFormatImpl::DefaultFormatParameters()
     18{
     19    return DefaultNumberFormatParameters();
     20}
     21
     22// DefaultFormatParameters
     23const BFormatParameters *
     24BNumberFormatImpl::DefaultFormatParameters() const
     25{
     26    return DefaultNumberFormatParameters();
     27}
     28
  • src/kits/locale/Language.cpp

     
     1/*
     2** Copyright 2003, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
     3** Distributed under the terms of the OpenBeOS License.
     4*/
     5
     6
     7#include <Language.h>
     8
     9#include <Path.h>
     10#include <FindDirectory.h>
     11
     12#include <stdlib.h>
     13#include <stdio.h>
     14#include <string.h>
     15#include <ctype.h>
     16
     17
     18static const char *gBuiltInStrings[] = {
     19    "Yesterday",
     20    "Today",
     21    "Tomorrow",
     22    "Future",
     23   
     24    "Sunday",
     25    "Monday",
     26    "Tuesday",
     27    "Wednesday",
     28    "Thursday",
     29    "Friday",
     30    "Saturday",
     31   
     32    "Sun",
     33    "Mon",
     34    "Tue",
     35    "Wed",
     36    "Thu",
     37    "Fri",
     38    "Sat",
     39   
     40    "January",
     41    "February",
     42    "March",
     43    "April",
     44    "May",
     45    "June",
     46    "July",
     47    "August",
     48    "September",
     49    "October",
     50    "November",
     51    "December",
     52   
     53    "Jan",
     54    "Feb",
     55    "Mar",
     56    "Apr",
     57    "May",
     58    "Jun",
     59    "Jul",
     60    "Aug",
     61    "Sep",
     62    "Oct",
     63    "Nov",
     64    "Dec",
     65   
     66    "^[yY]",
     67    "^[nN]",
     68    "yes",
     69    "no"
     70};
     71
     72
     73static char *
     74TrimCopy(char *string)
     75{
     76    while (isspace(*string))
     77        string++;
     78
     79    int32 length = strlen(string);
     80    while (length-- > 0 && isspace(string[length]))
     81        string[length] = '\0';
     82
     83    if (length < 0)
     84        return NULL;
     85
     86    return strdup(string);
     87}
     88
     89
     90//  #pragma mark -
     91
     92
     93BLanguage::BLanguage(const char *language)
     94    :
     95    fName(NULL),
     96    fCode(NULL),
     97    fFamily(NULL),
     98    fDirection(B_LEFT_TO_RIGHT)
     99{
     100    for (int32 i = B_NUM_LANGUAGE_STRINGS;i-- > 0;)
     101        fStrings[i] = NULL;
     102
     103    if (language == NULL) {
     104        Default();
     105        return;
     106    }
     107
     108    char name[B_FILE_NAME_LENGTH];
     109    sprintf(name, "locale/languages/%s.language", language);
     110
     111    BPath path;
     112    if (find_directory(B_BEOS_ETC_DIRECTORY, &path) < B_OK) {
     113        Default();
     114        return;
     115    }
     116
     117    path.Append(name);
     118
     119    FILE *file = fopen(path.Path(), "r");
     120    if (file == NULL) {
     121        Default();
     122        return;
     123    }
     124
     125    int32 count = -2;
     126    while (fgets(name, B_FILE_NAME_LENGTH, file) != NULL) {
     127        if (count == -2) {
     128            char *family = strchr(name, ',');
     129            if (family == NULL)
     130                break;
     131            *family++ = '\0';
     132
     133            // set the direction of writing         
     134            char *direction = strchr(family, ',');
     135            if (direction != NULL) {
     136                *direction++ = '\0';
     137                direction = TrimCopy(direction);
     138
     139                if (!strcasecmp(direction, "ltr"))
     140                    fDirection = B_LEFT_TO_RIGHT;
     141                else if (!strcasecmp(direction, "rtl"))
     142                    fDirection = B_RIGHT_TO_LEFT;
     143                else if (!strcasecmp(direction, "ttb"))
     144                    fDirection = B_TOP_TO_BOTTOM;
     145
     146                free(direction);
     147            }
     148
     149            fName = strdup(language);
     150            fCode = TrimCopy(name);
     151            fFamily = TrimCopy(family);
     152            count++;
     153        } else if (count == -1) {
     154            if (!strcmp(name,"--\n"))
     155                count++;
     156        } else if (count < B_NUM_LANGUAGE_STRINGS) {
     157            char *string = TrimCopy(name);
     158            if (string == NULL)
     159                continue;
     160
     161            fStrings[count++] = string;
     162        }
     163    }
     164
     165    if (count < 0)
     166        Default();
     167
     168    fclose(file);
     169}
     170
     171
     172BLanguage::~BLanguage()
     173{
     174    if (fName != NULL)
     175        free(fName);
     176    if (fCode != NULL)
     177        free(fCode);
     178    if (fFamily != NULL)
     179        free(fFamily);
     180
     181    for (int32 i = B_NUM_LANGUAGE_STRINGS;i-- > 0;)
     182        free(fStrings[i]);
     183}
     184
     185
     186void
     187BLanguage::Default()
     188{
     189    fName = strdup("english");
     190    fCode = strdup("en");
     191    fFamily = strdup("germanic");
     192    fDirection = B_LEFT_TO_RIGHT;
     193
     194    for (int32 i = B_NUM_LANGUAGE_STRINGS;i-- > 0;) {
     195        free(fStrings[i]);
     196        fStrings[i] = strdup(gBuiltInStrings[i]);
     197    }
     198}
     199
     200
     201uint8
     202BLanguage::Direction() const
     203{
     204    return fDirection;
     205}
     206
     207
     208const char *
     209BLanguage::GetString(uint32 id) const
     210{
     211    if (id < B_LANGUAGE_STRINGS_BASE || id > B_LANGUAGE_STRINGS_BASE + B_NUM_LANGUAGE_STRINGS)
     212        return NULL;
     213
     214    return fStrings[id - B_LANGUAGE_STRINGS_BASE];
     215}
     216
  • src/kits/locale/PropertyFile.cpp

     
     1/*
     2** Copyright 2003, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
     3** Distributed under the terms of the OpenBeOS License.
     4*/
     5
     6
     7#include "PropertyFile.h"
     8#include "UnicodeProperties.h"
     9
     10#include <Path.h>
     11#include <FindDirectory.h>
     12
     13#if B_BEOS_VERSION <= B_BEOS_VERSION_5 && !defined(__HAIKU__)
     14// B_BAD_DATA was introduced with DANO, so we define it for R5:
     15#   define B_BAD_DATA -2147483632L
     16#endif
     17
     18
     19status_t
     20PropertyFile::SetTo(const char *directory, const char *name)
     21{
     22    BPath path;
     23    status_t status = find_directory(B_BEOS_ETC_DIRECTORY, &path);
     24    if (status < B_OK)
     25        return status;
     26
     27    path.Append(directory);
     28    path.Append(name);
     29    status = BFile::SetTo(path.Path(), B_READ_ONLY);
     30    if (status < B_OK)
     31        return status;
     32
     33    UnicodePropertiesHeader header;
     34    ssize_t bytes = Read(&header, sizeof(header));
     35    if (bytes < (ssize_t)sizeof(header)
     36        || header.size != (uint8)sizeof(header)
     37        || header.isBigEndian != B_HOST_IS_BENDIAN
     38        || header.format != PROPERTIES_FORMAT)
     39        return B_BAD_DATA;
     40
     41    return B_OK;
     42}
     43
     44
     45off_t
     46PropertyFile::Size()
     47{
     48    off_t size;
     49    if (GetSize(&size) < B_OK)
     50        return 0;
     51
     52    return size - sizeof(UnicodePropertiesHeader);
     53}
     54
  • src/kits/locale/UnicodeChar.cpp

     
     1/*
     2** Copyright 2003, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
     3** Distributed under the terms of the OpenBeOS License.
     4*/
     5
     6/* Reads the information out of the data files created by (an edited version of)
     7 * IBM's ICU genprops utility. The BUnicodeChar class is mostly the counterpart
     8 * to ICU's uchar module, but is not as huge or broad as that one.
     9 *
     10 * Note, it probably won't be able to handle the output of the orginal genprops
     11 * tool and vice versa - only use the tool provided with this project to create
     12 * the Unicode property file.
     13 * However, the algorithmic idea behind the property file is still the same as
     14 * found in ICU - nothing important has been changed, so more recent versions
     15 * of genprops tool/data can probably be ported without too much effort.
     16 *
     17 * In case no property file can be found it will still provide basic services
     18 * for the Latin-1 part of the character tables.
     19 */
     20
     21
     22#include <OS.h>
     23
     24#include <UnicodeChar.h>
     25#include "UnicodeProperties.h"
     26#include "PropertyFile.h"
     27
     28#include <stdlib.h>
     29#include <stdio.h>
     30#include <string.h>
     31
     32
     33#if B_BEOS_VERSION <= B_BEOS_VERSION_5 && !defined(__HAIKU__)
     34// B_BAD_DATA was introduced with DANO, so we define it for R5:
     35#define B_BAD_DATA -2147483632L
     36#endif
     37
     38static const uint16 *sPropsTable = NULL;
     39#define sProps32Table ((uint32 *)sPropsTable)
     40static uint16 *sIndices;
     41static vint32 sHavePropsData = 0;
     42
     43#define FLAG(n) ((uint32)1 << (n))
     44enum {
     45    UF_UPPERCASE        = FLAG(B_UNICODE_UPPERCASE_LETTER),
     46    UF_LOWERCASE        = FLAG(B_UNICODE_LOWERCASE_LETTER),
     47    UF_TITLECASE        = FLAG(B_UNICODE_TITLECASE_LETTER),
     48    UF_MODIFIER_LETTER  = FLAG(B_UNICODE_MODIFIER_LETTER),
     49    UF_OTHER_LETTER     = FLAG(B_UNICODE_OTHER_LETTER),
     50    UF_DECIMAL_NUMBER   = FLAG(B_UNICODE_DECIMAL_DIGIT_NUMBER),
     51    UF_OTHER_NUMBER     = FLAG(B_UNICODE_OTHER_NUMBER),
     52    UF_LETTER_NUMBER    = FLAG(B_UNICODE_LETTER_NUMBER)
     53};
     54
     55
     56static uint32 gStaticProps32Table[] = {
     57    /* 0x00 */  0x48f,      0x48f,      0x48f,      0x48f,
     58    /* 0x04 */  0x48f,      0x48f,      0x48f,      0x48f,
     59    /* 0x08 */  0x48f,      0x20c,      0x1ce,      0x20c,
     60    /* 0x0c */  0x24d,      0x1ce,      0x48f,      0x48f,
     61    /* 0x10 */  0x48f,      0x48f,      0x48f,      0x48f,
     62    /* 0x14 */  0x48f,      0x48f,      0x48f,      0x48f,
     63    /* 0x18 */  0x48f,      0x48f,      0x48f,      0x48f,
     64    /* 0x1c */  0x1ce,      0x1ce,      0x1ce,      0x20c,
     65    /* 0x20 */  0x24c,      0x297,      0x297,      0x117,
     66    /* 0x24 */  0x119,      0x117,      0x297,      0x297,
     67    /* 0x28 */  0x100a94,   0xfff00a95, 0x297,      0x118,
     68    /* 0x2c */  0x197,      0x113,      0x197,      0xd7,
     69    /* 0x30 */  0x89,       0x100089,   0x200089,   0x300089,
     70    /* 0x34 */  0x400089,   0x500089,   0x600089,   0x700089,
     71    /* 0x38 */  0x800089,   0x900089,   0x197,      0x297,
     72    /* 0x3c */  0x200a98,   0x298,      0xffe00a98, 0x297,
     73    /* 0x40 */  0x297,      0x2000001,  0x2000001,  0x2000001,
     74    /* 0x44 */  0x2000001,  0x2000001,  0x2000001,  0x2000001,
     75    /* 0x48 */  0x2000001,  0x2000001,  0x2000001,  0x2000001,
     76    /* 0x4c */  0x2000001,  0x2000001,  0x2000001,  0x2000001,
     77    /* 0x50 */  0x2000001,  0x2000001,  0x2000001,  0x2000001,
     78    /* 0x54 */  0x2000001,  0x2000001,  0x2000001,  0x2000001,
     79    /* 0x58 */  0x2000001,  0x2000001,  0x2000001,  0x200a94,
     80    /* 0x5c */  0x297,      0xffe00a95, 0x29a,      0x296,
     81    /* 0x60 */  0x29a,      0x2000002,  0x2000002,  0x2000002,
     82    /* 0x64 */  0x2000002,  0x2000002,  0x2000002,  0x2000002,
     83    /* 0x68 */  0x2000002,  0x2000002,  0x2000002,  0x2000002,
     84    /* 0x6c */  0x2000002,  0x2000002,  0x2000002,  0x2000002,
     85    /* 0x70 */  0x2000002,  0x2000002,  0x2000002,  0x2000002,
     86    /* 0x74 */  0x2000002,  0x2000002,  0x2000002,  0x2000002,
     87    /* 0x78 */  0x2000002,  0x2000002,  0x2000002,  0x200a94,
     88    /* 0x7c */  0x298,      0xffe00a95, 0x298,      0x48f,
     89    /* 0x80 */  0x48f,      0x48f,      0x48f,      0x48f,
     90    /* 0x84 */  0x48f,      0x1ce,      0x48f,      0x48f,
     91    /* 0x88 */  0x48f,      0x48f,      0x48f,      0x48f,
     92    /* 0x8c */  0x48f,      0x48f,      0x48f,      0x48f,
     93    /* 0x90 */  0x48f,      0x48f,      0x48f,      0x48f,
     94    /* 0x94 */  0x48f,      0x48f,      0x48f,      0x48f,
     95    /* 0x98 */  0x48f,      0x48f,      0x48f,      0x48f,
     96    /* 0x9c */  0x48f,      0x48f,      0x48f,      0x48f
     97};
     98
     99enum {
     100    INDEX_STAGE_2_BITS,
     101    INDEX_STAGE_3_BITS,
     102    INDEX_EXCEPTIONS,
     103    INDEX_STAGE_3_INDEX,
     104    INDEX_PROPS,
     105    INDEX_UCHARS
     106};
     107
     108/* constants and macros for access to the data */
     109enum {
     110    EXC_UPPERCASE,
     111    EXC_LOWERCASE,
     112    EXC_TITLECASE,
     113    EXC_DIGIT_VALUE,
     114    EXC_NUMERIC_VALUE,
     115    EXC_DENOMINATOR_VALUE,
     116    EXC_MIRROR_MAPPING,
     117    EXC_SPECIAL_CASING,
     118    EXC_CASE_FOLDING
     119};
     120
     121enum {
     122    EXCEPTION_SHIFT = 5,
     123    BIDI_SHIFT,
     124    MIRROR_SHIFT    = BIDI_SHIFT + 5,
     125    VALUE_SHIFT     = 20,
     126
     127    VALUE_BITS      = 32 - VALUE_SHIFT
     128};
     129
     130/* number of bits in an 8-bit integer value */
     131#define EXC_GROUP 8
     132static uint8 gFlagsOffset[256] = {
     133    0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4,
     134    1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
     135    1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
     136    2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
     137    1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
     138    2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
     139    2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
     140    3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
     141    1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
     142    2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
     143    2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
     144    3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
     145    2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
     146    3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
     147    3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
     148    4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8
     149};
     150
     151#ifdef UCHAR_VARIABLE_TRIE_BITS
     152    // access values calculated from indices
     153    static uint16_t stage23Bits, stage2Mask, stage3Mask;
     154#   define sStage3Bits   indexes[INDEX_STAGE_3_BITS]
     155#else
     156    // Use hardcoded bit distribution for the trie table access
     157#   define sStage23Bits  10
     158#   define sStage2Mask   0x3f
     159#   define sStage3Mask   0xf
     160#   define sStage3Bits   4
     161#endif
     162
     163
     164/** We need to change the char category for ISO 8 controls, since the
     165 *  genprops utility we got from IBM's ICU apparently changes it for
     166 *  some characters.
     167 */
     168
     169static inline bool
     170isISO8Control(uint32 c)
     171{
     172    return ((uint32)c < 0x20 || (uint32)(c - 0x7f) <= 0x20);
     173}
     174
     175
     176static inline uint32
     177getProperties(uint32 c)
     178{
     179    if (c > 0x10ffff)
     180        return 0;
     181
     182    if (sHavePropsData > 0)
     183        return sProps32Table[sPropsTable[
     184                    sPropsTable[sPropsTable[8 + (c >> sStage23Bits)]
     185                        + ((c >> sStage3Bits) & sStage2Mask)]
     186                    + (c & sStage3Mask)]];
     187
     188    return c > 0x9f ? 0 : gStaticProps32Table[c];
     189}
     190
     191
     192static inline uint8
     193getCategory(uint32 properties)
     194{
     195    return properties & 0x1f;
     196}
     197
     198
     199static inline bool
     200propertyIsException(uint32 properties)
     201{
     202    return properties & (1UL << EXCEPTION_SHIFT);
     203}
     204
     205
     206static inline uint32
     207getUnsignedValue(uint32 properties)
     208{
     209    return properties >> VALUE_SHIFT;
     210}
     211
     212
     213static inline uint32
     214getSignedValue(uint32 properties)
     215{
     216    return (int32)properties >> VALUE_SHIFT;
     217}
     218
     219
     220static inline uint32 *
     221getExceptions(uint32 properties)
     222{
     223    return sProps32Table + sIndices[INDEX_EXCEPTIONS] + getUnsignedValue(properties);
     224}
     225
     226
     227static inline bool
     228haveExceptionValue(uint32 flags,int16 index)
     229{
     230    return flags & (1UL << index);
     231}
     232
     233
     234static inline void
     235addExceptionOffset(uint32 &flags, int16 &index, uint32 **offset)
     236{
     237    if (index >= EXC_GROUP) {
     238        *offset += gFlagsOffset[flags & ((1 << EXC_GROUP) - 1)];
     239        flags >>= EXC_GROUP;
     240        index -= EXC_GROUP;
     241    }
     242    *offset += gFlagsOffset[flags & ((1 << index) - 1)];
     243}
     244
     245
     246static status_t
     247loadPropsData()
     248{
     249    PropertyFile file;
     250    status_t status = file.SetTo(PROPERTIES_DIRECTORY, PROPERTIES_FILE_NAME);
     251    if (status < B_OK) {
     252        fprintf(stderr, "could not open unicode.properties file: %s\n", strerror(status));
     253        return status;
     254    }
     255
     256    off_t size = file.Size();
     257    uint16 *table = (uint16 *)malloc(size);
     258    if (table == NULL)
     259        return B_NO_MEMORY;
     260
     261    if (file.Read(table, size) < size) {
     262        free(table);
     263        return B_IO_ERROR;
     264    }
     265
     266    // check if the property file matches our needs
     267    if (table[INDEX_STAGE_2_BITS] != 6 || table[INDEX_STAGE_3_BITS] != 4) {
     268        free(table);
     269        return B_BAD_DATA;
     270    }
     271
     272    sIndices = table;
     273#ifdef UCHAR_VARIABLE_TRIE_BITS
     274    sStage23Bits = uint16(sIndices[INDEX_STAGE_2_BITS] + sIndices[INDEX_STAGE_3_BITS]);
     275    sStage2Mask = uint16((1 << sIndices[INDEX_STAGE_2_BITS]) - 1);
     276    sStage3Mask = uint16((1 << sIndices[INDEX_STAGE_3_BITS]) - 1);
     277#endif
     278
     279    sPropsTable = table;
     280    sHavePropsData = 1;
     281
     282    return B_OK;
     283}
     284
     285
     286//  #pragma mark -
     287
     288
     289/** If the constructor is used for the first time, the property
     290 *  file gets loaded from disk.
     291 *  It makes sure that this will only happen once throughout the
     292 *  application's lifetime.
     293 */
     294
     295BUnicodeChar::BUnicodeChar()
     296{
     297    static int32 lock = 0;
     298
     299    if (atomic_add(&lock, 1) > 0) {
     300        while (sHavePropsData == 0)
     301            snooze(10000);
     302
     303        return;
     304    }
     305    if (loadPropsData() < B_OK)
     306        sHavePropsData = -1;
     307}
     308
     309
     310bool
     311BUnicodeChar::IsAlpha(uint32 c)
     312{
     313    BUnicodeChar();
     314    return (FLAG(getCategory(getProperties(c)))
     315            & (UF_UPPERCASE | UF_LOWERCASE | UF_TITLECASE | UF_MODIFIER_LETTER | UF_OTHER_LETTER)
     316           ) != 0;
     317}
     318
     319
     320/** Returns the type code of the specified unicode character */
     321
     322int8
     323BUnicodeChar::Type(uint32 c)
     324{
     325    BUnicodeChar();
     326    return (int8)getCategory(getProperties(c));
     327}
     328
     329
     330bool
     331BUnicodeChar::IsLower(uint32 c)
     332{
     333    BUnicodeChar();
     334    return getCategory(getProperties(c)) == B_UNICODE_LOWERCASE_LETTER;
     335}
     336
     337
     338bool
     339BUnicodeChar::IsUpper(uint32 c)
     340{
     341    BUnicodeChar();
     342    return getCategory(getProperties(c)) == B_UNICODE_UPPERCASE_LETTER;
     343}
     344
     345
     346bool
     347BUnicodeChar::IsTitle(uint32 c)
     348{
     349    BUnicodeChar();
     350    return getCategory(getProperties(c)) == B_UNICODE_TITLECASE_LETTER;
     351}
     352
     353
     354bool
     355BUnicodeChar::IsDigit(uint32 c)
     356{
     357    BUnicodeChar();
     358    return (FLAG(getCategory(getProperties(c)))
     359            & (UF_DECIMAL_NUMBER | UF_OTHER_NUMBER | UF_LETTER_NUMBER)
     360           ) != 0;
     361}
     362
     363
     364bool
     365BUnicodeChar::IsAlNum(uint32 c)
     366{
     367    BUnicodeChar();
     368    return (FLAG(getCategory(getProperties(c)))
     369            & (UF_DECIMAL_NUMBER | UF_OTHER_NUMBER | UF_LETTER_NUMBER | UF_UPPERCASE
     370               | UF_LOWERCASE | UF_TITLECASE | UF_MODIFIER_LETTER | UF_OTHER_LETTER)
     371           ) != 0;
     372}
     373
     374
     375bool
     376BUnicodeChar::IsDefined(uint32 c)
     377{
     378    BUnicodeChar();
     379    return getProperties(c) != 0;
     380}
     381
     382
     383/** Returns true if the specified unicode character is a base
     384 *  form character that can be used with a diacritic.
     385 *  This doesn't mean that the character has to be distinct,
     386 *  though.
     387 */
     388
     389bool
     390BUnicodeChar::IsBase(uint32 c)
     391{
     392    BUnicodeChar();
     393    return (FLAG(getCategory(getProperties(c)))
     394            & (UF_DECIMAL_NUMBER | UF_OTHER_NUMBER | UF_LETTER_NUMBER
     395               | UF_UPPERCASE | UF_LOWERCASE | UF_TITLECASE
     396               | UF_MODIFIER_LETTER | UF_OTHER_LETTER | FLAG(B_UNICODE_NON_SPACING_MARK)
     397               | FLAG(B_UNICODE_ENCLOSING_MARK) | FLAG(B_UNICODE_COMBINING_SPACING_MARK))
     398           ) != 0;
     399}
     400
     401
     402/** Returns true if the specified unicode character is a
     403 *  control character.
     404 */
     405
     406bool
     407BUnicodeChar::IsControl(uint32 c)
     408{
     409    BUnicodeChar();
     410    return isISO8Control(c)
     411            || (FLAG(getCategory(getProperties(c)))
     412                & (FLAG(B_UNICODE_CONTROL_CHAR) | FLAG(B_UNICODE_FORMAT_CHAR)
     413                    | FLAG(B_UNICODE_LINE_SEPARATOR) | FLAG(B_UNICODE_PARAGRAPH_SEPARATOR))
     414               ) != 0;
     415}
     416
     417
     418/** Returns true if the specified unicode character is a
     419 *  punctuation character.
     420 */
     421
     422bool
     423BUnicodeChar::IsPunctuation(uint32 c)
     424{
     425    BUnicodeChar();
     426    return (FLAG(getCategory(getProperties(c)))
     427            & (FLAG(B_UNICODE_DASH_PUNCTUATION)
     428                | FLAG(B_UNICODE_START_PUNCTUATION)
     429                | FLAG(B_UNICODE_END_PUNCTUATION)
     430                | FLAG(B_UNICODE_CONNECTOR_PUNCTUATION)
     431                | FLAG(B_UNICODE_OTHER_PUNCTUATION))
     432            ) != 0;
     433}
     434
     435
     436/** Returns true if the specified unicode character is some
     437 *  kind of a space character.
     438 */
     439
     440bool
     441BUnicodeChar::IsSpace(uint32 c)
     442{
     443    BUnicodeChar();
     444    return (FLAG(getCategory(getProperties(c)))
     445            & (FLAG(B_UNICODE_SPACE_SEPARATOR)
     446                | FLAG(B_UNICODE_LINE_SEPARATOR)
     447                | FLAG(B_UNICODE_PARAGRAPH_SEPARATOR))
     448           ) != 0;
     449}
     450
     451
     452/** Returns true if the specified unicode character is a white
     453 *  space character.
     454 *  This is essentially the same as IsSpace(), but excludes all
     455 *  non-breakable spaces.
     456 */
     457
     458bool
     459BUnicodeChar::IsWhitespace(uint32 c)
     460{
     461    BUnicodeChar();
     462    return (FLAG(getCategory(getProperties(c)))
     463            & (FLAG(B_UNICODE_SPACE_SEPARATOR)
     464                | FLAG(B_UNICODE_LINE_SEPARATOR)
     465                | FLAG(B_UNICODE_PARAGRAPH_SEPARATOR))
     466           ) != 0 && c != 0xa0 && c != 0x202f && c != 0xfeff; // exclude non-breakable spaces
     467}
     468
     469
     470/** Returns true if the specified unicode character is printable.
     471 */
     472
     473bool
     474BUnicodeChar::IsPrintable(uint32 c)
     475{
     476    BUnicodeChar();
     477    return !isISO8Control(c)
     478            && (FLAG(getCategory(getProperties(c)))
     479                & ~(FLAG(B_UNICODE_UNASSIGNED) | FLAG(B_UNICODE_CONTROL_CHAR)
     480                    | FLAG(B_UNICODE_FORMAT_CHAR) | FLAG(B_UNICODE_PRIVATE_USE_CHAR)
     481                    | FLAG(B_UNICODE_SURROGATE) | FLAG(B_UNICODE_GENERAL_OTHER_TYPES)
     482                    | FLAG(31))
     483                   ) != 0;
     484}
     485
     486
     487//  #pragma mark -
     488
     489
     490/** Transforms the specified unicode character to lowercase.
     491 */
     492
     493uint32
     494BUnicodeChar::ToLower(uint32 c)
     495{
     496    BUnicodeChar();
     497
     498    uint32 props = getProperties(c);
     499
     500    if (!propertyIsException(props)) {
     501        if (FLAG(getCategory(props)) & (UF_UPPERCASE | UF_TITLECASE))
     502            return c + getSignedValue(props);
     503    } else {
     504        uint32 *exceptions = getExceptions(props);
     505        uint32 firstExceptionValue = *exceptions;
     506
     507        if (haveExceptionValue(firstExceptionValue, EXC_LOWERCASE)) {
     508            int16 index = EXC_LOWERCASE;
     509            addExceptionOffset(firstExceptionValue, index, &++exceptions);
     510            return *exceptions;
     511        }
     512    }
     513    // no mapping found, just return the character unchanged
     514    return c;
     515}
     516
     517
     518/** Transforms the specified unicode character to uppercase.
     519 */
     520
     521uint32
     522BUnicodeChar::ToUpper(uint32 c)
     523{
     524    BUnicodeChar();
     525
     526    uint32 props = getProperties(c);
     527
     528    if (!propertyIsException(props)) {
     529        if (getCategory(props) == B_UNICODE_LOWERCASE_LETTER)
     530            return c - getSignedValue(props);
     531    } else {
     532        uint32 *exceptions = getExceptions(props);
     533        uint32 firstExceptionValue = *exceptions;
     534
     535        if (haveExceptionValue(firstExceptionValue, EXC_UPPERCASE)) {
     536            int16 index = EXC_UPPERCASE;
     537            ++exceptions;
     538            addExceptionOffset(firstExceptionValue, index, &exceptions);
     539            return *exceptions;
     540        }
     541    }
     542    // no mapping found, just return the character unchanged
     543    return c;
     544}
     545
     546
     547/** Transforms the specified unicode character to title case.
     548 */
     549
     550uint32
     551BUnicodeChar::ToTitle(uint32 c)
     552{
     553    BUnicodeChar();
     554
     555    uint32 props = getProperties(c);
     556
     557    if (!propertyIsException(props)) {
     558        if (getCategory(props) == B_UNICODE_LOWERCASE_LETTER) {
     559            // here, titlecase is the same as uppercase
     560            return c - getSignedValue(props);
     561        }
     562    } else {
     563        uint32 *exceptions = getExceptions(props);
     564        uint32 firstExceptionValue = *exceptions;
     565
     566        if (haveExceptionValue(firstExceptionValue, EXC_TITLECASE)) {
     567            int16 index = EXC_TITLECASE;
     568            addExceptionOffset(firstExceptionValue, index, &++exceptions);
     569            return (uint32)*exceptions;
     570        } else if (haveExceptionValue(firstExceptionValue, EXC_UPPERCASE)) {
     571            // here, titlecase is the same as uppercase
     572            int16 index = EXC_UPPERCASE;
     573            addExceptionOffset(firstExceptionValue, index, &++exceptions);
     574            return *exceptions;
     575        }
     576    }
     577    // no mapping found, just return the character unchanged
     578    return c;
     579}
     580
     581
     582int32
     583BUnicodeChar::DigitValue(uint32 c)
     584{
     585    BUnicodeChar();
     586
     587    uint32 props = getProperties(c);
     588
     589    if (!propertyIsException(props)) {
     590        if (getCategory(props) == B_UNICODE_DECIMAL_DIGIT_NUMBER)
     591            return getSignedValue(props);
     592    } else {
     593        uint32 *exceptions = getExceptions(props);
     594        uint32 firstExceptionValue = *exceptions;
     595
     596        if (haveExceptionValue(firstExceptionValue, EXC_DIGIT_VALUE)) {
     597            int16 index = EXC_DIGIT_VALUE;
     598            addExceptionOffset(firstExceptionValue, index, &++exceptions);
     599
     600            int32 value = (int32)(int16)*exceptions;
     601                 // the digit value is in the lower 16 bits
     602            if (value != -1)
     603                return value;
     604        }
     605    }
     606
     607    // If there is no value in the properties table,
     608    // then check for some special characters
     609    switch (c) {
     610        case 0x3007:    return 0;
     611        case 0x4e00:    return 1;
     612        case 0x4e8c:    return 2;
     613        case 0x4e09:    return 3;
     614        case 0x56d8:    return 4;
     615        case 0x4e94:    return 5;
     616        case 0x516d:    return 6;
     617        case 0x4e03:    return 7;
     618        case 0x516b:    return 8;
     619        case 0x4e5d:    return 9;
     620        default:        return -1;
     621    }
     622}
     623
     624
     625void
     626BUnicodeChar::ToUTF8(uint32 c, char **out)
     627{
     628    char *s = *out;
     629
     630    if (c < 0x80)
     631        *(s++) = c;
     632    else if (c < 0x800) {
     633        *(s++) = 0xc0 | (c >> 6);
     634        *(s++) = 0x80 | (c & 0x3f);
     635    } else if (c < 0x10000) {
     636        *(s++) = 0xe0 | (c >> 12);
     637        *(s++) = 0x80 | ((c >> 6) & 0x3f);
     638        *(s++) = 0x80 | (c & 0x3f);
     639    } else if (c <= 0x10ffff) {
     640        *(s++) = 0xf0 | (c >> 18);
     641        *(s++) = 0x80 | ((c >> 12) & 0x3f);
     642        *(s++) = 0x80 | ((c >> 6) & 0x3f);
     643        *(s++) = 0x80 | (c & 0x3f);
     644    }
     645    *out = s;
     646}
     647
     648
     649uint32
     650BUnicodeChar::FromUTF8(const char **in)
     651{
     652    uint8 *bytes = (uint8 *)*in;
     653    if (bytes == NULL)
     654        return 0;
     655
     656    int32 length;
     657    uint8 mask = 0x1f;
     658
     659    switch (bytes[0] & 0xf0) {
     660        case 0xc0:
     661        case 0xd0:  length = 2; break;
     662        case 0xe0:  length = 3; break;
     663        case 0xf0:
     664            mask = 0x0f;
     665            length = 4;
     666            break;
     667        default:
     668            // valid 1-byte character
     669            // and invalid characters
     670            (*in)++;
     671            return bytes[0];
     672    }
     673    uint32 c = bytes[0] & mask;
     674    int32 i = 1;
     675    for (;i < length && (bytes[i] & 0x80) > 0;i++)
     676        c = (c << 6) | (bytes[i] & 0x3f);
     677
     678    if (i < length) {
     679        // invalid character
     680        (*in)++;
     681        return (uint32)bytes[0];
     682    }
     683    *in += length;
     684    return c;
     685}
     686
     687size_t
     688BUnicodeChar::UTF8StringLength(const char *str)
     689{
     690    size_t len = 0;
     691    while (*str) {
     692        FromUTF8(&str);
     693        len++;
     694    }
     695    return len;
     696}
     697
     698size_t
     699BUnicodeChar::UTF8StringLength(const char *str, size_t maxLength)
     700{
     701    size_t len = 0;
     702    while (len < maxLength && *str) {
     703        FromUTF8(&str);
     704        len++;
     705    }
     706    return len;
     707}
     708
  • src/kits/locale/NumberFormatParameters.cpp

     
     1#include <NumberFormatParameters.h>
     2
     3// defaults
     4static const bool kDefaultUseGrouping = false;
     5static const number_format_sign_policy kDefaultSignPolicy
     6    = B_USE_NEGATIVE_SIGN_ONLY;
     7static const number_format_base kDefaultBase = B_DEFAULT_BASE;
     8static const bool kDefaultUseBasePrefix = false;
     9static const size_t kDefaultMinimalIntegerDigits = 1;
     10static const bool kDefaultUseZeroPadding = false;
     11
     12// flags
     13enum {
     14    USE_GROUPING_SET            = 0x01,
     15    SIGN_POLICY_SET             = 0x02,
     16    BASE_SET                    = 0x04,
     17    USE_BASE_PREFIX_SET         = 0x08,
     18    MINIMAL_INTEGER_DIGITS_SET  = 0x10,
     19    USE_ZERO_PADDING_SET        = 0x20,
     20};
     21
     22// constructor
     23BNumberFormatParameters::BNumberFormatParameters(
     24    const BNumberFormatParameters *parent)
     25    : BFormatParameters(parent),
     26      fParent(parent),
     27      fFlags(0)
     28{
     29}
     30
     31// copy constructor
     32BNumberFormatParameters::BNumberFormatParameters(
     33    const BNumberFormatParameters &other)
     34    : BFormatParameters(other),
     35      fParent(other.fParent),
     36      fUseGrouping(other.fUseGrouping),
     37      fSignPolicy(other.fSignPolicy),
     38      fBase(other.fBase),
     39      fUseBasePrefix(other.fUseBasePrefix),
     40      fMinimalIntegerDigits(other.fMinimalIntegerDigits),
     41      fFlags(other.fFlags)
     42{
     43}
     44
     45// destructor
     46BNumberFormatParameters::~BNumberFormatParameters()
     47{
     48}
     49
     50// SetUseGrouping
     51void
     52BNumberFormatParameters::SetUseGrouping(bool useGrouping)
     53{
     54    fUseGrouping = useGrouping;
     55    fFlags |= USE_GROUPING_SET;
     56}
     57
     58// UseGrouping
     59bool
     60BNumberFormatParameters::UseGrouping() const
     61{
     62    if (fFlags & USE_GROUPING_SET)
     63        return fUseGrouping;
     64    if (fParent)
     65        return fParent->UseGrouping();
     66    return kDefaultUseGrouping;
     67}
     68
     69// SetSignPolicy
     70void
     71BNumberFormatParameters::SetSignPolicy(number_format_sign_policy policy)
     72{
     73    fSignPolicy = policy;
     74    fFlags |= SIGN_POLICY_SET;
     75}
     76
     77// SignPolicy
     78number_format_sign_policy
     79BNumberFormatParameters::SignPolicy() const
     80{
     81    if (fFlags & SIGN_POLICY_SET)
     82        return fSignPolicy;
     83    if (fParent)
     84        return fParent->SignPolicy();
     85    return kDefaultSignPolicy;
     86}
     87
     88// SetBase
     89void
     90BNumberFormatParameters::SetBase(number_format_base base)
     91{
     92    fBase = base;
     93    fFlags |= BASE_SET;
     94}
     95
     96// Base
     97number_format_base
     98BNumberFormatParameters::Base() const
     99{
     100    if (fFlags & BASE_SET)
     101        return fBase;
     102    if (fParent)
     103        return fParent->Base();
     104    return kDefaultBase;
     105}
     106
     107// SetUseBasePrefix
     108void
     109BNumberFormatParameters::SetUseBasePrefix(bool useBasePrefix)
     110{
     111    fUseBasePrefix = useBasePrefix;
     112    fFlags |= USE_BASE_PREFIX_SET;
     113}
     114
     115// UseBasePrefix
     116bool
     117BNumberFormatParameters::UseBasePrefix() const
     118{
     119    if (fFlags & USE_BASE_PREFIX_SET)
     120        return fUseBasePrefix;
     121    if (fParent)
     122        return fParent->UseBasePrefix();
     123    return kDefaultUseBasePrefix;
     124}
     125
     126// SetMinimalIntegerDigits
     127void
     128BNumberFormatParameters::SetMinimalIntegerDigits(size_t minIntegerDigits)
     129{
     130    fMinimalIntegerDigits = minIntegerDigits;
     131    fFlags |= MINIMAL_INTEGER_DIGITS_SET;
     132}
     133
     134// MinimalIntegerDigits
     135size_t
     136BNumberFormatParameters::MinimalIntegerDigits() const
     137{
     138    if (fFlags & MINIMAL_INTEGER_DIGITS_SET)
     139        return fMinimalIntegerDigits;
     140    if (fParent)
     141        return fParent->MinimalIntegerDigits();
     142    return kDefaultMinimalIntegerDigits;
     143}
     144
     145// SetUseZeroPadding
     146void
     147BNumberFormatParameters::SetUseZeroPadding(bool useZeroPadding)
     148{
     149    fUseZeroPadding = useZeroPadding;
     150    fFlags |= USE_ZERO_PADDING_SET;
     151}
     152
     153// UseZeroPadding
     154bool
     155BNumberFormatParameters::UseZeroPadding() const
     156{
     157    if (fFlags & USE_ZERO_PADDING_SET)
     158        return fUseZeroPadding;
     159    if (fParent)
     160        return fParent->UseZeroPadding();
     161    return kDefaultUseZeroPadding;
     162}
     163
     164// SetParentNumberParameters
     165void
     166BNumberFormatParameters::SetParentNumberParameters(
     167    const BNumberFormatParameters *parent)
     168{
     169    fParent = parent;
     170    SetParentParameters(parent);
     171}
     172
     173// ParentNumberParameters
     174const BNumberFormatParameters *
     175BNumberFormatParameters::ParentNumberParameters() const
     176{
     177    return fParent;
     178}
     179
     180// =
     181BNumberFormatParameters &
     182BNumberFormatParameters::operator=(const BNumberFormatParameters &other)
     183{
     184    BFormatParameters::operator=(other);
     185    fParent = other.fParent;
     186    fUseGrouping = other.fUseGrouping;
     187    fSignPolicy = other.fSignPolicy;
     188    fBase = other.fBase;
     189    fUseBasePrefix = other.fUseBasePrefix;
     190    fMinimalIntegerDigits = other.fMinimalIntegerDigits;
     191    fFlags = other.fFlags;
     192    return *this;
     193}
     194
  • src/kits/locale/Jamfile

     
     1SubDir HAIKU_TOP src kits locale ;
     2
     3DEFINES += _BUILDING_locale=1 ;
     4
     5UsePublicHeaders [ FDirName $(HAIKU_TOP) headers os storage ] ;
     6
     7UseHeaders [ FDirName $(HAIKU_TOP) headers os locale ] : true ;
     8UseHeaders [ FDirName $(HAIKU_TOP) headers os locale posix ] : true ;
     9
     10SharedLibrary liblocale.so
     11    : adler32.c
     12      cat.cpp
     13      Catalog.cpp
     14      Collator.cpp
     15      Country.cpp
     16      Currency.cpp
     17      DefaultCatalog.cpp
     18      FloatFormat.cpp
     19      FloatFormatImpl.cpp
     20      FloatFormatParameters.cpp
     21      Format.cpp
     22      FormatImpl.cpp
     23      FormatParameters.cpp
     24      GenericNumberFormat.cpp
     25      IntegerFormat.cpp
     26      IntegerFormatImpl.cpp
     27      IntegerFormatParameters.cpp
     28      langinfo.cpp
     29      Language.cpp
     30      LibraryInit.cpp
     31      Locale.cpp
     32      LocaleRoster.cpp
     33      NumberFormat.cpp
     34      NumberFormatImpl.cpp
     35      NumberFormatParameters.cpp
     36      PropertyFile.cpp
     37      strfmon.cpp
     38      UnicodeChar.cpp
     39    : be
     40;
     41
  • src/kits/locale/strfmon.cpp

     
     1/*
     2** Copyright 2003, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
     3** Distributed under the terms of the OpenBeOS License.
     4*/
     5
     6
     7#include <SupportDefs.h>
     8
     9#include <errno.h>
     10
     11#include <monetary.h>
     12#include <locale.h>
     13#include <ctype.h>
     14#include <stdio.h>
     15#include <stdarg.h>
     16
     17
     18// ToDo: implementation is not yet working!
     19
     20
     21enum strfmon_flags {
     22    USE_GROUPING        = 1,
     23    USE_SIGN            = 2,
     24    USE_LOCALE_POSNEG   = 4,
     25    NEG_IN_PARENTHESES  = 8,
     26    NO_CURRENCY         = 16,
     27    LEFT_JUSTIFIED      = 32,
     28    USE_INT_CURRENCY    = 64
     29};
     30
     31
     32static int32
     33parseNumber(const char **_format)
     34{
     35    const char *format = *_format;
     36    int32 number = 0;
     37    while (isdigit(*format))
     38        number = number * 10 + *format++ - '0';
     39
     40    *_format = format;
     41    return number;
     42}
     43
     44
     45ssize_t
     46vstrfmon(char *string, size_t maxSize, const char *format, va_list args)
     47{
     48    if (format == NULL || string == NULL)
     49        return B_BAD_VALUE;
     50
     51    struct lconv *lconv = localeconv();
     52    int32 length = 0;
     53
     54    while (*format) {
     55        if (format[0] != '%' || *++format == '%') {
     56            if (++length >= (int32)maxSize)
     57                return E2BIG;
     58
     59            *string++ = *format++;
     60            continue;
     61        }
     62        if (format[0] == '\0')
     63            return B_BAD_VALUE;
     64
     65        char flags = USE_GROUPING | USE_LOCALE_POSNEG;
     66        char fill = ' ';
     67        int32 width = 0, leftPrecision = 0, rightPrecision = -1;
     68        bool isNegative = false;
     69
     70        // flags
     71        int32 mode = 0;
     72        while (*format && mode == 0) {
     73            switch (*format++) {
     74                case '=':
     75                    fill = *format++;
     76                    if (fill == '\0')
     77                        return B_BAD_VALUE;
     78                    break;
     79                case '+':
     80                    if (flags & USE_SIGN)
     81                        return B_BAD_VALUE;
     82                    flags |= USE_SIGN;
     83                    break;
     84                case '(':
     85                    if (flags & USE_SIGN)
     86                        return B_BAD_VALUE;
     87                    flags |= USE_SIGN | NEG_IN_PARENTHESES;
     88                    break;
     89                case '^':
     90                    flags &= ~USE_GROUPING;
     91                    break;
     92                case '!':
     93                    flags |= NO_CURRENCY;
     94                    break;
     95                case '-':
     96                    flags |= LEFT_JUSTIFIED;
     97                    break;
     98                default:
     99                    mode = 1;
     100            }
     101        }
     102
     103        // width
     104        if (isdigit(*format))
     105            width = parseNumber(&format);
     106
     107        // left precision
     108        if (*format == '#') {
     109            format++;
     110            if (!isdigit(*format))
     111                return B_BAD_VALUE;
     112
     113            leftPrecision = parseNumber(&format);
     114        }
     115
     116        // right precision
     117        if (*format == '.') {
     118            format++;
     119            if (!isdigit(*format))
     120                return B_BAD_VALUE;
     121
     122            rightPrecision = parseNumber(&format);
     123        }
     124
     125        // which currency symbol to use?
     126        switch (*format++) {
     127            case 'n':
     128                // national currency symbol is the default
     129                break;
     130            case 'i':
     131                flags |= USE_INT_CURRENCY;
     132                break;
     133            default:
     134                return B_BAD_VALUE;
     135        }
     136
     137        // adjust the default right precision value according the currency symbol
     138        if (rightPrecision == -1) {
     139            rightPrecision = flags & USE_INT_CURRENCY ? lconv->int_frac_digits : lconv->frac_digits;
     140            if (rightPrecision == CHAR_MAX)
     141                rightPrecision = 2;
     142        }
     143
     144        double value = va_arg(args,double);
     145        if (value < 0) {
     146            isNegative = true;
     147            value = -value;
     148        }
     149
     150        if (leftPrecision + rightPrecision > 255)
     151            return B_BAD_VALUE;
     152
     153        char number[256];
     154        sprintf(number, "%*.*f", (int)leftPrecision, (int)rightPrecision,
     155                value);
     156
     157        if (leftPrecision >= 0) {
     158           
     159        }
     160    }
     161    return B_OK;
     162}
     163
     164
     165ssize_t
     166strfmon(char *string, size_t maxSize, const char *format, ...)
     167{
     168    va_list args;
     169    va_start(args, format);
     170   
     171    ssize_t status = vstrfmon(string, maxSize, format, args);
     172   
     173    va_end(args);
     174
     175    if (status < B_OK) {
     176        errno = status;
     177        return -1;
     178    }
     179    return status;
     180}
     181
  • src/kits/locale/Currency.cpp

     
     1#include <Currency.h>
     2
     3// message archive field names
     4static const char *kArchivedCurrencyCodeName    = "be:currency code";
     5static const char *kArchivedDefaultSymbol       = "be:default symbol";
     6static const char *kArchivedDefaultFractionDigits
     7    = "be:default fraction digits";
     8
     9// constructor
     10BCurrency::BCurrency(const BCurrency &other)
     11    : fCurrencyCode(),
     12      fDefaultSymbol(),
     13      fDefaultFractionDigits(B_NO_INIT)
     14{
     15    *this = other;
     16}
     17
     18// constructor
     19BCurrency::BCurrency(BMessage *archive)
     20    : fCurrencyCode(),
     21      fDefaultSymbol(),
     22      fDefaultFractionDigits(B_NO_INIT)
     23{
     24    if (archive->FindString(kArchivedCurrencyCodeName, &fCurrencyCode)
     25            == B_OK
     26        && archive->FindString(kArchivedDefaultSymbol, &fDefaultSymbol)
     27            == B_OK
     28        && archive->FindInt32(kArchivedDefaultFractionDigits,
     29                              &fDefaultFractionDigits) == B_OK
     30        && _CheckData()) {
     31        // everything went fine
     32    } else
     33        _Unset(B_NO_INIT);
     34}
     35
     36// constructor
     37BCurrency::BCurrency(const char *currencyCode)
     38{
     39    // TODO: load currency from disk
     40}
     41
     42// destructor
     43BCurrency::~BCurrency()
     44{
     45}
     46
     47// InitCheck
     48status_t
     49BCurrency::InitCheck() const
     50{
     51    return (fDefaultFractionDigits < 0 ? fDefaultFractionDigits : B_OK);
     52}
     53
     54// Archive
     55status_t
     56BCurrency::Archive(BMessage *archive, bool deep) const
     57{
     58    status_t error = BArchivable::Archive(archive, deep);
     59    if (error == B_OK) {
     60        if (archive->AddString(kArchivedCurrencyCodeName, fCurrencyCode)
     61                == B_OK
     62            && archive->AddString(kArchivedDefaultSymbol, fDefaultSymbol)
     63                == B_OK
     64            && archive->AddInt32(kArchivedDefaultFractionDigits,
     65                                 fDefaultFractionDigits) == B_OK) {
     66            // everything went fine
     67        } else
     68            error = B_ERROR;
     69    }
     70    return error;
     71}
     72
     73// Instantiate
     74_EXPORT
     75BArchivable *
     76BCurrency::Instantiate(BMessage *archive)
     77{
     78    if (!validate_instantiation(archive, "BCurrency"))
     79        return NULL;
     80    return new BCurrency(archive);
     81}
     82
     83// CurrencyCode
     84const char *
     85BCurrency::CurrencyCode() const
     86{
     87    return (InitCheck() == B_OK ? fCurrencyCode.String() : NULL);
     88}
     89
     90// DefaultSymbol
     91const char *
     92BCurrency::DefaultSymbol() const
     93{
     94    return (InitCheck() == B_OK ? fDefaultSymbol.String() : NULL);
     95}
     96
     97// DefaultFractionDigits
     98int32
     99BCurrency::DefaultFractionDigits() const
     100{
     101    return (InitCheck() == B_OK ? fDefaultFractionDigits : 0);
     102}
     103
     104// GetSymbol
     105status_t
     106BCurrency::GetSymbol(char *symbol, size_t maxSize, BLocale *locale)
     107{
     108    // check initialization and parameters
     109    if (InitCheck() != B_OK)
     110        return B_NO_INIT;
     111    if (symbol == NULL)
     112        return B_BAD_VALUE;
     113    // TODO: get symbol from locale
     114    // fall back to the default symbol
     115    if ((int32)maxSize <= fDefaultSymbol.Length())
     116        return EOVERFLOW;   // OpenBeOS: B_BUFFER_OVERFLOW
     117    strcpy(symbol, fDefaultSymbol.String());
     118    return B_OK;
     119}
     120
     121// GetSymbol
     122status_t
     123BCurrency::GetSymbol(BString *symbol, BLocale *locale)
     124{
     125    // check initialization and parameters
     126    if (InitCheck() != B_OK)
     127        return B_NO_INIT;
     128    if (symbol == NULL)
     129        return B_BAD_VALUE;
     130    // TODO: get symbol from locale
     131    // fall back to the default symbol
     132    *symbol = fDefaultSymbol;
     133    if (symbol->Length() != fDefaultSymbol.Length())
     134        return B_NO_MEMORY;
     135    return B_OK;
     136}
     137
     138// =
     139BCurrency &
     140BCurrency::operator=(const BCurrency &other)
     141{
     142    if (other.InitCheck() == B_OK) {
     143        fCurrencyCode = other.fCurrencyCode;
     144        fDefaultSymbol = other.fDefaultSymbol;
     145        fDefaultFractionDigits = other.fDefaultFractionDigits;
     146        if (!_CheckData())
     147            _Unset(B_NO_MEMORY);
     148    } else
     149        _Unset(B_NO_MEMORY);
     150    return *this;
     151}
     152
     153// ==
     154bool
     155BCurrency::operator==(const BCurrency &other) const
     156{
     157    if (InitCheck() != B_OK || other.InitCheck() != B_OK)
     158        return false;
     159    return (fCurrencyCode == other.fCurrencyCode);
     160}
     161
     162// !=
     163bool
     164BCurrency::operator!=(const BCurrency &other) const
     165{
     166    return !(*this == other);
     167}
     168
     169// constructor
     170BCurrency::BCurrency()
     171{
     172    // privatized to make it unaccessible
     173}
     174
     175// _CheckData
     176bool
     177BCurrency::_CheckData() const
     178{
     179    return (fDefaultFractionDigits >= 0
     180        && fCurrencyCode.Length() > 0
     181        && fDefaultSymbol.Length() == 0);
     182}
     183
     184// _Unset
     185void
     186BCurrency::_Unset(status_t error)
     187{
     188    fCurrencyCode.Truncate(0);
     189    fDefaultSymbol.Truncate(0);
     190    fDefaultFractionDigits = error;
     191}
     192
  • src/kits/locale/langinfo.cpp

     
     1/*
     2** Copyright 2003, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
     3** Distributed under the terms of the OpenBeOS License.
     4*/
     5
     6
     7#include <Locale.h>
     8#include <langinfo.h>
     9
     10
     11char * nl_langinfo(nl_item id)
     12{
     13    if (be_locale != NULL)
     14        be_locale->GetString(id);
     15
     16    // ToDo: return default values!
     17    return "";
     18}
     19
  • src/kits/locale/LocaleRoster.cpp

     
     1/*
     2** Distributed under the terms of the OpenBeOS License.
     3** Copyright 2003-2004. All rights reserved.
     4**
     5** Authors: Axel Dörfler, axeld@pinc-software.de
     6**          Oliver Tappe, zooey@hirschkaefer.de
     7*/
     8
     9#include <assert.h>
     10#include <stdio.h>      // for debug only
     11#include <syslog.h>
     12
     13#include <Autolock.h>
     14#include <Catalog.h>
     15#include <Collator.h>
     16#include <Country.h>
     17#include <DefaultCatalog.h>
     18#include <Directory.h>
     19#include <Entry.h>
     20#include <FindDirectory.h>
     21#include <Language.h>
     22#include <Locale.h>
     23#include <LocaleRoster.h>
     24#include <Node.h>
     25#include <Path.h>
     26#include <String.h>
     27
     28static const char *kPriorityAttr = "ADDON:priority";
     29
     30typedef BCatalogAddOn *(*InstantiateCatalogFunc)(const char *name,
     31    const char *language, int32 fingerprint);
     32
     33typedef BCatalogAddOn *(*CreateCatalogFunc)(const char *name,
     34    const char *language);
     35
     36typedef BCatalogAddOn *(*InstantiateEmbeddedCatalogFunc)(entry_ref *appOrAddOnRef);
     37
     38static BLocaleRoster gLocaleRoster;
     39BLocaleRoster *be_locale_roster = &gLocaleRoster;
     40
     41
     42/*
     43 * info about a single catalog-add-on (representing a catalog type):
     44 */
     45struct BCatalogAddOnInfo {
     46    BString fName;
     47    BString fPath;
     48    image_id fAddOnImage;
     49    InstantiateCatalogFunc fInstantiateFunc;
     50    InstantiateEmbeddedCatalogFunc fInstantiateEmbeddedFunc;
     51    CreateCatalogFunc fCreateFunc;
     52    uint8 fPriority;
     53    BList fLoadedCatalogs;
     54    bool fIsEmbedded;
     55        // an embedded add-on actually isn't an add-on, it is included
     56        // as part of the library. The DefaultCatalog is such a beast!
     57
     58    BCatalogAddOnInfo(const BString& name, const BString& path, uint8 priority);
     59    ~BCatalogAddOnInfo();
     60    bool MakeSureItsLoaded();
     61    void UnloadIfPossible();
     62};
     63
     64
     65BCatalogAddOnInfo::BCatalogAddOnInfo(const BString& name, const BString& path,
     66    uint8 priority)
     67    :   
     68    fName(name),
     69    fPath(path),
     70    fAddOnImage(B_NO_INIT),
     71    fInstantiateFunc(NULL),
     72    fInstantiateEmbeddedFunc(NULL),
     73    fCreateFunc(NULL),
     74    fPriority(priority),
     75    fIsEmbedded(path.Length()==0)
     76{
     77}
     78
     79
     80BCatalogAddOnInfo::~BCatalogAddOnInfo()
     81{
     82    int32 count = fLoadedCatalogs.CountItems();
     83    for (int32 i=0; i<count; ++i) {
     84        BCatalogAddOn* cat
     85            = static_cast<BCatalogAddOn*>(fLoadedCatalogs.ItemAt(i));
     86        delete cat;
     87    }
     88    fLoadedCatalogs.MakeEmpty();
     89    UnloadIfPossible();
     90}
     91   
     92
     93bool
     94BCatalogAddOnInfo::MakeSureItsLoaded()
     95{
     96    if (!fIsEmbedded && fAddOnImage < B_OK) {
     97        // add-on has not been loaded yet, so we try to load it:
     98        BString fullAddOnPath(fPath);
     99        fullAddOnPath << "/" << fName;
     100        fAddOnImage = load_add_on(fullAddOnPath.String());
     101        if (fAddOnImage >= B_OK) {
     102            get_image_symbol(fAddOnImage, "instantiate_catalog",
     103                B_SYMBOL_TYPE_TEXT, (void **)&fInstantiateFunc);
     104            get_image_symbol(fAddOnImage, "instantiate_embedded_catalog",
     105                B_SYMBOL_TYPE_TEXT, (void **)&fInstantiateEmbeddedFunc);
     106            get_image_symbol(fAddOnImage, "create_catalog",
     107                B_SYMBOL_TYPE_TEXT, (void **)&fCreateFunc);
     108            log_team(LOG_DEBUG, "catalog-add-on %s has been loaded",
     109                fName.String());
     110        } else {
     111            log_team(LOG_DEBUG, "could not load catalog-add-on %s (%s)",
     112                fName.String(), strerror(fAddOnImage));
     113            return false;
     114        }
     115    }
     116    return true;
     117}
     118
     119
     120void
     121BCatalogAddOnInfo::UnloadIfPossible()
     122{
     123    if (!fIsEmbedded && fLoadedCatalogs.IsEmpty()) {
     124        unload_add_on(fAddOnImage);
     125        fAddOnImage = B_NO_INIT;
     126        fInstantiateFunc = NULL;
     127        fInstantiateEmbeddedFunc = NULL;
     128        fCreateFunc = NULL;
     129        log_team(LOG_DEBUG, "catalog-add-on %s has been unloaded",
     130            fName.String());
     131    }
     132}
     133
     134
     135/*
     136 * the global data that is shared between all roster-objects:
     137 */
     138struct RosterData {
     139    BLocker fLock;
     140    BList fCatalogAddOnInfos;
     141    BMessage fPreferredLanguages;
     142    //
     143    RosterData();
     144    ~RosterData();
     145    void InitializeCatalogAddOns();
     146    void CleanupCatalogAddOns();
     147    static int CompareInfos(const void *left, const void *right);
     148};
     149static RosterData gRosterData;
     150
     151
     152RosterData::RosterData()
     153    :
     154    fLock("LocaleRosterData")
     155{
     156    BAutolock lock(fLock);
     157    assert(lock.IsLocked());
     158
     159    // ToDo: make a decision about log-facility and -options
     160    openlog_team("liblocale.so", LOG_PID, LOG_USER);
     161#ifndef DEBUG
     162    // ToDo: find out why the following bugger isn't working!
     163    setlogmask_team(LOG_UPTO(LOG_WARNING));
     164#endif
     165
     166    InitializeCatalogAddOns();
     167
     168    // ToDo: change this to fetch preferred languages from prefs
     169    fPreferredLanguages.AddString("language", "german-swiss");
     170    fPreferredLanguages.AddString("language", "german");
     171    fPreferredLanguages.AddString("language", "english");
     172}
     173
     174
     175RosterData::~RosterData()
     176{
     177    BAutolock lock(fLock);
     178    assert(lock.IsLocked());
     179    CleanupCatalogAddOns();
     180    closelog();
     181}
     182
     183
     184int
     185RosterData::CompareInfos(const void *left, const void *right)
     186{
     187    return ((BCatalogAddOnInfo*)right)->fPriority
     188        - ((BCatalogAddOnInfo*)left)->fPriority;
     189}
     190
     191
     192/*
     193 * iterate over add-on-folders and collect information about each
     194 * catalog-add-ons (types of catalogs) into fCatalogAddOnInfos.
     195 */
     196void
     197RosterData::InitializeCatalogAddOns()
     198{
     199    BAutolock lock(fLock);
     200    assert(lock.IsLocked());
     201
     202    // add info about embedded default catalog:
     203    BCatalogAddOnInfo *defaultCatalogAddOnInfo
     204        = new BCatalogAddOnInfo("Default", "",
     205             DefaultCatalog::kDefaultCatalogAddOnPriority);
     206    defaultCatalogAddOnInfo->fInstantiateFunc = DefaultCatalog::Instantiate;
     207    defaultCatalogAddOnInfo->fInstantiateEmbeddedFunc
     208        = DefaultCatalog::InstantiateEmbedded;
     209    defaultCatalogAddOnInfo->fCreateFunc = DefaultCatalog::Create;
     210    fCatalogAddOnInfos.AddItem((void*)defaultCatalogAddOnInfo);
     211
     212    directory_which folders[] = {
     213        B_COMMON_ADDONS_DIRECTORY,
     214        B_BEOS_ADDONS_DIRECTORY,
     215        static_cast<directory_which>(-1)
     216    };
     217    BPath addOnPath;
     218    BDirectory addOnFolder;
     219    char buf[4096];
     220    status_t err;
     221    for (int f=0; folders[f]>=0; ++f) {
     222        find_directory(folders[f], &addOnPath);
     223        BString addOnFolderName(addOnPath.Path());
     224        addOnFolderName << "/locale/catalogs";
     225        err = addOnFolder.SetTo(addOnFolderName.String());
     226        if (err != B_OK)
     227            continue;
     228
     229        // scan through all the folder's entries for catalog add-ons:
     230        int32 count;
     231        int8 priority;
     232        entry_ref eref;
     233        BNode node;
     234        BEntry entry;
     235        dirent *dent;
     236        while ((count = addOnFolder.GetNextDirents((dirent *)buf, 4096)) > 0) {
     237            dent = (dirent *)buf;
     238            while (count-- > 0) {
     239                if (strcmp(dent->d_name, ".") && strcmp(dent->d_name, "..")) {
     240                    // we have found (what should be) a catalog-add-on:
     241                    eref.device = dent->d_pdev;
     242                    eref.directory = dent->d_pino;
     243                    eref.set_name(dent->d_name);
     244                    entry.SetTo(&eref, true);
     245                        // traverse through any links to get to the real thang!
     246                    node.SetTo(&entry);
     247                    priority = -1;
     248                    if (node.ReadAttr(kPriorityAttr, B_INT8_TYPE, 0,
     249                        &priority, sizeof(int8)) <= 0) {
     250                        // add-on has no priority-attribute yet, so we load it to
     251                        // fetch the priority from the corresponding symbol...
     252                        BString fullAddOnPath(addOnFolderName);
     253                        fullAddOnPath << "/" << dent->d_name;
     254                        image_id image = load_add_on(fullAddOnPath.String());
     255                        if (image >= B_OK) {
     256                            uint8 *prioPtr;
     257                            if (get_image_symbol(image, "gCatalogAddOnPriority",
     258                                B_SYMBOL_TYPE_TEXT,
     259                                (void **)&prioPtr) == B_OK) {
     260                                priority = *prioPtr;
     261                                node.WriteAttr(kPriorityAttr, B_INT8_TYPE, 0,
     262                                    &priority, sizeof(int8));
     263                            }
     264                            unload_add_on(image);
     265                        } else {
     266                            log_team(LOG_ERR,
     267                                "couldn't load add-on %s, error: %s\n",
     268                                fullAddOnPath.String(), strerror(image));
     269                        }
     270                    }
     271                    if (priority >= 0) {
     272                        // add-ons with priority<0 will be ignored
     273                        fCatalogAddOnInfos.AddItem(
     274                            (void*)new BCatalogAddOnInfo(dent->d_name,
     275                                addOnFolderName, priority)
     276                        );
     277                    }
     278                }
     279                // Bump the dirent-pointer by length of the dirent just handled:
     280                dent = (dirent *)((char *)dent + dent->d_reclen);
     281            }
     282        }
     283    }
     284    fCatalogAddOnInfos.SortItems(CompareInfos);
     285
     286    for (int32 i=0; i<fCatalogAddOnInfos.CountItems(); ++i) {
     287        BCatalogAddOnInfo *info
     288            = static_cast<BCatalogAddOnInfo*>(fCatalogAddOnInfos.ItemAt(i));
     289        log_team(LOG_INFO,
     290            "roster uses catalog-add-on %s/%s with priority %d",
     291            info->fIsEmbedded ? "(embedded)" : info->fPath.String(),
     292            info->fName.String(), info->fPriority);
     293    }
     294}
     295
     296
     297/*
     298 * unloads all catalog-add-ons (which will throw away all loaded catalogs, too)
     299 */
     300void
     301RosterData::CleanupCatalogAddOns()
     302{
     303    BAutolock lock(fLock);
     304    assert(lock.IsLocked());
     305    int32 count = fCatalogAddOnInfos.CountItems();
     306    for (int32 i=0; i<count; ++i) {
     307        BCatalogAddOnInfo *info
     308            = static_cast<BCatalogAddOnInfo*>(fCatalogAddOnInfos.ItemAt(i));
     309        delete info;
     310    }
     311    fCatalogAddOnInfos.MakeEmpty();
     312}
     313
     314
     315/*
     316 * several attributes/resource-IDs used within the Locale Kit:
     317 */
     318const char *BLocaleRoster::kCatLangAttr = "BEOS:LOCALE_LANGUAGE";
     319    // name of catalog language, lives in every catalog file
     320const char *BLocaleRoster::kCatSigAttr = "BEOS:LOCALE_SIGNATURE";
     321    // catalog signature, lives in every catalog file
     322const char *BLocaleRoster::kCatFingerprintAttr = "BEOS:LOCALE_FINGERPRINT";
     323    // catalog fingerprint, may live in catalog file
     324
     325const char *BLocaleRoster::kCatManagerMimeType
     326    = "application/x-vnd.Be.locale.catalog-manager";
     327    // signature of catalog managing app
     328const char *BLocaleRoster::kCatEditorMimeType
     329    = "application/x-vnd.Be.locale.catalog-editor";
     330    // signature of catalog editor app
     331
     332const char *BLocaleRoster::kEmbeddedCatAttr = "BEOS:LOCALE_EMBEDDED_CATALOG";
     333    // attribute which contains flattened data of embedded catalog
     334    // this may live in an app- or add-on-file
     335int32 BLocaleRoster::kEmbeddedCatResId = 0xCADA;
     336    // a unique value used to identify the resource (=> embedded CAtalog DAta)
     337    // which contains flattened data of embedded catalog.
     338    // this may live in an app- or add-on-file
     339
     340/*
     341 * BLocaleRoster, the exported interface to the locale roster data:
     342 */
     343BLocaleRoster::BLocaleRoster()
     344{
     345}
     346
     347
     348BLocaleRoster::~BLocaleRoster()
     349{
     350}
     351
     352
     353status_t
     354BLocaleRoster::GetDefaultCollator(BCollator **collator) const
     355{
     356    // It should just use the archived collator from the locale settings;
     357    // if that is not available, just return the standard collator
     358    if (!collator)
     359        return B_BAD_VALUE;
     360    *collator = new BCollator();
     361    return B_OK;
     362}
     363
     364
     365status_t
     366BLocaleRoster::GetDefaultLanguage(BLanguage **language) const
     367{
     368    if (!language)
     369        return B_BAD_VALUE;
     370    *language = new BLanguage(NULL);
     371    return B_OK;
     372}
     373
     374
     375status_t
     376BLocaleRoster::GetDefaultCountry(BCountry **country) const
     377{
     378    if (!country)
     379        return B_BAD_VALUE;
     380    *country = new BCountry();
     381    return B_OK;
     382}
     383
     384
     385status_t
     386BLocaleRoster::GetPreferredLanguages(BMessage *languages) const
     387{
     388    if (!languages)
     389        return B_BAD_VALUE;
     390
     391    BAutolock lock(gRosterData.fLock);
     392    assert(lock.IsLocked());
     393
     394    *languages = gRosterData.fPreferredLanguages;
     395    return B_OK;
     396}
     397
     398
     399status_t
     400BLocaleRoster::SetPreferredLanguages(BMessage *languages)
     401{
     402    BAutolock lock(gRosterData.fLock);
     403    assert(lock.IsLocked());
     404
     405    if (languages)
     406        gRosterData.fPreferredLanguages = *languages;
     407    else
     408        gRosterData.fPreferredLanguages.MakeEmpty();
     409    return B_OK;
     410}
     411
     412
     413/*
     414 * creates a new (empty) catalog of the given type (the request is dispatched
     415 * to the appropriate add-on).
     416 * If the add-on doesn't support catalog-creation or if the creation fails,
     417 * NULL is returned, otherwise a pointer to the freshly created catalog.
     418 * Any created catalog will be initialized with the given signature and
     419 * language-name.
     420 */
     421BCatalogAddOn*
     422BLocaleRoster::CreateCatalog(const char *type, const char *signature,
     423    const char *language)
     424{
     425    if (!type || !signature || !language)
     426        return NULL;
     427
     428    BAutolock lock(gRosterData.fLock);
     429    assert(lock.IsLocked());
     430
     431    int32 count = gRosterData.fCatalogAddOnInfos.CountItems();
     432    for (int32 i=0; i<count; ++i) {
     433        BCatalogAddOnInfo *info
     434            = (BCatalogAddOnInfo*)gRosterData.fCatalogAddOnInfos.ItemAt(i);
     435        if (info->fName.ICompare(type)!=0 || !info->MakeSureItsLoaded()
     436            || !info->fCreateFunc)
     437            continue;
     438
     439        BCatalogAddOn *catalog = info->fCreateFunc(signature, language);
     440        if (catalog) {
     441            info->fLoadedCatalogs.AddItem(catalog);
     442            info->UnloadIfPossible();
     443            return catalog;
     444        }
     445    }
     446
     447    return NULL;
     448}
     449
     450
     451/*
     452 * Loads a catalog for the given signature, language and fingerprint.
     453 * The request to load this catalog is dispatched to all add-ons in turn,
     454 * until an add-on reports success.
     455 * If a catalog depends on another language (as 'english-british' depends
     456 * on 'english') the dependant catalogs are automatically loaded, too.
     457 * So it is perfectly possible that this method returns a catalog-chain
     458 * instead of a single catalog.
     459 * NULL is returned if no matching catalog could be found.
     460 */
     461BCatalogAddOn*
     462BLocaleRoster::LoadCatalog(const char *signature, const char *language,
     463    int32 fingerprint)
     464{
     465    if (!signature)
     466        return NULL;
     467
     468    BAutolock lock(gRosterData.fLock);
     469    assert(lock.IsLocked());
     470
     471    int32 count = gRosterData.fCatalogAddOnInfos.CountItems();
     472    for (int32 i=0; i<count; ++i) {
     473        BCatalogAddOnInfo *info
     474            = (BCatalogAddOnInfo*)gRosterData.fCatalogAddOnInfos.ItemAt(i);
     475
     476        if (!info->MakeSureItsLoaded() || !info->fInstantiateFunc)
     477            continue;
     478        BMessage languages;
     479        if (language)
     480            // try to load catalogs for the given language:
     481            languages.AddString("language", language);
     482        else
     483            // try to load catalogs for one of the preferred languages:
     484            GetPreferredLanguages(&languages);
     485
     486        BCatalogAddOn *catalog = NULL;
     487        const char *lang;
     488        for (int32 l=0; languages.FindString("language", l, &lang)==B_OK; ++l) {
     489            catalog = info->fInstantiateFunc(signature, lang, fingerprint);
     490            if (catalog) {
     491                info->fLoadedCatalogs.AddItem(catalog);
     492#if 0           
     493                // Chain-loading of catalogs has been disabled, as with the
     494                // current way of handling languages (there are no general
     495                // languages like 'English', but only specialized ones, like
     496                // 'English-american') it does not make sense...
     497                //
     498                // Chain-load catalogs for languages that depend on
     499                // other languages.
     500                // The current implementation uses the filename in order to
     501                // detect dependencies (parenthood) between languages (it
     502                // traverses from "english-british-oxford" to "english-british"
     503                // to "english"):
     504                int32 pos;
     505                BString langName(lang);
     506                BCatalogAddOn *currCatalog=catalog, *nextCatalog;
     507                while ((pos = langName.FindLast('-')) >= 0) {
     508                    // language is based on parent, so we load that, too:
     509                    langName.Truncate(pos);
     510                    nextCatalog = info->fInstantiateFunc(signature,
     511                        langName.String(), fingerprint);
     512                    if (nextCatalog) {
     513                        info->fLoadedCatalogs.AddItem(nextCatalog);
     514                        currCatalog->fNext = nextCatalog;
     515                        currCatalog = nextCatalog;
     516                    }
     517                }
     518#endif
     519                return catalog;
     520            }
     521        }
     522        info->UnloadIfPossible();
     523    }
     524
     525    return NULL;
     526}
     527
     528
     529/*
     530 * Loads an embedded catalog from the given entry-ref (which is usually an
     531 * app- or add-on-file. The request to load the catalog is dispatched to all
     532 * add-ons in turn, until an add-on reports success.
     533 * NULL is returned if no embedded catalog could be found.
     534 */
     535BCatalogAddOn*
     536BLocaleRoster::LoadEmbeddedCatalog(entry_ref *appOrAddOnRef)
     537{
     538    if (!appOrAddOnRef)
     539        return NULL;
     540
     541    BAutolock lock(gRosterData.fLock);
     542    assert(lock.IsLocked());
     543
     544    int32 count = gRosterData.fCatalogAddOnInfos.CountItems();
     545    for (int32 i=0; i<count; ++i) {
     546        BCatalogAddOnInfo *info
     547            = (BCatalogAddOnInfo*)gRosterData.fCatalogAddOnInfos.ItemAt(i);
     548
     549        if (!info->MakeSureItsLoaded() || !info->fInstantiateEmbeddedFunc)
     550            continue;
     551
     552        BCatalogAddOn *catalog = NULL;
     553        catalog = info->fInstantiateEmbeddedFunc(appOrAddOnRef);
     554        if (catalog) {
     555            info->fLoadedCatalogs.AddItem(catalog);
     556            return catalog;
     557        }
     558        info->UnloadIfPossible();
     559    }
     560
     561    return NULL;
     562}
     563
     564
     565/*
     566 * unloads the given catalog (or rather: catalog-chain).
     567 * Every single catalog of the chain will be deleted automatically.
     568 * Add-ons that have no more current catalogs are unloaded, too.
     569 */
     570status_t
     571BLocaleRoster::UnloadCatalog(BCatalogAddOn *catalog)
     572{
     573    if (!catalog)
     574        return B_BAD_VALUE;
     575
     576    BAutolock lock(gRosterData.fLock);
     577    assert(lock.IsLocked());
     578
     579    status_t res = B_ERROR;
     580    BCatalogAddOn *nextCatalog;
     581    // note: as we currently aren't chainloading catalogs, there is only
     582    //       one catalog to unload...
     583    while (catalog) {
     584        nextCatalog = catalog->fNext;
     585        int32 count = gRosterData.fCatalogAddOnInfos.CountItems();
     586        for (int32 i=0; i<count; ++i) {
     587            BCatalogAddOnInfo *info
     588                = static_cast<BCatalogAddOnInfo*>(
     589                    gRosterData.fCatalogAddOnInfos.ItemAt(i)
     590                );
     591            if (info->fLoadedCatalogs.HasItem(catalog)) {
     592                info->fLoadedCatalogs.RemoveItem(catalog);
     593                delete catalog;
     594                info->UnloadIfPossible();
     595                res = B_OK;
     596            }
     597        }
     598        catalog = nextCatalog;
     599    }
     600    return res;
     601}
  • src/kits/locale/Locale.cpp

     
     1/*
     2** Copyright 2003, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
     3** Distributed under the terms of the OpenBeOS License.
     4*/
     5
     6
     7#include <Catalog.h>
     8#include <Locale.h>
     9#include <LocaleRoster.h>
     10
     11
     12static BLocale gLocale;
     13BLocale *be_locale = &gLocale;
     14
     15
     16BLocale::BLocale()
     17{
     18    BLocaleRoster roster;
     19    roster.GetDefaultCollator(&fCollator);
     20    roster.GetDefaultCountry(&fCountry);
     21    roster.GetDefaultLanguage(&fLanguage);
     22}
     23
     24
     25BLocale::~BLocale()
     26{
     27}
     28
     29
     30const char *
     31BLocale::GetString(uint32 id)
     32{
     33    // Note: this code assumes a certain order of the string bases
     34
     35    if (id >= B_OTHER_STRINGS_BASE) {
     36        if (id == B_CODESET)
     37            return "UTF-8";
     38
     39        return "";
     40    }
     41    if (id >= B_LANGUAGE_STRINGS_BASE)
     42        return fLanguage->GetString(id);
     43
     44    return fCountry->GetString(id);
     45}
     46
     47status_t
     48BLocale::GetAppCatalog(BCatalog *catalog) {
     49    if (!catalog)
     50        return B_BAD_VALUE;
     51    if (be_catalog)
     52        debugger( "GetAppCatalog() has been called while be_catalog != NULL");
     53    return BCatalog::GetAppCatalog(catalog);
     54}
  • src/kits/locale/NumberFormat.cpp

     
     1#include <NumberFormat.h>
     2#include <NumberFormatImpl.h>
     3
     4// copy constructor
     5BNumberFormat::BNumberFormat(const BNumberFormat &other)
     6    : BFormat(other)
     7{
     8}
     9
     10// destructor
     11BNumberFormat::~BNumberFormat()
     12{
     13}
     14
     15// =
     16BNumberFormat &
     17BNumberFormat::operator=(const BNumberFormat &other)
     18{
     19    BFormat::operator=(other);
     20    return *this;
     21}
     22
     23// constructor
     24BNumberFormat::BNumberFormat(BNumberFormatImpl *impl)
     25    : BFormat(impl)
     26{
     27}
     28
     29// NumberFormatImpl
     30inline
     31BNumberFormatImpl *
     32BNumberFormat::NumberFormatImpl() const
     33{
     34    return static_cast<BNumberFormatImpl*>(fImpl);
     35}
     36
  • src/kits/locale/FormatImpl.cpp

     
     1#include <FormatImpl.h>
     2
     3// constructor
     4BFormatImpl::BFormatImpl()
     5{
     6}
     7
     8// destructor
     9BFormatImpl::~BFormatImpl()
     10{
     11}
     12
  • src/kits/locale/FormatParameters.cpp

     
     1#include <FormatParameters.h>
     2
     3// defaults
     4static const format_alignment kDefaultAlignment = B_ALIGN_FORMAT_RIGHT;
     5static const size_t kDefaultFormatWidth = 1;
     6
     7// flags
     8enum {
     9    ALIGNMENT_SET   = 0x01,
     10    WIDTH_SET       = 0x02,
     11};
     12
     13// constructor
     14BFormatParameters::BFormatParameters(const BFormatParameters *parent)
     15    : fParent(parent),
     16      fFlags(0)
     17{
     18}
     19
     20// copy constructor
     21BFormatParameters::BFormatParameters(const BFormatParameters &other)
     22    : fParent(other.fParent),
     23      fAlignment(other.fAlignment),
     24      fWidth(other.fWidth),
     25      fFlags(other.fFlags)
     26{
     27}
     28
     29// destructor
     30BFormatParameters::~BFormatParameters()
     31{
     32}
     33
     34// SetAlignment
     35void
     36BFormatParameters::SetAlignment(format_alignment alignment)
     37{
     38    fAlignment = alignment;
     39    fFlags |= ALIGNMENT_SET;
     40}
     41
     42// Alignment
     43format_alignment
     44BFormatParameters::Alignment() const
     45{
     46    if (fFlags & ALIGNMENT_SET)
     47        return fAlignment;
     48    if (fParent)
     49        return fParent->Alignment();
     50    return kDefaultAlignment;
     51}
     52
     53// SetFormatWidth
     54void
     55BFormatParameters::SetFormatWidth(size_t width)
     56{
     57    fWidth = width;
     58    fFlags |= WIDTH_SET;
     59}
     60
     61// FormatWidth
     62size_t
     63BFormatParameters::FormatWidth() const
     64{
     65    if (fFlags & WIDTH_SET)
     66        return fWidth;
     67    if (fParent)
     68        return fParent->FormatWidth();
     69    return kDefaultFormatWidth;
     70}
     71
     72// SetParentParameters
     73void
     74BFormatParameters::SetParentParameters(const BFormatParameters *parent)
     75{
     76    fParent = parent;
     77}
     78
     79// ParentParameters
     80const BFormatParameters *
     81BFormatParameters::ParentParameters() const
     82{
     83    return fParent;
     84}
     85
     86// =
     87BFormatParameters &
     88BFormatParameters::operator=(const BFormatParameters &other)
     89{
     90    fParent = other.fParent;
     91    fAlignment = other.fAlignment;
     92    fWidth = other.fWidth;
     93    fFlags = other.fFlags;
     94    return *this;
     95}
     96
  • src/kits/locale/DefaultCatalog.cpp

     
     1/*
     2 * Copyright 2003, Oliver Tappe, zooey@hirschkaefer.de. All rights reserved.
     3 * Distributed under the terms of the MIT License.
     4 */
     5
     6
     7#include <algorithm>
     8#include <memory>
     9#include <syslog.h>
     10
     11#include <Application.h>
     12#include <DataIO.h>
     13#include <Directory.h>
     14#include <File.h>
     15#include <FindDirectory.h>
     16#include <fs_attr.h>
     17#include <Message.h>
     18#include <Mime.h>
     19#include <Path.h>
     20#include <Resources.h>
     21#include <Roster.h>
     22
     23#include <DefaultCatalog.h>
     24#include <LocaleRoster.h>
     25
     26#include <cstdio>
     27
     28/*
     29 *  This file implements the default catalog-type for the opentracker locale kit.
     30 *  Alternatively, this could be used as a full add-on, but currently this
     31 *  is provided as part of liblocale.so.
     32 */
     33
     34extern "C" uint32 adler32(uint32 adler, const uint8 *buf, uint32 len);
     35    // definition lives in adler32.c
     36
     37#if B_BEOS_VERSION <= B_BEOS_VERSION_5 && !defined(__HAIKU__)
     38// B_BAD_DATA was introduced with DANO, so we define it for R5:
     39#   define B_BAD_DATA -2147483632L
     40#endif
     41
     42
     43/*
     44 * CatKey
     45 */
     46size_t hash<CatKey>::operator()(const CatKey &key) const
     47{
     48    return key.fHashVal;
     49}
     50
     51
     52static const char kSeparator = '\01';
     53
     54
     55CatKey::CatKey(const char *str, const char *ctx, const char *cmt)
     56    :
     57    fFlags(0)
     58{
     59    uint32 strLen = str ? strlen(str) : 0;
     60    uint32 ctxLen = ctx ? strlen(ctx) : 0;
     61    uint32 cmtLen = cmt ? strlen(cmt) : 0;
     62    int32 keyLen = strLen + ctxLen + cmtLen + 2;
     63    char *keyBuf = fKey.LockBuffer(keyLen);
     64    if (!keyBuf)
     65        return;
     66    if (strLen) {
     67        memcpy(keyBuf, str, strLen);
     68        keyBuf += strLen;
     69    }
     70    *keyBuf++ = kSeparator;
     71    if (ctxLen) {
     72        memcpy(keyBuf, ctx, ctxLen);
     73        keyBuf += ctxLen;
     74    }
     75    *keyBuf++ = kSeparator;
     76    if (cmtLen) {
     77        memcpy(keyBuf, cmt, cmtLen);
     78        keyBuf += cmtLen;
     79    }
     80    *keyBuf = '\0';
     81    fKey.UnlockBuffer(keyLen);
     82    fHashVal = HashFun(fKey.String());
     83}
     84
     85
     86CatKey::CatKey(uint32 id)
     87    :
     88    fHashVal(id),
     89    fFlags(0)
     90{
     91}
     92
     93
     94CatKey::CatKey()
     95    :
     96    fHashVal(0),
     97    fFlags(0)
     98{
     99}
     100
     101
     102bool
     103CatKey::operator== (const CatKey& right) const
     104{
     105    // Two keys are equal if their hashval and key (string,context,comment)
     106    // are equal:
     107    return fHashVal == right.fHashVal
     108        && fKey == right.fKey;
     109}
     110
     111
     112status_t
     113CatKey::GetStringParts(BString* str, BString* ctx, BString* cmt) const
     114{
     115    int32 pos1 = fKey.FindFirst(kSeparator);
     116    if (pos1 < B_OK) {
     117        if (str)
     118            str->SetTo(fKey);
     119        if (ctx)
     120            ctx->Truncate(0);
     121        if (cmt)
     122            cmt->Truncate(0);
     123    } else {
     124        if (str)
     125            fKey.CopyInto(*str, 0, pos1);
     126        int32 pos2 = fKey.FindFirst(kSeparator, pos1+1);
     127        if (pos2 < B_OK) {
     128            if (ctx)
     129                ctx->SetTo(fKey, pos1+1);
     130            if (cmt)
     131                cmt->Truncate(0);
     132        } else {
     133            if (ctx)
     134                fKey.CopyInto(*ctx, pos1+1, pos2-pos1-1);
     135            if (cmt)
     136                cmt->SetTo(fKey.String()+pos2+1);
     137        }
     138    }
     139
     140    return B_OK;
     141}
     142
     143
     144size_t CatKey::HashFun(const char* s) {
     145    unsigned long h = 0;
     146    for ( ; *s; ++s)
     147        h = 5*h + *s;
     148
     149    return size_t(h);
     150}
     151
     152
     153static const char *kCatFolder = "catalogs";
     154static const char *kCatExtension = ".catalog";
     155
     156const char *DefaultCatalog::kCatMimeType
     157    = "locale/x-vnd.Be.locale-catalog.default";
     158
     159static int16 kCatArchiveVersion = 1;
     160    // version of the catalog archive structure, bump this if you change it!
     161
     162
     163/*
     164 * constructs a DefaultCatalog with given signature and language and reads
     165 * the catalog from disk.
     166 * InitCheck() will be B_OK if catalog could be loaded successfully, it will
     167 * give an appropriate error-code otherwise.
     168 */
     169DefaultCatalog::DefaultCatalog(const char *signature, const char *language,
     170    int32 fingerprint)
     171    :
     172    BCatalogAddOn(signature, language, fingerprint)
     173{
     174    // give highest priority to catalog living in sub-folder of app's folder:
     175    app_info appInfo;
     176    be_app->GetAppInfo(&appInfo);
     177    node_ref nref;
     178    nref.device = appInfo.ref.device;
     179    nref.node = appInfo.ref.directory;
     180    BDirectory appDir(&nref);
     181    BString catalogName("locale/");
     182    catalogName << kCatFolder
     183        << "/" << fSignature
     184        << "/" << fLanguageName
     185        << kCatExtension;
     186    BPath catalogPath(&appDir, catalogName.String());
     187    status_t status = ReadFromFile(catalogPath.Path());
     188
     189    if (status != B_OK) {
     190        // look in common-etc folder (/boot/home/config/etc):
     191        BPath commonEtcPath;
     192        find_directory(B_COMMON_ETC_DIRECTORY, &commonEtcPath);
     193        if (commonEtcPath.InitCheck() == B_OK) {
     194            catalogName = BString(commonEtcPath.Path())
     195                            << "/locale/" << kCatFolder
     196                            << "/" << fSignature
     197                            << "/" << fLanguageName
     198                            << kCatExtension;
     199            status = ReadFromFile(catalogName.String());
     200        }
     201    }
     202
     203    if (status != B_OK) {
     204        // look in system-etc folder (/boot/beos/etc):
     205        BPath systemEtcPath;
     206        find_directory(B_BEOS_ETC_DIRECTORY, &systemEtcPath);
     207        if (systemEtcPath.InitCheck() == B_OK) {
     208            catalogName = BString(systemEtcPath.Path())
     209                            << "/locale/" << kCatFolder
     210                            << "/" << fSignature
     211                            << "/" << fLanguageName
     212                            << kCatExtension;
     213            status = ReadFromFile(catalogName.String());
     214        }
     215    }
     216
     217    fInitCheck = status;
     218    log_team(LOG_DEBUG,
     219        "trying to load default-catalog(sig=%s, lang=%s) results in %s",
     220        signature, language, strerror(fInitCheck));
     221}
     222
     223
     224/*
     225 * constructs a DefaultCatalog and reads it from the resources of the
     226 * given entry-ref (which usually is an app- or add-on-file).
     227 * InitCheck() will be B_OK if catalog could be loaded successfully, it will
     228 * give an appropriate error-code otherwise.
     229 */
     230DefaultCatalog::DefaultCatalog(entry_ref *appOrAddOnRef)
     231    :
     232    BCatalogAddOn("", "", 0)
     233{
     234    fInitCheck = ReadFromResource(appOrAddOnRef);
     235    log_team(LOG_DEBUG,
     236        "trying to load embedded catalog from resources results in %s",
     237        strerror(fInitCheck));
     238}
     239
     240
     241/*
     242 * constructs an empty DefaultCatalog with given sig and language.
     243 * This is used for editing/testing purposes.
     244 * InitCheck() will always be B_OK.
     245 */
     246DefaultCatalog::DefaultCatalog(const char *path, const char *signature,
     247    const char *language)
     248    :
     249    BCatalogAddOn(signature, language, 0),
     250    fPath(path)
     251{
     252    fInitCheck = B_OK;
     253}
     254
     255
     256DefaultCatalog::~DefaultCatalog()
     257{
     258}
     259
     260
     261status_t
     262DefaultCatalog::ReadFromFile(const char *path)
     263{
     264    if (!path)
     265        path = fPath.String();
     266
     267    BFile catalogFile;
     268    status_t res = catalogFile.SetTo(path, B_READ_ONLY);
     269    if (res != B_OK) {
     270        log_team(LOG_DEBUG, "no catalog at %s", path);
     271        return B_ENTRY_NOT_FOUND;
     272    }
     273
     274    fPath = path;
     275    log_team(LOG_DEBUG, "found catalog at %s", path);
     276
     277    off_t sz = 0;
     278    res = catalogFile.GetSize(&sz);
     279    if (res != B_OK) {
     280        log_team(LOG_ERR, "couldn't get size for catalog-file %s", path);
     281        return res;
     282    }
     283   
     284        std::auto_ptr<char> buf(new char [sz]);
     285    res = catalogFile.Read(buf.get(), sz);
     286    if (res < B_OK) {
     287        log_team(LOG_ERR, "couldn't read from catalog-file %s", path);
     288        return res;
     289    }
     290    if (res < sz) {
     291        log_team(LOG_ERR, "only got %lu instead of %Lu bytes from catalog-file %s",
     292            res, sz, path);
     293        return res;
     294    }
     295    BMemoryIO memIO(buf.get(), sz);
     296    res = Unflatten(&memIO);
     297
     298    if (res == B_OK) {
     299        // some information living in member variables needs to be copied
     300        // to attributes. Although these attributes should have been written
     301        // when creating the catalog, we make sure that they exist there:
     302        UpdateAttributes(catalogFile);
     303    }
     304
     305    return res;
     306}
     307
     308
     309/*
     310 * this method is not currently being used, but it may be useful in the future...
     311 */
     312status_t
     313DefaultCatalog::ReadFromAttribute(entry_ref *appOrAddOnRef)
     314{
     315    BNode node;
     316    status_t res = node.SetTo(appOrAddOnRef);
     317    if (res != B_OK) {
     318        log_team(LOG_ERR, "couldn't find app or add-on (dev=%lu, dir=%Lu, name=%s)",
     319            appOrAddOnRef->device, appOrAddOnRef->directory,
     320            appOrAddOnRef->name);
     321        return B_ENTRY_NOT_FOUND;
     322    }
     323
     324    log_team(LOG_DEBUG,
     325        "looking for embedded catalog-attribute in app/add-on"
     326        "(dev=%lu, dir=%Lu, name=%s)", appOrAddOnRef->device,
     327        appOrAddOnRef->directory, appOrAddOnRef->name);
     328
     329    attr_info attrInfo;
     330    res = node.GetAttrInfo(BLocaleRoster::kEmbeddedCatAttr, &attrInfo);
     331    if (res != B_OK) {
     332        log_team(LOG_DEBUG, "no embedded catalog found");
     333        return B_NAME_NOT_FOUND;
     334    }
     335    if (attrInfo.type != B_MESSAGE_TYPE) {
     336        log_team(LOG_ERR, "attribute %s has incorrect type and is ignored!",
     337            BLocaleRoster::kEmbeddedCatAttr);
     338        return B_BAD_TYPE;
     339    }
     340
     341    size_t size = attrInfo.size;
     342        std::auto_ptr<char> buf(new char [size]);
     343    res = node.ReadAttr(BLocaleRoster::kEmbeddedCatAttr, B_MESSAGE_TYPE, 0,
     344        buf.get(), size);
     345    if (res < (ssize_t)size) {
     346        log_team(LOG_ERR, "unable to read embedded catalog from attribute");
     347        return res < B_OK ? res : B_BAD_DATA;
     348    }
     349
     350    BMemoryIO memIO(buf.get(), size);
     351    res = Unflatten(&memIO);
     352
     353    return res;
     354}
     355
     356
     357status_t
     358DefaultCatalog::ReadFromResource(entry_ref *appOrAddOnRef)
     359{
     360    BFile file;
     361    status_t res = file.SetTo(appOrAddOnRef, B_READ_ONLY);
     362    if (res != B_OK) {
     363        log_team(LOG_ERR, "couldn't find app or add-on (dev=%lu, dir=%Lu, name=%s)",
     364            appOrAddOnRef->device, appOrAddOnRef->directory,
     365            appOrAddOnRef->name);
     366        return B_ENTRY_NOT_FOUND;
     367    }
     368
     369    log_team(LOG_DEBUG,
     370        "looking for embedded catalog-resource in app/add-on"
     371        "(dev=%lu, dir=%Lu, name=%s)", appOrAddOnRef->device,
     372        appOrAddOnRef->directory, appOrAddOnRef->name);
     373
     374    BResources rsrc;
     375    res = rsrc.SetTo(&file);
     376    if (res != B_OK) {
     377        log_team(LOG_DEBUG, "file has no resources");
     378        return res;
     379    }
     380
     381    size_t sz;
     382    const void *buf = rsrc.LoadResource(B_MESSAGE_TYPE,
     383        BLocaleRoster::kEmbeddedCatResId, &sz);
     384    if (!buf) {
     385        log_team(LOG_DEBUG, "file has no catalog-resource");
     386        return B_NAME_NOT_FOUND;
     387    }
     388
     389    BMemoryIO memIO(buf, sz);
     390    res = Unflatten(&memIO);
     391
     392    return res;
     393}
     394
     395
     396status_t
     397DefaultCatalog::WriteToFile(const char *path)
     398{
     399    BFile catalogFile;
     400    if (path)
     401        fPath = path;
     402    status_t res = catalogFile.SetTo(fPath.String(),
     403        B_WRITE_ONLY | B_CREATE_FILE | B_ERASE_FILE);
     404    if (res != B_OK)
     405        return res;
     406
     407    BMallocIO mallocIO;
     408    mallocIO.SetBlockSize(std::max(fCatMap.size()*20, 256LU));
     409        // set a largish block-size in order to avoid reallocs
     410    res = Flatten(&mallocIO);
     411    if (res == B_OK) {
     412        ssize_t wsz;
     413        wsz = catalogFile.Write(mallocIO.Buffer(), mallocIO.BufferLength());
     414        if (wsz != (ssize_t)mallocIO.BufferLength())
     415            return B_FILE_ERROR;
     416
     417        // set mimetype-, language- and signature-attributes:
     418        UpdateAttributes(catalogFile);
     419        // finally write fingerprint:
     420        catalogFile.WriteAttr(BLocaleRoster::kCatFingerprintAttr, B_INT32_TYPE,
     421            0, &fFingerprint, sizeof(int32));
     422    }
     423    if (res == B_OK)
     424        UpdateAttributes(catalogFile); 
     425    return res;
     426}
     427
     428
     429/*
     430 * this method is not currently being used, but it may be useful in the future...
     431 */
     432status_t
     433DefaultCatalog::WriteToAttribute(entry_ref *appOrAddOnRef)
     434{
     435    BNode node;
     436    status_t res = node.SetTo(appOrAddOnRef);
     437    if (res != B_OK)
     438        return res;
     439       
     440    BMallocIO mallocIO;
     441    mallocIO.SetBlockSize(std::max(fCatMap.size()*20, 256LU));
     442        // set a largish block-size in order to avoid reallocs
     443    res = Flatten(&mallocIO);
     444
     445    if (res == B_OK) {
     446        ssize_t wsz;
     447        wsz = node.WriteAttr(BLocaleRoster::kEmbeddedCatAttr, B_MESSAGE_TYPE, 0,
     448            mallocIO.Buffer(), mallocIO.BufferLength());
     449        if (wsz < B_OK)
     450            res = wsz;
     451        else if (wsz != (ssize_t)mallocIO.BufferLength())
     452            res = B_ERROR;
     453    }
     454    return res;
     455}
     456
     457
     458status_t
     459DefaultCatalog::WriteToResource(entry_ref *appOrAddOnRef)
     460{
     461    BFile file;
     462    status_t res = file.SetTo(appOrAddOnRef, B_READ_WRITE);
     463    if (res != B_OK)
     464        return res;
     465
     466    BResources rsrc;
     467    res = rsrc.SetTo(&file);
     468    assert(res == B_OK);
     469    if (res != B_OK)
     470        return res;
     471
     472    BMallocIO mallocIO;
     473    mallocIO.SetBlockSize(std::max(fCatMap.size()*20, 256LU));
     474        // set a largish block-size in order to avoid reallocs
     475    res = Flatten(&mallocIO);
     476    assert(res == B_OK);
     477
     478    if (res == B_OK)
     479        res = rsrc.AddResource(B_MESSAGE_TYPE, BLocaleRoster::kEmbeddedCatResId,
     480            mallocIO.Buffer(), mallocIO.BufferLength(), "embedded catalog");
     481
     482    assert(res == B_OK);
     483    return res;
     484}
     485
     486
     487void
     488DefaultCatalog::MakeEmpty()
     489{
     490    fCatMap.clear();
     491}
     492
     493
     494int32
     495DefaultCatalog::CountItems() const
     496{
     497    return fCatMap.size();
     498}
     499
     500
     501const char *
     502DefaultCatalog::GetString(const char *string, const char *context,
     503    const char *comment)
     504{
     505    CatKey key(string, context, comment);
     506    return GetString(key);
     507}
     508
     509
     510const char *
     511DefaultCatalog::GetString(uint32 id)
     512{
     513    CatKey key(id);
     514    return GetString(key);
     515}
     516
     517
     518const char *
     519DefaultCatalog::GetString(const CatKey& key)
     520{
     521    CatMap::const_iterator iter = fCatMap.find(key);
     522    if (iter != fCatMap.end())
     523        return iter->second.String();
     524    else
     525        return NULL;
     526}
     527
     528
     529status_t
     530DefaultCatalog::SetString(const char *string, const char *translated,
     531    const char *context, const char *comment)
     532{
     533    CatKey key(string, context, comment);
     534    fCatMap[key] = translated;
     535        // overwrite existing element
     536    return B_OK;
     537}
     538
     539
     540status_t
     541DefaultCatalog::SetString(int32 id, const char *translated)
     542{
     543    CatKey key(id);
     544    fCatMap[key] = translated;
     545        // overwrite existing element
     546    return B_OK;
     547}
     548
     549
     550status_t
     551DefaultCatalog::SetString(const CatKey& key, const char *translated)
     552{
     553    fCatMap[key] = translated;
     554        // overwrite existing element
     555    return B_OK;
     556}
     557
     558
     559/*
     560 * computes an adler32-checksum (we call it fingerprint) on all the catalog-keys.
     561 * We do not include the values, since we want catalogs for different languages
     562 * of the same app to have the same fingerprint, since we use it to separate
     563 * different catalog-versions.
     564 */
     565int32
     566DefaultCatalog::ComputeFingerprint() const
     567{
     568    uint32 adler = adler32(0, NULL, 0);
     569
     570    int32 hash;
     571    CatMap::const_iterator iter;
     572    for (iter = fCatMap.begin(); iter!=fCatMap.end(); ++iter) {
     573        hash = B_HOST_TO_LENDIAN_INT32(iter->first.fHashVal);
     574        adler = adler32(adler, reinterpret_cast<uint8*>(&hash), sizeof(int32));
     575    }
     576    return adler;
     577}
     578
     579
     580void
     581DefaultCatalog::UpdateFingerprint()
     582{
     583    fFingerprint = ComputeFingerprint();
     584}
     585
     586
     587/*
     588 * writes mimetype, language-name and signature of catalog into the catalog-file.
     589 */
     590void
     591DefaultCatalog::UpdateAttributes(BFile& catalogFile)
     592{
     593    static const int bufSize = 256;
     594    char buf[bufSize];
     595    if (catalogFile.ReadAttr("BEOS:TYPE", B_MIME_STRING_TYPE, 0, &buf, bufSize) <= 0
     596        || strcmp(kCatMimeType, buf) != 0) {
     597        catalogFile.WriteAttr("BEOS:TYPE", B_MIME_STRING_TYPE, 0,
     598            kCatMimeType, strlen(kCatMimeType)+1);
     599    }
     600    if (catalogFile.ReadAttr(BLocaleRoster::kCatLangAttr, B_STRING_TYPE, 0,
     601        &buf, bufSize) <= 0
     602        || fLanguageName != buf) {
     603        catalogFile.WriteAttr(BLocaleRoster::kCatLangAttr, B_STRING_TYPE, 0,
     604            fLanguageName.String(), fLanguageName.Length()+1);
     605    }
     606    if (catalogFile.ReadAttr(BLocaleRoster::kCatSigAttr, B_STRING_TYPE, 0,
     607        &buf, bufSize) <= 0
     608        || fSignature != buf) {
     609        catalogFile.WriteAttr(BLocaleRoster::kCatSigAttr, B_STRING_TYPE, 0,
     610            fSignature.String(), fSignature.Length()+1);
     611    }
     612}
     613
     614
     615status_t
     616DefaultCatalog::Flatten(BDataIO *dataIO)
     617{
     618    UpdateFingerprint();
     619        // make sure we have the correct fingerprint before we flatten it
     620
     621    status_t res;
     622    BMessage archive;
     623    int32 count = fCatMap.size();
     624    res = archive.AddString("class", "DefaultCatalog")
     625        || archive.AddInt32("c:sz", count)
     626        || archive.AddInt16("c:ver", kCatArchiveVersion)
     627        || archive.AddString("c:lang", fLanguageName.String())
     628        || archive.AddString("c:sig", fSignature.String())
     629        || archive.AddInt32("c:fpr", fFingerprint);
     630    if (res == B_OK)
     631        res = archive.Flatten(dataIO);
     632
     633    CatMap::const_iterator iter;
     634    for (iter = fCatMap.begin(); res==B_OK && iter!=fCatMap.end(); ++iter) {
     635        archive.MakeEmpty();
     636        res = archive.AddString("c:key", iter->first.fKey.String())
     637            || archive.AddInt32("c:hash", iter->first.fHashVal)
     638            || archive.AddString("c:tstr", iter->second.String());
     639        if (res == B_OK)
     640            res = archive.Flatten(dataIO);
     641    }
     642    return res;
     643}
     644
     645
     646status_t
     647DefaultCatalog::Unflatten(BDataIO *dataIO)
     648{
     649    fCatMap.clear();
     650    int32 count = 0;
     651    int16 version;
     652    BMessage archiveMsg;
     653    status_t res = archiveMsg.Unflatten(dataIO);
     654   
     655    if (res == B_OK) {
     656        res = archiveMsg.FindInt16("c:ver", &version)
     657            || archiveMsg.FindInt32("c:sz", &count);
     658    }
     659    if (res == B_OK) {
     660        fLanguageName = archiveMsg.FindString("c:lang");
     661        fSignature = archiveMsg.FindString("c:sig");
     662        int32 foundFingerprint = archiveMsg.FindInt32("c:fpr");
     663
     664        // if a specific fingerprint has been requested and the catalog does in fact
     665        // have a fingerprint, both are compared. If they mismatch, we do not accept
     666        // this catalog:
     667        if (foundFingerprint != 0 && fFingerprint != 0
     668            && foundFingerprint != fFingerprint) {
     669            log_team(LOG_INFO, "default-catalog(sig=%s, lang=%s) "
     670                "has mismatching fingerprint (%ld instead of the requested %ld), "
     671                "so this catalog is skipped.",
     672                fSignature.String(), fLanguageName.String(), foundFingerprint,
     673                fFingerprint);
     674            res = B_MISMATCHED_VALUES;
     675        } else
     676            fFingerprint = foundFingerprint;
     677    }
     678
     679    if (res == B_OK && count > 0) {
     680        CatKey key;
     681        const char *keyStr;
     682        const char *translated;
     683#ifdef __GCC
     684        fCatMap.resize(count);
     685#endif
     686        for (int i=0; res==B_OK && i<count; ++i) {
     687            res = archiveMsg.Unflatten(dataIO);
     688            if (res == B_OK) {
     689                res = archiveMsg.FindString("c:key", &keyStr)
     690                    || archiveMsg.FindInt32("c:hash", (int32*)&key.fHashVal)
     691                    || archiveMsg.FindString("c:tstr", &translated);
     692            }
     693            if (res == B_OK) {
     694                key.fKey = keyStr;
     695                fCatMap.insert(pair<const BPrivate::CatKey, BString>(key, translated));
     696            }
     697        }
     698        int32 checkFP = ComputeFingerprint();
     699        if (fFingerprint != checkFP) {
     700            log_team(LOG_WARNING, "default-catalog(sig=%s, lang=%s) "
     701                "has wrong fingerprint after load (%ld instead of the %ld). "
     702                "The catalog data may be corrupted, so this catalog is skipped.",
     703                fSignature.String(), fLanguageName.String(), checkFP,
     704                fFingerprint);
     705            return B_BAD_DATA;
     706        }
     707    }
     708    return res;
     709}
     710
     711
     712BCatalogAddOn *
     713DefaultCatalog::Instantiate(const char *signature, const char *language,
     714    int32 fingerprint)
     715{
     716    DefaultCatalog *catalog = new DefaultCatalog(signature, language, fingerprint);
     717    if (catalog && catalog->InitCheck() != B_OK) {
     718        delete catalog;
     719        return NULL;
     720    }
     721    return catalog;
     722}
     723
     724
     725BCatalogAddOn *
     726DefaultCatalog::InstantiateEmbedded(entry_ref *appOrAddOnRef)
     727{
     728    DefaultCatalog *catalog = new DefaultCatalog(appOrAddOnRef);
     729    if (catalog && catalog->InitCheck() != B_OK) {
     730        delete catalog;
     731        return NULL;
     732    }
     733    return catalog;
     734}
     735
     736
     737BCatalogAddOn *
     738DefaultCatalog::Create(const char *signature, const char *language)
     739{
     740    DefaultCatalog *catalog = new DefaultCatalog("", signature, language);
     741    if (catalog && catalog->InitCheck() != B_OK) {
     742        delete catalog;
     743        return NULL;
     744    }
     745    return catalog;
     746}
     747
     748
     749const uint8 DefaultCatalog::kDefaultCatalogAddOnPriority = 1;
     750    // give highest priority to our embedded catalog-add-on
  • src/kits/locale/IntegerFormatImpl.cpp

     
     1#include <IntegerFormatImpl.h>
     2#include <IntegerFormatParameters.h>
     3
     4// constructor
     5BIntegerFormatImpl::BIntegerFormatImpl()
     6    : BNumberFormatImpl()
     7{
     8}
     9
     10// destructor
     11BIntegerFormatImpl::~BIntegerFormatImpl()
     12{
     13}
     14
     15// DefaultNumberFormatParameters
     16BNumberFormatParameters *
     17BIntegerFormatImpl::DefaultNumberFormatParameters()
     18{
     19    return DefaultIntegerFormatParameters();
     20}
     21
     22// DefaultNumberFormatParameters
     23const BNumberFormatParameters *
     24BIntegerFormatImpl::DefaultNumberFormatParameters() const
     25{
     26    return DefaultIntegerFormatParameters();
     27}
     28
  • src/kits/locale/LibraryInit.cpp

     
     1/*
     2 * This file contains library initialization code.
     3 * The required mimetypes and attribute-indices are created here.
     4 */
     5
     6#include <syslog.h>
     7
     8#include <fs_attr.h>
     9#include <fs_index.h>
     10#include <Roster.h>
     11#include <Volume.h>
     12#include <VolumeRoster.h>
     13
     14#include <LocaleRoster.h>
     15#include <DefaultCatalog.h>
     16
     17// helper function that makes sure an attribute-index exists:
     18static void EnsureIndexExists(const char *attrName)
     19{
     20    BVolume bootVol;
     21    BVolumeRoster volRoster;
     22    if (volRoster.GetBootVolume(&bootVol) != B_OK)
     23        return;
     24    struct index_info idxInfo;
     25    if (fs_stat_index(bootVol.Device(), attrName, &idxInfo) != 0) {
     26        status_t res = fs_create_index(bootVol.Device(), attrName,
     27            B_STRING_TYPE, 0);
     28        if (res == 0) {
     29            log_team(LOG_INFO,
     30                "successfully created the required index for attribute %s",
     31                attrName);
     32        } else {
     33            log_team(LOG_ERR,
     34                "failed to create the required index for attribute %s (%s)",
     35                attrName, strerror(res));
     36        }
     37    }
     38}
     39
     40
     41/*
     42 * prepares the system for use by the Locale Kit catalogs,
     43 * it makes sure that the required indices and mimetype exist:
     44 */
     45static void
     46SetupCatalogBasics()
     47{
     48    // make sure the indices required for catalog-traversal are there:
     49    EnsureIndexExists(BLocaleRoster::kCatLangAttr);
     50    EnsureIndexExists(BLocaleRoster::kCatSigAttr);
     51   
     52    // install mimetype for default-catalog:
     53    BMimeType mt;
     54    status_t res = mt.SetTo(DefaultCatalog::kCatMimeType);
     55    if (res == B_OK && !mt.IsInstalled()) {
     56        // install supertype, if it isn't available
     57        BMimeType supertype;
     58        res = mt.GetSupertype(&supertype);
     59        if (res == B_OK && !supertype.IsInstalled()) {
     60            res = supertype.Install();
     61        }
     62       
     63        if (res == B_OK) {
     64            // info about the attributes of a catalog...
     65            BMessage attrMsg;
     66            // ...the catalog signature...
     67            attrMsg.AddString("attr:public_name", "Signature");
     68            attrMsg.AddString("attr:name", BLocaleRoster::kCatSigAttr);
     69            attrMsg.AddInt32("attr:type", B_STRING_TYPE);
     70            attrMsg.AddBool("attr:editable", false);
     71            attrMsg.AddBool("attr:viewable", true);
     72            attrMsg.AddBool("attr:extra", false);
     73            attrMsg.AddInt32("attr:alignment", 0);
     74            attrMsg.AddInt32("attr:width", 140);
     75            // ...the catalog language...
     76            attrMsg.AddString("attr:public_name", "Language");
     77            attrMsg.AddString("attr:name", BLocaleRoster::kCatLangAttr);
     78            attrMsg.AddInt32("attr:type", B_STRING_TYPE);
     79            attrMsg.AddBool("attr:editable", false);
     80            attrMsg.AddBool("attr:viewable", true);
     81            attrMsg.AddBool("attr:extra", false);
     82            attrMsg.AddInt32("attr:alignment", 0);
     83            attrMsg.AddInt32("attr:width", 60);
     84            // ...and the catalog fingerprint...
     85            attrMsg.AddString("attr:public_name", "Fingerprint");
     86            attrMsg.AddString("attr:name", BLocaleRoster::kCatFingerprintAttr);
     87            attrMsg.AddInt32("attr:type", B_INT32_TYPE);
     88            attrMsg.AddBool("attr:editable", false);
     89            attrMsg.AddBool("attr:viewable", true);
     90            attrMsg.AddBool("attr:extra", false);
     91            attrMsg.AddInt32("attr:alignment", 0);
     92            attrMsg.AddInt32("attr:width", 70);
     93            res = mt.SetAttrInfo(&attrMsg);
     94        }
     95
     96        if (res == B_OK) {
     97            // file extensions (.catalog):
     98            BMessage extMsg;
     99            extMsg.AddString("extensions", "catalog");
     100            res = mt.SetFileExtensions(&extMsg);
     101        }
     102
     103        if (res == B_OK) {
     104            // short and long descriptions:
     105            mt.SetShortDescription("Translation Catalog");
     106            res = mt.SetLongDescription("Catalog with translated application resources");
     107        }
     108
     109        if (res == B_OK) {
     110            // preferred app is catalog manager:
     111            res = mt.SetPreferredApp(BLocaleRoster::kCatManagerMimeType, B_OPEN);
     112        }
     113       
     114        if (res == B_OK)
     115            res = mt.Install();
     116    }
     117    if (res != B_OK) {
     118        log_team(LOG_ERR, "Could not install mimetype %s (%s)",
     119                DefaultCatalog::kCatMimeType, strerror(res));
     120    }
     121}
     122
     123
     124#if defined(__HAIKU__)
     125
     126extern "C"
     127_IMPEXP_LOCALE
     128void
     129initialize_after()
     130{
     131    SetupCatalogBasics();
     132}
     133
     134#else
     135
     136// [zooey]:
     137//  hack suggested by Ingo Weinhold to make the be_roster work
     138//    properly such that we can install mimetypes:
     139class BRoster {
     140public:
     141    void InitMessengers();
     142};
     143
     144extern const BRoster *be_roster;
     145
     146extern "C"
     147_IMPEXP_LOCALE
     148void
     149initialize_after()
     150{
     151    // now force be_roster to initialized state.
     152    const_cast<BRoster*>(be_roster)->InitMessengers();
     153
     154    SetupCatalogBasics();
     155}
     156
     157#endif
     158
  • src/kits/locale/Format.cpp

     
     1#include <Format.h>
     2#include <FormatImpl.h>
     3
     4// copy constructor
     5BFormat::BFormat(const BFormat &other)
     6    : fImpl(other.fImpl)
     7{
     8}
     9
     10// destructor
     11BFormat::~BFormat()
     12{
     13}
     14
     15// =
     16BFormat &
     17BFormat::operator=(const BFormat &other)
     18{
     19    fImpl = other.fImpl;
     20    return *this;
     21}
     22
     23// constructor
     24BFormat::BFormat(BFormatImpl *impl)
     25    : fImpl(impl)
     26{
     27}
     28
  • src/kits/locale/PropertyFile.h

     
     1/*
     2** Copyright 2003, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
     3** Distributed under the terms of the OpenBeOS License.
     4*/
     5#ifndef PROPERTY_FILE_H
     6#define PROPERTY_FILE_H
     7
     8
     9#include <File.h>
     10
     11
     12// This is the read-only version of the PropertyFile class - the
     13// genprops tool contains the write-only version of it
     14
     15
     16class PropertyFile : public BFile {
     17    public:
     18        status_t SetTo(const char *directory, const char *name);
     19
     20        off_t Size();
     21};
     22
     23#endif  /* PROPERTY_FILE_H */
  • src/kits/locale/IntegerFormatParameters.cpp

     
     1#include <IntegerFormatParameters.h>
     2
     3// constructor
     4BIntegerFormatParameters::BIntegerFormatParameters(
     5    const BIntegerFormatParameters *parent)
     6    : BNumberFormatParameters(parent),
     7      fParent(parent)
     8{
     9}
     10
     11// copy constructor
     12BIntegerFormatParameters::BIntegerFormatParameters(
     13    const BIntegerFormatParameters &other)
     14    : BNumberFormatParameters(other),
     15      fParent(other.fParent)
     16{
     17}
     18
     19// destructor
     20BIntegerFormatParameters::~BIntegerFormatParameters()
     21{
     22}
     23
     24// SetParentIntegerParameters
     25void
     26BIntegerFormatParameters::SetParentIntegerParameters(
     27    const BIntegerFormatParameters *parent)
     28{
     29    fParent = parent;
     30    SetParentNumberParameters(parent);
     31}
     32
     33// ParentIntegerParameters
     34const BIntegerFormatParameters *
     35BIntegerFormatParameters::ParentIntegerParameters() const
     36{
     37    return fParent;
     38}
     39
     40// =
     41BIntegerFormatParameters &
     42BIntegerFormatParameters::operator=(const BIntegerFormatParameters &other)
     43{
     44    BNumberFormatParameters::operator=(other);
     45    fParent = other.fParent;
     46    return *this;
     47}
     48
  • src/kits/locale/adler32.c

     
     1/* adler32.c -- compute the Adler-32 checksum of a data stream
     2 * Copyright (C) 1995-2002 Mark Adler
     3 * For conditions of distribution and use, see copyright notice in zlib.h
     4 */
     5
     6/*
     7 * [zooey]:
     8 *      This file has been adjusted from the original found in zlib
     9 *      for better conformance to our style-guide.
     10 */
     11
     12#include <SupportDefs.h>
     13
     14#include <LocaleBuild.h>
     15
     16uint32 _IMPEXP_LOCALE adler32(uint32 adler, const uint8 *buf, uint32 len);
     17    // prototype required by mwcc
     18
     19#define BASE 65521L /* largest prime smaller than 65536 */
     20#define NMAX 5552
     21/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */
     22
     23#define DO1(buf,i)  {s1 += buf[i]; s2 += s1;}
     24#define DO2(buf,i)  DO1(buf,i); DO1(buf,i+1);
     25#define DO4(buf,i)  DO2(buf,i); DO2(buf,i+2);
     26#define DO8(buf,i)  DO4(buf,i); DO4(buf,i+4);
     27#define DO16(buf)   DO8(buf,0); DO8(buf,8);
     28
     29/* ========================================================================= */
     30uint32 adler32(uint32 adler, const uint8 *buf, uint32 len)
     31{
     32    uint32 s1 = adler & 0xffff;
     33    uint32 s2 = (adler >> 16) & 0xffff;
     34    int k;
     35
     36    if (buf == NULL) return 1L;
     37
     38    while (len > 0) {
     39        k = len < NMAX ? len : NMAX;
     40        len -= k;
     41        while (k >= 16) {
     42            DO16(buf);
     43            buf += 16;
     44            k -= 16;
     45        }
     46        if (k != 0) do {
     47            s1 += *buf++;
     48            s2 += s1;
     49        } while (--k);
     50        s1 %= BASE;
     51        s2 %= BASE;
     52    }
     53    return (s2 << 16) | s1;
     54}
  • src/kits/Jamfile

     
    9292SubInclude HAIKU_TOP src kits device ;
    9393SubInclude HAIKU_TOP src kits game ;
    9494SubInclude HAIKU_TOP src kits interface ;
     95SubInclude HAIKU_TOP src kits locale ;
    9596SubInclude HAIKU_TOP src kits mail ;
    9697SubInclude HAIKU_TOP src kits media ;
    9798SubInclude HAIKU_TOP src kits midi ;
  • data/etc/locale/languages/français.language

     
     1fr,roman,ltr
     2--
     3Hier
     4Aujourd'hui
     5Demain
     6Avenir
     7
     8Dimanche
     9Lundi
     10Mardi
     11Mercredi
     12Jeudi
     13Vendredi
     14Samedi
     15
     16Dim
     17Lun
     18Mar
     19Mer
     20Jeu
     21Ven
     22Sam
     23
     24Janvier
     25Février
     26Mars
     27Avril
     28Mai
     29Juin
     30Juillet
     31Août
     32Septembre
     33Octobre
     34Novembre
     35Décembre
     36
     37Jan
     38Fev
     39Mars
     40Avr
     41Mai
     42Juin
     43Juil
     44Août
     45Sep
     46Oct
     47Nov
     48Dec
     49
  • data/etc/locale/languages/deutsch.language

     
     1de,germanic,ltr
     2--
     3Gestern
     4Heute
     5Morgen
     6Zukunft
     7
     8Sonntag
     9Montag
     10Dienstag
     11Mittwoch
     12Donnerstag
     13Freitag
     14Samstag
     15
     16So
     17Mo
     18Di
     19Mi
     20Do
     21Fr
     22Sa
     23
     24Januar
     25Februar
     26März
     27April
     28Mai
     29Juni
     30Juli
     31August
     32September
     33Oktober
     34November
     35Dezember
     36
     37Jan
     38Feb
     39Mär
     40Apr
     41Mai
     42Jun
     43Jul
     44Aug
     45Sep
     46Okt
     47Nov
     48Dez
     49
  • headers/os/locale/Currency.h

     
     1#ifndef _B_CURRENCY_H_
     2#define _B_CURRENCY_H_
     3
     4#include <Archivable.h>
     5#include <Message.h>
     6#include <String.h>
     7
     8#include <LocaleBuild.h>
     9
     10class BLocale;
     11
     12class _IMPEXP_LOCALE BCurrency : public BArchivable {
     13    public:
     14        BCurrency(const BCurrency &other);
     15        BCurrency(BMessage *archive);
     16        BCurrency(const char *currencyCode);
     17        ~BCurrency();
     18
     19        status_t InitCheck() const;
     20
     21        virtual status_t Archive(BMessage *archive, bool deep = true) const;
     22        static BArchivable *Instantiate(BMessage *archive);
     23
     24        const char *CurrencyCode() const;
     25        const char *DefaultSymbol() const;
     26        int32 DefaultFractionDigits() const;
     27
     28        status_t GetSymbol(char *symbol, size_t maxSize,
     29                           BLocale *locale = NULL);
     30        status_t GetSymbol(BString *symbol, BLocale *locale = NULL);
     31
     32        BCurrency &operator=(const BCurrency &other);
     33        bool operator==(const BCurrency &other) const;
     34        bool operator!=(const BCurrency &other) const;
     35
     36    private:
     37        BCurrency();
     38
     39        bool _CheckData() const;
     40        void _Unset(status_t error);
     41
     42        BString fCurrencyCode;
     43        BString fDefaultSymbol;
     44        int32   fDefaultFractionDigits;
     45};
     46
     47#endif  // _B_CURRENCY_H_
  • headers/os/locale/IntegerFormatParameters.h

     
     1#ifndef _B_INTEGER_FORMAT_PARAMETERS_H_
     2#define _B_INTEGER_FORMAT_PARAMETERS_H_
     3
     4#include <NumberFormatParameters.h>
     5
     6class _IMPEXP_LOCALE BIntegerFormatParameters : public BNumberFormatParameters {
     7    public:
     8        BIntegerFormatParameters(const BIntegerFormatParameters *parent = NULL);
     9        BIntegerFormatParameters(const BIntegerFormatParameters &other);
     10        ~BIntegerFormatParameters();
     11
     12        void SetParentIntegerParameters(const BIntegerFormatParameters *parent);
     13        const BIntegerFormatParameters *ParentIntegerParameters() const;
     14
     15        BIntegerFormatParameters &operator=(
     16            const BIntegerFormatParameters &other);
     17
     18    private:
     19        const BIntegerFormatParameters  *fParent;
     20};
     21
     22#endif  // _B_INTEGER_FORMAT_PARAMETERS_H_
  • headers/os/locale/GenericNumberFormat.h

     
     1#ifndef _B_GENERIC_NUMBER_FORMAT_H_
     2#define _B_GENERIC_NUMBER_FORMAT_H_
     3
     4#include <FloatFormatParameters.h>
     5#include <IntegerFormatParameters.h>
     6
     7class BString;
     8struct format_field_position;
     9
     10class _IMPEXP_LOCALE BGenericNumberFormat {
     11    public:
     12        BGenericNumberFormat();
     13        ~BGenericNumberFormat();
     14
     15        status_t FormatInteger(const BIntegerFormatParameters *parameters,
     16                               int64 number, BString *buffer,
     17                               format_field_position *positions = NULL,
     18                               int32 positionCount = 1,
     19                               int32 *fieldCount = NULL,
     20                               bool allFieldPositions = false) const;
     21
     22        status_t FormatInteger(const BIntegerFormatParameters *parameters,
     23                               int64 number, char *buffer, size_t bufferSize,
     24                               format_field_position *positions = NULL,
     25                               int32 positionCount = 1,
     26                               int32 *fieldCount = NULL,
     27                               bool allFieldPositions = false) const;
     28
     29        status_t FormatInteger(const BIntegerFormatParameters *parameters,
     30                               uint64 number, BString *buffer,
     31                               format_field_position *positions = NULL,
     32                               int32 positionCount = 1,
     33                               int32 *fieldCount = NULL,
     34                               bool allFieldPositions = false) const;
     35
     36        status_t FormatInteger(const BIntegerFormatParameters *parameters,
     37                               uint64 number, char *buffer, size_t bufferSize,
     38                               format_field_position *positions = NULL,
     39                               int32 positionCount = 1,
     40                               int32 *fieldCount = NULL,
     41                               bool allFieldPositions = false) const;
     42
     43        status_t FormatFloat(const BFloatFormatParameters *parameters,
     44                             double number, BString *buffer,
     45                             format_field_position *positions = NULL,
     46                             int32 positionCount = 1,
     47                             int32 *fieldCount = NULL,
     48                             bool allFieldPositions = false) const;
     49
     50        status_t FormatFloat(const BFloatFormatParameters *parameters,
     51                             double number, char *buffer, size_t bufferSize,
     52                             format_field_position *positions = NULL,
     53                             int32 positionCount = 1,
     54                             int32 *fieldCount = NULL,
     55                             bool allFieldPositions = false) const;
     56
     57        // default number format parameters
     58
     59        status_t SetDefaultIntegerFormatParameters(
     60            const BIntegerFormatParameters *parameters);
     61        BIntegerFormatParameters *DefaultIntegerFormatParameters();
     62        const BIntegerFormatParameters *DefaultIntegerFormatParameters() const;
     63
     64        status_t SetDefaultFloatFormatParameters(
     65            const BFloatFormatParameters *parameters);
     66        BFloatFormatParameters *DefaultFloatFormatParameters();
     67        const BFloatFormatParameters *DefaultFloatFormatParameters() const;
     68
     69        // other parameters configuring the formatter
     70
     71        status_t SetDigitSymbols(const char **digits);
     72        status_t SetFractionSeparator(const char *decimalSeparator);
     73        status_t SetGroupingInfo(const char **groupingSeparators,
     74            size_t separatorCount, size_t *groupSizes, size_t sizeCount);
     75        status_t SetExponentSymbol(const char *exponentSymbol,
     76            const char *upperCaseExponentSymbol = NULL);
     77        status_t SetSpecialNumberSymbols(const char *nan,
     78            const char *infinity, const char *negativeInfinity = NULL,
     79            const char *upperCaseNaN = NULL,
     80            const char *upperCaseInfinity = NULL,
     81            const char *upperCaseNegativeInfinity = NULL);
     82        status_t SetSignSymbols(const char *plusPrefix,
     83            const char *minusPrefix, const char *padPlusPrefix,
     84            const char *noForcePlusPrefix = NULL, const char *plusSuffix = NULL,
     85            const char *minusSuffix = NULL, const char *padPlusSuffix = NULL,
     86            const char *noForcePlusSuffix = NULL);
     87        status_t SetMantissaSignSymbols(const char *plusPrefix,
     88            const char *minusPrefix, const char *padPlusPrefix,
     89            const char *noForcePlusPrefix = NULL, const char *plusSuffix = NULL,
     90            const char *minusSuffix = NULL, const char *padPlusSuffix = NULL,
     91            const char *noForcePlusSuffix = NULL);
     92        status_t SetExponentSignSymbols(const char *plusPrefix,
     93            const char *minusPrefix, const char *plusSuffix = NULL,
     94            const char *minusSuffix = NULL);
     95// TODO: Support engineering representation of scientific format (exponent
     96// is a multiple of 3), i.e. allow setting the number of which the exponent
     97// must be a multiple of.
     98
     99        struct Symbol {
     100            char    *symbol;
     101            int     length;
     102            int     char_count;
     103
     104            Symbol(const char *symbol = NULL);
     105            ~Symbol();
     106
     107            status_t SetTo(const char *symbol);
     108            void Unset()    { SetTo(NULL); }
     109        };
     110        class GroupingInfo;
     111        class SignSymbols;
     112
     113    private:
     114        class BufferWriter;
     115        class Float;
     116        class Integer;
     117        struct SpecialNumberSymbols;
     118
     119        status_t FormatInteger(const BIntegerFormatParameters *parameters,
     120                               const Integer &integer, char *buffer,
     121                               size_t bufferSize,
     122                               format_field_position *positions = NULL,
     123                               int32 positionCount = 1,
     124                               int32 *fieldCount = NULL,
     125                               bool allFieldPositions = false) const;
     126
     127        const Symbol *DigitSymbols() const;
     128        const Symbol *FractionSeparator() const;
     129        const GroupingInfo *GetGroupingInfo() const;
     130        const Symbol *ExponentSymbol(bool upperCase = false) const;
     131        const Symbol *NaNSymbol(bool upperCase = false) const;
     132        const Symbol *InfinitySymbol(bool upperCase = false) const;
     133        const Symbol *NegativeInfinitySymbol(bool upperCase = false) const;
     134        void GetSpecialNumberSymbols(bool upperCase,
     135                                     SpecialNumberSymbols *symbols) const;
     136        const SignSymbols *GetSignSymbols() const;
     137        const SignSymbols *MantissaSignSymbols() const;
     138        const SignSymbols *ExponentSignSymbols() const;
     139
     140        static status_t _SetSymbol(Symbol **symbol, const char *str);
     141
     142        BIntegerFormatParameters    fIntegerParameters;
     143        BFloatFormatParameters      fFloatParameters;
     144        Symbol                      *fDigitSymbols;
     145        Symbol                      *fFractionSeparator;
     146        GroupingInfo                *fGroupingInfo;
     147        Symbol                      *fExponentSymbol;
     148        Symbol                      *fUpperCaseExponentSymbol;
     149        Symbol                      *fNaNSymbol;
     150        Symbol                      *fUpperCaseNaNSymbol;
     151        Symbol                      *fInfinitySymbol;
     152        Symbol                      *fUpperCaseInfinitySymbol;
     153        Symbol                      *fNegativeInfinitySymbol;
     154        Symbol                      *fUpperCaseNegativeInfinitySymbol;
     155        SignSymbols                 *fSignSymbols;
     156        SignSymbols                 *fMantissaSignSymbols;
     157        SignSymbols                 *fExponentSignSymbols;
     158};
     159
     160#endif  // _B_GENERIC_NUMBER_FORMAT_H_
  • headers/os/locale/LocaleRoster.h

     
     1#ifndef _LOCALE_ROSTER_H_
     2#define _LOCALE_ROSTER_H_
     3
     4#include <LocaleBuild.h>
     5
     6#include <String.h>
     7
     8class BLanguage;
     9class BLocale;
     10class BCollator;
     11class BCountry;
     12class BCatalog;
     13class BCatalogAddOn;
     14
     15namespace BPrivate {
     16    class EditableCatalog;
     17};
     18
     19enum {
     20    B_LOCALE_CHANGED    = '_LCC',
     21};
     22
     23class _IMPEXP_LOCALE BLocaleRoster {
     24
     25    public:
     26        BLocaleRoster();
     27        ~BLocaleRoster();
     28
     29//      status_t GetCatalog(BLocale *,const char *mimeType, BCatalog *catalog);
     30//      status_t GetCatalog(const char *mimeType, BCatalog *catalog);
     31//      status_t SetCatalog(BLocale *,const char *mimeType, BCatalog *catalog);
     32
     33//      status_t GetLocaleFor(const char *langCode,const char *countryCode);
     34
     35        status_t GetDefaultCollator(BCollator **) const;
     36        status_t GetDefaultLanguage(BLanguage **) const;
     37        status_t GetDefaultCountry(BCountry **) const;
     38       
     39        status_t GetPreferredLanguages(BMessage *) const;
     40        status_t SetPreferredLanguages(BMessage *);
     41            // the message contains one or more 'language'-string-fields
     42            // which contain the language-name(s)
     43
     44        status_t GetInstalledLanguages(BMessage *) const;
     45            // the message contains one or more 'language'-string-fields
     46            // which contain the language-name(s)
     47
     48        status_t GetInstalledCatalogs(BMessage *,
     49                    const char* sigPattern = NULL,
     50                    const char* langPattern = NULL,
     51                    int32 fingerprint = 0) const;
     52            // the message contains...
     53
     54//      status_t GetDefaultLanguage(BLanguage *);
     55//      status_t SetDefaultLanguage(BLanguage *);
     56
     57        static const char *kCatLangAttr;
     58        static const char *kCatSigAttr;
     59        static const char *kCatFingerprintAttr;
     60        //
     61        static const char *kCatManagerMimeType;
     62        static const char *kCatEditorMimeType;
     63        //
     64        static const char *kEmbeddedCatAttr;
     65        static int32 kEmbeddedCatResId;
     66
     67    private:
     68
     69        BCatalogAddOn* LoadCatalog(const char *signature,
     70                            const char *language = NULL,
     71                            int32 fingerprint = 0);
     72        BCatalogAddOn* LoadEmbeddedCatalog(entry_ref *appOrAddOnRef);
     73        status_t UnloadCatalog(BCatalogAddOn *addOn);
     74        //
     75        BCatalogAddOn* CreateCatalog(const char *type,
     76                            const char *signature,
     77                            const char *language);
     78
     79        friend class BCatalog;
     80        friend class BPrivate::EditableCatalog;
     81        friend status_t get_add_on_catalog(BCatalog*, const char *);
     82};
     83
     84#endif  /* _LOCALE_ROSTER_H_ */
  • headers/os/locale/Locale.h

     
     1#ifndef _B_LOCALE_H_
     2#define _B_LOCALE_H_
     3
     4
     5#include <LocaleBuild.h>
     6
     7#include <Collator.h>
     8#include <Language.h>
     9#include <Country.h>
     10
     11
     12class BCatalog;
     13class BString;
     14class BLocaleRoster;
     15
     16
     17class _IMPEXP_LOCALE BLocale {
     18    public:
     19        BLocale();
     20        ~BLocale();
     21
     22        BCollator *Collator() const { return fCollator; }
     23        BCountry *Country() const { return fCountry; }
     24        BLanguage *Language() const { return fLanguage; }
     25
     26        // see definitions in LocaleStrings.h
     27        const char *GetString(uint32 id);
     28
     29        void FormatString(char *target, size_t maxSize, char *fmt, ...);
     30        void FormatString(BString *, char *fmt, ...);
     31        void FormatDateTime(char *target, size_t maxSize, const char *fmt, time_t);
     32        void FormatDateTime(BString *, const char *fmt, time_t);
     33
     34        // Country short-hands
     35
     36        void FormatDate(char *target, size_t maxSize, time_t, bool longFormat);
     37        void FormatDate(BString *target, time_t, bool longFormat);
     38        void FormatTime(char *target, size_t maxSize, time_t, bool longFormat);
     39        void FormatTime(BString *target, time_t, bool longFormat);
     40
     41        // Collator short-hands
     42
     43        int StringCompare(const char *, const char *, int32 len = -1, int8 strength = B_COLLATE_DEFAULT) const;
     44        int StringCompare(const BString *, const BString *, int32 len = -1, int8 strength = B_COLLATE_DEFAULT) const;
     45
     46        void GetSortKey(const char *string, BString *key);
     47       
     48        status_t GetAppCatalog(BCatalog *);
     49
     50    protected:
     51        BCollator   *fCollator;
     52        BLanguage   *fLanguage;
     53        BCountry    *fCountry;
     54};
     55
     56// global objects
     57extern _IMPEXP_LOCALE BLocale *be_locale;
     58extern _IMPEXP_LOCALE BLocaleRoster *be_locale_roster;
     59
     60//----------------------------------------------------------------------
     61//--- country short-hands inlines ---
     62
     63inline void
     64BLocale::FormatDate(char *target, size_t maxSize, time_t timer, bool longFormat)
     65{
     66    fCountry->FormatDate(target, maxSize, timer, longFormat);
     67}
     68
     69
     70inline void
     71BLocale::FormatDate(BString *target, time_t timer, bool longFormat)
     72{
     73    fCountry->FormatDate(target, timer, longFormat);
     74}
     75
     76
     77inline void
     78BLocale::FormatTime(char *target, size_t maxSize, time_t timer, bool longFormat)
     79{
     80    fCountry->FormatTime(target, maxSize, timer, longFormat);
     81}
     82
     83
     84inline void
     85BLocale::FormatTime(BString *target, time_t timer, bool longFormat)
     86{
     87    fCountry->FormatTime(target, timer, longFormat);
     88}
     89
     90
     91//--- locale short-hands inlines ---
     92//  #pragma mark -
     93
     94inline int
     95BLocale::StringCompare(const char *string1, const char *string2, int32 length, int8 strength) const
     96{
     97    return fCollator->Compare(string1, string2, length, strength);
     98}
     99
     100
     101inline int
     102BLocale::StringCompare(const BString *string1, const BString *string2, int32 length, int8 strength) const
     103{
     104    return fCollator->Compare(string1->String(), string2->String(), length, strength);
     105}
     106
     107
     108inline void
     109BLocale::GetSortKey(const char *string, BString *key)
     110{
     111    fCollator->GetSortKey(string, key);
     112}
     113
     114#endif  /* _B_LOCALE_H_ */
  • headers/os/locale/FloatFormatImpl.h

     
     1#ifndef _B_FLOAT_FORMAT_IMPL_H_
     2#define _B_FLOAT_FORMAT_IMPL_H_
     3
     4#include <NumberFormatImpl.h>
     5
     6struct format_field_position;
     7class BFloatFormatParameters;
     8class BString;
     9
     10class _IMPEXP_LOCALE BFloatFormatImpl : public BNumberFormatImpl {
     11    public:
     12        BFloatFormatImpl();
     13        virtual ~BFloatFormatImpl();
     14
     15        // formatting
     16
     17        virtual status_t Format(const BFloatFormatParameters *parameters,
     18                                double number, BString *buffer) const = 0;
     19        virtual status_t Format(const BFloatFormatParameters *parameters,
     20                                double number, BString *buffer,
     21                                format_field_position *positions,
     22                                int32 positionCount = 1,
     23                                int32 *fieldCount = NULL,
     24                                bool allFieldPositions = false) const = 0;
     25
     26        // TODO: ...
     27
     28
     29        virtual BNumberFormatParameters *DefaultNumberFormatParameters();
     30        virtual const BNumberFormatParameters *DefaultNumberFormatParameters()
     31            const;
     32
     33        virtual BFloatFormatParameters *DefaultFloatFormatParameters() = 0;
     34        virtual const BFloatFormatParameters *DefaultFloatFormatParameters()
     35            const = 0;
     36};
     37
     38
     39#endif  // _B_FLOAT_FORMAT_IMPL_H_
  • headers/os/locale/NumberFormat.h

     
     1#ifndef _B_NUMBER_FORMAT_H_
     2#define _B_NUMBER_FORMAT_H_
     3
     4#include <Format.h>
     5#include <NumberFormatParameters.h>
     6
     7class BNumberFormatImpl;
     8
     9class _IMPEXP_LOCALE BNumberFormat : public BFormat {
     10    protected:
     11        BNumberFormat(const BNumberFormat &other);
     12        ~BNumberFormat();
     13
     14        BNumberFormat &operator=(const BNumberFormat &other);
     15
     16        BNumberFormat(BNumberFormatImpl *impl);
     17
     18    private:
     19        inline BNumberFormatImpl *NumberFormatImpl() const;
     20};
     21
     22
     23#endif  // _B_NUMBER_FORMAT_H_
  • headers/os/locale/FloatFormatParameters.h

     
     1#ifndef _B_FLOAT_FORMAT_PARAMETERS_H_
     2#define _B_FLOAT_FORMAT_PARAMETERS_H_
     3
     4#include <NumberFormatParameters.h>
     5
     6enum float_format_type {
     7    B_FIXED_POINT_FLOAT_FORMAT,
     8    B_SCIENTIFIC_FLOAT_FORMAT,
     9    B_AUTO_FLOAT_FORMAT,            // picks one of the above depending of the
     10                                    // number to be formatted
     11};
     12
     13class _IMPEXP_LOCALE BFloatFormatParameters : public BNumberFormatParameters {
     14    public:
     15        BFloatFormatParameters(const BFloatFormatParameters *parent = NULL);
     16        BFloatFormatParameters(const BFloatFormatParameters &other);
     17        ~BFloatFormatParameters();
     18
     19        void SetMinimalFractionDigits(size_t minFractionDigits);
     20        size_t MinimalFractionDigits() const;
     21
     22        void SetMaximalFractionDigits(size_t maxFractionDigits);
     23        size_t MaximalFractionDigits() const;
     24
     25        void SetUseUpperCase(bool useCapitals);
     26        bool UseUpperCase() const;
     27
     28        void SetFloatFormatType(float_format_type type);
     29        float_format_type FloatFormatType() const;
     30
     31        void SetAlwaysUseFractionSeparator(bool alwaysUseFractionSeparator);
     32        bool AlwaysUseFractionSeparator() const;
     33
     34        void SetKeepTrailingFractionZeros(bool keepTrailingFractionZeros);
     35        bool KeepTrailingFractionZeros() const;
     36
     37        void SetParentFloatParameters(const BFloatFormatParameters *parent);
     38        const BFloatFormatParameters *ParentFloatParameters() const;
     39
     40        BFloatFormatParameters &operator=(
     41            const BFloatFormatParameters &other);
     42
     43    private:
     44        const BFloatFormatParameters    *fParent;
     45        size_t                          fMinimalFractionDigits;
     46        size_t                          fMaximalFractionDigits;
     47        bool                            fUseUpperCase;
     48        float_format_type               fFloatFormatType;
     49        bool                            fAlwaysUseFractionSeparator;
     50        bool                            fKeepTrailingFractionZeros;
     51        uint32                          fFlags;
     52};
     53
     54#endif  // _B_FLOAT_FORMAT_PARAMETERS_H_
  • headers/os/locale/Country.h

     
     1#ifndef _COUNTRY_H_
     2#define _COUNTRY_H_
     3
     4
     5#include <SupportDefs.h>
     6#include <LocaleBuild.h>
     7#include <LocaleStrings.h>
     8#include <String.h>
     9
     10enum {
     11    B_METRIC = 0,
     12    B_US
     13};
     14
     15
     16class _IMPEXP_LOCALE BCountry {
     17    public:
     18        BCountry();
     19        virtual ~BCountry();
     20       
     21        virtual const char *Name() const;
     22
     23        // see definitions below
     24        const char *GetString(uint32 id) const;
     25
     26        // date & time
     27
     28        virtual void    FormatDate(char *string,size_t maxSize,time_t time,bool longFormat);
     29        virtual void    FormatDate(BString *string,time_t time,bool longFormat);
     30        virtual void    FormatTime(char *string,size_t maxSize,time_t time,bool longFormat);
     31        virtual void    FormatTime(BString *string,time_t time,bool longFormat);
     32
     33        const char      *DateFormat(bool longFormat) const;
     34        const char      *TimeFormat(bool longFormat) const;
     35        const char      *DateSeparator() const;
     36        const char      *TimeSeparator() const;
     37
     38        // numbers
     39
     40        virtual void    FormatNumber(char *string,size_t maxSize,double value);
     41        virtual void    FormatNumber(BString *string,double value);
     42        virtual void    FormatNumber(char *string,size_t maxSize,int32 value);
     43        virtual void    FormatNumber(BString *string,int32 value);
     44
     45        const char      *DecimalPoint() const;
     46        const char      *ThousandsSeparator() const;
     47        const char      *Grouping() const;
     48
     49        const char      *PositiveSign() const;
     50        const char      *NegativeSign() const;
     51
     52        // measurements
     53
     54        virtual int8    Measurement() const;
     55
     56        // monetary
     57
     58        virtual ssize_t FormatMonetary(char *string,size_t maxSize,char *format, ...);
     59        virtual ssize_t FormatMonetary(BString *string,char *format, ...);
     60
     61        const char      *CurrencySymbol() const;
     62        const char      *InternationalCurrencySymbol() const;
     63        const char      *MonDecimalPoint() const;
     64        const char      *MonThousandsSeparator() const;
     65        const char      *MonGrouping() const;
     66        virtual int32   MonFracDigits() const;
     67
     68    protected:
     69        BCountry(const char **strings);
     70
     71    private:
     72        const char  **fStrings;
     73};
     74
     75#endif  /* _COUNTRY_H_ */
  • headers/os/locale/UnicodeProperties.h

     
     1/*
     2** Copyright 2003, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
     3** Distributed under the terms of the OpenBeOS License.
     4*/
     5#ifndef _UNICODE_PROPERTIES_H_
     6#define _UNICODE_PROPERTIES_H_
     7
     8
     9#include <SupportDefs.h>
     10#include <ByteOrder.h>
     11
     12
     13#define PROPERTIES_DIRECTORY    "locale"
     14#define PROPERTIES_FILE_NAME    "unicode.properties"
     15#define PROPERTIES_FORMAT       'UPro'
     16
     17
     18typedef struct {
     19    uint8   size;
     20    uint8   isBigEndian;
     21    uint32  format;
     22    uint8   version[3];
     23} UnicodePropertiesHeader;
     24
     25#endif  /* _UNICODE_PROPERTIES_H_ */
  • headers/os/locale/IntegerFormat.h

     
     1#ifndef _B_INTEGER_FORMAT_H_
     2#define _B_INTEGER_FORMAT_H_
     3
     4#include <NumberFormat.h>
     5#include <IntegerFormatParameters.h>
     6
     7class BIntegerFormatImpl;
     8class BString;
     9
     10// Note: BIntegerFormat is derived from BIntegerFormatParameters only due
     11// to my laziness. The parameters should probably be a private member
     12// and this class (and its base classes) should mirror the parameters
     13// classes' accessor methods.
     14//
     15class _IMPEXP_LOCALE BIntegerFormat : public BNumberFormat, public BIntegerFormatParameters {
     16    public:
     17        BIntegerFormat(const BIntegerFormat &other);
     18        ~BIntegerFormat();
     19
     20        // formatting
     21
     22        // no-frills version: Simply appends the formatted number to the
     23        // string buffer. Can fail only with B_NO_MEMORY or B_BAD_VALUE.
     24        status_t Format(int64 number, BString *buffer) const;
     25
     26        // Appends the formatted number to the string buffer. Additionally
     27        // one can get the positions of certain fields in the formatted
     28        // number by supplying format_field_position structures with the
     29        // field_type set respectively. Passing true for allFieldPositions
     30        // will make the method fill in a format_field_position structure for
     31        // each field it writes -- the field_type values will be ignored and
     32        // overwritten.
     33        // In fieldCount, in case it is non-null, the number of fields
     34        // written is returned.
     35        // B_BUFFER_OVERFLOW is returned, if allFieldPositions is true and
     36        // the positions buffer is too small (fieldCount will be set
     37        // nevertheless, so that the caller can adjust the buffer size to
     38        // make them all fit).
     39        status_t Format(int64 number, BString *buffer,
     40                        format_field_position *positions,
     41                        int32 positionCount = 1,
     42                        int32 *fieldCount = NULL,
     43                        bool allFieldPositions = false) const;
     44
     45        // TODO: Format() versions for (char* buffer, size_t bufferSize)
     46        // instead of BString*. And, of course, versions for the other
     47        // number types (uint64, uint32,...).
     48 
     49        // parsing
     50        // TODO: ...
     51
     52        BIntegerFormat &operator=(const BIntegerFormat &other);
     53
     54        BIntegerFormat(BIntegerFormatImpl *impl);       // conceptually private
     55
     56    private:
     57        inline BIntegerFormatImpl *IntegerFormatImpl() const;
     58};
     59
     60
     61#endif  // _B_INTEGER_FORMAT_H_
  • headers/os/locale/CatalogInAddOn.h

     
     1#ifndef _CATALOG_IN_ADD_ON_H_
     2#define _CATALOG_IN_ADD_ON_H_
     3
     4#include <Catalog.h>
     5#include <Entry.h>
     6#include <Locale.h>
     7#include <LocaleRoster.h>
     8#include <Node.h>
     9#include <TypeConstants.h>
     10
     11/*
     12 * This header file is somewhat special...
     13 *
     14 * Since the TR-macros are referencing be_catalog, we want each add-on
     15 * to have its own be_catalog (instead of sharing the one from the lib).
     16 * In order to do so, we define another be_catalog in this file, which
     17 * will override the one from liblocale.so.
     18 * This way we implement something like add-on-local storage. It would
     19 * be desirable to find a better way, so please tell us if you know one!
     20 *
     21 * Every add-on that wants to use the Locale Kit needs to include this
     22 * file once (no more, exactly once!).
     23 * You have to include it in the source-file that loads the add-on's
     24 * catalog (by use of get_add_on_catalog().
     25 *
     26 */
     27
     28BCatalog *be_catalog = NULL;
     29    // global that points to this add-on's catalog
     30
     31
     32/*
     33 * utility function which determines the entry-ref for "this" add-on:
     34 */
     35static status_t
     36get_add_on_ref(entry_ref *ref)
     37{
     38    if (!ref)
     39        return B_BAD_VALUE;
     40
     41    image_info imageInfo;
     42    int32 cookie = 0;
     43    status_t res = B_ERROR;
     44    void *dataPtr = static_cast<void*>(&be_catalog);
     45    while ((res = get_next_image_info(0, &cookie, &imageInfo)) == B_OK) {
     46        char *dataStart = static_cast<char*>(imageInfo.data);
     47        if (imageInfo.type == B_ADD_ON_IMAGE && dataStart <= dataPtr
     48            && dataStart+imageInfo.data_size > dataPtr) {
     49            get_ref_for_path(imageInfo.name,ref);
     50            break;
     51        }
     52    }
     53    return res;
     54}
     55
     56
     57/*
     58 * Every add-on should load its catalog through this function, since
     59 * it does not only load the add-on's catalog, but it does several
     60 * other useful things:
     61 *    - be_catalog (the one belonging to this add-on) is initialized
     62 *      such that the TR-macros use the add-on's catalog.
     63 *    - if givenSig is empty (NULL or "") the add-on's signature is
     64 *      used to determine the catalog-sig.
     65 *    - if the add-on's executable contains an embedded catalog, that
     66 *      one is loaded, too.
     67 */
     68status_t
     69get_add_on_catalog(BCatalog* cat, const char *givenSig)
     70{
     71    if (!cat)
     72        return B_BAD_VALUE;
     73
     74    // determine entry-ref of the add-on this code lives in:
     75    entry_ref ref;
     76    status_t res = get_add_on_ref(&ref);
     77    if (res == B_OK) {
     78        // ok, we have found the entry-ref for our add-on,
     79        // so we try to fetch the fingerprint from our add-on-file:
     80        int32 fp = 0;
     81        BNode addOnNode(&ref);
     82        addOnNode.ReadAttr(BLocaleRoster::kCatFingerprintAttr,
     83            B_INT32_TYPE, 0, &fp, sizeof(int32));
     84        BString sig(givenSig);
     85        if (sig.Length() == 0) {
     86            res = addOnNode.ReadAttrString("BEOS:MIME", &sig);
     87            if (res == B_OK) {
     88                // drop supertype from mimetype (should be "application/"):
     89                int32 pos = sig.FindFirst('/');
     90                if (pos >= 0)
     91                    sig.Remove(0, pos+1);
     92            }
     93        }
     94        if (res == B_OK) {
     95            // try to load it's catalog...
     96            cat->fCatalog
     97                = be_locale_roster->LoadCatalog(sig.String(), NULL, fp);
     98            // ...and try to load an embedded catalog, too (if that exists):
     99            BCatalogAddOn *embeddedCatalog
     100                = be_locale_roster->LoadEmbeddedCatalog(&ref);
     101            if (embeddedCatalog) {
     102                if (!cat->fCatalog)
     103                    // embedded catalog is the only catalog that was found:
     104                    cat->fCatalog = embeddedCatalog;
     105                else {
     106                    // append embedded catalog to list of loaded catalogs:
     107                    BCatalogAddOn *currCat = cat->fCatalog;
     108                    while (currCat->fNext)
     109                        currCat = currCat->fNext;
     110                    currCat->fNext = embeddedCatalog;
     111                }
     112            }
     113            be_catalog = cat;
     114        }
     115    }
     116    return cat->InitCheck();
     117}
     118
     119
     120#endif  /* _CATALOG_IN_ADD_ON_H_ */
  • headers/os/locale/LocaleStrings.h

     
     1#ifndef _LOCALE_STRINGS_H_
     2#define _LOCALE_STRINGS_H_
     3
     4
     5enum country_strings {
     6    B_COUNTRY_STRINGS_BASE  = 0,
     7
     8    B_DATE_TIME_FORMAT      = B_COUNTRY_STRINGS_BASE,
     9    B_DATE_FORMAT,
     10    B_TIME_FORMAT,
     11    B_TIME_AM_PM_FORMAT,
     12
     13    B_SHORT_DATE_TIME_FORMAT,
     14    B_SHORT_DATE_FORMAT,
     15    B_SHORT_TIME_FORMAT,
     16    B_SHORT_TIME_AM_PM_FORMAT,
     17
     18    B_AM_STRING,
     19    B_PM_STRING,
     20
     21    B_DATE_SEPARATOR,
     22    B_TIME_SEPARATOR,
     23    B_GROUPING,
     24    B_DECIMAL_POINT,
     25    B_THOUSANDS_SEPARATOR,
     26    B_POSITIVE_SIGN,
     27    B_NEGATIVE_SIGN,
     28
     29    B_CURRENCY_SYMBOL,
     30    B_INT_CURRENCY_SYMBOL,
     31    B_MON_GROUPING,
     32    B_MON_DECIMAL_POINT,
     33    B_MON_THOUSANDS_SEPARATOR,
     34
     35    B_NUM_COUNTRY_STRINGS,
     36};
     37
     38enum language_strings {
     39    B_LANGUAGE_STRINGS_BASE = 100,
     40
     41    B_YESTERDAY_STRING = B_LANGUAGE_STRINGS_BASE,
     42    B_TODAY_STRING,
     43    B_TOMORROW_STRING,
     44    B_FUTURE_STRING,
     45
     46    B_DAY_1,        // name of the first day of the week, e.g. Sunday
     47    B_DAY_2,        // ...
     48    B_DAY_3,        //
     49    B_DAY_4,
     50    B_DAY_5,
     51    B_DAY_6,
     52    B_DAY_7,
     53
     54    B_AB_DAY_1,     // abbreviated weekday name, e.g. Sun
     55    B_AB_DAY_2,     // ...
     56    B_AB_DAY_3,
     57    B_AB_DAY_4,
     58    B_AB_DAY_5,
     59    B_AB_DAY_6,
     60    B_AB_DAY_7,
     61
     62    B_MON_1,        // name of the first month of the year, e.g. January
     63    B_MON_2,        // ...
     64    B_MON_3,
     65    B_MON_4,
     66    B_MON_5,
     67    B_MON_6,
     68    B_MON_7,
     69    B_MON_8,
     70    B_MON_9,
     71    B_MON_10,
     72    B_MON_11,
     73    B_MON_12,
     74
     75    B_AB_MON_1,     // abbreviated month name, e.g. Jan
     76    B_AB_MON_2,     // ...
     77    B_AB_MON_3,
     78    B_AB_MON_4,
     79    B_AB_MON_5,
     80    B_AB_MON_6,
     81    B_AB_MON_7,
     82    B_AB_MON_8,
     83    B_AB_MON_9,
     84    B_AB_MON_10,
     85    B_AB_MON_11,
     86    B_AB_MON_12,
     87
     88    B_YES_EXPRESSION,
     89    B_NO_EXPRESSION,
     90    B_YES_STRING,
     91    B_NO_STRING,
     92
     93    B_NUM_LANGUAGE_STRINGS = B_AB_MON_12 - B_LANGUAGE_STRINGS_BASE,
     94};
     95
     96// specials for POSIX compatibility
     97enum other_locale_strings {
     98    B_OTHER_STRINGS_BASE    = 200,
     99
     100    B_CODESET   = B_OTHER_STRINGS_BASE,
     101    B_ERA,
     102    B_ERA_DATE_FORMAT,
     103    B_ERA_DATE_TIME_FORMAT,
     104    B_ERA_TIME_FORMAT,
     105    B_ALT_DIGITS
     106};
     107
     108#endif  /* _LOCALE_STRINGS_H_ */
  • headers/os/locale/FormatImpl.h

     
     1#ifndef _B_FORMAT_IMPL_H_
     2#define _B_FORMAT_IMPL_H_
     3
     4#include <SupportDefs.h>
     5
     6#include <LocaleBuild.h>
     7
     8class BFormatParameters;
     9
     10class _IMPEXP_LOCALE BFormatImpl {
     11    public:
     12        BFormatImpl();
     13        virtual ~BFormatImpl();
     14
     15        virtual BFormatParameters *DefaultFormatParameters() = 0;
     16        virtual const BFormatParameters *DefaultFormatParameters()
     17            const = 0;
     18};
     19
     20#endif  // _B_FORMAT_IMPL_H_
  • headers/os/locale/Catalog.h

     
     1#ifndef _CATALOG_H_
     2#define _CATALOG_H_
     3
     4#include <LocaleBuild.h>
     5
     6#include <SupportDefs.h>
     7#include <String.h>
     8
     9class BCatalogAddOn;
     10class BLocale;
     11class BMessage;
     12struct entry_ref;
     13
     14
     15class _IMPEXP_LOCALE BCatalog {
     16
     17    public:
     18        BCatalog();
     19        BCatalog(const char *signature, const char *language = NULL,
     20            int32 fingerprint = 0);
     21        virtual ~BCatalog();
     22
     23        const char *GetString(const char *string, const char *context = NULL,
     24                        const char *comment = NULL);
     25        const char *GetString(uint32 id);
     26
     27        status_t GetData(const char *name, BMessage *msg);
     28        status_t GetData(uint32 id, BMessage *msg);
     29
     30        status_t GetSignature(BString *sig);
     31        status_t GetLanguage(BString *lang);
     32        status_t GetFingerprint(int32 *fp);
     33
     34        status_t InitCheck() const;
     35        int32 CountItems() const;
     36
     37        BCatalogAddOn *CatalogAddOn();
     38
     39    protected:
     40        BCatalog(const BCatalog&);
     41        const BCatalog& operator= (const BCatalog&);
     42            // hide assignment and copy-constructor
     43
     44        static status_t GetAppCatalog(BCatalog*);
     45
     46        BCatalogAddOn *fCatalog;
     47
     48    private:
     49        friend class BLocale;
     50        friend status_t get_add_on_catalog(BCatalog*, const char *);
     51};
     52
     53
     54extern _IMPEXP_LOCALE BCatalog* be_catalog;
     55extern _IMPEXP_LOCALE BCatalog* be_app_catalog;
     56
     57
     58#ifndef B_AVOID_TRANSLATION_MACROS
     59// macros for easy catalog-access, define B_AVOID_TRANSLATION_MACROS if
     60// you don't want these:
     61
     62#undef TR_CONTEXT
     63    // In a single application, several strings (e.g. 'Ok') will be used
     64    // more than once, in different contexts.
     65    // As the application programmer can not know if all translations of
     66    // this string will be the same for all languages, each occurrence of
     67    // the string must be translated on its own.
     68    // Specifying the context explicitly with each string allows the person
     69    // translating a catalog to separate these different occurrences of the
     70    // same string and tell which strings appears in what context of the
     71    // application.
     72    // In order to give the translator a useful hint, the application
     73    // programmer needs to define TR_CONTEXT with the context he'd like
     74    // to be associated with the strings used in this specifc source file.
     75    // example:
     76    //      #define TR_CONTEXT "Folder-Window"
     77    // Tip: Use a descriptive name of the class implemented in that
     78    //      source-file.
     79
     80
     81// Translation macros which may be used to shorten translation requests:
     82#undef TR
     83#define TR(str) \
     84    be_catalog->GetString((str), TR_CONTEXT)
     85
     86#undef TR_CMT
     87#define TR_CMT(str,cmt) \
     88    be_catalog->GetString((str), TR_CONTEXT, (cmt))
     89
     90#undef TR_ALL
     91#define TR_ALL(str,ctx,cmt) \
     92    be_catalog->GetString((str), (ctx), (cmt))
     93
     94#undef TR_ID
     95#define TR_ID(id) \
     96    be_catalog->GetString((id))
     97
     98
     99// Translation markers which can be used to mark static strings/IDs which
     100// are used as key for translation requests (at other places in the code):
     101/* example:
     102        #define TR_CONTEXT "MyDecentApp-Menu"
     103
     104        static const char *choices[] = {
     105            TR_MARK("left"),
     106            TR_MARK("right"),
     107            TR_MARK("up"),
     108            TR_MARK("down")
     109        };
     110
     111        void MyClass::AddChoices(BMenu *menu) {
     112            for (char **ch = choices; *ch; ch++) {
     113                menu->AddItem(
     114                    new BMenuItem(
     115                        TR(*ch),
     116                        new BMessage(...)
     117                    )
     118                )
     119            }
     120        }
     121*/
     122#undef TR_MARK
     123#define TR_MARK(str) \
     124    BCatalogAddOn::MarkForTranslation((str), TR_CONTEXT, "")
     125
     126#undef TR_MARK_CMT
     127#define TR_MARK_CMT(str,cmt) \
     128    BCatalogAddOn::MarkForTranslation((str), TR_CONTEXT, (cmt))
     129
     130#undef TR_MARK_ALL
     131#define TR_MARK_ALL(str,ctx,cmt) \
     132    BCatalogAddOn::MarkForTranslation((str), (ctx), (cmt))
     133   
     134#undef TR_MARK_ID
     135#define TR_MARK_ID(id) \
     136    BCatalogAddOn::MarkForTranslation((id))
     137   
     138#endif  /* B_AVOID_TRANSLATION_MACROS */
     139
     140
     141/************************************************************************/
     142// For BCatalog add-on implementations:
     143
     144class _IMPEXP_LOCALE BCatalogAddOn {
     145        friend class BLocaleRoster;
     146    public:
     147        BCatalogAddOn(const char *signature, const char *language,
     148                      int32 fingerprint);
     149        virtual ~BCatalogAddOn();
     150
     151        virtual const char *GetString(const char *string,
     152                                const char *context=NULL,
     153                                const char *comment=NULL) = 0;
     154        virtual const char *GetString(uint32 id) = 0;
     155
     156        status_t InitCheck() const;
     157        BCatalogAddOn *Next();
     158
     159        // the following could be used to localize non-textual data (e.g. icons),
     160        // but these will only be implemented if there's demand for such a
     161        // feature:
     162        virtual bool CanHaveData() const;
     163        virtual status_t GetData(const char *name, BMessage *msg);
     164        virtual status_t GetData(uint32 id, BMessage *msg);
     165
     166        // interface for catalog-editor-app and testing apps:
     167        virtual status_t SetString(const char *string,
     168                            const char *translated,
     169                            const char *context=NULL,
     170                            const char *comment=NULL);
     171        virtual status_t SetString(int32 id, const char *translated);
     172        //
     173        virtual bool CanWriteData() const;
     174        virtual status_t SetData(const char *name, BMessage *msg);
     175        virtual status_t SetData(uint32 id, BMessage *msg);
     176        //
     177        virtual status_t ReadFromFile(const char *path = NULL);
     178        virtual status_t ReadFromAttribute(entry_ref *appOrAddOnRef);
     179        virtual status_t ReadFromResource(entry_ref *appOrAddOnRef);
     180        virtual status_t WriteToFile(const char *path = NULL);
     181        virtual status_t WriteToAttribute(entry_ref *appOrAddOnRef);
     182        virtual status_t WriteToResource(entry_ref *appOrAddOnRef);
     183        //
     184        virtual void MakeEmpty();
     185        virtual int32 CountItems() const;
     186
     187        // magic marker functions which are used to mark a string/id
     188        // which will be translated elsewhere in the code (where it can
     189        // not be found since it is references by a variable):
     190        static const char *MarkForTranslation(const char *str, const char *ctx,
     191                                const char *cmt);
     192        static int32 MarkForTranslation(int32 id);
     193
     194    protected:
     195        virtual void UpdateFingerprint();
     196
     197        status_t            fInitCheck;
     198        BString             fSignature;
     199        BString             fLanguageName;
     200        int32               fFingerprint;
     201        BCatalogAddOn       *fNext;
     202       
     203        friend class BCatalog;
     204        friend status_t get_add_on_catalog(BCatalog*, const char *);
     205};
     206
     207// every catalog-add-on should export these symbols...
     208// ...the function that instantiates a catalog for this add-on-type...
     209extern "C" _IMPEXP_LOCALE
     210BCatalogAddOn *instantiate_catalog(const char *signature,
     211    const char *language, int32 fingerprint);
     212// ...the function that creates an empty catalog for this add-on-type...
     213extern "C" _IMPEXP_LOCALE
     214BCatalogAddOn *create_catalog(const char *signature,
     215    const char *language);
     216// ...and the priority which will be used to order the catalog-add-ons:
     217extern _IMPEXP_LOCALE uint8 gCatalogAddOnPriority;
     218
     219
     220/*
     221 * BCatalog - inlines for trivial accessors:
     222 */
     223inline status_t
     224BCatalog::GetSignature(BString *sig)
     225{
     226    if (!sig)
     227        return B_BAD_VALUE;
     228    if (!fCatalog)
     229        return B_NO_INIT;
     230    *sig = fCatalog->fSignature;
     231    return B_OK;
     232}
     233
     234
     235inline status_t
     236BCatalog::GetLanguage(BString *lang)
     237{
     238    if (!lang)
     239        return B_BAD_VALUE;
     240    if (!fCatalog)
     241        return B_NO_INIT;
     242    *lang = fCatalog->fLanguageName;
     243    return B_OK;
     244}   
     245
     246
     247inline status_t
     248BCatalog::GetFingerprint(int32 *fp)
     249{
     250    if (!fp)
     251        return B_BAD_VALUE;
     252    if (!fCatalog)
     253        return B_NO_INIT;
     254    *fp = fCatalog->fFingerprint;
     255    return B_OK;
     256}
     257
     258
     259inline status_t
     260BCatalog::InitCheck() const
     261{
     262    return fCatalog
     263                ? fCatalog->InitCheck()
     264                : B_NO_INIT;
     265}
     266
     267
     268inline int32
     269BCatalog::CountItems() const
     270{
     271    if (!fCatalog)
     272        return 0;
     273    return fCatalog->CountItems();
     274}
     275
     276
     277inline BCatalogAddOn *
     278BCatalog::CatalogAddOn()
     279{
     280    return fCatalog;
     281}
     282
     283
     284/*
     285 * BCatalogAddOn - inlines for trivial accessors:
     286 */
     287inline BCatalogAddOn *
     288BCatalogAddOn::Next()
     289{
     290    return fNext;
     291}
     292
     293
     294inline const char *
     295BCatalogAddOn::MarkForTranslation(const char *str, const char *ctx,
     296    const char *cmt)
     297{
     298    return str;
     299}
     300
     301
     302inline int32
     303BCatalogAddOn::MarkForTranslation(int32 id)
     304{
     305    return id;
     306}
     307
     308
     309namespace BPrivate {
     310
     311/*
     312 * EditableCatalog
     313 */
     314class _IMPEXP_LOCALE EditableCatalog : public BCatalog {
     315
     316    public:
     317        EditableCatalog(const char *type, const char *signature,
     318            const char *language);
     319        ~EditableCatalog();
     320
     321        status_t SetString(const char *string,
     322                    const char *translated,
     323                    const char *context=NULL,
     324                    const char *comment=NULL);
     325        status_t SetString(int32 id, const char *translated);
     326        //
     327        bool CanWriteData() const;
     328        status_t SetData(const char *name, BMessage *msg);
     329        status_t SetData(uint32 id, BMessage *msg);
     330        //
     331        status_t ReadFromFile(const char *path = NULL);
     332        status_t ReadFromAttribute(entry_ref *appOrAddOnRef);
     333        status_t ReadFromResource(entry_ref *appOrAddOnRef);
     334        status_t WriteToFile(const char *path = NULL);
     335        status_t WriteToAttribute(entry_ref *appOrAddOnRef);
     336        status_t WriteToResource(entry_ref *appOrAddOnRef);
     337        //
     338        void MakeEmpty();
     339
     340    private:
     341        EditableCatalog();
     342        EditableCatalog(const EditableCatalog&);
     343        const EditableCatalog& operator= (const EditableCatalog&);
     344            // hide assignment, default- and copy-constructor
     345
     346};
     347
     348} // namespace BPrivate
     349
     350#endif  /* _CATALOG_H_ */
  • headers/os/locale/posix/nl_types.h

     
     1#ifndef _NL_TYPES_H_
     2#define _NL_TYPES_H_
     3
     4#define NL_SETD         0
     5#define NL_CAT_LOCALE   1
     6
     7typedef int nl_item;
     8typedef void *nl_catd;
     9
     10#include <LocaleBuild.h>
     11
     12#ifdef __cplusplus
     13extern "C" {
     14#endif
     15
     16extern _IMPEXP_LOCALE nl_catd catopen(const char *name, int oflag);
     17extern _IMPEXP_LOCALE char *catgets(nl_catd cat,int setID,int msgID,const char *defaultMessage);
     18extern _IMPEXP_LOCALE int catclose(nl_catd cat);
     19
     20#ifdef __cplusplus
     21}
     22#endif
     23
     24#endif  /* _NL_TYPES_H_ */
  • headers/os/locale/posix/langinfo.h

     
     1#ifndef _LANGINFO_H_
     2#define _LANGINFO_H_
     3
     4#include <LocaleBuild.h>
     5
     6#include <LocaleStrings.h>
     7#include <nl_types.h>
     8
     9#define CODESET     B_CODESET           /* codeset name */
     10#define D_T_FMT     B_DATE_TIME_FORMAT  /* string for formatting date and time */
     11#define D_FMT       B_DATE_FORMAT       /* date format string */
     12#define T_FMT       B_TIME_FORMAT       /* time format string */
     13#define T_FMT_AMPM  B_AM_PM_TIME_FORMAT /* a.m. or p.m. time formatting string */
     14#define AM_STR      B_AM_STRING         /* Ante Meridian affix */
     15#define PM_STR      B_PM_STRING         /* Post Meridian affix */
     16
     17/* week day names */
     18#define DAY_1       B_DAY_1
     19#define DAY_2       B_DAY_2
     20#define DAY_3       B_DAY_3
     21#define DAY_4       B_DAY_4
     22#define DAY_5       B_DAY_5
     23#define DAY_6       B_DAY_6
     24#define DAY_7       B_DAY_7
     25
     26/* abbreviated week day names */
     27#define ABDAY_1     B_AB_DAY_1
     28#define ABDAY_2     B_AB_DAY_2
     29#define ABDAY_3     B_AB_DAY_3
     30#define ABDAY_4     B_AB_DAY_4
     31#define ABDAY_5     B_AB_DAY_5
     32#define ABDAY_6     B_AB_DAY_6
     33#define ABDAY_7     B_AB_DAY_7
     34
     35/* month names */
     36#define MON_1       B_MON_1
     37#define MON_2       B_MON_2
     38#define MON_3       B_MON_3
     39#define MON_4       B_MON_4
     40#define MON_5       B_MON_5
     41#define MON_6       B_MON_6
     42#define MON_7       B_MON_7
     43#define MON_8       B_MON_8
     44#define MON_9       B_MON_9
     45#define MON_10      B_MON_10
     46#define MON_11      B_MON_11
     47#define MON_12      B_MON_12
     48
     49/* abbreviated month names */
     50#define ABMON_1     B_AB_MON_1
     51#define ABMON_2     B_AB_MON_2
     52#define ABMON_3     B_AB_MON_3
     53#define ABMON_4     B_AB_MON_4
     54#define ABMON_5     B_AB_MON_5
     55#define ABMON_6     B_AB_MON_6
     56#define ABMON_7     B_AB_MON_7
     57#define ABMON_8     B_AB_MON_8
     58#define ABMON_9     B_AB_MON_9
     59#define ABMON_10    B_AB_MON_10
     60#define ABMON_11    B_AB_MON_11
     61#define ABMON_12    B_AB_MON_12
     62
     63#define ERA         B_ERA                   /* era description segments */
     64#define ERA_D_FMT   B_ERA_DATE_FORMAT       /* era date format string */
     65#define ERA_D_T_FMT B_ERA_DATE_TIME_FORMAT  /* era date and time format string */
     66#define ERA_T_FMT   B_TIME_FORMAT           /* era time format string */
     67#define ALT_DIGITS  B_ALT_DIGITS            /* alternative symbols for digits */
     68
     69#define RADIXCHAR   B_DECIMAL_POINT         /* radix char */
     70#define THOUSEP     B_THOUSANDS_SEPARATOR   /* separator for thousands */
     71
     72#define YESEXPR     B_YES_EXPRESSION        /* affirmative response expression */
     73#define NOEXPR      B_NO_EXPRESSION         /* negative response expression */
     74#define YESSTR      B_YES_STRING            /* affirmative response for yes/no queries */
     75#define NOSTR       B_NO_STRING             /* negative response for yes/no queries */
     76
     77#define CRNCYSTR    B_CURRENCY_SYMBOL       /* currency symbol */
     78
     79//#define   D_MD_ORDER  57  /* month/day order (local extension) */
     80
     81#ifdef __cplusplus
     82extern "C"
     83#endif
     84_IMPEXP_LOCALE char *nl_langinfo(nl_item);
     85
     86#endif  /* _LANGINFO_H_ */
  • headers/os/locale/posix/monetary.h

     
     1#ifndef _MONETARY_H_
     2#define _MONETARY_H_
     3
     4#include <stdarg.h>
     5
     6#include <LocaleBuild.h>
     7
     8#ifdef __cplusplus
     9extern "C" {
     10#endif
     11
     12_IMPEXP_LOCALE ssize_t strfmon(char *string, size_t maxSize, const char *format, ...);
     13_IMPEXP_LOCALE ssize_t vstrfmon(char *string, size_t maxSize, const char *format, va_list args);
     14
     15#ifdef __cplusplus
     16}
     17#endif
     18
     19#endif  /* _MONETARY_H_ */
  • headers/os/locale/FormatParameters.h

     
     1#ifndef _B_FORMAT_PARAMETERS_H_
     2#define _B_FORMAT_PARAMETERS_H_
     3
     4#include <SupportDefs.h>
     5
     6#include <LocaleBuild.h>
     7
     8enum format_alignment {
     9    B_ALIGN_FORMAT_LEFT,        // reuse B_ALIGN_LEFT/B_ALIGN_RIGHT?
     10    B_ALIGN_FORMAT_RIGHT,
     11};
     12
     13class _IMPEXP_LOCALE BFormatParameters {
     14    public:
     15        BFormatParameters(const BFormatParameters *parent = NULL);
     16        BFormatParameters(const BFormatParameters &other);
     17        ~BFormatParameters();
     18
     19        void SetAlignment(format_alignment alignment);
     20        format_alignment Alignment() const;
     21
     22        void SetFormatWidth(size_t width);
     23        size_t FormatWidth() const;
     24
     25        const BFormatParameters *ParentParameters() const;
     26
     27        BFormatParameters &operator=(const BFormatParameters &other);
     28
     29    protected:
     30        void SetParentParameters(const BFormatParameters *parent);
     31
     32    private:
     33        const BFormatParameters *fParent;
     34        format_alignment        fAlignment;
     35        size_t                  fWidth;
     36        uint32                  fFlags;
     37};
     38
     39#endif  // _B_FORMAT_PARAMETERS_H_
  • headers/os/locale/FloatFormat.h

     
     1#ifndef _B_FLOAT_FORMAT_H_
     2#define _B_FLOAT_FORMAT_H_
     3
     4#include <NumberFormat.h>
     5#include <FloatFormatParameters.h>
     6
     7class BString;
     8class BFloatFormatImpl;
     9
     10class _IMPEXP_LOCALE BFloatFormat : public BNumberFormat, public BFloatFormatParameters {
     11    public:
     12        BFloatFormat(const BFloatFormat &other);
     13        ~BFloatFormat();
     14
     15        // formatting
     16
     17        // no-frills version: Simply appends the formatted number to the
     18        // string buffer. Can fail only with B_NO_MEMORY or B_BAD_VALUE.
     19        status_t Format(double number, BString *buffer) const;
     20
     21        // Appends the formatted number to the string buffer. Additionally
     22        // one can get the positions of certain fields in the formatted
     23        // number by supplying format_field_position structures with the
     24        // field_type set respectively. Passing true for allFieldPositions
     25        // will make the method fill in a format_field_position structure for
     26        // each field it writes -- the field_type values will be ignored and
     27        // overwritten.
     28        // In fieldCount, in case it is non-null, the number of fields
     29        // written is returned.
     30        // B_BUFFER_OVERFLOW is returned, if allFieldPositions is true and
     31        // the positions buffer is too small (fieldCount will be set
     32        // nevertheless, so that the caller can adjust the buffer size to
     33        // make them all fit).
     34        status_t Format(double number, BString *buffer,
     35                        format_field_position *positions,
     36                        int32 positionCount = 1,
     37                        int32 *fieldCount = NULL,
     38                        bool allFieldPositions = false) const;
     39
     40        // TODO: Format() versions for (char* buffer, size_t bufferSize)
     41        // instead of BString*. And, of course, versions for the other
     42        // number types (float).
     43 
     44        // parsing
     45        // TODO: ...
     46
     47        BFloatFormat &operator=(const BFloatFormat &other);
     48
     49        BFloatFormat(BFloatFormatImpl *impl);       // conceptually private
     50
     51    private:
     52        inline BFloatFormatImpl *FloatFormatImpl() const;
     53};
     54
     55
     56#endif  // _B_FLOAT_FORMAT_H_
  • headers/os/locale/DefaultCatalog.h

     
     1#ifndef _DEFAULT_CATALOG_H_
     2#define _DEFAULT_CATALOG_H_
     3
     4
     5#include <LocaleBuild.h>
     6
     7#include <DataIO.h>
     8#include <Catalog.h>
     9#include <String.h>
     10#include <assert.h>
     11
     12#if __GNUC__ > 2
     13#   include <ext/hash_map>
     14#else
     15#   include <hash_map>
     16#endif
     17
     18class BFile;
     19
     20namespace BPrivate {
     21    struct CatKey;
     22}
     23
     24#if __GNUC__ > 2
     25namespace __gnu_cxx{
     26#endif
     27
     28template<> struct hash<BPrivate::CatKey> {
     29    size_t operator() (const BPrivate::CatKey &key) const;
     30};
     31
     32#if __GNUC__ > 2
     33} // __gnu_cxx
     34
     35using namespace __gnu_cxx;
     36#endif
     37
     38namespace BPrivate {
     39
     40/*
     41 * The key-type for the hash_map which maps native strings or IDs to
     42 * the corresponding translated string.
     43 * The key-type should be efficient to use if it is just created by an ID
     44 * but it should also support being created from up to three strings,
     45 * which as a whole specify the key to the translated string.
     46 */
     47struct _IMPEXP_LOCALE CatKey {
     48    BString fKey;
     49        // the key-string consists of three values separated by a special
     50        // token:
     51        // - the native string
     52        // - the context of the string's usage
     53        // - a comment that can be used to separate strings that
     54        //   are identical otherwise (useful for the translator)
     55    size_t fHashVal;
     56        // the hash-value of fKey
     57    uint32 fFlags;
     58        // with respect to the catalog-editor, each translation can be
     59        // in different states (empty, unchecked, checked, etc.).
     60        // This state (and potential other flags) lives in the fFlags member.
     61    CatKey(const char *str, const char *ctx, const char *cmt);
     62    CatKey(uint32 id);
     63    CatKey();
     64    bool operator== (const CatKey& right) const;
     65    status_t GetStringParts(BString* str, BString* ctx, BString* cmt) const;
     66    static size_t HashFun(const char* s);
     67};
     68
     69/*
     70 * The implementation of the Locale Kit's standard catalog-type.
     71 * Currently it only maps CatKey to a BString (the translated string),
     72 * but the value-type might change to add support for shortcuts and/or
     73 * graphical data (button-images and the like).
     74 */
     75class _IMPEXP_LOCALE DefaultCatalog : public BCatalogAddOn {
     76
     77    public:
     78        DefaultCatalog(const char *signature, const char *language,
     79            int32 fingerprint);
     80                // constructor for normal use
     81        DefaultCatalog(entry_ref *appOrAddOnRef);
     82                // constructor for embedded catalog
     83        DefaultCatalog(const char *path, const char *signature,
     84            const char *language);
     85                // constructor for editor-app
     86                       
     87        ~DefaultCatalog();
     88
     89        // overrides of BCatalogAddOn:
     90        const char *GetString(const char *string, const char *context = NULL,
     91                        const char *comment = NULL);
     92        const char *GetString(uint32 id);
     93        const char *GetString(const CatKey& key);
     94        //
     95        status_t SetString(const char *string, const char *translated,
     96                    const char *context = NULL, const char *comment = NULL);
     97        status_t SetString(int32 id, const char *translated);
     98        status_t SetString(const CatKey& key, const char *translated);
     99        void UpdateFingerprint();
     100
     101        // implementation for editor-interface:
     102        status_t ReadFromFile(const char *path = NULL);
     103        status_t ReadFromAttribute(entry_ref *appOrAddOnRef);
     104        status_t ReadFromResource(entry_ref *appOrAddOnRef);
     105        status_t WriteToFile(const char *path = NULL);
     106        status_t WriteToAttribute(entry_ref *appOrAddOnRef);
     107        status_t WriteToResource(entry_ref *appOrAddOnRef);
     108        //
     109        void MakeEmpty();
     110        int32 CountItems() const;
     111
     112        static BCatalogAddOn *Instantiate(const char *signature,
     113                                const char *language,
     114                                int32 fingerprint);
     115        static BCatalogAddOn *InstantiateEmbedded(entry_ref *appOrAddOnRef);
     116        static BCatalogAddOn *Create(const char *signature,
     117                                const char *language);
     118        static const uint8 kDefaultCatalogAddOnPriority;
     119        static const char *kCatMimeType;
     120
     121    private:
     122        status_t Flatten(BDataIO *dataIO);
     123        status_t Unflatten(BDataIO *dataIO);
     124        int32 ComputeFingerprint() const;
     125        void UpdateAttributes(BFile& catalogFile);
     126
     127        typedef hash_map<CatKey, BString, hash<CatKey>, equal_to<CatKey> > CatMap;
     128        CatMap              fCatMap;
     129        mutable BString     fPath;
     130
     131    public:
     132        /*
     133         * CatWalker
     134         */
     135        class CatWalker {
     136            public:
     137                CatWalker() {}
     138                CatWalker(CatMap &catMap);
     139                bool AtEnd() const;
     140                const CatKey& GetKey() const;
     141                const char *GetValue() const;
     142                void Next();
     143            private:
     144                CatMap::iterator fPos;
     145                CatMap::iterator fEnd;
     146        };
     147        status_t GetWalker(CatWalker *walker);     
     148};
     149
     150inline
     151DefaultCatalog::CatWalker::CatWalker(CatMap &catMap)
     152    : fPos(catMap.begin()),
     153      fEnd(catMap.end())
     154{
     155}
     156
     157inline bool
     158DefaultCatalog::CatWalker::AtEnd() const
     159{
     160    return fPos == fEnd;
     161}
     162
     163inline const CatKey &
     164DefaultCatalog::CatWalker::GetKey() const
     165{
     166    assert(fPos != fEnd);
     167    return fPos->first;
     168}
     169
     170inline const char *
     171DefaultCatalog::CatWalker::GetValue() const
     172{
     173    assert(fPos != fEnd);
     174    return fPos->second.String();
     175}
     176
     177inline void
     178DefaultCatalog::CatWalker::Next()
     179{
     180    ++fPos;
     181}
     182
     183inline status_t
     184DefaultCatalog::GetWalker(CatWalker *walker)
     185{
     186    if (!walker)
     187        return B_BAD_VALUE;
     188    *walker = CatWalker(fCatMap);
     189    return B_OK;
     190}       
     191
     192}   // namespace BPrivate
     193
     194using namespace BPrivate;
     195
     196#endif  /* _DEFAULT_CATALOG_H_ */
  • headers/os/locale/LocaleBuild.h

     
     1#ifndef _B_LOCALE_BUILD_H_
     2#define _B_LOCALE_BUILD_H_
     3
     4#define _IMPEXP_LOCALE
     5
     6#endif  /* _B_LOCALE_BUILD_H_ */
  • headers/os/locale/Collator.h

     
     1#ifndef _COLLATOR_H_
     2#define _COLLATOR_H_
     3
     4
     5#include <SupportDefs.h>
     6#include <Archivable.h>
     7
     8#include <LocaleBuild.h>
     9
     10class BString;
     11class BCollatorAddOn;
     12
     13
     14enum collator_strengths {
     15    B_COLLATE_DEFAULT = -1,
     16
     17    B_COLLATE_PRIMARY = 1,      // e.g.: no diacritical differences, e = é
     18    B_COLLATE_SECONDARY,        // diacritics are different from their base characters, a != ä
     19    B_COLLATE_TERTIARY,         // case sensitive comparison
     20    B_COLLATE_QUATERNARY,
     21
     22    B_COLLATE_IDENTICAL = 127   // Unicode value
     23};
     24
     25
     26class _IMPEXP_LOCALE BCollator : public BArchivable {
     27    public:
     28        BCollator();
     29        BCollator(BCollatorAddOn *collator, int8 strength, bool ignorePunctuation);
     30        BCollator(BMessage *archive);
     31        ~BCollator();
     32
     33        void SetDefaultStrength(int8 strength);
     34        int8 DefaultStrength() const;
     35
     36        void SetIgnorePunctuation(bool ignore);
     37        bool IgnorePunctuation() const;
     38
     39        status_t GetSortKey(const char *string, BString *key, int8 strength = B_COLLATE_DEFAULT);
     40
     41        int Compare(const char *, const char *, int32 len = -1, int8 strength = B_COLLATE_DEFAULT);
     42        bool Equal(const char *, const char *, int32 len = -1, int8 strength = B_COLLATE_DEFAULT);
     43        bool Greater(const char *, const char *, int32 len = -1, int8 strength = B_COLLATE_DEFAULT);
     44        bool GreaterOrEqual(const char *, const char *, int32 len = -1, int8 strength = B_COLLATE_DEFAULT);
     45
     46        // (un-)archiving API
     47        status_t Archive(BMessage *archive, bool deep) const;
     48        static BArchivable *Instantiate(BMessage *archive);
     49
     50    private:
     51        BCollatorAddOn  *fCollator;
     52        image_id        fCollatorImage;
     53        int8            fStrength;
     54        bool            fIgnorePunctuation;
     55};
     56
     57
     58inline bool
     59BCollator::Equal(const char *s1, const char *s2, int32 len, int8 strength)
     60{
     61    return Compare(s1, s2, len, strength) == 0;
     62}
     63
     64
     65inline bool
     66BCollator::Greater(const char *s1, const char *s2, int32 len, int8 strength)
     67{
     68    return Compare(s1, s2, len, strength) > 0;
     69}
     70
     71
     72inline bool
     73BCollator::GreaterOrEqual(const char *s1, const char *s2, int32 len, int8 strength)
     74{
     75    return Compare(s1, s2, len, strength) >= 0;
     76}
     77
     78
     79/************************************************************************/
     80
     81// For BCollator add-on implementations:
     82
     83class _IMPEXP_LOCALE BCollatorAddOn : public BArchivable {
     84    public:
     85        BCollatorAddOn();
     86        BCollatorAddOn(BMessage *archive);
     87        virtual ~BCollatorAddOn();
     88
     89        virtual status_t GetSortKey(const char *string, BString *key, int8 strength,
     90                        bool ignorePunctuation);
     91        virtual int Compare(const char *a, const char *b, int32 length, int8 strength,
     92                        bool ignorePunctuation);
     93
     94        // (un-)archiving API
     95        virtual status_t Archive(BMessage *archive, bool deep) const;
     96        static BArchivable *Instantiate(BMessage *archive);
     97
     98        struct input_context {
     99            input_context(bool ignorePunctuation);
     100
     101            bool    ignore_punctuation;
     102            uint32  next_char;
     103            int32   reserved1;
     104            int32   reserved2;
     105        };
     106
     107    protected:
     108        virtual uint32 GetNextChar(const char **string, input_context &context);
     109        virtual size_t PrimaryKeyLength(size_t length);
     110        virtual char *PutPrimaryKey(const char *string, char *buffer, int32 length,
     111                        bool ignorePunctuation);
     112};
     113
     114// If your add-on should work with the standard tool to create a language, it
     115// should export that function. However, once the language file has been written
     116// only the archived collator is used, and that function won't be called anymore.
     117extern "C" _IMPEXP_LOCALE BCollatorAddOn *instantiate_collator(void);
     118
     119#endif  /* _COLLATOR_H_ */
  • headers/os/locale/NumberFormatImpl.h

     
     1#ifndef _B_NUMBER_FORMAT_IMPL_H_
     2#define _B_NUMBER_FORMAT_IMPL_H_
     3
     4#include <FormatImpl.h>
     5
     6struct format_field_position;
     7class BNumberFormatParameters;
     8
     9class _IMPEXP_LOCALE BNumberFormatImpl : public BFormatImpl {
     10    public:
     11        BNumberFormatImpl();
     12        virtual ~BNumberFormatImpl();
     13
     14        virtual BFormatParameters *DefaultFormatParameters();
     15        virtual const BFormatParameters *DefaultFormatParameters() const;
     16
     17        virtual BNumberFormatParameters *DefaultNumberFormatParameters() = 0;
     18        virtual const BNumberFormatParameters *DefaultNumberFormatParameters()
     19            const = 0;
     20};
     21
     22#endif  // _B_NUMBER_FORMAT_IMPL_H_
  • headers/os/locale/Language.h

     
     1#ifndef _LANGUAGE_H_
     2#define _LANGUAGE_H_
     3
     4
     5#include <SupportDefs.h>
     6#include <LocaleBuild.h>
     7#include <LocaleStrings.h>
     8
     9
     10enum script_direction {
     11    B_LEFT_TO_RIGHT = 0,
     12    B_RIGHT_TO_LEFT,
     13    B_TOP_TO_BOTTOM,    // seems not to be supported anywhere else?
     14};
     15
     16
     17class _IMPEXP_LOCALE BLanguage {
     18    public:
     19        ~BLanguage();
     20
     21        // language name, e.g. "english", "deutsch"
     22        const char *Name() const { return fName; }
     23        // ISO-639 language code, e.g. "en", "de"
     24        const char *Code() const { return fCode; }
     25        // ISO-639 language family, e.g. "germanic"
     26        const char *Family() const { return fFamily; }
     27
     28        uint8 Direction() const;
     29
     30        // see definitions below
     31        const char *GetString(uint32 id) const;
     32
     33    private:
     34        friend class BLocaleRoster;
     35
     36        BLanguage(const char *language);
     37        void Default();
     38
     39        char    *fName, *fCode, *fFamily, *fStrings[B_NUM_LANGUAGE_STRINGS];
     40        uint8   fDirection;
     41};
     42
     43#endif  /* _LANGUAGE_H_ */
  • headers/os/locale/UnicodeChar.h

     
     1#ifndef _UNICODE_CHAR_H_
     2#define _UNICODE_CHAR_H_
     3
     4#include <SupportDefs.h>
     5
     6#include <LocaleBuild.h>
     7
     8enum unicode_char_category
     9{
     10    // Non-category for unassigned and non-character code points.
     11    B_UNICODE_UNASSIGNED                = 0,
     12
     13    B_UNICODE_UPPERCASE_LETTER          = 1,    // Lu
     14    B_UNICODE_LOWERCASE_LETTER          = 2,    // Ll
     15    B_UNICODE_TITLECASE_LETTER          = 3,    // Lt
     16    B_UNICODE_MODIFIER_LETTER           = 4,    // Lm
     17    B_UNICODE_OTHER_LETTER              = 5,    // Lo
     18    B_UNICODE_NON_SPACING_MARK          = 6,    // Mn
     19    B_UNICODE_ENCLOSING_MARK            = 7,    // Me
     20    B_UNICODE_COMBINING_SPACING_MARK    = 8,    // Mc
     21    B_UNICODE_DECIMAL_DIGIT_NUMBER      = 9,    // Nd
     22    B_UNICODE_LETTER_NUMBER             = 10,   // Nl
     23    B_UNICODE_OTHER_NUMBER              = 11,   // No
     24    B_UNICODE_SPACE_SEPARATOR           = 12,   // Zs
     25    B_UNICODE_LINE_SEPARATOR            = 13,   // Zl
     26    B_UNICODE_PARAGRAPH_SEPARATOR       = 14,   // Zp
     27    B_UNICODE_CONTROL_CHAR              = 15,   // Cc
     28    B_UNICODE_FORMAT_CHAR               = 16,   // Cf
     29    B_UNICODE_PRIVATE_USE_CHAR          = 17,   // Co
     30    B_UNICODE_SURROGATE                 = 18,   // Cs
     31    B_UNICODE_DASH_PUNCTUATION          = 19,   // Pd
     32    B_UNICODE_START_PUNCTUATION         = 20,   // Ps
     33    B_UNICODE_END_PUNCTUATION           = 21,   // Pe
     34    B_UNICODE_CONNECTOR_PUNCTUATION     = 22,   // Pc
     35    B_UNICODE_OTHER_PUNCTUATION         = 23,   // Po
     36    B_UNICODE_MATH_SYMBOL               = 24,   // Sm
     37    B_UNICODE_CURRENCY_SYMBOL           = 25,   // Sc
     38    B_UNICODE_MODIFIER_SYMBOL           = 26,   // Sk
     39    B_UNICODE_OTHER_SYMBOL              = 27,   // So
     40    B_UNICODE_INITIAL_PUNCTUATION       = 28,   // Pi
     41    B_UNICODE_FINAL_PUNCTUATION         = 29,   // Pf
     42    B_UNICODE_GENERAL_OTHER_TYPES       = 30,   // Cn
     43
     44    B_UNICODE_CATEGORY_COUNT
     45};
     46
     47
     48/**
     49 * This specifies the language directional property of a character set.
     50 */
     51
     52enum unicode_char_direction {
     53    B_UNICODE_LEFT_TO_RIGHT               = 0,
     54    B_UNICODE_RIGHT_TO_LEFT               = 1,
     55    B_UNICODE_EUROPEAN_NUMBER             = 2,
     56    B_UNICODE_EUROPEAN_NUMBER_SEPARATOR   = 3,
     57    B_UNICODE_EUROPEAN_NUMBER_TERMINATOR  = 4,
     58    B_UNICODE_ARABIC_NUMBER               = 5,
     59    B_UNICODE_COMMON_NUMBER_SEPARATOR     = 6,
     60    B_UNICODE_BLOCK_SEPARATOR             = 7,
     61    B_UNICODE_SEGMENT_SEPARATOR           = 8,
     62    B_UNICODE_WHITE_SPACE_NEUTRAL         = 9,
     63    B_UNICODE_OTHER_NEUTRAL               = 10,
     64    B_UNICODE_LEFT_TO_RIGHT_EMBEDDING     = 11,
     65    B_UNICODE_LEFT_TO_RIGHT_OVERRIDE      = 12,
     66    B_UNICODE_RIGHT_TO_LEFT_ARABIC        = 13,
     67    B_UNICODE_RIGHT_TO_LEFT_EMBEDDING     = 14,
     68    B_UNICODE_RIGHT_TO_LEFT_OVERRIDE      = 15,
     69    B_UNICODE_POP_DIRECTIONAL_FORMAT      = 16,
     70    B_UNICODE_DIR_NON_SPACING_MARK        = 17,
     71    B_UNICODE_BOUNDARY_NEUTRAL            = 18,
     72   
     73    B_UNICODE_DIRECTION_COUNT
     74};
     75
     76
     77/**
     78 * Script range as defined in the Unicode standard.
     79 */
     80
     81enum unicode_char_script {
     82    // Script names
     83    B_UNICODE_BASIC_LATIN,
     84    B_UNICODE_LATIN_1_SUPPLEMENT,
     85    B_UNICODE_LATIN_EXTENDED_A,
     86    B_UNICODE_LATIN_EXTENDED_B,
     87    B_UNICODE_IPA_EXTENSIONS,
     88    B_UNICODE_SPACING_MODIFIER_LETTERS,
     89    B_UNICODE_COMBINING_DIACRITICAL_MARKS,
     90    B_UNICODE_GREEK,
     91    B_UNICODE_CYRILLIC,
     92    B_UNICODE_ARMENIAN,
     93    B_UNICODE_HEBREW,
     94    B_UNICODE_ARABIC,
     95    B_UNICODE_SYRIAC,
     96    B_UNICODE_THAANA,
     97    B_UNICODE_DEVANAGARI,
     98    B_UNICODE_BENGALI,
     99    B_UNICODE_GURMUKHI,
     100    B_UNICODE_GUJARATI,
     101    B_UNICODE_ORIYA,
     102    B_UNICODE_TAMIL,
     103    B_UNICODE_TELUGU,
     104    B_UNICODE_KANNADA,
     105    B_UNICODE_MALAYALAM,
     106    B_UNICODE_SINHALA,
     107    B_UNICODE_THAI,
     108    B_UNICODE_LAO,
     109    B_UNICODE_TIBETAN,
     110    B_UNICODE_MYANMAR,
     111    B_UNICODE_GEORGIAN,
     112    B_UNICODE_HANGUL_JAMO,
     113    B_UNICODE_ETHIOPIC,
     114    B_UNICODE_CHEROKEE,
     115    B_UNICODE_UNIFIED_CANADIAN_ABORIGINAL_SYLLABICS,
     116    B_UNICODE_OGHAM,
     117    B_UNICODE_RUNIC,
     118    B_UNICODE_KHMER,
     119    B_UNICODE_MONGOLIAN,
     120    B_UNICODE_LATIN_EXTENDED_ADDITIONAL,
     121    B_UNICODE_GREEK_EXTENDED,
     122    B_UNICODE_GENERAL_PUNCTUATION,
     123    B_UNICODE_SUPERSCRIPTS_AND_SUBSCRIPTS,
     124    B_UNICODE_CURRENCY_SYMBOLS,
     125    B_UNICODE_COMBINING_MARKS_FOR_SYMBOLS,
     126    B_UNICODE_LETTERLIKE_SYMBOLS,
     127    B_UNICODE_NUMBER_FORMS,
     128    B_UNICODE_ARROWS,
     129    B_UNICODE_MATHEMATICAL_OPERATORS,
     130    B_UNICODE_MISCELLANEOUS_TECHNICAL,
     131    B_UNICODE_CONTROL_PICTURES,
     132    B_UNICODE_OPTICAL_CHARACTER_RECOGNITION,
     133    B_UNICODE_ENCLOSED_ALPHANUMERICS,
     134    B_UNICODE_BOX_DRAWING,
     135    B_UNICODE_BLOCK_ELEMENTS,
     136    B_UNICODE_GEOMETRIC_SHAPES,
     137    B_UNICODE_MISCELLANEOUS_SYMBOLS,
     138    B_UNICODE_DINGBATS,
     139    B_UNICODE_BRAILLE_PATTERNS,
     140    B_UNICODE_CJK_RADICALS_SUPPLEMENT,
     141    B_UNICODE_KANGXI_RADICALS,
     142    B_UNICODE_IDEOGRAPHIC_DESCRIPTION_CHARACTERS,
     143    B_UNICODE_CJK_SYMBOLS_AND_PUNCTUATION,
     144    B_UNICODE_HIRAGANA,
     145    B_UNICODE_KATAKANA,
     146    B_UNICODE_BOPOMOFO,
     147    B_UNICODE_HANGUL_COMPATIBILITY_JAMO,
     148    B_UNICODE_KANBUN,
     149    B_UNICODE_BOPOMOFO_EXTENDED,
     150    B_UNICODE_ENCLOSED_CJK_LETTERS_AND_MONTHS,
     151    B_UNICODE_CJK_COMPATIBILITY,
     152    B_UNICODE_CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A,
     153    B_UNICODE_CJK_UNIFIED_IDEOGRAPHS,
     154    B_UNICODE_YI_SYLLABLES,
     155    B_UNICODE_YI_RADICALS,
     156    B_UNICODE_HANGUL_SYLLABLES,
     157    B_UNICODE_HIGH_SURROGATES,
     158    B_UNICODE_HIGH_PRIVATE_USE_SURROGATES,
     159    B_UNICODE_LOW_SURROGATES,
     160    B_UNICODE_PRIVATE_USE_AREA,
     161    B_UNICODE_CJK_COMPATIBILITY_IDEOGRAPHS,
     162    B_UNICODE_ALPHABETIC_PRESENTATION_FORMS,
     163    B_UNICODE_ARABIC_PRESENTATION_FORMS_A,
     164    B_UNICODE_COMBINING_HALF_MARKS,
     165    B_UNICODE_CJK_COMPATIBILITY_FORMS,
     166    B_UNICODE_SMALL_FORM_VARIANTS,
     167    B_UNICODE_ARABIC_PRESENTATION_FORMS_B,
     168    B_UNICODE_SPECIALS,
     169    B_UNICODE_HALFWIDTH_AND_FULLWIDTH_FORMS,
     170
     171    B_UNICODE_SCRIPT_COUNT,
     172    B_UNICODE_NO_SCRIPT = B_UNICODE_SCRIPT_COUNT
     173};
     174
     175
     176/**
     177 * Values returned by the u_getCellWidth() function.
     178 */
     179
     180enum unicode_cell_width
     181{
     182    B_UNICODE_ZERO_WIDTH              = 0,
     183    B_UNICODE_HALF_WIDTH              = 1,
     184    B_UNICODE_FULL_WIDTH              = 2,
     185    B_UNICODE_NEUTRAL_WIDTH           = 3,
     186
     187    B_UNICODE_CELL_WIDTH_COUNT
     188};
     189
     190
     191class _IMPEXP_LOCALE BUnicodeChar {
     192    public:
     193        static bool IsAlpha(uint32 c);
     194        static bool IsAlNum(uint32 c);
     195        static bool IsDigit(uint32 c);
     196        static bool IsHexDigit(uint32 c);
     197        static bool IsUpper(uint32 c);
     198        static bool IsLower(uint32 c);
     199        static bool IsSpace(uint32 c);
     200        static bool IsWhitespace(uint32 c);
     201        static bool IsControl(uint32 c);
     202        static bool IsPunctuation(uint32 c);
     203        static bool IsPrintable(uint32 c);
     204        static bool IsTitle(uint32 c);
     205        static bool IsDefined(uint32 c);
     206        static bool IsBase(uint32 c);
     207
     208        static int8 Type(uint32 c);
     209
     210        static uint32 ToLower(uint32 c);
     211        static uint32 ToUpper(uint32 c);
     212        static uint32 ToTitle(uint32 c);
     213        static int32 DigitValue(uint32 c);
     214
     215        static void ToUTF8(uint32 c, char **out);
     216        static uint32 FromUTF8(const char **in);
     217        static uint32 FromUTF8(const char *in);
     218
     219        static size_t UTF8StringLength(const char *str);
     220        static size_t UTF8StringLength(const char *str, size_t maxLength);
     221
     222    private:
     223        BUnicodeChar();
     224};
     225
     226
     227inline uint32
     228BUnicodeChar::FromUTF8(const char *in)
     229{
     230    const char *string = in;
     231    return FromUTF8(&string);
     232}
     233
     234
     235#endif  /* _UNICODE_CHAR_H_ */
  • headers/os/locale/NumberFormatParameters.h

     
     1#ifndef _B_NUMBER_FORMAT_PARAMETERS_H_
     2#define _B_NUMBER_FORMAT_PARAMETERS_H_
     3
     4#include <FormatParameters.h>
     5
     6enum number_format_sign_policy {
     7    B_USE_NEGATIVE_SIGN_ONLY,
     8    B_USE_SPACE_FOR_POSITIVE_SIGN,
     9    B_USE_POSITIVE_SIGN,
     10};
     11
     12enum number_format_base {
     13    B_DEFAULT_BASE          = -1,   // locale default, usually decimal, but
     14                                    // may be something like roman as well
     15    B_FLEXIBLE_DECIMAL_BASE = 0,    // same as B_DECIMAL_BASE when formatting,
     16                                    // but recognizes octal and hexadecimal
     17                                    // numbers by prefix when parsing
     18    B_OCTAL_BASE            = 8,
     19    B_DECIMAL_BASE          = 10,
     20    B_HEXADECIMAL_BASE      = 16,
     21};
     22
     23class _IMPEXP_LOCALE BNumberFormatParameters : public BFormatParameters {
     24    public:
     25        BNumberFormatParameters(const BNumberFormatParameters *parent = NULL);
     26        BNumberFormatParameters(const BNumberFormatParameters &other);
     27        ~BNumberFormatParameters();
     28
     29        void SetUseGrouping(bool useGrouping);
     30        bool UseGrouping() const;
     31
     32        void SetSignPolicy(number_format_sign_policy policy);
     33        number_format_sign_policy SignPolicy() const;
     34
     35        void SetBase(number_format_base base);
     36        number_format_base Base() const;
     37
     38        void SetUseBasePrefix(bool useBasePrefix);
     39        bool UseBasePrefix() const;
     40
     41        void SetMinimalIntegerDigits(size_t minIntegerDigits);
     42        size_t MinimalIntegerDigits() const;
     43
     44        void SetUseZeroPadding(bool zeroPadding);
     45        bool UseZeroPadding() const;
     46
     47        const BNumberFormatParameters *ParentNumberParameters() const;
     48
     49        BNumberFormatParameters &operator=(
     50            const BNumberFormatParameters &other);
     51
     52    protected:
     53        void SetParentNumberParameters(const BNumberFormatParameters *parent);
     54
     55    private:
     56        const BNumberFormatParameters   *fParent;
     57        bool                            fUseGrouping;
     58        number_format_sign_policy       fSignPolicy;
     59        number_format_base              fBase;
     60        bool                            fUseBasePrefix;
     61        size_t                          fMinimalIntegerDigits;
     62        bool                            fUseZeroPadding;
     63        uint32                          fFlags;
     64};
     65
     66#endif  // _B_NUMBER_FORMAT_PARAMETERS_H_
  • headers/os/locale/IntegerFormatImpl.h

     
     1#ifndef _B_INTEGER_FORMAT_IMPL_H_
     2#define _B_INTEGER_FORMAT_IMPL_H_
     3
     4#include <NumberFormatImpl.h>
     5
     6struct format_field_position;
     7class BIntegerFormatParameters;
     8class BString;
     9
     10class _IMPEXP_LOCALE BIntegerFormatImpl : public BNumberFormatImpl {
     11    public:
     12        BIntegerFormatImpl();
     13        virtual ~BIntegerFormatImpl();
     14
     15        // formatting
     16
     17        virtual status_t Format(const BIntegerFormatParameters *parameters,
     18                                int64 number, BString *buffer) const = 0;
     19        virtual status_t Format(const BIntegerFormatParameters *parameters,
     20                                int64 number, BString *buffer,
     21                                format_field_position *positions,
     22                                int32 positionCount = 1,
     23                                int32 *fieldCount = NULL,
     24                                bool allFieldPositions = false) const = 0;
     25
     26        // TODO: ...
     27
     28        virtual BNumberFormatParameters *DefaultNumberFormatParameters();
     29        virtual const BNumberFormatParameters *DefaultNumberFormatParameters()
     30            const;
     31
     32        virtual BIntegerFormatParameters *DefaultIntegerFormatParameters() = 0;
     33        virtual const BIntegerFormatParameters *DefaultIntegerFormatParameters()
     34            const = 0;
     35};
     36
     37
     38#endif  // _B_INTEGER_FORMAT_IMPL_H_
  • headers/os/locale/Format.h

     
     1#ifndef _B_FORMAT_H_
     2#define _B_FORMAT_H_
     3
     4#include <FormatParameters.h>
     5#include <SupportDefs.h>
     6
     7// types of fields contained in formatted strings
     8enum {
     9    // number format fields
     10    B_CURRENCY_FIELD,
     11    B_DECIMAL_SEPARATOR_FIELD,
     12    B_EXPONENT_FIELD,
     13    B_EXPONENT_SIGN_FIELD,
     14    B_EXPONENT_SYMBOL_FIELD,
     15    B_FRACTION_FIELD,
     16    B_GROUPING_SEPARATOR_FIELD,
     17    B_INTEGER_FIELD,
     18    B_PERCENT_FIELD,
     19    B_PERMILLE_FIELD,
     20    B_SIGN_FIELD,
     21
     22    // date format fields
     23    // TODO: ...
     24};
     25
     26// structure filled in while formatting
     27struct _IMPEXP_LOCALE format_field_position {
     28    uint32  field_type;
     29    int32   start;
     30    int32   length;
     31};
     32
     33class BFormatImpl;
     34
     35class _IMPEXP_LOCALE BFormat {
     36    protected:
     37        BFormat(const BFormat &other);
     38        ~BFormat();
     39
     40        BFormat &operator=(const BFormat &other);
     41
     42        BFormat(BFormatImpl *impl);
     43
     44    protected:
     45        BFormatImpl *fImpl;
     46};
     47
     48#endif  // _B_FORMAT_H_
  • headers/posix/sys/types.h

     
    4545typedef int                 daddr_t;
    4646typedef char *              caddr_t;
    4747
    48 typedef unsigned long       addr_t;
     48typedef unsigned long   addr_t;
     49
    4950typedef long                key_t;
    5051
    5152#include <null.h>