unistr.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:5k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. /*
  2.  * unistr.c - Unicode string handling. Part of the Linux-NTFS project.
  3.  *
  4.  * Copyright (c) 2000,2001 Anton Altaparmakov.
  5.  *
  6.  * This program/include file is free software; you can redistribute it and/or
  7.  * modify it under the terms of the GNU General Public License as published
  8.  * by the Free Software Foundation; either version 2 of the License, or
  9.  * (at your option) any later version.
  10.  *
  11.  * This program/include file is distributed in the hope that it will be 
  12.  * useful, but WITHOUT ANY WARRANTY; without even the implied warranty 
  13.  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.  * GNU General Public License for more details.
  15.  *
  16.  * You should have received a copy of the GNU General Public License
  17.  * along with this program (in the main directory of the Linux-NTFS 
  18.  * distribution in the file COPYING); if not, write to the Free Software
  19.  * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  20.  */
  21. #include <linux/string.h>
  22. #include <asm/byteorder.h>
  23. #include "unistr.h"
  24. #include "macros.h"
  25. /*
  26.  * This is used by the name collation functions to quickly determine what
  27.  * characters are (in)valid.
  28.  */
  29. const __u8 legal_ansi_char_array[0x40] = {
  30. 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
  31. 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
  32. 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
  33. 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
  34. 0x17, 0x07, 0x18, 0x17, 0x17, 0x17, 0x17, 0x17,
  35. 0x17, 0x17, 0x18, 0x16, 0x16, 0x17, 0x07, 0x00,
  36. 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17,
  37. 0x17, 0x17, 0x04, 0x16, 0x18, 0x16, 0x18, 0x18,
  38. };
  39. /**
  40.  * ntfs_are_names_equal - compare two Unicode names for equality
  41.  * @s1: name to compare to @s2
  42.  * @s1_len: length in Unicode characters of @s1
  43.  * @s2: name to compare to @s1
  44.  * @s2_len: length in Unicode characters of @s2
  45.  * @ic: ignore case bool
  46.  * @upcase: upcase table (only if @ic == IGNORE_CASE)
  47.  * @upcase_size: length in Unicode characters of @upcase (if present)
  48.  *
  49.  * Compare the names @s1 and @s2 and return TRUE (1) if the names are
  50.  * identical, or FALSE (0) if they are not identical. If @ic is IGNORE_CASE,
  51.  * the @upcase table is used to performa a case insensitive comparison.
  52.  */
  53. int ntfs_are_names_equal(wchar_t *s1, size_t s1_len,
  54.      wchar_t *s2, size_t s2_len, int ic,
  55.      wchar_t *upcase, __u32 upcase_size)
  56. {
  57. if (s1_len != s2_len)
  58. return 0;
  59. if (!ic)
  60. return memcmp(s1, s2, s1_len << 1) ? 0: 1;
  61. return ntfs_wcsncasecmp(s1, s2, s1_len, upcase, upcase_size) ? 0: 1;
  62. }
  63. /**
  64.  * ntfs_collate_names - collate two Unicode names
  65.  * @upcase: upcase table (ignored if @ic is CASE_SENSITIVE)
  66.  * @upcase_len: upcase table size (ignored if @ic is CASE_SENSITIVE)
  67.  * @name1: first Unicode name to compare
  68.  * @name2: second Unicode name to compare
  69.  * @ic:         either CASE_SENSITIVE or IGNORE_CASE
  70.  * @err_val: if @name1 contains an invalid character return this value
  71.  *
  72.  * ntfs_collate_names collates two Unicode names and returns:
  73.  * 
  74.  *  -1 if the first name collates before the second one,
  75.  *   0 if the names match,
  76.  *   1 if the second name collates before the first one, or
  77.  * @ec if an invalid character is encountered in @name1 during the comparison.
  78.  *
  79.  * The following characters are considered invalid: '"', '*', '<', '>' and '?'.
  80.  */
  81. int ntfs_collate_names(wchar_t *upcase, __u32 upcase_len,
  82.        wchar_t *name1, __u32 name1_len,
  83.        wchar_t *name2, __u32 name2_len,
  84.        int ic, int err_val)
  85. {
  86. __u32 cnt, min_len;
  87. wchar_t c1, c2;
  88. min_len = name1_len;
  89. if (min_len > name2_len)
  90. min_len = name2_len;
  91. for (cnt = 0; cnt < min_len; ++cnt) {
  92. c1 = le16_to_cpu(*name1++);
  93. c2 = le16_to_cpu(*name2++);
  94. if (ic) {
  95. if (c1 < upcase_len)
  96. c1 = le16_to_cpu(upcase[c1]);
  97. if (c2 < upcase_len)
  98. c2 = le16_to_cpu(upcase[c2]);
  99. }
  100. if (c1 < 64 && legal_ansi_char_array[c1] & 8)
  101. return err_val;
  102. if (c1 < c2)
  103. return -1;
  104. if (c1 > c2)
  105. return 1;
  106. ++name1;
  107. ++name2;
  108. }
  109. if (name1_len < name2_len)
  110. return -1;
  111. if (name1_len == name2_len)
  112. return 0;
  113. /* name1_len > name2_len */
  114. c1 = le16_to_cpu(*name1);
  115. if (c1 < 64 && legal_ansi_char_array[c1] & 8)
  116. return err_val;
  117. return 1;
  118. }
  119. /**
  120.  * ntfs_wcsncasecmp - compare two little endian Unicode strings, ignoring case
  121.  * @s1: first string
  122.  * @s2: second string
  123.  * @n: maximum unicode characters to compare
  124.  * @upcase: upcase table
  125.  * @upcase_size: upcase table size in Unicode characters
  126.  *
  127.  * Compare the first @n characters of the Unicode strings @s1 and @s2,
  128.  * ignoring case. The strings in little endian format and appropriate
  129.  * le16_to_cpu() conversion is performed on non-little endian machines.
  130.  * 
  131.  * Each character is uppercased using the @upcase table before the comparison.
  132.  *
  133.  * The function returns an integer less than, equal to, or greater than zero
  134.  * if @s1 (or the first @n Unicode characters thereof) is found, respectively,
  135.  * to be less than, to match, or be greater than @s2.
  136.  */
  137. int ntfs_wcsncasecmp(wchar_t *s1, wchar_t *s2, size_t n,
  138.      wchar_t *upcase, __u32 upcase_size)
  139. {
  140. wchar_t c1, c2;
  141. size_t i;
  142. for (i = 0; i < n; ++i) {
  143. if ((c1 = le16_to_cpu(s1[i])) < upcase_size)
  144. c1 = le16_to_cpu(upcase[c1]);
  145. if ((c2 = le16_to_cpu(s2[i])) < upcase_size)
  146. c2 = le16_to_cpu(upcase[c2]);
  147. if (c1 < c2)
  148. return -1;
  149. if (c1 > c2)
  150. return 1;
  151. if (!c1)
  152. break;
  153. }
  154. return 0;
  155. }