1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 #include <i18nutil/oneToOneMapping.hxx>
29 
30 namespace com { namespace sun { namespace star { namespace i18n {
31 
32 oneToOneMapping::oneToOneMapping( OneToOneMappingTable_t *rpTable, const size_t rnBytes, const size_t rnUnitSize )
33     : mpTable( rpTable ),
34       mnSize( rnBytes / rnUnitSize )
35 {
36 }
37 
38 oneToOneMapping::~oneToOneMapping()
39 {
40 }
41 
42 sal_Unicode oneToOneMapping::find(const sal_Unicode nKey) const
43 {
44     if( mpTable )
45     {
46         // binary search
47 	    int bottom = 0;
48 	    int top = mnSize - 1;
49 	    int current;
50 
51 	    for (;;) {
52             current = (top + bottom) / 2;
53             if( nKey < mpTable[current].first )
54                 top = current - 1;
55             else if( nKey > mpTable[current].first )
56                 bottom = current + 1;
57             else
58                 return mpTable[current].second;
59 
60             if( bottom > top )
61                 return sal_Unicode( nKey );
62 	    }
63     }
64     else
65         return sal_Unicode( nKey );
66 }
67 
68 oneToOneMappingWithFlag::oneToOneMappingWithFlag( UnicodePairWithFlag *rpTableWF, const size_t rnSize, const UnicodePairFlag rnFlag )
69     : oneToOneMapping( NULL, rnSize, sizeof(UnicodePairWithFlag) ),
70       mpTableWF ( rpTableWF ),
71       mnFlag    ( rnFlag ),
72       mbHasIndex( sal_False )
73 {
74 }
75 
76 oneToOneMappingWithFlag::~oneToOneMappingWithFlag()
77 {
78 	if( mbHasIndex )
79         for( int i = 0; i < 256; i++ )
80             if( mpIndex[i] )
81                 delete [] mpIndex[i];
82 }
83 
84 
85 void oneToOneMappingWithFlag::makeIndex()
86 {
87     if( !mbHasIndex && mpTableWF )
88     {
89         int i, j, high, low, current = -1;
90 
91         for( i = 0; i < 256; i++ )
92             mpIndex[i] = NULL;
93 
94         for( size_t k = 0; k < mnSize; k++ )
95         {
96             high = (mpTableWF[k].first >> 8) & 0xFF;
97             low  = (mpTableWF[k].first)      & 0xFF;
98             if( high != current )
99             {
100                 current = high;
101                 mpIndex[high] = new UnicodePairWithFlag*[256];
102 
103                 for( j = 0; j < 256; j++ )
104                     mpIndex[high][j] = NULL;
105             }
106             mpIndex[high][low] = &mpTableWF[k];
107         }
108 
109         mbHasIndex = sal_True;
110     }
111 }
112 
113 sal_Unicode oneToOneMappingWithFlag::find( const sal_Unicode nKey ) const
114 {
115     if( mpTableWF )
116     {
117         if( mbHasIndex )
118         {
119             // index search
120             int high, low;
121             high = (nKey >> 8) & 0xFF;
122             low = nKey & 0xFF;
123             if( mpIndex[high] != NULL &&
124                 mpIndex[high][low] != NULL &&
125                 mpIndex[high][low]->flag & mnFlag )
126                 return mpIndex[high][low]->second;
127             else
128                 return sal_Unicode( nKey );
129         }
130         else
131         {
132             // binary search
133             int bottom = 0;
134             int top = mnSize - 1;
135             int current;
136 
137             for (;;) {
138                 current = (top + bottom) / 2;
139                 if( nKey < mpTableWF[current].first )
140                     top = current - 1;
141                 else if( nKey > mpTableWF[current].first )
142                     bottom = current + 1;
143                 else
144                 {
145                     if( mpTableWF[current].flag & mnFlag )
146                         return mpTableWF[current].second;
147                     else
148                         return sal_Unicode( nKey );
149                 }
150 
151                 if( bottom > top )
152                     return sal_Unicode( nKey );
153             }
154 	    }
155 	}
156     else
157         return sal_Unicode( nKey );
158 }
159 
160 
161 } } } }
162