Ticket #3829: localekit_base.patch
File localekit_base.patch, 311.5 KB (added by , 16 years ago) |
---|
-
build/jam/HaikuImage
47 47 uptime urlwrapper useradd uudecode uuencode 48 48 vdir version vim vmstat waitfor wc wget whoami xargs xres yes 49 49 zdiff zforce zgrep zip zipcloak <bin>zipgrep zipnote zipsplit zmore znew 50 collectcatkeys linkcatkeys dumpcatalog genprops 50 51 ; 51 52 52 53 SYSTEM_APPS = AboutSystem ActivityMonitor CharacterMap CodyCam DeskCalc DiskProbe … … 56 57 StyledEdit Terminal TextSearch TV Workspaces 57 58 ; 58 59 SYSTEM_PREFERENCES = Appearance Backgrounds CPUFrequency DataTranslations E-mail 59 FileTypes Fonts Keyboard Keymap Media Menu Mouse Network Printers Screen60 FileTypes Fonts Keyboard Keymap Locale Media Menu Mouse Network Printers Screen 60 61 ScreenSaver Sounds Time Touchpad <preference>Tracker VirtualMemory 61 62 ; 62 63 SYSTEM_DEMOS = BSnow Chart Clock Cortex FontDemo … … 68 69 libmail.so libtextencoding.so libz.so libfreetype.so libpng.so libmidi.so 69 70 libmidi2.so libdevice.so libgame.so libscreensaver.so <revisioned>libroot.so 70 71 libGL.so libfluidsynth.so liblpsolve55.so liblinprog.so libalm.so 71 libilmimf.so libiconv.so 72 libilmimf.so libiconv.so liblocale.so 72 73 ; 73 74 SYSTEM_SERVERS = registrar debug_server syslog_daemon media_server 74 75 net_server media_addon_server input_server app_server fake_app_server … … 273 274 # TODO/NOTE: Cannot use $(SYSTEM_PREFERENCES) here since there is 274 275 # "<preferences>Tracker"... 275 276 DESKBAR_PREFERENCES = Appearance Backgrounds CPUFrequency DataTranslations 276 E-mail FileTypes Fonts Keyboard Keymap Media Menu Mouse Network Printers277 E-mail FileTypes Fonts Keyboard Keymap Locale Media Menu Mouse Network Printers 277 278 Screen ScreenSaver Sounds Time Touchpad Tracker VirtualMemory 278 279 ; 279 280 for linkTarget in $(DESKBAR_PREFERENCES) { … … 328 329 = [ FDirName $(HAIKU_TOP) src apps mail ] ; 329 330 AddFilesToHaikuImage system etc word_dictionary : $(spellFiles) ; 330 331 332 # Locale kit system-wide catalogs 333 local catalogs = deutsch français ; 334 catalogs = $(catalogs:G=catalogs).language ; 335 SEARCH on $(catalogs) 336 = [ FDirName $(HAIKU_TOP) data etc locale languages ] ; 337 AddFilesToHaikuImage system etc locale languages : $(catalogs) ; 338 331 339 local etcFiles = bash_completion inputrc profile teapot.data ; 332 340 etcFiles = $(etcFiles:G=etc) ; 333 341 SEARCH 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 21 const char *kSignature = "application/x-vnd.Haiku-Locale"; 22 23 static const uint32 kMsgLocaleSettings = 'LCst'; 24 25 26 class 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 42 class 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 63 Settings::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 78 Settings::~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 92 status_t 93 Settings::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 105 void 106 Settings::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 119 Locale::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 129 Locale::~Locale() 130 { 131 } 132 133 134 void 135 Locale::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 146 void 147 Locale::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 161 void 162 Locale::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 181 bool 182 Locale::QuitRequested() 183 { 184 return true; 185 } 186 187 188 // #pragma mark - 189 190 191 int 192 main(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 12 extern const char *kSignature; 13 14 static const uint32 kMsgOpenFilePanel = 'opFp'; 15 static const uint32 kMsgOpenOpenWindow = 'opOw'; 16 static const uint32 kMsgOpenWindowClosed = 'clOw'; 17 static const uint32 kMsgWindowClosed = 'WiCl'; 18 static const uint32 kMsgSettingsChanged = 'SeCh'; 19 20 static const uint32 kMsgOpenFindWindow = 'OpFw'; 21 static const uint32 kMsgFindWindowClosed = 'clFw'; 22 static const uint32 kMsgFindTarget = 'FTgt'; 23 static 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
1 SubDir HAIKU_TOP src preferences locale ; 2 3 AddResources Locale : Locale.rsrc ; 4 5 Preference 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 18 const static uint32 kMsgSelectLanguage = 'slng'; 19 const static uint32 kMsgDefaults = 'dflt'; 20 const static uint32 kMsgRevert = 'revt'; 21 22 23 LocaleWindow::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 96 bool 97 LocaleWindow::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 108 void 109 LocaleWindow::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 11 class BButton; 12 13 14 class 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
12 12 SubInclude HAIKU_TOP src preferences joysticks ; 13 13 SubInclude HAIKU_TOP src preferences keyboard ; 14 14 SubInclude HAIKU_TOP src preferences keymap ; 15 SubInclude HAIKU_TOP src preferences locale ; 15 16 SubInclude HAIKU_TOP src preferences mail ; 16 17 SubInclude HAIKU_TOP src preferences media ; 17 18 SubInclude HAIKU_TOP src preferences menu ; -
src/bin/locale/RegExp.h
1 /* 2 Open Tracker License 3 4 Terms and Conditions 5 6 Copyright (c) 1991-2000, Be Incorporated. All rights reserved. 7 8 Permission is hereby granted, free of charge, to any person obtaining a copy of 9 this software and associated documentation files (the "Software"), to deal in 10 the Software without restriction, including without limitation the rights to 11 use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 12 of the Software, and to permit persons to whom the Software is furnished to do 13 so, subject to the following conditions: 14 15 The above copyright notice and this permission notice applies to all licensees 16 and shall be included in all copies or substantial portions of the Software. 17 18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF TITLE, MERCHANTABILITY, 20 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 21 BE INCORPORATED BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 22 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF, OR IN CONNECTION 23 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 25 Except as contained in this notice, the name of Be Incorporated shall not be 26 used in advertising or otherwise to promote the sale, use or other dealings in 27 this Software without prior written authorization from Be Incorporated. 28 29 Tracker(TM), Be(R), BeOS(R), and BeIA(TM) are trademarks or registered trademarks 30 of Be Incorporated in the United States and other countries. Other brand product 31 names are registered trademarks or trademarks of their respective holders. 32 All 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 70 namespace BPrivate { 71 72 enum { 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 90 const int32 kSubExpressionMax = 10; 91 92 struct 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 102 class RegExp { 103 104 public: 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 127 private: 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 182 using 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 14 void 15 usage() 16 { 17 fprintf(stderr, "usage: dumpcatalog <catalogFiles>\n"); 18 exit(-1); 19 } 20 21 22 int 23 main(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 16 void 17 usage() 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 35 int 36 main(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
1 SubDir HAIKU_TOP src bin locale ; 2 3 UseHeaders [ FDirName $(HAIKU_TOP) headers os locale ] : true ; 4 5 AddResources collectcatkeys : collectcatkeys.rsrc ; 6 Application collectcatkeys : collectcatkeys.cpp RegExp.cpp : be liblocale.so ; 7 8 AddResources linkcatkeys : linkcatkeys.rsrc ; 9 Application linkcatkeys : linkcatkeys.cpp : be liblocale.so ; 10 11 AddResources dumpcatalog ; 12 Application 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> 12 using namespace BPrivate; 13 #include <Entry.h> 14 #include <File.h> 15 #include "RegExp.h" 16 #include <String.h> 17 18 bool showKeys = false; 19 bool showSummary = false; 20 bool showWarnings = false; 21 const char *inputFile = NULL; 22 BString outputFile; 23 const char *catalogSig = NULL; 24 const char *catalogLang = "English"; 25 BString rxString("be_catalog\\s*->\\s*GetString\\s*"); 26 27 28 BString str, ctx, cmt; 29 bool haveID; 30 int32 id; 31 32 33 EditableCatalog *catalog = NULL; 34 35 36 void 37 usage() 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 55 bool 56 fetchStr(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 113 bool 114 fetchKey(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 137 void 138 collectAllCatalogKeys(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 187 int 188 main(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 /* 2 Open Tracker License 3 4 Terms and Conditions 5 6 Copyright (c) 1991-2000, Be Incorporated. All rights reserved. 7 8 Permission is hereby granted, free of charge, to any person obtaining a copy of 9 this software and associated documentation files (the "Software"), to deal in 10 the Software without restriction, including without limitation the rights to 11 use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 12 of the Software, and to permit persons to whom the Software is furnished to do 13 so, subject to the following conditions: 14 15 The above copyright notice and this permission notice applies to all licensees 16 and shall be included in all copies or substantial portions of the Software. 17 18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF TITLE, MERCHANTABILITY, 20 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 21 BE INCORPORATED BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 22 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF, OR IN CONNECTION 23 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 25 Except as contained in this notice, the name of Be Incorporated shall not be 26 used in advertising or otherwise to promote the sale, use or other dealings in 27 this Software without prior written authorization from Be Incorporated. 28 29 Tracker(TM), Be(R), BeOS(R), and BeIA(TM) are trademarks or registered trademarks 30 of Be Incorporated in the United States and other countries. Other brand product 31 names are registered trademarks or trademarks of their respective holders. 32 All 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 75 const 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 113 enum { 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 164 const char *kMeta = "^$.[()|?+*\\"; 165 const int32 kMaxSize = 32767L; // Probably could be 65535L. 166 167 // Flags to be passed up and down: 168 enum { 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 175 const 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 194 int32 regnarrate = 0; 195 #endif 196 197 RegExp::RegExp() 198 : fError(B_OK), 199 fRegExp(NULL) 200 { 201 } 202 203 RegExp::RegExp(const char *pattern) 204 : fError(B_OK), 205 fRegExp(NULL) 206 { 207 fRegExp = Compile(pattern); 208 } 209 210 RegExp::RegExp(const BString &pattern) 211 : fError(B_OK), 212 fRegExp(NULL) 213 { 214 fRegExp = Compile(pattern.String()); 215 } 216 217 RegExp::~RegExp() 218 { 219 free(fRegExp); 220 } 221 222 223 224 status_t 225 RegExp::InitCheck() const 226 { 227 return fError; 228 } 229 230 status_t 231 RegExp::SetTo(const char *pattern) 232 { 233 fError = B_OK; 234 free(fRegExp); 235 fRegExp = Compile(pattern); 236 return fError; 237 } 238 239 status_t 240 RegExp::SetTo(const BString &pattern) 241 { 242 fError = B_OK; 243 free(fRegExp); 244 fRegExp = Compile(pattern.String()); 245 return fError; 246 } 247 248 bool 249 RegExp::Matches(const char *string) const 250 { 251 if (!fRegExp || !string) 252 return false; 253 254 return RunMatcher(fRegExp, string) == 1; 255 } 256 257 bool 258 RegExp::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 282 regexp * 283 RegExp::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 368 regexp * 369 RegExp::Expression() const 370 { 371 return fRegExp; 372 } 373 374 const char * 375 RegExp::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 385 void 386 RegExp::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 // 401 char * 402 RegExp::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 // 477 char * 478 RegExp::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 // 517 char * 518 RegExp::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 // 583 char * 584 RegExp::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 // 701 char * // Location. 702 RegExp::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 // 725 void 726 RegExp::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 // 739 void 740 RegExp::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 // 766 void 767 RegExp::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 // 797 void 798 RegExp::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 // 813 int32 814 RegExp::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 // 872 int32 // 0 failure, 1 success 873 RegExp::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 /// 907 int32 // 0 failure, 1 success 908 RegExp::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 // 1098 int32 1099 RegExp::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 // 1147 char * 1148 RegExp::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 1165 const char * 1166 RegExp::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 1183 inline int32 1184 RegExp::UCharAt(const char *p) const 1185 { 1186 return (int32)*(unsigned char *)p; 1187 } 1188 1189 inline char * 1190 RegExp::Operand(char* p) const 1191 { 1192 return p + 3; 1193 } 1194 1195 inline const char * 1196 RegExp::Operand(const char* p) const 1197 { 1198 return p + 3; 1199 } 1200 1201 inline bool 1202 RegExp::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 // 1213 void 1214 RegExp::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 // 1254 char * 1255 RegExp::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 1334 void 1335 RegExp::RegExpError(const char *) const 1336 { 1337 // does nothing now, perhaps it should printf? 1338 } 1339 1340 #endif -
src/bin/Jamfile
222 222 # Network command line tools 223 223 SubInclude HAIKU_TOP src bin network ; 224 224 225 # Locale kit tools 226 SubInclude HAIKU_TOP src bin locale ; 227 225 228 # Compression command line tools 226 229 SubInclude HAIKU_TOP src bin unzip ; 227 230 SubInclude 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 13 static const int kMaxIntDigitCount = 20; // int64: 19 + sign, uint64: 20 14 static const int kMaxFloatDigitCount = DBL_DIG + 2; 15 // double: mantissa precision + 2 16 17 18 // Symbol 19 20 // constructor 21 BGenericNumberFormat::Symbol::Symbol(const char *symbol) 22 : symbol(NULL), 23 length(0), 24 char_count(0) 25 { 26 SetTo(symbol); 27 } 28 29 // destructor 30 BGenericNumberFormat::Symbol::~Symbol() 31 { 32 Unset(); 33 } 34 35 // SetTo 36 status_t 37 BGenericNumberFormat::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 58 struct BGenericNumberFormat::SpecialNumberSymbols { 59 const Symbol *nan; 60 const Symbol *infinity; 61 const Symbol *negative_infinity; 62 }; 63 64 65 // GroupingInfo 66 class 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 181 class 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 306 class 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 410 static const BGenericNumberFormat::Symbol kDefaultDigitSymbols[] = { 411 "0", "1", "2", "3", "4", "5", "6", "7", "8", "9" 412 }; 413 414 // decimal separator symbol 415 static const BGenericNumberFormat::Symbol kDefaultFractionSeparator = "."; 416 417 // grouping separator symbols 418 static const char *kDefaultGroupingSeparators[] = { "," }; 419 static const int32 kDefaultGroupingSeparatorCount 420 = sizeof(kDefaultGroupingSeparators) / sizeof(const char*); 421 static const char *kNoGroupingSeparators[] = { NULL }; // to please mwcc 422 static const int32 kNoGroupingSeparatorCount = 0; 423 424 // grouping sizes 425 static const size_t kDefaultGroupingSizes[] = { 3 }; 426 static const int32 kDefaultGroupingSizeCount 427 = sizeof(kDefaultGroupingSizes) / sizeof(size_t); 428 static const size_t kNoGroupingSizes[] = { 0 }; // to please mwcc 429 static const int32 kNoGroupingSizeCount = 0; 430 431 // grouping info 432 static const BGenericNumberFormat::GroupingInfo kDefaultGroupingInfo( 433 kDefaultGroupingSeparators, kDefaultGroupingSeparatorCount, 434 kDefaultGroupingSizes, kDefaultGroupingSizeCount 435 ); 436 static const BGenericNumberFormat::GroupingInfo kNoGroupingInfo( 437 kNoGroupingSeparators, kNoGroupingSeparatorCount, 438 kNoGroupingSizes, kNoGroupingSizeCount 439 ); 440 441 // exponent symbol 442 static const BGenericNumberFormat::Symbol kDefaultExponentSymbol = "e"; 443 static const BGenericNumberFormat::Symbol kDefaultUpperCaseExponentSymbol 444 = "E"; 445 446 // NaN symbol 447 static const BGenericNumberFormat::Symbol kDefaultNaNSymbol = "NaN"; 448 static const BGenericNumberFormat::Symbol kDefaultUpperCaseNaNSymbol = "NaN"; 449 450 // infinity symbol 451 static const BGenericNumberFormat::Symbol kDefaultInfinitySymbol 452 = "infinity"; 453 static const BGenericNumberFormat::Symbol kDefaultUpperCaseInfinitySymbol 454 = "INFINITY"; 455 456 // negative infinity symbol 457 static const BGenericNumberFormat::Symbol kDefaultNegativeInfinitySymbol 458 = "-infinity"; 459 static const BGenericNumberFormat::Symbol 460 kDefaultUpperCaseNegativeInfinitySymbol = "-INFINITY"; 461 462 // sign symbols 463 static const BGenericNumberFormat::SignSymbols kDefaultSignSymbols( 464 "+", "-", " ", "", // prefixes 465 "", "", "", "" // suffixes 466 ); 467 468 // mantissa sign symbols 469 static const BGenericNumberFormat::SignSymbols kDefaultMantissaSignSymbols( 470 "", "", "", "", // prefixes 471 "", "", "", "" // suffixes 472 ); 473 474 // exponent sign symbols 475 static const BGenericNumberFormat::SignSymbols kDefaultExponentSignSymbols( 476 "+", "-", " ", "", // prefixes 477 "", "", "", "" // suffixes 478 ); 479 480 481 // Integer 482 class 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 609 class 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 977 BGenericNumberFormat::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 998 BGenericNumberFormat::~BGenericNumberFormat() 999 { 1000 } 1001 1002 // FormatInteger 1003 status_t 1004 BGenericNumberFormat::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 1023 status_t 1024 BGenericNumberFormat::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 1043 status_t 1044 BGenericNumberFormat::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 1055 status_t 1056 BGenericNumberFormat::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 1067 status_t 1068 BGenericNumberFormat::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 1087 status_t 1088 BGenericNumberFormat::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 1144 status_t 1145 BGenericNumberFormat::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 1155 BIntegerFormatParameters * 1156 BGenericNumberFormat::DefaultIntegerFormatParameters() 1157 { 1158 return &fIntegerParameters; 1159 } 1160 1161 // DefaultIntegerFormatParameters 1162 const BIntegerFormatParameters * 1163 BGenericNumberFormat::DefaultIntegerFormatParameters() const 1164 { 1165 return &fIntegerParameters; 1166 } 1167 1168 // SetDefaultFloatFormatParameters 1169 status_t 1170 BGenericNumberFormat::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 1180 BFloatFormatParameters * 1181 BGenericNumberFormat::DefaultFloatFormatParameters() 1182 { 1183 return &fFloatParameters; 1184 } 1185 1186 // DefaultFloatFormatParameters 1187 const BFloatFormatParameters * 1188 BGenericNumberFormat::DefaultFloatFormatParameters() const 1189 { 1190 return &fFloatParameters; 1191 } 1192 1193 // SetDigitSymbols 1194 status_t 1195 BGenericNumberFormat::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 1226 status_t 1227 BGenericNumberFormat::SetFractionSeparator(const char *decimalSeparator) 1228 { 1229 return _SetSymbol(&fFractionSeparator, decimalSeparator); 1230 } 1231 1232 // SetGroupingInfo 1233 status_t 1234 BGenericNumberFormat::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 1268 status_t 1269 BGenericNumberFormat::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 1281 status_t 1282 BGenericNumberFormat::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 1306 status_t 1307 BGenericNumberFormat::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 1324 status_t 1325 BGenericNumberFormat::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 1342 status_t 1343 BGenericNumberFormat::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 1356 status_t 1357 BGenericNumberFormat::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 1399 const BGenericNumberFormat::Symbol * 1400 BGenericNumberFormat::DigitSymbols() const 1401 { 1402 return (fDigitSymbols ? fDigitSymbols : kDefaultDigitSymbols); 1403 } 1404 1405 // FractionSeparator 1406 const BGenericNumberFormat::Symbol * 1407 BGenericNumberFormat::FractionSeparator() const 1408 { 1409 return (fFractionSeparator ? fFractionSeparator 1410 : &kDefaultFractionSeparator); 1411 } 1412 1413 // GetGroupingInfo 1414 const BGenericNumberFormat::GroupingInfo * 1415 BGenericNumberFormat::GetGroupingInfo() const 1416 { 1417 return (fGroupingInfo ? fGroupingInfo : &kDefaultGroupingInfo); 1418 } 1419 1420 // ExponentSymbol 1421 const BGenericNumberFormat::Symbol * 1422 BGenericNumberFormat::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 1433 const BGenericNumberFormat::Symbol * 1434 BGenericNumberFormat::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 1445 const BGenericNumberFormat::Symbol * 1446 BGenericNumberFormat::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 1457 const BGenericNumberFormat::Symbol * 1458 BGenericNumberFormat::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 1469 void 1470 BGenericNumberFormat::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 1479 const BGenericNumberFormat::SignSymbols * 1480 BGenericNumberFormat::GetSignSymbols() const 1481 { 1482 return (fSignSymbols ? fSignSymbols : &kDefaultSignSymbols); 1483 } 1484 1485 // MantissaSignSymbols 1486 const BGenericNumberFormat::SignSymbols * 1487 BGenericNumberFormat::MantissaSignSymbols() const 1488 { 1489 return (fMantissaSignSymbols ? fMantissaSignSymbols 1490 : &kDefaultMantissaSignSymbols); 1491 } 1492 1493 // ExponentSignSymbols 1494 const BGenericNumberFormat::SignSymbols * 1495 BGenericNumberFormat::ExponentSignSymbols() const 1496 { 1497 return (fExponentSignSymbols ? fExponentSignSymbols 1498 : &kDefaultExponentSignSymbols); 1499 } 1500 1501 // _SetSymbol 1502 status_t 1503 BGenericNumberFormat::_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 5 BFloatFormatImpl::BFloatFormatImpl() 6 : BNumberFormatImpl() 7 { 8 } 9 10 // destructor 11 BFloatFormatImpl::~BFloatFormatImpl() 12 { 13 } 14 15 // DefaultNumberFormatParameters 16 BNumberFormatParameters * 17 BFloatFormatImpl::DefaultNumberFormatParameters() 18 { 19 return DefaultFloatFormatParameters(); 20 } 21 22 // DefaultNumberFormatParameters 23 const BNumberFormatParameters * 24 BFloatFormatImpl::DefaultNumberFormatParameters() const 25 { 26 return DefaultFloatFormatParameters(); 27 } 28 -
src/kits/locale/FloatFormatParameters.cpp
1 #include <FloatFormatParameters.h> 2 3 // defaults 4 static const size_t kDefaultMinimalFractionDigits = 0; 5 static const size_t kDefaultMaximalFractionDigits = 6; 6 static const bool kDefaultUseUpperCase = false; 7 static const float_format_type kDefaultFloatFormatType = B_AUTO_FLOAT_FORMAT; 8 static const bool kDefaultAlwaysUseFractionSeparator = false; 9 static const bool kDefaultKeepTrailingFractionZeros = false; 10 11 12 // flags 13 enum { 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 23 BFloatFormatParameters::BFloatFormatParameters( 24 const BFloatFormatParameters *parent) 25 : BNumberFormatParameters(parent), 26 fParent(parent), 27 fFlags(0) 28 { 29 } 30 31 // copy constructor 32 BFloatFormatParameters::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 47 BFloatFormatParameters::~BFloatFormatParameters() 48 { 49 } 50 51 // SetMinimalFractionDigits 52 void 53 BFloatFormatParameters::SetMinimalFractionDigits(size_t minFractionDigits) 54 { 55 fMinimalFractionDigits = minFractionDigits; 56 fFlags |= MINIMAL_FRACTION_DIGITS_SET; 57 } 58 59 // MinimalFractionDigits 60 size_t 61 BFloatFormatParameters::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 71 void 72 BFloatFormatParameters::SetMaximalFractionDigits(size_t maxFractionDigits) 73 { 74 fMaximalFractionDigits = maxFractionDigits; 75 fFlags |= MAXIMAL_FRACTION_DIGITS_SET; 76 } 77 78 // MaximalFractionDigits 79 size_t 80 BFloatFormatParameters::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 90 void 91 BFloatFormatParameters::SetUseUpperCase(bool useCapitals) 92 { 93 fUseUpperCase = useCapitals; 94 fFlags |= USE_UPPER_CASE_SET; 95 } 96 97 // UseUpperCase 98 bool 99 BFloatFormatParameters::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 109 void 110 BFloatFormatParameters::SetFloatFormatType(float_format_type type) 111 { 112 fFloatFormatType = type; 113 fFlags |= FLOAT_FORMAT_TYPE_SET; 114 } 115 116 // FloatFormatType 117 float_format_type 118 BFloatFormatParameters::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 128 void 129 BFloatFormatParameters::SetAlwaysUseFractionSeparator( 130 bool alwaysUseFractionSeparator) 131 { 132 fAlwaysUseFractionSeparator = alwaysUseFractionSeparator; 133 fFlags |= ALWAYS_USE_FRACTION_SEPARATOR_SET; 134 } 135 136 // AlwaysUseFractionSeparator 137 bool 138 BFloatFormatParameters::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 148 void 149 BFloatFormatParameters::SetKeepTrailingFractionZeros( 150 bool keepTrailingFractionZeros) 151 { 152 fKeepTrailingFractionZeros = keepTrailingFractionZeros; 153 fFlags |= KEEP_TRAILING_FRACTION_ZEROS_SET; 154 } 155 156 // KeepTrailingFractionZeros 157 bool 158 BFloatFormatParameters::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 168 void 169 BFloatFormatParameters::SetParentFloatParameters( 170 const BFloatFormatParameters *parent) 171 { 172 fParent = parent; 173 SetParentNumberParameters(parent); 174 } 175 176 // ParentFloatParameters 177 const BFloatFormatParameters * 178 BFloatFormatParameters::ParentFloatParameters() const 179 { 180 return fParent; 181 } 182 183 // = 184 BFloatFormatParameters & 185 BFloatFormatParameters::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 14 const 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 45 BCountry::BCountry() 46 : 47 fStrings(gStrings) 48 { 49 } 50 51 52 BCountry::BCountry(const char **strings) 53 : 54 fStrings(strings) 55 { 56 } 57 58 59 BCountry::~BCountry() 60 { 61 } 62 63 64 const char * 65 BCountry::Name() const 66 { 67 return "United States Of America"; 68 } 69 70 71 const char * 72 BCountry::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 81 void 82 BCountry::FormatDate(char *string, size_t maxSize, time_t time, bool longFormat) 83 { 84 // ToDo: implement us 85 } 86 87 88 void 89 BCountry::FormatDate(BString *string, time_t time, bool longFormat) 90 { 91 } 92 93 94 void 95 BCountry::FormatTime(char *string, size_t maxSize, time_t time, bool longFormat) 96 { 97 } 98 99 100 void 101 BCountry::FormatTime(BString *string, time_t time, bool longFormat) 102 { 103 } 104 105 106 const char * 107 BCountry::DateFormat(bool longFormat) const 108 { 109 return fStrings[longFormat ? B_DATE_FORMAT : B_SHORT_DATE_FORMAT]; 110 } 111 112 113 const char * 114 BCountry::TimeFormat(bool longFormat) const 115 { 116 return fStrings[longFormat ? B_TIME_FORMAT : B_SHORT_TIME_FORMAT]; 117 } 118 119 120 const char * 121 BCountry::DateSeparator() const 122 { 123 return fStrings[B_DATE_SEPARATOR]; 124 } 125 126 127 const char * 128 BCountry::TimeSeparator() const 129 { 130 return fStrings[B_TIME_SEPARATOR]; 131 } 132 133 134 void 135 BCountry::FormatNumber(char *string, size_t maxSize, double value) 136 { 137 } 138 139 140 void 141 BCountry::FormatNumber(BString *string, double value) 142 { 143 } 144 145 146 void 147 BCountry::FormatNumber(char *string, size_t maxSize, int32 value) 148 { 149 } 150 151 152 void 153 BCountry::FormatNumber(BString *string, int32 value) 154 { 155 } 156 157 158 const char * 159 BCountry::DecimalPoint() const 160 { 161 return fStrings[B_DECIMAL_POINT]; 162 } 163 164 165 const char * 166 BCountry::ThousandsSeparator() const 167 { 168 return fStrings[B_THOUSANDS_SEPARATOR]; 169 } 170 171 172 const char * 173 BCountry::Grouping() const 174 { 175 return fStrings[B_GROUPING]; 176 } 177 178 179 const char * 180 BCountry::PositiveSign() const 181 { 182 return fStrings[B_POSITIVE_SIGN]; 183 } 184 185 186 const char * 187 BCountry::NegativeSign() const 188 { 189 return fStrings[B_NEGATIVE_SIGN]; 190 } 191 192 193 int8 194 BCountry::Measurement() const 195 { 196 return B_US; 197 } 198 199 200 ssize_t 201 BCountry::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 214 ssize_t 215 BCountry::FormatMonetary(BString *string, char *format, ...) 216 { 217 return B_OK; 218 } 219 220 221 const char * 222 BCountry::CurrencySymbol() const 223 { 224 return fStrings[B_CURRENCY_SYMBOL]; 225 } 226 227 228 const char * 229 BCountry::InternationalCurrencySymbol() const 230 { 231 return fStrings[B_INT_CURRENCY_SYMBOL]; 232 } 233 234 235 const char * 236 BCountry::MonDecimalPoint() const 237 { 238 return fStrings[B_MON_DECIMAL_POINT]; 239 } 240 241 242 const char * 243 BCountry::MonThousandsSeparator() const 244 { 245 return fStrings[B_MON_THOUSANDS_SEPARATOR]; 246 } 247 248 249 const char * 250 BCountry::MonGrouping() const 251 { 252 return fStrings[B_MON_GROUPING]; 253 } 254 255 256 int32 257 BCountry::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 5 BIntegerFormat::BIntegerFormat(const BIntegerFormat &other) 6 : BNumberFormat(other), 7 BIntegerFormatParameters(other) 8 { 9 } 10 11 // destructor 12 BIntegerFormat::~BIntegerFormat() 13 { 14 } 15 16 // Format 17 status_t 18 BIntegerFormat::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 26 status_t 27 BIntegerFormat::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 // = 38 BIntegerFormat & 39 BIntegerFormat::operator=(const BIntegerFormat &other) 40 { 41 BNumberFormat::operator=(other); 42 BIntegerFormatParameters::operator=(other); 43 return *this; 44 } 45 46 // constructor 47 BIntegerFormat::BIntegerFormat(BIntegerFormatImpl *impl) 48 : BNumberFormat(impl), 49 BIntegerFormatParameters(impl ? impl->DefaultIntegerFormatParameters() 50 : NULL) 51 { 52 } 53 54 // IntegerFormatImpl 55 inline 56 BIntegerFormatImpl * 57 BIntegerFormat::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 10 nl_catd 11 catopen(const char *name, int oflag) 12 { 13 return (nl_catd)1; 14 } 15 16 17 char * 18 catgets(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 25 int 26 catclose(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 18 typedef 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 20 BCatalog* be_catalog = NULL; 21 // catalog used by translation macros 22 BCatalog* 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 28 BCatalog::BCatalog() 29 : 30 fCatalog(NULL) 31 { 32 } 33 34 35 BCatalog::BCatalog(const char *signature, const char *language, 36 int32 fingerprint) 37 { 38 fCatalog = be_locale_roster->LoadCatalog(signature, language, fingerprint); 39 } 40 41 42 BCatalog::~BCatalog() 43 { 44 if (be_catalog == this) 45 be_app_catalog = be_catalog = NULL; 46 be_locale_roster->UnloadCatalog(fCatalog); 47 } 48 49 50 const char * 51 BCatalog::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 63 const char * 64 BCatalog::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 76 status_t 77 BCatalog::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 92 status_t 93 BCatalog::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 108 status_t 109 BCatalog::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 155 BCatalogAddOn::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 169 BCatalogAddOn::~BCatalogAddOn() 170 { 171 } 172 173 174 void 175 BCatalogAddOn::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 183 status_t 184 BCatalogAddOn::InitCheck() const 185 { 186 return fInitCheck; 187 } 188 189 190 bool 191 BCatalogAddOn::CanHaveData() const 192 { 193 return false; 194 } 195 196 197 status_t 198 BCatalogAddOn::GetData(const char *name, BMessage *msg) 199 { 200 return EOPNOTSUPP; 201 } 202 203 204 status_t 205 BCatalogAddOn::GetData(uint32 id, BMessage *msg) 206 { 207 return EOPNOTSUPP; 208 } 209 210 211 status_t 212 BCatalogAddOn::SetString(const char *string, const char *translated, 213 const char *context, const char *comment) 214 { 215 return EOPNOTSUPP; 216 } 217 218 219 status_t 220 BCatalogAddOn::SetString(int32 id, const char *translated) 221 { 222 return EOPNOTSUPP; 223 } 224 225 226 bool 227 BCatalogAddOn::CanWriteData() const 228 { 229 return false; 230 } 231 232 233 status_t 234 BCatalogAddOn::SetData(const char *name, BMessage *msg) 235 { 236 return EOPNOTSUPP; 237 } 238 239 240 status_t 241 BCatalogAddOn::SetData(uint32 id, BMessage *msg) 242 { 243 return EOPNOTSUPP; 244 } 245 246 247 status_t 248 BCatalogAddOn::ReadFromFile(const char *path) 249 { 250 return EOPNOTSUPP; 251 } 252 253 254 status_t 255 BCatalogAddOn::ReadFromAttribute(entry_ref *appOrAddOnRef) 256 { 257 return EOPNOTSUPP; 258 } 259 260 261 status_t 262 BCatalogAddOn::ReadFromResource(entry_ref *appOrAddOnRef) 263 { 264 return EOPNOTSUPP; 265 } 266 267 268 status_t 269 BCatalogAddOn::WriteToFile(const char *path) 270 { 271 return EOPNOTSUPP; 272 } 273 274 275 status_t 276 BCatalogAddOn::WriteToAttribute(entry_ref *appOrAddOnRef) 277 { 278 return EOPNOTSUPP; 279 } 280 281 282 status_t 283 BCatalogAddOn::WriteToResource(entry_ref *appOrAddOnRef) 284 { 285 assert(0); 286 return EOPNOTSUPP; 287 } 288 289 290 void BCatalogAddOn::MakeEmpty() 291 { 292 } 293 294 295 int32 296 BCatalogAddOn::CountItems() const 297 { 298 return 0; 299 } 300 301 302 //#pragma mark - EditableCatalog 303 namespace BPrivate { 304 EditableCatalog::EditableCatalog(const char *type, const char *signature, 305 const char *language) 306 { 307 fCatalog = be_locale_roster->CreateCatalog(type, signature, language); 308 } 309 310 311 EditableCatalog::~EditableCatalog() 312 { 313 } 314 315 316 status_t 317 EditableCatalog::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 326 status_t 327 EditableCatalog::SetString(int32 id, const char *translated) 328 { 329 if (!fCatalog) 330 return B_NO_INIT; 331 return fCatalog->SetString(id, translated); 332 } 333 334 335 bool 336 EditableCatalog::CanWriteData() const 337 { 338 if (!fCatalog) 339 return false; 340 return fCatalog->CanWriteData(); 341 } 342 343 344 status_t 345 EditableCatalog::SetData(const char *name, BMessage *msg) 346 { 347 if (!fCatalog) 348 return B_NO_INIT; 349 return fCatalog->SetData(name, msg); 350 } 351 352 353 status_t 354 EditableCatalog::SetData(uint32 id, BMessage *msg) 355 { 356 if (!fCatalog) 357 return B_NO_INIT; 358 return fCatalog->SetData(id, msg); 359 } 360 361 362 status_t 363 EditableCatalog::ReadFromFile(const char *path) 364 { 365 if (!fCatalog) 366 return B_NO_INIT; 367 return fCatalog->ReadFromFile(path); 368 } 369 370 371 status_t 372 EditableCatalog::ReadFromAttribute(entry_ref *appOrAddOnRef) 373 { 374 if (!fCatalog) 375 return B_NO_INIT; 376 return fCatalog->ReadFromAttribute(appOrAddOnRef); 377 } 378 379 380 status_t 381 EditableCatalog::ReadFromResource(entry_ref *appOrAddOnRef) 382 { 383 if (!fCatalog) 384 return B_NO_INIT; 385 return fCatalog->ReadFromResource(appOrAddOnRef); 386 } 387 388 389 status_t 390 EditableCatalog::WriteToFile(const char *path) 391 { 392 if (!fCatalog) 393 return B_NO_INIT; 394 return fCatalog->WriteToFile(path); 395 } 396 397 398 status_t 399 EditableCatalog::WriteToAttribute(entry_ref *appOrAddOnRef) 400 { 401 if (!fCatalog) 402 return B_NO_INIT; 403 return fCatalog->WriteToAttribute(appOrAddOnRef); 404 } 405 406 407 status_t 408 EditableCatalog::WriteToResource(entry_ref *appOrAddOnRef) 409 { 410 if (!fCatalog) 411 return B_NO_INIT; 412 return fCatalog->WriteToResource(appOrAddOnRef); 413 } 414 415 416 void 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 5 BFloatFormat::BFloatFormat(const BFloatFormat &other) 6 : BNumberFormat(other), 7 BFloatFormatParameters(other) 8 { 9 } 10 11 // destructor 12 BFloatFormat::~BFloatFormat() 13 { 14 } 15 16 // Format 17 status_t 18 BFloatFormat::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 26 status_t 27 BFloatFormat::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 // = 38 BFloatFormat & 39 BFloatFormat::operator=(const BFloatFormat &other) 40 { 41 BNumberFormat::operator=(other); 42 BFloatFormatParameters::operator=(other); 43 return *this; 44 } 45 46 // constructor 47 BFloatFormat::BFloatFormat(BFloatFormatImpl *impl) 48 : BNumberFormat(impl), 49 BFloatFormatParameters(impl ? impl->DefaultFloatFormatParameters() 50 : NULL) 51 { 52 } 53 54 // FloatFormatImpl 55 inline 56 BFloatFormatImpl * 57 BFloatFormat::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 17 static 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 34 static inline uint32 35 getPrimaryChar(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 52 BCollatorAddOn::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 65 BCollator::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 79 BCollator::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 91 BCollator::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 122 BCollator::~BCollator() 123 { 124 delete fCollator; 125 126 if (fCollatorImage >= B_OK) 127 unload_add_on(fCollatorImage); 128 } 129 130 131 void 132 BCollator::SetDefaultStrength(int8 strength) 133 { 134 fStrength = strength; 135 } 136 137 138 int8 139 BCollator::DefaultStrength() const 140 { 141 return fStrength; 142 } 143 144 145 void 146 BCollator::SetIgnorePunctuation(bool ignore) 147 { 148 fIgnorePunctuation = ignore; 149 } 150 151 152 bool 153 BCollator::IgnorePunctuation() const 154 { 155 return fIgnorePunctuation; 156 } 157 158 159 status_t 160 BCollator::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 169 int 170 BCollator::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 180 status_t 181 BCollator::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 203 BArchivable * 204 BCollator::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 216 BCollatorAddOn::BCollatorAddOn() 217 { 218 } 219 220 221 BCollatorAddOn::BCollatorAddOn(BMessage *archive) 222 : BArchivable(archive) 223 { 224 } 225 226 227 BCollatorAddOn::~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 238 uint32 239 BCollatorAddOn::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 267 char * 268 BCollatorAddOn::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 285 size_t 286 BCollatorAddOn::PrimaryKeyLength(size_t length) 287 { 288 return length * 2; 289 // the primary key needs to make space for doubled characters (like 'Ã') 290 } 291 292 293 status_t 294 BCollatorAddOn::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 377 int 378 BCollatorAddOn::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 460 status_t 461 BCollatorAddOn::Archive(BMessage *archive, bool deep) const 462 { 463 return BArchivable::Archive(archive, deep); 464 } 465 466 467 BArchivable * 468 BCollatorAddOn::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 /* 2 Open Tracker License 3 4 Terms and Conditions 5 6 Copyright (c) 1991-2000, Be Incorporated. All rights reserved. 7 8 Permission is hereby granted, free of charge, to any person obtaining a copy of 9 this software and associated documentation files (the "Software"), to deal in 10 the Software without restriction, including without limitation the rights to 11 use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 12 of the Software, and to permit persons to whom the Software is furnished to do 13 so, subject to the following conditions: 14 15 The above copyright notice and this permission notice applies to all licensees 16 and shall be included in all copies or substantial portions of the Software. 17 18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF TITLE, MERCHANTABILITY, 20 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 21 BE INCORPORATED BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 22 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF, OR IN CONNECTION 23 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 25 Except as contained in this notice, the name of Be Incorporated shall not be 26 used in advertising or otherwise to promote the sale, use or other dealings in 27 this Software without prior written authorization from Be Incorporated. 28 29 Tracker(TM), Be(R), BeOS(R), and BeIA(TM) are trademarks or registered trademarks 30 of Be Incorporated in the United States and other countries. Other brand product 31 names are registered trademarks or trademarks of their respective holders. 32 All 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 43 namespace BPrivate { 44 45 template <class Element> 46 class 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 56 class 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 66 const 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 72 template <class Element, class ElementVec = ElementVector<Element> > 73 class 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 104 template <class Element> 105 class 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 132 template<class Element, class ElementVec> 133 OpenHashTable<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 144 template<class Element, class ElementVec> 145 OpenHashTable<Element, ElementVec>::~OpenHashTable() 146 { 147 delete fHashArray; 148 } 149 150 151 template<class Element, class ElementVec> 152 int32 153 OpenHashTable<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 163 template<class Element, class ElementVec> 164 Element * 165 OpenHashTable<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 176 template<class Element, class ElementVec> 177 int32 178 OpenHashTable<Element, ElementVec>::ElementIndex(const Element *element) const 179 { 180 return fElementVector->IndexOf(*element); 181 } 182 183 184 template<class Element, class ElementVec> 185 Element * 186 OpenHashTable<Element, ElementVec>::ElementAt(int32 index) const 187 { 188 return &fElementVector->At(index); 189 } 190 191 192 template<class Element, class ElementVec> 193 int32 194 OpenHashTable<Element, ElementVec>::VectorSize() const 195 { 196 return fElementVector->Size(); 197 } 198 199 200 template<class Element, class ElementVec> 201 Element & 202 OpenHashTable<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 213 template<class Element, class ElementVec> 214 void 215 OpenHashTable<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 245 template<class Element, class ElementVec> 246 void 247 OpenHashTable<Element, ElementVec>::SetElementVector(ElementVec *elementVector) 248 { 249 fElementVector = elementVector; 250 } 251 252 253 template<class Element> 254 OpenHashElementArray<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 266 template<class Element> 267 OpenHashElementArray<Element>::~OpenHashElementArray() 268 { 269 free(fData); 270 } 271 272 273 template<class Element> 274 Element & 275 OpenHashElementArray<Element>::At(int32 index) 276 { 277 ASSERT(index < fSize); 278 return fData[index]; 279 } 280 281 282 template<class Element> 283 const Element & 284 OpenHashElementArray<Element>::At(int32 index) const 285 { 286 ASSERT(index < fSize); 287 return fData[index]; 288 } 289 290 291 template<class Element> 292 int32 293 OpenHashElementArray<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 303 template<class Element> 304 int32 305 OpenHashElementArray<Element>::Size() const 306 { 307 return fSize; 308 } 309 310 311 template<class Element> 312 int32 313 OpenHashElementArray<Element>::Add(const Element &newElement) 314 { 315 int32 index = Add(); 316 At(index).Adopt(newElement); 317 return index; 318 } 319 320 321 #if DEBUG 322 const int32 kGrowChunk = 10; 323 #else 324 const int32 kGrowChunk = 1024; 325 #endif 326 327 328 template<class Element> 329 int32 330 OpenHashElementArray<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 358 template<class Element> 359 void 360 OpenHashElementArray<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 374 using namespace BPrivate; 375 376 #endif -
src/kits/locale/NumberFormatImpl.cpp
1 #include <NumberFormatImpl.h> 2 #include <NumberFormatParameters.h> 3 4 // constructor 5 BNumberFormatImpl::BNumberFormatImpl() 6 : BFormatImpl() 7 { 8 } 9 10 // destructor 11 BNumberFormatImpl::~BNumberFormatImpl() 12 { 13 } 14 15 // DefaultFormatParameters 16 BFormatParameters * 17 BNumberFormatImpl::DefaultFormatParameters() 18 { 19 return DefaultNumberFormatParameters(); 20 } 21 22 // DefaultFormatParameters 23 const BFormatParameters * 24 BNumberFormatImpl::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 18 static 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 73 static char * 74 TrimCopy(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 93 BLanguage::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 172 BLanguage::~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 186 void 187 BLanguage::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 201 uint8 202 BLanguage::Direction() const 203 { 204 return fDirection; 205 } 206 207 208 const char * 209 BLanguage::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 19 status_t 20 PropertyFile::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 45 off_t 46 PropertyFile::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 38 static const uint16 *sPropsTable = NULL; 39 #define sProps32Table ((uint32 *)sPropsTable) 40 static uint16 *sIndices; 41 static vint32 sHavePropsData = 0; 42 43 #define FLAG(n) ((uint32)1 << (n)) 44 enum { 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 56 static 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 99 enum { 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 */ 109 enum { 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 121 enum { 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 132 static 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 169 static inline bool 170 isISO8Control(uint32 c) 171 { 172 return ((uint32)c < 0x20 || (uint32)(c - 0x7f) <= 0x20); 173 } 174 175 176 static inline uint32 177 getProperties(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 192 static inline uint8 193 getCategory(uint32 properties) 194 { 195 return properties & 0x1f; 196 } 197 198 199 static inline bool 200 propertyIsException(uint32 properties) 201 { 202 return properties & (1UL << EXCEPTION_SHIFT); 203 } 204 205 206 static inline uint32 207 getUnsignedValue(uint32 properties) 208 { 209 return properties >> VALUE_SHIFT; 210 } 211 212 213 static inline uint32 214 getSignedValue(uint32 properties) 215 { 216 return (int32)properties >> VALUE_SHIFT; 217 } 218 219 220 static inline uint32 * 221 getExceptions(uint32 properties) 222 { 223 return sProps32Table + sIndices[INDEX_EXCEPTIONS] + getUnsignedValue(properties); 224 } 225 226 227 static inline bool 228 haveExceptionValue(uint32 flags,int16 index) 229 { 230 return flags & (1UL << index); 231 } 232 233 234 static inline void 235 addExceptionOffset(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 246 static status_t 247 loadPropsData() 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 295 BUnicodeChar::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 310 bool 311 BUnicodeChar::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 322 int8 323 BUnicodeChar::Type(uint32 c) 324 { 325 BUnicodeChar(); 326 return (int8)getCategory(getProperties(c)); 327 } 328 329 330 bool 331 BUnicodeChar::IsLower(uint32 c) 332 { 333 BUnicodeChar(); 334 return getCategory(getProperties(c)) == B_UNICODE_LOWERCASE_LETTER; 335 } 336 337 338 bool 339 BUnicodeChar::IsUpper(uint32 c) 340 { 341 BUnicodeChar(); 342 return getCategory(getProperties(c)) == B_UNICODE_UPPERCASE_LETTER; 343 } 344 345 346 bool 347 BUnicodeChar::IsTitle(uint32 c) 348 { 349 BUnicodeChar(); 350 return getCategory(getProperties(c)) == B_UNICODE_TITLECASE_LETTER; 351 } 352 353 354 bool 355 BUnicodeChar::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 364 bool 365 BUnicodeChar::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 375 bool 376 BUnicodeChar::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 389 bool 390 BUnicodeChar::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 406 bool 407 BUnicodeChar::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 422 bool 423 BUnicodeChar::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 440 bool 441 BUnicodeChar::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 458 bool 459 BUnicodeChar::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 473 bool 474 BUnicodeChar::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 493 uint32 494 BUnicodeChar::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 521 uint32 522 BUnicodeChar::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 550 uint32 551 BUnicodeChar::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 582 int32 583 BUnicodeChar::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 625 void 626 BUnicodeChar::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 649 uint32 650 BUnicodeChar::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 687 size_t 688 BUnicodeChar::UTF8StringLength(const char *str) 689 { 690 size_t len = 0; 691 while (*str) { 692 FromUTF8(&str); 693 len++; 694 } 695 return len; 696 } 697 698 size_t 699 BUnicodeChar::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 4 static const bool kDefaultUseGrouping = false; 5 static const number_format_sign_policy kDefaultSignPolicy 6 = B_USE_NEGATIVE_SIGN_ONLY; 7 static const number_format_base kDefaultBase = B_DEFAULT_BASE; 8 static const bool kDefaultUseBasePrefix = false; 9 static const size_t kDefaultMinimalIntegerDigits = 1; 10 static const bool kDefaultUseZeroPadding = false; 11 12 // flags 13 enum { 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 23 BNumberFormatParameters::BNumberFormatParameters( 24 const BNumberFormatParameters *parent) 25 : BFormatParameters(parent), 26 fParent(parent), 27 fFlags(0) 28 { 29 } 30 31 // copy constructor 32 BNumberFormatParameters::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 46 BNumberFormatParameters::~BNumberFormatParameters() 47 { 48 } 49 50 // SetUseGrouping 51 void 52 BNumberFormatParameters::SetUseGrouping(bool useGrouping) 53 { 54 fUseGrouping = useGrouping; 55 fFlags |= USE_GROUPING_SET; 56 } 57 58 // UseGrouping 59 bool 60 BNumberFormatParameters::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 70 void 71 BNumberFormatParameters::SetSignPolicy(number_format_sign_policy policy) 72 { 73 fSignPolicy = policy; 74 fFlags |= SIGN_POLICY_SET; 75 } 76 77 // SignPolicy 78 number_format_sign_policy 79 BNumberFormatParameters::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 89 void 90 BNumberFormatParameters::SetBase(number_format_base base) 91 { 92 fBase = base; 93 fFlags |= BASE_SET; 94 } 95 96 // Base 97 number_format_base 98 BNumberFormatParameters::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 108 void 109 BNumberFormatParameters::SetUseBasePrefix(bool useBasePrefix) 110 { 111 fUseBasePrefix = useBasePrefix; 112 fFlags |= USE_BASE_PREFIX_SET; 113 } 114 115 // UseBasePrefix 116 bool 117 BNumberFormatParameters::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 127 void 128 BNumberFormatParameters::SetMinimalIntegerDigits(size_t minIntegerDigits) 129 { 130 fMinimalIntegerDigits = minIntegerDigits; 131 fFlags |= MINIMAL_INTEGER_DIGITS_SET; 132 } 133 134 // MinimalIntegerDigits 135 size_t 136 BNumberFormatParameters::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 146 void 147 BNumberFormatParameters::SetUseZeroPadding(bool useZeroPadding) 148 { 149 fUseZeroPadding = useZeroPadding; 150 fFlags |= USE_ZERO_PADDING_SET; 151 } 152 153 // UseZeroPadding 154 bool 155 BNumberFormatParameters::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 165 void 166 BNumberFormatParameters::SetParentNumberParameters( 167 const BNumberFormatParameters *parent) 168 { 169 fParent = parent; 170 SetParentParameters(parent); 171 } 172 173 // ParentNumberParameters 174 const BNumberFormatParameters * 175 BNumberFormatParameters::ParentNumberParameters() const 176 { 177 return fParent; 178 } 179 180 // = 181 BNumberFormatParameters & 182 BNumberFormatParameters::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
1 SubDir HAIKU_TOP src kits locale ; 2 3 DEFINES += _BUILDING_locale=1 ; 4 5 UsePublicHeaders [ FDirName $(HAIKU_TOP) headers os storage ] ; 6 7 UseHeaders [ FDirName $(HAIKU_TOP) headers os locale ] : true ; 8 UseHeaders [ FDirName $(HAIKU_TOP) headers os locale posix ] : true ; 9 10 SharedLibrary 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 21 enum 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 32 static int32 33 parseNumber(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 45 ssize_t 46 vstrfmon(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 165 ssize_t 166 strfmon(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 4 static const char *kArchivedCurrencyCodeName = "be:currency code"; 5 static const char *kArchivedDefaultSymbol = "be:default symbol"; 6 static const char *kArchivedDefaultFractionDigits 7 = "be:default fraction digits"; 8 9 // constructor 10 BCurrency::BCurrency(const BCurrency &other) 11 : fCurrencyCode(), 12 fDefaultSymbol(), 13 fDefaultFractionDigits(B_NO_INIT) 14 { 15 *this = other; 16 } 17 18 // constructor 19 BCurrency::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 37 BCurrency::BCurrency(const char *currencyCode) 38 { 39 // TODO: load currency from disk 40 } 41 42 // destructor 43 BCurrency::~BCurrency() 44 { 45 } 46 47 // InitCheck 48 status_t 49 BCurrency::InitCheck() const 50 { 51 return (fDefaultFractionDigits < 0 ? fDefaultFractionDigits : B_OK); 52 } 53 54 // Archive 55 status_t 56 BCurrency::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 75 BArchivable * 76 BCurrency::Instantiate(BMessage *archive) 77 { 78 if (!validate_instantiation(archive, "BCurrency")) 79 return NULL; 80 return new BCurrency(archive); 81 } 82 83 // CurrencyCode 84 const char * 85 BCurrency::CurrencyCode() const 86 { 87 return (InitCheck() == B_OK ? fCurrencyCode.String() : NULL); 88 } 89 90 // DefaultSymbol 91 const char * 92 BCurrency::DefaultSymbol() const 93 { 94 return (InitCheck() == B_OK ? fDefaultSymbol.String() : NULL); 95 } 96 97 // DefaultFractionDigits 98 int32 99 BCurrency::DefaultFractionDigits() const 100 { 101 return (InitCheck() == B_OK ? fDefaultFractionDigits : 0); 102 } 103 104 // GetSymbol 105 status_t 106 BCurrency::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 122 status_t 123 BCurrency::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 // = 139 BCurrency & 140 BCurrency::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 // == 154 bool 155 BCurrency::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 // != 163 bool 164 BCurrency::operator!=(const BCurrency &other) const 165 { 166 return !(*this == other); 167 } 168 169 // constructor 170 BCurrency::BCurrency() 171 { 172 // privatized to make it unaccessible 173 } 174 175 // _CheckData 176 bool 177 BCurrency::_CheckData() const 178 { 179 return (fDefaultFractionDigits >= 0 180 && fCurrencyCode.Length() > 0 181 && fDefaultSymbol.Length() == 0); 182 } 183 184 // _Unset 185 void 186 BCurrency::_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 11 char * 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 28 static const char *kPriorityAttr = "ADDON:priority"; 29 30 typedef BCatalogAddOn *(*InstantiateCatalogFunc)(const char *name, 31 const char *language, int32 fingerprint); 32 33 typedef BCatalogAddOn *(*CreateCatalogFunc)(const char *name, 34 const char *language); 35 36 typedef BCatalogAddOn *(*InstantiateEmbeddedCatalogFunc)(entry_ref *appOrAddOnRef); 37 38 static BLocaleRoster gLocaleRoster; 39 BLocaleRoster *be_locale_roster = &gLocaleRoster; 40 41 42 /* 43 * info about a single catalog-add-on (representing a catalog type): 44 */ 45 struct 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 65 BCatalogAddOnInfo::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 80 BCatalogAddOnInfo::~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 93 bool 94 BCatalogAddOnInfo::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 120 void 121 BCatalogAddOnInfo::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 */ 138 struct 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 }; 149 static RosterData gRosterData; 150 151 152 RosterData::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 175 RosterData::~RosterData() 176 { 177 BAutolock lock(fLock); 178 assert(lock.IsLocked()); 179 CleanupCatalogAddOns(); 180 closelog(); 181 } 182 183 184 int 185 RosterData::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 */ 196 void 197 RosterData::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 */ 300 void 301 RosterData::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 */ 318 const char *BLocaleRoster::kCatLangAttr = "BEOS:LOCALE_LANGUAGE"; 319 // name of catalog language, lives in every catalog file 320 const char *BLocaleRoster::kCatSigAttr = "BEOS:LOCALE_SIGNATURE"; 321 // catalog signature, lives in every catalog file 322 const char *BLocaleRoster::kCatFingerprintAttr = "BEOS:LOCALE_FINGERPRINT"; 323 // catalog fingerprint, may live in catalog file 324 325 const char *BLocaleRoster::kCatManagerMimeType 326 = "application/x-vnd.Be.locale.catalog-manager"; 327 // signature of catalog managing app 328 const char *BLocaleRoster::kCatEditorMimeType 329 = "application/x-vnd.Be.locale.catalog-editor"; 330 // signature of catalog editor app 331 332 const 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 335 int32 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 */ 343 BLocaleRoster::BLocaleRoster() 344 { 345 } 346 347 348 BLocaleRoster::~BLocaleRoster() 349 { 350 } 351 352 353 status_t 354 BLocaleRoster::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 365 status_t 366 BLocaleRoster::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 375 status_t 376 BLocaleRoster::GetDefaultCountry(BCountry **country) const 377 { 378 if (!country) 379 return B_BAD_VALUE; 380 *country = new BCountry(); 381 return B_OK; 382 } 383 384 385 status_t 386 BLocaleRoster::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 399 status_t 400 BLocaleRoster::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 */ 421 BCatalogAddOn* 422 BLocaleRoster::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 */ 461 BCatalogAddOn* 462 BLocaleRoster::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 */ 535 BCatalogAddOn* 536 BLocaleRoster::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 */ 570 status_t 571 BLocaleRoster::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 12 static BLocale gLocale; 13 BLocale *be_locale = &gLocale; 14 15 16 BLocale::BLocale() 17 { 18 BLocaleRoster roster; 19 roster.GetDefaultCollator(&fCollator); 20 roster.GetDefaultCountry(&fCountry); 21 roster.GetDefaultLanguage(&fLanguage); 22 } 23 24 25 BLocale::~BLocale() 26 { 27 } 28 29 30 const char * 31 BLocale::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 47 status_t 48 BLocale::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 5 BNumberFormat::BNumberFormat(const BNumberFormat &other) 6 : BFormat(other) 7 { 8 } 9 10 // destructor 11 BNumberFormat::~BNumberFormat() 12 { 13 } 14 15 // = 16 BNumberFormat & 17 BNumberFormat::operator=(const BNumberFormat &other) 18 { 19 BFormat::operator=(other); 20 return *this; 21 } 22 23 // constructor 24 BNumberFormat::BNumberFormat(BNumberFormatImpl *impl) 25 : BFormat(impl) 26 { 27 } 28 29 // NumberFormatImpl 30 inline 31 BNumberFormatImpl * 32 BNumberFormat::NumberFormatImpl() const 33 { 34 return static_cast<BNumberFormatImpl*>(fImpl); 35 } 36 -
src/kits/locale/FormatImpl.cpp
1 #include <FormatImpl.h> 2 3 // constructor 4 BFormatImpl::BFormatImpl() 5 { 6 } 7 8 // destructor 9 BFormatImpl::~BFormatImpl() 10 { 11 } 12 -
src/kits/locale/FormatParameters.cpp
1 #include <FormatParameters.h> 2 3 // defaults 4 static const format_alignment kDefaultAlignment = B_ALIGN_FORMAT_RIGHT; 5 static const size_t kDefaultFormatWidth = 1; 6 7 // flags 8 enum { 9 ALIGNMENT_SET = 0x01, 10 WIDTH_SET = 0x02, 11 }; 12 13 // constructor 14 BFormatParameters::BFormatParameters(const BFormatParameters *parent) 15 : fParent(parent), 16 fFlags(0) 17 { 18 } 19 20 // copy constructor 21 BFormatParameters::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 30 BFormatParameters::~BFormatParameters() 31 { 32 } 33 34 // SetAlignment 35 void 36 BFormatParameters::SetAlignment(format_alignment alignment) 37 { 38 fAlignment = alignment; 39 fFlags |= ALIGNMENT_SET; 40 } 41 42 // Alignment 43 format_alignment 44 BFormatParameters::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 54 void 55 BFormatParameters::SetFormatWidth(size_t width) 56 { 57 fWidth = width; 58 fFlags |= WIDTH_SET; 59 } 60 61 // FormatWidth 62 size_t 63 BFormatParameters::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 73 void 74 BFormatParameters::SetParentParameters(const BFormatParameters *parent) 75 { 76 fParent = parent; 77 } 78 79 // ParentParameters 80 const BFormatParameters * 81 BFormatParameters::ParentParameters() const 82 { 83 return fParent; 84 } 85 86 // = 87 BFormatParameters & 88 BFormatParameters::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 34 extern "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 */ 46 size_t hash<CatKey>::operator()(const CatKey &key) const 47 { 48 return key.fHashVal; 49 } 50 51 52 static const char kSeparator = '\01'; 53 54 55 CatKey::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 86 CatKey::CatKey(uint32 id) 87 : 88 fHashVal(id), 89 fFlags(0) 90 { 91 } 92 93 94 CatKey::CatKey() 95 : 96 fHashVal(0), 97 fFlags(0) 98 { 99 } 100 101 102 bool 103 CatKey::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 112 status_t 113 CatKey::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 144 size_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 153 static const char *kCatFolder = "catalogs"; 154 static const char *kCatExtension = ".catalog"; 155 156 const char *DefaultCatalog::kCatMimeType 157 = "locale/x-vnd.Be.locale-catalog.default"; 158 159 static 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 */ 169 DefaultCatalog::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 */ 230 DefaultCatalog::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 */ 246 DefaultCatalog::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 256 DefaultCatalog::~DefaultCatalog() 257 { 258 } 259 260 261 status_t 262 DefaultCatalog::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 */ 312 status_t 313 DefaultCatalog::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 357 status_t 358 DefaultCatalog::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 396 status_t 397 DefaultCatalog::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 */ 432 status_t 433 DefaultCatalog::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 458 status_t 459 DefaultCatalog::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 487 void 488 DefaultCatalog::MakeEmpty() 489 { 490 fCatMap.clear(); 491 } 492 493 494 int32 495 DefaultCatalog::CountItems() const 496 { 497 return fCatMap.size(); 498 } 499 500 501 const char * 502 DefaultCatalog::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 510 const char * 511 DefaultCatalog::GetString(uint32 id) 512 { 513 CatKey key(id); 514 return GetString(key); 515 } 516 517 518 const char * 519 DefaultCatalog::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 529 status_t 530 DefaultCatalog::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 540 status_t 541 DefaultCatalog::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 550 status_t 551 DefaultCatalog::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 */ 565 int32 566 DefaultCatalog::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 580 void 581 DefaultCatalog::UpdateFingerprint() 582 { 583 fFingerprint = ComputeFingerprint(); 584 } 585 586 587 /* 588 * writes mimetype, language-name and signature of catalog into the catalog-file. 589 */ 590 void 591 DefaultCatalog::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 615 status_t 616 DefaultCatalog::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 646 status_t 647 DefaultCatalog::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 712 BCatalogAddOn * 713 DefaultCatalog::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 725 BCatalogAddOn * 726 DefaultCatalog::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 737 BCatalogAddOn * 738 DefaultCatalog::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 749 const 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 5 BIntegerFormatImpl::BIntegerFormatImpl() 6 : BNumberFormatImpl() 7 { 8 } 9 10 // destructor 11 BIntegerFormatImpl::~BIntegerFormatImpl() 12 { 13 } 14 15 // DefaultNumberFormatParameters 16 BNumberFormatParameters * 17 BIntegerFormatImpl::DefaultNumberFormatParameters() 18 { 19 return DefaultIntegerFormatParameters(); 20 } 21 22 // DefaultNumberFormatParameters 23 const BNumberFormatParameters * 24 BIntegerFormatImpl::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: 18 static 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 */ 45 static void 46 SetupCatalogBasics() 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 126 extern "C" 127 _IMPEXP_LOCALE 128 void 129 initialize_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: 139 class BRoster { 140 public: 141 void InitMessengers(); 142 }; 143 144 extern const BRoster *be_roster; 145 146 extern "C" 147 _IMPEXP_LOCALE 148 void 149 initialize_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 5 BFormat::BFormat(const BFormat &other) 6 : fImpl(other.fImpl) 7 { 8 } 9 10 // destructor 11 BFormat::~BFormat() 12 { 13 } 14 15 // = 16 BFormat & 17 BFormat::operator=(const BFormat &other) 18 { 19 fImpl = other.fImpl; 20 return *this; 21 } 22 23 // constructor 24 BFormat::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 16 class 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 4 BIntegerFormatParameters::BIntegerFormatParameters( 5 const BIntegerFormatParameters *parent) 6 : BNumberFormatParameters(parent), 7 fParent(parent) 8 { 9 } 10 11 // copy constructor 12 BIntegerFormatParameters::BIntegerFormatParameters( 13 const BIntegerFormatParameters &other) 14 : BNumberFormatParameters(other), 15 fParent(other.fParent) 16 { 17 } 18 19 // destructor 20 BIntegerFormatParameters::~BIntegerFormatParameters() 21 { 22 } 23 24 // SetParentIntegerParameters 25 void 26 BIntegerFormatParameters::SetParentIntegerParameters( 27 const BIntegerFormatParameters *parent) 28 { 29 fParent = parent; 30 SetParentNumberParameters(parent); 31 } 32 33 // ParentIntegerParameters 34 const BIntegerFormatParameters * 35 BIntegerFormatParameters::ParentIntegerParameters() const 36 { 37 return fParent; 38 } 39 40 // = 41 BIntegerFormatParameters & 42 BIntegerFormatParameters::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 16 uint32 _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 /* ========================================================================= */ 30 uint32 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
92 92 SubInclude HAIKU_TOP src kits device ; 93 93 SubInclude HAIKU_TOP src kits game ; 94 94 SubInclude HAIKU_TOP src kits interface ; 95 SubInclude HAIKU_TOP src kits locale ; 95 96 SubInclude HAIKU_TOP src kits mail ; 96 97 SubInclude HAIKU_TOP src kits media ; 97 98 SubInclude HAIKU_TOP src kits midi ; -
data/etc/locale/languages/français.language
1 fr,roman,ltr 2 -- 3 Hier 4 Aujourd'hui 5 Demain 6 Avenir 7 8 Dimanche 9 Lundi 10 Mardi 11 Mercredi 12 Jeudi 13 Vendredi 14 Samedi 15 16 Dim 17 Lun 18 Mar 19 Mer 20 Jeu 21 Ven 22 Sam 23 24 Janvier 25 Février 26 Mars 27 Avril 28 Mai 29 Juin 30 Juillet 31 Août 32 Septembre 33 Octobre 34 Novembre 35 Décembre 36 37 Jan 38 Fev 39 Mars 40 Avr 41 Mai 42 Juin 43 Juil 44 Août 45 Sep 46 Oct 47 Nov 48 Dec 49 -
data/etc/locale/languages/deutsch.language
1 de,germanic,ltr 2 -- 3 Gestern 4 Heute 5 Morgen 6 Zukunft 7 8 Sonntag 9 Montag 10 Dienstag 11 Mittwoch 12 Donnerstag 13 Freitag 14 Samstag 15 16 So 17 Mo 18 Di 19 Mi 20 Do 21 Fr 22 Sa 23 24 Januar 25 Februar 26 März 27 April 28 Mai 29 Juni 30 Juli 31 August 32 September 33 Oktober 34 November 35 Dezember 36 37 Jan 38 Feb 39 Mär 40 Apr 41 Mai 42 Jun 43 Jul 44 Aug 45 Sep 46 Okt 47 Nov 48 Dez 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 10 class BLocale; 11 12 class _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 6 class _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 7 class BString; 8 struct format_field_position; 9 10 class _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 8 class BLanguage; 9 class BLocale; 10 class BCollator; 11 class BCountry; 12 class BCatalog; 13 class BCatalogAddOn; 14 15 namespace BPrivate { 16 class EditableCatalog; 17 }; 18 19 enum { 20 B_LOCALE_CHANGED = '_LCC', 21 }; 22 23 class _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 12 class BCatalog; 13 class BString; 14 class BLocaleRoster; 15 16 17 class _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 57 extern _IMPEXP_LOCALE BLocale *be_locale; 58 extern _IMPEXP_LOCALE BLocaleRoster *be_locale_roster; 59 60 //---------------------------------------------------------------------- 61 //--- country short-hands inlines --- 62 63 inline void 64 BLocale::FormatDate(char *target, size_t maxSize, time_t timer, bool longFormat) 65 { 66 fCountry->FormatDate(target, maxSize, timer, longFormat); 67 } 68 69 70 inline void 71 BLocale::FormatDate(BString *target, time_t timer, bool longFormat) 72 { 73 fCountry->FormatDate(target, timer, longFormat); 74 } 75 76 77 inline void 78 BLocale::FormatTime(char *target, size_t maxSize, time_t timer, bool longFormat) 79 { 80 fCountry->FormatTime(target, maxSize, timer, longFormat); 81 } 82 83 84 inline void 85 BLocale::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 94 inline int 95 BLocale::StringCompare(const char *string1, const char *string2, int32 length, int8 strength) const 96 { 97 return fCollator->Compare(string1, string2, length, strength); 98 } 99 100 101 inline int 102 BLocale::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 108 inline void 109 BLocale::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 6 struct format_field_position; 7 class BFloatFormatParameters; 8 class BString; 9 10 class _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 7 class BNumberFormatImpl; 8 9 class _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 6 enum 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 13 class _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 10 enum { 11 B_METRIC = 0, 12 B_US 13 }; 14 15 16 class _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 18 typedef 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 7 class BIntegerFormatImpl; 8 class 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 // 15 class _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 28 BCatalog *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 */ 35 static status_t 36 get_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 */ 68 status_t 69 get_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 5 enum 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 38 enum 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 97 enum 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 8 class BFormatParameters; 9 10 class _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 9 class BCatalogAddOn; 10 class BLocale; 11 class BMessage; 12 struct entry_ref; 13 14 15 class _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 54 extern _IMPEXP_LOCALE BCatalog* be_catalog; 55 extern _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 144 class _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... 209 extern "C" _IMPEXP_LOCALE 210 BCatalogAddOn *instantiate_catalog(const char *signature, 211 const char *language, int32 fingerprint); 212 // ...the function that creates an empty catalog for this add-on-type... 213 extern "C" _IMPEXP_LOCALE 214 BCatalogAddOn *create_catalog(const char *signature, 215 const char *language); 216 // ...and the priority which will be used to order the catalog-add-ons: 217 extern _IMPEXP_LOCALE uint8 gCatalogAddOnPriority; 218 219 220 /* 221 * BCatalog - inlines for trivial accessors: 222 */ 223 inline status_t 224 BCatalog::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 235 inline status_t 236 BCatalog::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 247 inline status_t 248 BCatalog::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 259 inline status_t 260 BCatalog::InitCheck() const 261 { 262 return fCatalog 263 ? fCatalog->InitCheck() 264 : B_NO_INIT; 265 } 266 267 268 inline int32 269 BCatalog::CountItems() const 270 { 271 if (!fCatalog) 272 return 0; 273 return fCatalog->CountItems(); 274 } 275 276 277 inline BCatalogAddOn * 278 BCatalog::CatalogAddOn() 279 { 280 return fCatalog; 281 } 282 283 284 /* 285 * BCatalogAddOn - inlines for trivial accessors: 286 */ 287 inline BCatalogAddOn * 288 BCatalogAddOn::Next() 289 { 290 return fNext; 291 } 292 293 294 inline const char * 295 BCatalogAddOn::MarkForTranslation(const char *str, const char *ctx, 296 const char *cmt) 297 { 298 return str; 299 } 300 301 302 inline int32 303 BCatalogAddOn::MarkForTranslation(int32 id) 304 { 305 return id; 306 } 307 308 309 namespace BPrivate { 310 311 /* 312 * EditableCatalog 313 */ 314 class _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 7 typedef int nl_item; 8 typedef void *nl_catd; 9 10 #include <LocaleBuild.h> 11 12 #ifdef __cplusplus 13 extern "C" { 14 #endif 15 16 extern _IMPEXP_LOCALE nl_catd catopen(const char *name, int oflag); 17 extern _IMPEXP_LOCALE char *catgets(nl_catd cat,int setID,int msgID,const char *defaultMessage); 18 extern _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 82 extern "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 9 extern "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 8 enum format_alignment { 9 B_ALIGN_FORMAT_LEFT, // reuse B_ALIGN_LEFT/B_ALIGN_RIGHT? 10 B_ALIGN_FORMAT_RIGHT, 11 }; 12 13 class _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 7 class BString; 8 class BFloatFormatImpl; 9 10 class _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 18 class BFile; 19 20 namespace BPrivate { 21 struct CatKey; 22 } 23 24 #if __GNUC__ > 2 25 namespace __gnu_cxx{ 26 #endif 27 28 template<> struct hash<BPrivate::CatKey> { 29 size_t operator() (const BPrivate::CatKey &key) const; 30 }; 31 32 #if __GNUC__ > 2 33 } // __gnu_cxx 34 35 using namespace __gnu_cxx; 36 #endif 37 38 namespace 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 */ 47 struct _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 */ 75 class _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 150 inline 151 DefaultCatalog::CatWalker::CatWalker(CatMap &catMap) 152 : fPos(catMap.begin()), 153 fEnd(catMap.end()) 154 { 155 } 156 157 inline bool 158 DefaultCatalog::CatWalker::AtEnd() const 159 { 160 return fPos == fEnd; 161 } 162 163 inline const CatKey & 164 DefaultCatalog::CatWalker::GetKey() const 165 { 166 assert(fPos != fEnd); 167 return fPos->first; 168 } 169 170 inline const char * 171 DefaultCatalog::CatWalker::GetValue() const 172 { 173 assert(fPos != fEnd); 174 return fPos->second.String(); 175 } 176 177 inline void 178 DefaultCatalog::CatWalker::Next() 179 { 180 ++fPos; 181 } 182 183 inline status_t 184 DefaultCatalog::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 194 using 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 10 class BString; 11 class BCollatorAddOn; 12 13 14 enum 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 26 class _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 58 inline bool 59 BCollator::Equal(const char *s1, const char *s2, int32 len, int8 strength) 60 { 61 return Compare(s1, s2, len, strength) == 0; 62 } 63 64 65 inline bool 66 BCollator::Greater(const char *s1, const char *s2, int32 len, int8 strength) 67 { 68 return Compare(s1, s2, len, strength) > 0; 69 } 70 71 72 inline bool 73 BCollator::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 83 class _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. 117 extern "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 6 struct format_field_position; 7 class BNumberFormatParameters; 8 9 class _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 10 enum 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 17 class _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 8 enum 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 52 enum 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 81 enum 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 180 enum 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 191 class _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 227 inline uint32 228 BUnicodeChar::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 6 enum number_format_sign_policy { 7 B_USE_NEGATIVE_SIGN_ONLY, 8 B_USE_SPACE_FOR_POSITIVE_SIGN, 9 B_USE_POSITIVE_SIGN, 10 }; 11 12 enum 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 23 class _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 6 struct format_field_position; 7 class BIntegerFormatParameters; 8 class BString; 9 10 class _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 8 enum { 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 27 struct _IMPEXP_LOCALE format_field_position { 28 uint32 field_type; 29 int32 start; 30 int32 length; 31 }; 32 33 class BFormatImpl; 34 35 class _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
45 45 typedef int daddr_t; 46 46 typedef char * caddr_t; 47 47 48 typedef unsigned long addr_t; 48 typedef unsigned long addr_t; 49 49 50 typedef long key_t; 50 51 51 52 #include <null.h>