]>
git.cameronkatri.com Git - apple_cmds.git/blob - text_cmds/tr/cmap.c
2 * Copyright (c) 2004 Tim J. Robbins.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * "Character map" ADT. Stores mappings between pairs of characters in a
28 * splay tree, with a lookup table cache to simplify looking up the first
29 * bunch of characters (which are presumably more common than others).
32 #include <sys/cdefs.h>
33 __FBSDID("$FreeBSD: src/usr.bin/tr/cmap.c,v 1.2 2004/07/14 08:36:09 tjr Exp $");
42 static struct cmapnode
*cmap_splay(struct cmapnode
*, wint_t);
46 * Allocate a character map.
53 cm
= malloc(sizeof(*cm
));
57 cm
->cm_def
= CM_DEF_SELF
;
58 cm
->cm_havecache
= false;
59 cm
->cm_min
= cm
->cm_max
= 0;
65 * Add a mapping from "from" to "to" to the map.
68 cmap_add(struct cmap
*cm
, wint_t from
, wint_t to
)
70 struct cmapnode
*cmn
, *ncmn
;
72 cm
->cm_havecache
= false;
74 if (cm
->cm_root
== NULL
) {
75 cmn
= malloc(sizeof(*cmn
));
80 cmn
->cmn_left
= cmn
->cmn_right
= NULL
;
82 cm
->cm_min
= cm
->cm_max
= from
;
86 cmn
= cm
->cm_root
= cmap_splay(cm
->cm_root
, from
);
88 if (cmn
->cmn_from
== from
) {
93 ncmn
= malloc(sizeof(*ncmn
));
96 ncmn
->cmn_from
= from
;
98 if (from
< cmn
->cmn_from
) {
99 ncmn
->cmn_left
= cmn
->cmn_left
;
100 ncmn
->cmn_right
= cmn
;
101 cmn
->cmn_left
= NULL
;
103 ncmn
->cmn_right
= cmn
->cmn_right
;
104 ncmn
->cmn_left
= cmn
;
105 cmn
->cmn_right
= NULL
;
107 if (from
< cm
->cm_min
)
109 if (from
> cm
->cm_max
)
117 * cmap_lookup_hard --
118 * Look up the mapping for a character without using the cache.
121 cmap_lookup_hard(struct cmap
*cm
, wint_t ch
)
124 if (cm
->cm_root
!= NULL
) {
125 cm
->cm_root
= cmap_splay(cm
->cm_root
, ch
);
126 if (cm
->cm_root
->cmn_from
== ch
)
127 return (cm
->cm_root
->cmn_to
);
129 return (cm
->cm_def
== CM_DEF_SELF
? ch
: cm
->cm_def
);
137 cmap_cache(struct cmap
*cm
)
141 for (ch
= 0; ch
< CM_CACHE_SIZE
; ch
++)
142 cm
->cm_cache
[ch
] = cmap_lookup_hard(cm
, ch
);
144 cm
->cm_havecache
= true;
149 * Change the value that characters without mappings map to, and
150 * return the old value. The special character value CM_MAP_SELF
151 * means characters map to themselves.
154 cmap_default(struct cmap
*cm
, wint_t def
)
160 cm
->cm_havecache
= false;
164 static struct cmapnode
*
165 cmap_splay(struct cmapnode
*t
, wint_t ch
)
167 struct cmapnode N
, *l
, *r
, *y
;
170 * Based on public domain code from Sleator.
175 N
.cmn_left
= N
.cmn_right
= NULL
;
178 if (ch
< t
->cmn_from
) {
179 if (t
->cmn_left
!= NULL
&&
180 ch
< t
->cmn_left
->cmn_from
) {
182 t
->cmn_left
= y
->cmn_right
;
186 if (t
->cmn_left
== NULL
)
191 } else if (ch
> t
->cmn_from
) {
192 if (t
->cmn_right
!= NULL
&&
193 ch
> t
->cmn_right
->cmn_from
) {
195 t
->cmn_right
= y
->cmn_left
;
199 if (t
->cmn_right
== NULL
)
207 l
->cmn_right
= t
->cmn_left
;
208 r
->cmn_left
= t
->cmn_right
;
209 t
->cmn_left
= N
.cmn_right
;
210 t
->cmn_right
= N
.cmn_left
;