53febb8b5e5399b5905880cf8c747890c87eae8a
[samba.git] / lib / util / charset / codepoints.c
1 /* 
2    Unix SMB/CIFS implementation.
3    Samba utility functions
4    Copyright (C) Andrew Tridgell 1992-2001
5    Copyright (C) Simo Sorce 2001
6    
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 3 of the License, or
10    (at your option) any later version.
11    
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16    
17    You should have received a copy of the GNU General Public License
18    along with this program.  If not, see <http://www.gnu.org/licenses/>.
19 */
20
21 #include "includes.h"
22 #include "system/locale.h"
23 #include "dynconfig.h"
24
25 /**
26  * @file
27  * @brief Unicode string manipulation
28  */
29
30 /* these 2 tables define the unicode case handling.  They are loaded
31    at startup either via mmap() or read() from the lib directory */
32 static void *upcase_table;
33 static void *lowcase_table;
34
35
36 /*******************************************************************
37 load the case handling tables
38 ********************************************************************/
39 void load_case_tables(void)
40 {
41         TALLOC_CTX *mem_ctx;
42
43         mem_ctx = talloc_init("load_case_tables");
44         if (!mem_ctx) {
45                 smb_panic("No memory for case_tables");
46         }
47         upcase_table = map_file(talloc_asprintf(mem_ctx, "%s/upcase.dat", get_dyn_CODEPAGEDIR()), 0x20000);
48         lowcase_table = map_file(talloc_asprintf(mem_ctx, "%s/lowcase.dat", get_dyn_CODEPAGEDIR()), 0x20000);
49         talloc_free(mem_ctx);
50         if (upcase_table == NULL) {
51                 DEBUG(1, ("Failed to load upcase.dat, will use lame ASCII-only case sensitivity rules\n"));
52                 upcase_table = (void *)-1;
53         }
54         if (lowcase_table == NULL) {
55                 DEBUG(1, ("Failed to load lowcase.dat, will use lame ASCII-only case sensitivity rules\n"));
56                 lowcase_table = (void *)-1;
57         }
58 }
59
60 /**
61  Convert a codepoint_t to upper case.
62 **/
63 _PUBLIC_ codepoint_t toupper_m(codepoint_t val)
64 {
65         if (val < 128) {
66                 return toupper(val);
67         }
68         if (upcase_table == NULL) {
69                 load_case_tables();
70         }
71         if (upcase_table == (void *)-1) {
72                 return val;
73         }
74         if (val & 0xFFFF0000) {
75                 return val;
76         }
77         return SVAL(upcase_table, val*2);
78 }
79
80 /**
81  Convert a codepoint_t to lower case.
82 **/
83 _PUBLIC_ codepoint_t tolower_m(codepoint_t val)
84 {
85         if (val < 128) {
86                 return tolower(val);
87         }
88         if (lowcase_table == NULL) {
89                 load_case_tables();
90         }
91         if (lowcase_table == (void *)-1) {
92                 return val;
93         }
94         if (val & 0xFFFF0000) {
95                 return val;
96         }
97         return SVAL(lowcase_table, val*2);
98 }
99
100 /**
101  If we upper cased this character, would we get the same character?
102 **/
103 _PUBLIC_ bool islower_m(codepoint_t val)
104 {
105         return (toupper_m(val) != val);
106 }
107
108 /**
109  If we lower cased this character, would we get the same character?
110 **/
111 _PUBLIC_ bool isupper_m(codepoint_t val)
112 {
113         return (tolower_m(val) != val);
114 }
115
116 /**
117   compare two codepoints case insensitively
118 */
119 _PUBLIC_ int codepoint_cmpi(codepoint_t c1, codepoint_t c2)
120 {
121         if (c1 == c2 ||
122             toupper_m(c1) == toupper_m(c2)) {
123                 return 0;
124         }
125         return c1 - c2;
126 }
127
128