home *** CD-ROM | disk | FTP | other *** search
/ Tools / WinSN5.0Ver.iso / NETSCAP.50 / WIN1998.ZIP / ns / lib / libi18n / intlcomp.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-04-08  |  11.0 KB  |  379 lines

  1. /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  2.  *
  3.  * The contents of this file are subject to the Netscape Public License
  4.  * Version 1.0 (the "NPL"); you may not use this file except in
  5.  * compliance with the NPL.  You may obtain a copy of the NPL at
  6.  * http://www.mozilla.org/NPL/
  7.  *
  8.  * Software distributed under the NPL is distributed on an "AS IS" basis,
  9.  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
  10.  * for the specific language governing rights and limitations under the
  11.  * NPL.
  12.  *
  13.  * The Initial Developer of this code under the NPL is Netscape
  14.  * Communications Corporation.  Portions created by Netscape are
  15.  * Copyright (C) 1998 Netscape Communications Corporation.  All Rights
  16.  * Reserved.
  17.  */
  18. /*    intlcomp.c    */
  19. /*
  20.     This file implement 
  21.         INTL_MatchOneChar
  22.         INTL_MatchOneCaseChar
  23.         INTL_Strstr
  24.         INTL_Strcasestr
  25. */
  26. #include "intlpriv.h"
  27. #include "pintlcmp.h"
  28.  
  29. #define CHECK_CSID_AND_ASSERT(csid)    \
  30. { \
  31.     XP_ASSERT(CS_UNKNOWN != (csid));    /*   Please don't pass in CS_UNKNOWN here, you need to know the csid  */    \
  32.     XP_ASSERT(CS_DEFAULT != (csid));    /*   Please don't pass in CS_DEFAULT here, you need to know the csid  */    \
  33.     XP_ASSERT(CS_ASCII != (csid));    /*   Please don't pass in CS_ASCII here, you need to know the csid  */        \
  34. }
  35. /*    Private Function Prototype */
  36. extern unsigned char lower_lookup_ascii[];
  37. #define INTL_SingleByteToLower(lower, ch)    ((ch & 0x80) ? (lower[(ch & 0x7f)]) : (lower_lookup_ascii[ch]))
  38. MODULE_PRIVATE void INTL_DoubleByteToLower(DoubleByteToLowerMap *, unsigned char* , unsigned char* );
  39.  
  40.  
  41. PRIVATE void intl_strip_CRLF(unsigned char* str)
  42. {
  43.     unsigned char* in;
  44.     unsigned char* out;
  45.     for(in = out = str; 0 != *in; in++)
  46.     {
  47.         if((CR != *in) && (LF !=  *in))
  48.             *out++ = *in;
  49.     }
  50.     *out = 0;
  51. }
  52. /*
  53.     Function intl_caseless_normalize
  54.     This function have side effect to modify the string it got. 
  55.     It will normalize the string in a caseless matter
  56. */
  57. PRIVATE void intl_caseless_normalize(int16 csid, unsigned char* str)
  58. {
  59.     unsigned char *sb_tolowermap = INTL_GetSingleByteToLowerMap(csid);
  60.     unsigned char *p;
  61.  
  62.     CHECK_CSID_AND_ASSERT(csid);    
  63.     XP_ASSERT(NULL != str);
  64.  
  65.     intl_strip_CRLF(str);
  66.  
  67.     if(SINGLEBYTE == INTL_CharSetType(csid)) {
  68.         /*    for singlebyte csid */
  69.         for(p = str; *p != 0 ; p++)
  70.             *p = INTL_SingleByteToLower(sb_tolowermap, *p);
  71.         return;
  72.     }
  73.     else
  74.     {
  75.         /*    for multibyte csid */
  76.         DoubleByteToLowerMap *db_tolowermap = INTL_GetDoubleByteToLowerMap(csid);
  77.         unsigned char *p;
  78.         int l;
  79.         for(p = str; *p != 0; p += l)
  80.         {
  81.             l = INTL_CharLen(csid ,p);    /* *** FIX ME: IMPROVE PERFORMANCE */
  82.             switch(l)
  83.             {
  84.             case 1:
  85.                 *p = INTL_SingleByteToLower(sb_tolowermap, *p);
  86.                 break;
  87.             case 2:
  88.                 if(0 == *(p+1))
  89.                 {
  90.                     /* Check weather we hit partial characters. This happen when we use wrong csid */
  91.                     /* However, we should not pass array bondary even we use wrong csid */
  92.                     XP_ASSERT(FALSE);
  93.                     return;    /* get partial characters, return */
  94.                 }
  95.                 INTL_DoubleByteToLower(db_tolowermap, p, p);
  96.                 break;
  97.             default:
  98.                 {
  99.                     unsigned char *ck;
  100.                     /* Check weather we hit partial characters. This happen when we use wrong csid */
  101.                     /* However, we should not pass array bondary even we use wrong csid */
  102.                     for(ck = p+l-1; ck != p ;ck--)
  103.                     {
  104.                         if(0 == *ck)
  105.                         {
  106.                             XP_ASSERT(FALSE);
  107.                             return;    /* get partial characters, return */
  108.                         }
  109.                     }
  110.                     /* We current do not handle 3 byte normalization. We need  to work on this for UTF8 */
  111.                 }
  112.                 break;
  113.             }
  114.  
  115.         }
  116.     }
  117. }
  118.  
  119.  
  120.  
  121. PRIVATE void INTL_DoubleByteToLower(DoubleByteToLowerMap *db_tolowermap, unsigned char* lowertext, unsigned char* text)
  122. {
  123.     DoubleByteToLowerMap *p;
  124.     for(p = db_tolowermap; !((p->src_b1 == 0) && (p->src_b2_start == 0)); p++)
  125.     {
  126.         if( (p->src_b1       == text[0]) &&
  127.             (p->src_b2_start <= text[1] ) &&
  128.             (p->src_b2_end   >= text[1]) )
  129.         {
  130.             lowertext[0] = p->dest_b1;
  131.             lowertext[1] = text[1] - p->src_b2_start + p->dest_b2_start;
  132.             return;
  133.         }
  134.         else 
  135.         {    /*    The map have to be sorted order to implement a fast search */
  136.             if(p->src_b1 > text[0])
  137.                 break;
  138.             else {
  139.                 if((p->src_b1 == text[0]) && (p->src_b2_start > text[1]))
  140.                     break;
  141.             }
  142.         }
  143.     }
  144.     lowertext[0] = text[0];
  145.     lowertext[1] = text[1];
  146.     return;
  147. }
  148.  
  149. PUBLIC XP_Bool INTL_MatchOneChar(int16 csid, unsigned char *text1,unsigned char *text2,int *charlen)
  150. {
  151.     if((INTL_CharSetType(csid) == SINGLEBYTE) ) {
  152.         unsigned char *sb_tolowermap;
  153.         *charlen = 1;
  154.         sb_tolowermap = INTL_GetSingleByteToLowerMap(csid);
  155.         return( INTL_SingleByteToLower(sb_tolowermap,text1[0]) == INTL_SingleByteToLower(sb_tolowermap, text2[0]));
  156.     }
  157.     else
  158.     {
  159.         int l1, l2;
  160.         l1 = INTL_CharLen(csid ,text1);    /* *** FIX ME: IMPROVE PERFORMANCE */
  161.         l2 = INTL_CharLen(csid ,text2);    /* *** FIX ME: IMPROVE PERFORMANCE */
  162.         if(l1 != l2)
  163.             return FALSE;
  164.         if(l1 == 1)
  165.         {
  166.             unsigned char *sb_tolowermap;
  167.             *charlen = 1;
  168.             sb_tolowermap = INTL_GetSingleByteToLowerMap(csid);
  169.             return( INTL_SingleByteToLower(sb_tolowermap,text1[0]) == INTL_SingleByteToLower(sb_tolowermap, text2[0]));
  170.         }
  171.         else
  172.         {
  173.             if(l1 == 2)
  174.             {
  175.                 DoubleByteToLowerMap *db_tolowermap;
  176.                 unsigned char lowertext1[2], lowertext2[2];
  177.                 *charlen = 2;
  178.                 db_tolowermap = INTL_GetDoubleByteToLowerMap(csid);
  179.                 INTL_DoubleByteToLower(db_tolowermap, lowertext1, text1);
  180.                 INTL_DoubleByteToLower(db_tolowermap, lowertext2, text2);
  181.                 return( ( lowertext1[0] ==  lowertext2[0] ) &&
  182.                         ( lowertext1[1] ==  lowertext2[1] ) );
  183.             }
  184.             else
  185.             {
  186.                 /* for character which is neither one byte nor two byte, we cannot ignore case for them */
  187.                 int i;
  188.                 *charlen = l1;
  189.                 for(i=0;i<l1;i++)
  190.                 {
  191.                     if(text1[i] != text2[i])
  192.                         return FALSE;
  193.                 }
  194.                 return TRUE;
  195.             }
  196.         }
  197.     }
  198. }
  199. PUBLIC XP_Bool INTL_MatchOneCaseChar(int16 csid, unsigned char *text1,unsigned char *text2,int *charlen)
  200. {
  201.     if((INTL_CharSetType(csid) == SINGLEBYTE) ) {
  202.         *charlen = 1;
  203.         return( text1[0]== text2[0]);
  204.     }
  205.     else
  206.     {
  207.         int i,len;
  208.         *charlen = len  = INTL_CharLen(csid, (unsigned char *) text1);    /* *** FIX ME: IMPROVE PERFORMANCE */
  209.         for(i=0 ; i < len; i++)
  210.         {
  211.             if(text1[i] != text2[i]) 
  212.                 return FALSE;
  213.         }
  214.         return TRUE;
  215.     }
  216. }
  217. PUBLIC
  218. char *INTL_Strstr(int16 csid, const char *s1,const char *s2)
  219. {
  220.     int len;
  221.     char *p1, *pp1, *p2;
  222.     if((s2==NULL) || (*s2 == '\0'))
  223.         return (char *)s1;
  224.     if((s1==NULL) || (*s1 == '\0'))
  225.         return NULL;
  226.     
  227.     for(p1=(char*)s1; *p1  ;p1 = INTL_NextChar(csid ,p1))    /* *** FIX ME: IMPROVE PERFORMANCE */
  228.     {
  229.         for(p2=(char*)s2, pp1=p1 ;  
  230.             ((*pp1) && (*p2) && INTL_MatchOneCaseChar(csid, (unsigned char*)pp1, (unsigned char*)p2, &len)); 
  231.             pp1 += len, p2 += len)    /* *** FIX ME: IMPROVE PERFORMANCE */
  232.                 ;    /* do nothing in the loop */
  233.         if(*p2 == '\0')
  234.             return p1;
  235.     }
  236.     return NULL;
  237. }
  238.  
  239. /*
  240. To Do:
  241.     We should take advantage of INTL_GetNormalizeStr to improve the performance of this
  242. */
  243. PUBLIC
  244. char *INTL_Strcasestr(int16 csid, const char *s1, const char *s2)
  245. {
  246.     int len;
  247.     char *p1, *pp1, *p2;
  248.     if((s2==NULL) || (*s2 == '\0'))
  249.         return (char *)s1;
  250.     if((s1==NULL) || (*s1 == '\0'))
  251.         return NULL;
  252.  
  253.     for(p1=(char*)s1; *p1  ;p1 = INTL_NextChar(csid , p1))    /* *** FIX ME: IMPROVE PERFORMANCE */
  254.     {
  255.         for(p2=(char*)s2, pp1=p1 ;  
  256.             ((*pp1) && (*p2) && INTL_MatchOneChar(csid, (unsigned char*)pp1, (unsigned char*)p2, &len)); 
  257.             pp1 += len, p2 += len)    /* *** FIX ME: IMPROVE PERFORMANCE */
  258.                 ;    /* do nothing in the loop */
  259.         if(*p2 == '\0')
  260.             return p1;
  261.     }
  262.     return NULL;
  263. }
  264.  
  265. PUBLIC unsigned char* INTL_GetNormalizeStr(int16 csid, unsigned char* str)
  266. {
  267.     char* n_str = NULL;
  268.     StrAllocCopy(n_str, (char*) str);
  269.     XP_ASSERT(n_str);    /* Should only come here if Memory Not Enough */
  270.  
  271.     CHECK_CSID_AND_ASSERT(csid);    
  272.  
  273.     if(NULL != n_str)
  274.         intl_caseless_normalize(csid, (unsigned char*)n_str);
  275.     return (unsigned char*)n_str;
  276. }
  277.  
  278. #ifdef MOZ_MAIL_NEWS
  279.  
  280. PUBLIC unsigned char* INTL_GetNormalizeStrFromRFC1522(int16 csid, unsigned char* rfc1522header)
  281. {
  282.     char* n_header = (char*) INTL_DecodeMimePartIIStr((char*)rfc1522header, csid, FALSE);
  283.     if(NULL == n_header)    /* INTL_DecodeMimePartIIStr() may return NULL- Mean no conversion */
  284.         StrAllocCopy(n_header, (char*) rfc1522header);
  285.     XP_ASSERT(n_header);    /* Should only come here if Memory Not Enough */
  286.  
  287.     CHECK_CSID_AND_ASSERT(csid);    
  288.  
  289.     if(NULL != n_header)
  290.         intl_caseless_normalize(csid, (unsigned char*)n_header);
  291.     return (unsigned char*)n_header;
  292. }
  293.  
  294. #endif  /* MOZ_MAIL_NEWS */
  295.  
  296. PUBLIC XP_Bool    INTL_StrContains(    
  297.     int16 strcsid, unsigned char* normalizedStr, unsigned char* normalizedSubstr)
  298. {
  299.     /* 
  300.         It is the caller's responsibility to make sure the normalizedstr1 and normalizedstr2 
  301.         are normalized by calling 
  302.         INTL_GetNormalizeStr() or
  303.         INTL_GetNormalizeStrFromRFC1522()
  304.     */
  305.     char* p;
  306.     int l_char;
  307.     int l_idx;
  308.     int l_substr = XP_STRLEN((char*) normalizedSubstr);
  309.     int l_str = XP_STRLEN((char*) normalizedStr);
  310.  
  311.     CHECK_CSID_AND_ASSERT(strcsid);    
  312.  
  313.     for(p = (char*)normalizedStr, l_idx = 0, l_char = 0; (0 != *p) && (l_idx < l_str) ; p += l_char, l_idx += l_char)
  314.     {
  315.         l_char = INTL_CharLen(strcsid, (unsigned char*)p);    /* *** FIX ME: Should do better tune for performance here */
  316.         if(0 == XP_STRNCMP(p, (char*) normalizedSubstr, l_substr))
  317.             return TRUE;
  318.     }
  319.     return FALSE;
  320. }
  321. PUBLIC XP_Bool    INTL_StrIs(        
  322.     int16 strcsid, unsigned char* normalizedStr, unsigned char* normalizedSubstr)
  323. {
  324.     /* 
  325.         It is the caller's responsibility to make sure the normalizedstr1 and normalizedstr2 
  326.         are normalized by calling 
  327.         INTL_GetNormalizeStr() or
  328.         INTL_GetNormalizeStrFromRFC1522()
  329.     */
  330.  
  331.     CHECK_CSID_AND_ASSERT(strcsid);    
  332.  
  333.     return (0 == XP_STRCMP((char*) normalizedStr, (char*) normalizedSubstr));
  334. }
  335. PUBLIC XP_Bool    INTL_StrBeginWith(    
  336.     int16 strcsid, unsigned char* normalizedStr, unsigned char* normalizedSubstr)
  337. {
  338.     /* 
  339.         It is the caller's responsibility to make sure the normalizedstr1 and normalizedstr2 
  340.         are normalized by calling 
  341.         INTL_GetNormalizeStr() or
  342.         INTL_GetNormalizeStrFromRFC1522()
  343.     */
  344.  
  345.     CHECK_CSID_AND_ASSERT(strcsid);    
  346.  
  347.     return (0 == XP_STRNCMP((char*) normalizedStr, (char*) normalizedSubstr, XP_STRLEN((char*) normalizedSubstr)));
  348. }
  349.  
  350. PUBLIC XP_Bool    INTL_StrEndWith(    
  351.     int16 strcsid, unsigned char* normalizedStr, unsigned char* normalizedSubstr)
  352. {
  353.     /* 
  354.         It is the caller's responsibility to make sure the normalizedstr1 and normalizedstr2 
  355.         are normalized by calling 
  356.         INTL_GetNormalizeStr() or
  357.         INTL_GetNormalizeStrFromRFC1522()
  358.     */
  359.     char* p;
  360.     int l_char;
  361.     int l_idx;
  362.     int l_substr = XP_STRLEN((char*) normalizedSubstr);
  363.     int l_str = XP_STRLEN((char*) normalizedStr);
  364.     int l_stop = l_str - l_substr;
  365.  
  366.     CHECK_CSID_AND_ASSERT(strcsid);    
  367.  
  368.     for(p = (char*)normalizedStr, l_idx = 0, l_char = 0; (0 != *p) && (l_idx < l_stop) ; p += l_char, l_idx += l_char)
  369.         l_char = INTL_CharLen(strcsid, (unsigned char*)p);    /* *** FIX ME: Should do better tune for performance here */
  370.     if(l_idx != l_stop)
  371.         return FALSE;
  372.     return (0 == XP_STRCMP(p, (char*) normalizedSubstr));
  373. }
  374.  
  375.  
  376.  
  377.  
  378.  
  379.