linux/fs/ntfs3/upcase.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 *
   4 * Copyright (C) 2019-2021 Paragon Software GmbH, All rights reserved.
   5 *
   6 */
   7
   8#include <linux/kernel.h>
   9#include <linux/types.h>
  10
  11#include "ntfs_fs.h"
  12
  13static inline u16 upcase_unicode_char(const u16 *upcase, u16 chr)
  14{
  15        if (chr < 'a')
  16                return chr;
  17
  18        if (chr <= 'z')
  19                return chr - ('a' - 'A');
  20
  21        return upcase[chr];
  22}
  23
  24/*
  25 * ntfs_cmp_names
  26 *
  27 * Thanks Kari Argillander <kari.argillander@gmail.com> for idea and implementation 'bothcase'
  28 *
  29 * Straight way to compare names:
  30 * - Case insensitive
  31 * - If name equals and 'bothcases' then
  32 * - Case sensitive
  33 * 'Straight way' code scans input names twice in worst case.
  34 * Optimized code scans input names only once.
  35 */
  36int ntfs_cmp_names(const __le16 *s1, size_t l1, const __le16 *s2, size_t l2,
  37                   const u16 *upcase, bool bothcase)
  38{
  39        int diff1 = 0;
  40        int diff2;
  41        size_t len = min(l1, l2);
  42
  43        if (!bothcase && upcase)
  44                goto case_insentive;
  45
  46        for (; len; s1++, s2++, len--) {
  47                diff1 = le16_to_cpu(*s1) - le16_to_cpu(*s2);
  48                if (diff1) {
  49                        if (bothcase && upcase)
  50                                goto case_insentive;
  51
  52                        return diff1;
  53                }
  54        }
  55        return l1 - l2;
  56
  57case_insentive:
  58        for (; len; s1++, s2++, len--) {
  59                diff2 = upcase_unicode_char(upcase, le16_to_cpu(*s1)) -
  60                        upcase_unicode_char(upcase, le16_to_cpu(*s2));
  61                if (diff2)
  62                        return diff2;
  63        }
  64
  65        diff2 = l1 - l2;
  66        return diff2 ? diff2 : diff1;
  67}
  68
  69int ntfs_cmp_names_cpu(const struct cpu_str *uni1, const struct le_str *uni2,
  70                       const u16 *upcase, bool bothcase)
  71{
  72        const u16 *s1 = uni1->name;
  73        const __le16 *s2 = uni2->name;
  74        size_t l1 = uni1->len;
  75        size_t l2 = uni2->len;
  76        size_t len = min(l1, l2);
  77        int diff1 = 0;
  78        int diff2;
  79
  80        if (!bothcase && upcase)
  81                goto case_insentive;
  82
  83        for (; len; s1++, s2++, len--) {
  84                diff1 = *s1 - le16_to_cpu(*s2);
  85                if (diff1) {
  86                        if (bothcase && upcase)
  87                                goto case_insentive;
  88
  89                        return diff1;
  90                }
  91        }
  92        return l1 - l2;
  93
  94case_insentive:
  95        for (; len; s1++, s2++, len--) {
  96                diff2 = upcase_unicode_char(upcase, *s1) -
  97                        upcase_unicode_char(upcase, le16_to_cpu(*s2));
  98                if (diff2)
  99                        return diff2;
 100        }
 101
 102        diff2 = l1 - l2;
 103        return diff2 ? diff2 : diff1;
 104}
 105