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/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 */
32static void *upcase_table;
33static void *lowcase_table;
34
35
36/*******************************************************************
37load the case handling tables
38********************************************************************/
39void 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", dyn_DATADIR), 0x20000);
48	lowcase_table = map_file(talloc_asprintf(mem_ctx, "%s/lowcase.dat", dyn_DATADIR), 0x20000);
49	talloc_free(mem_ctx);
50	if (upcase_table == NULL) {
51		/* try also under codepages for testing purposes */
52		upcase_table = map_file("codepages/upcase.dat", 0x20000);
53		if (upcase_table == NULL) {
54			upcase_table = (void *)-1;
55		}
56	}
57	if (lowcase_table == NULL) {
58		/* try also under codepages for testing purposes */
59		lowcase_table = map_file("codepages/lowcase.dat", 0x20000);
60		if (lowcase_table == NULL) {
61			lowcase_table = (void *)-1;
62		}
63	}
64}
65
66/**
67 Convert a codepoint_t to upper case.
68**/
69_PUBLIC_ codepoint_t toupper_m(codepoint_t val)
70{
71	if (val < 128) {
72		return toupper(val);
73	}
74	if (upcase_table == NULL) {
75		load_case_tables();
76	}
77	if (upcase_table == (void *)-1) {
78		return val;
79	}
80	if (val & 0xFFFF0000) {
81		return val;
82	}
83	return SVAL(upcase_table, val*2);
84}
85
86/**
87 Convert a codepoint_t to lower case.
88**/
89_PUBLIC_ codepoint_t tolower_m(codepoint_t val)
90{
91	if (val < 128) {
92		return tolower(val);
93	}
94	if (lowcase_table == NULL) {
95		load_case_tables();
96	}
97	if (lowcase_table == (void *)-1) {
98		return val;
99	}
100	if (val & 0xFFFF0000) {
101		return val;
102	}
103	return SVAL(lowcase_table, val*2);
104}
105
106/**
107  compare two codepoints case insensitively
108*/
109_PUBLIC_ int codepoint_cmpi(codepoint_t c1, codepoint_t c2)
110{
111	if (c1 == c2 ||
112	    toupper_m(c1) == toupper_m(c2)) {
113		return 0;
114	}
115	return c1 - c2;
116}
117
118
119