1 /*
   2  * Copyright 2013 Garrett D'Amore <garrett@damore.org>
   3  * Copyright 2010 Nexenta Systems, Inc.  All rights reserved.
   4  * Copyright (c) 1989, 1993
   5  *      The Regents of the University of California.  All rights reserved.
   6  * (c) UNIX System Laboratories, Inc.
   7  * All or some portions of this file are derived from material licensed
   8  * to the University of California by American Telephone and Telegraph
   9  * Co. or Unix System Laboratories, Inc. and are reproduced herein with
  10  * the permission of UNIX System Laboratories, Inc.
  11  *
  12  * This code is derived from software contributed to Berkeley by
  13  * Paul Borman at Krystal Technologies.
  14  *
  15  * Redistribution and use in source and binary forms, with or without
  16  * modification, are permitted provided that the following conditions
  17  * are met:
  18  * 1. Redistributions of source code must retain the above copyright
  19  *    notice, this list of conditions and the following disclaimer.
  20  * 2. Redistributions in binary form must reproduce the above copyright
  21  *    notice, this list of conditions and the following disclaimer in the
  22  *    documentation and/or other materials provided with the distribution.
  23  * 4. Neither the name of the University nor the names of its contributors
  24  *    may be used to endorse or promote products derived from this software
  25  *    without specific prior written permission.
  26  *
  27  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  28  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  29  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  30  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  31  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  32  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  33  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  34  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  35  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  36  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  37  * SUCH DAMAGE.
  38  */
  39 
  40 #include "lint.h"
  41 #include <wctype.h>
  42 #include <stdio.h>
  43 #include "localeimpl.h"
  44 #include "lctype.h"
  45 #include "runetype.h"
  46 
  47 static wint_t
  48 change_case_ext(locale_t loc, wint_t c, int lower)
  49 {
  50         const _RuneLocale *rl;
  51         const _RuneRange *rr;
  52         const _RuneEntry *base, *re;
  53         size_t lim;
  54 
  55         if (c < 0 || c == EOF)
  56                 return (c);
  57 
  58         rl = loc->runelocale;
  59         rr = lower ? &rl->__maplower_ext : &rl->__mapupper_ext;
  60         /* Binary search -- see bsearch.c for explanation. */
  61         base = rr->__ranges;
  62         for (lim = rr->__nranges; lim != 0; lim >>= 1) {
  63                 re = base + (lim >> 1);
  64                 if (re->__min <= c && c <= re->__max) {
  65                         return (re->__map + c - re->__min);
  66                 } else if (c > re->__max) {
  67                         base = re + 1;
  68                         lim--;
  69                 }
  70         }
  71 
  72         return (c);
  73 }
  74 
  75 wint_t
  76 towlower_l(wint_t wc, locale_t loc)
  77 {
  78         return (iswascii(wc) ? __trans_lower[wc] :
  79             (wc < 0 || wc >= _CACHED_RUNES) ?
  80             change_case_ext(loc, wc, 1) :
  81             loc->runelocale->__maplower[wc]);
  82 }
  83 
  84 #undef towlower
  85 wint_t
  86 towlower(wint_t wc)
  87 {
  88         return (iswascii(wc) ? __trans_lower[wc] :
  89             (wc < 0 || wc >= _CACHED_RUNES) ?
  90             change_case_ext(uselocale(NULL), wc, 1) :
  91             uselocale(NULL)->runelocale->__maplower[wc]);
  92 }
  93 
  94 wint_t
  95 towupper_l(wint_t wc, locale_t loc)
  96 {
  97         return (iswascii(wc) ? __trans_upper[wc] :
  98             (wc < 0 || wc >= _CACHED_RUNES) ?
  99             change_case_ext(loc, wc, 0) :
 100             loc->runelocale->__mapupper[wc]);
 101 }
 102 
 103 #undef towupper
 104 wint_t
 105 towupper(wint_t wc)
 106 {
 107         return (iswascii(wc) ? __trans_upper[wc] :
 108             (wc < 0 || wc >= _CACHED_RUNES) ?
 109             change_case_ext(uselocale(NULL), wc, 0) :
 110             uselocale(NULL)->runelocale->__mapupper[wc]);
 111 }