home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 5 / 05.iso / a / a009 / 6.ddi / SAMPLE.LIF / EXAMPLEC.C < prev    next >
Encoding:
C/C++ Source or Header  |  1991-04-14  |  5.5 KB  |  303 lines

  1. /***
  2. *   examplec.c
  3. *   Sample C functions using the Clipper Extend interface.
  4. */
  5.  
  6. #include "extend.h"
  7.  
  8.  
  9. /* used below */
  10. #define ISALPHA(c)  ( (c) >= 'a' && (c) <= 'z' || (c) >= 'A' && (c) <= 'Z' )
  11. #define TOUPPER(c)  ( (c) >= 'a' && (c) <= 'z' ? (c) - 'a' + 'A' : (c) )
  12.  
  13. #define SOUNDEX_LENGTH    4
  14.  
  15.  
  16. /***
  17. *   step2()
  18. *   Return soundex result for a single letter.
  19. */
  20.  
  21. static char step2(char c)
  22.  
  23. {
  24.     switch (c)
  25.     {
  26.         case 'B':
  27.         case 'F':
  28.         case 'P':
  29.         case 'V':
  30.             return ('1');
  31.  
  32.         case 'C':
  33.         case 'G':
  34.         case 'J':
  35.         case 'K':
  36.         case 'Q':
  37.         case 'S':
  38.         case 'X':
  39.         case 'Z':
  40.             return ('2');
  41.  
  42.         case 'D':
  43.         case 'T':
  44.             return ('3');
  45.  
  46.         case 'L':
  47.             return ('4');
  48.  
  49.  
  50.         case 'M':
  51.         case 'N':
  52.             return ('5');
  53.  
  54.         case 'R':
  55.             return ('6');
  56.  
  57.         case 'A':
  58.         case 'E':
  59.         case 'H':
  60.         case 'I':
  61.         case 'O':
  62.         case 'U':
  63.         case 'W':
  64.         case 'Y':
  65.             return (NIL);
  66.     }
  67.  
  68.     /* bad param -- return something obviously wrong */
  69.     return ('9');
  70. }
  71.  
  72.  
  73. /***
  74. *   SoundexC()
  75. *   Convert a string to a soundex code (C-callable).
  76. *
  77. *    "Soundex" algorithm is standard Odell/Russell (1918):
  78. *
  79. *    Produce a code of the form "letter, digit, digit, digit"
  80. *    using these rules:
  81. *
  82. *    1)    Retain the first letter unchanged.
  83. *
  84. *    2)    For each succeeding letter, produce a result based
  85. *        on the following table:
  86. *
  87. *        letter                            result
  88. *
  89. *        B, F, P, V                        digit 1
  90. *        C, G, J, K, Q, S, X, Z            digit 2
  91. *        D, T                            digit 3
  92. *        L                                digit 4
  93. *        M, N                            digit 5
  94. *        R                                digit 6
  95. *        A, E, H, I, O, U, W, Y            (nothing)
  96. *
  97. *
  98. *    3)    If two or more adjacent letters produce the same
  99. *        result in step 2, ignore all but the first of the
  100. *        adjacent letters.
  101. *
  102. *    4)  Repeat steps 2 and 3 until three digits have been
  103. *        produced or until the source is exhausted.
  104. *
  105. *    5)    If less than three digits were produced, right-fill
  106. *        with zeros.
  107. *
  108. *
  109. *    Notes:
  110. *
  111. *    Non-alpha characters are ignored entirely; letters which
  112. *    are separated only by non-alpha characters are considered
  113. *    adjacent.  If the source contains no alpha characters, a
  114. *    value of "0000" is returned.
  115. *
  116. *    Case is not significant.
  117. *
  118. *    Letters which produce (nothing) in step 2 are still
  119. *    significant with respect to step 3.  That is, two letters
  120. *    which produce the same digit are not considered adjacent
  121. *    if they are separated by a letter that produces (nothing).
  122. *    This is in accordance with the original algorithm.
  123. *
  124. *    This C-callable function returns a pointer to a static
  125. *    buffer.  The buffer is overwritten by successive calls.
  126. */
  127.  
  128. static char *SoundexC(char *source, short len)
  129.  
  130. {
  131.     static char code[SOUNDEX_LENGTH+1] = "";
  132.  
  133.     short i;
  134.     short j;
  135.     char c;
  136.     char result;
  137.     char prev;
  138.  
  139.  
  140.     /* make Soundex code */
  141.     for ( i = 0, j = 0, prev = NIL;  i < len && j < SOUNDEX_LENGTH;  i++ )
  142.     {
  143.         c = TOUPPER(source[i]);
  144.  
  145.         if ( ISALPHA(c) )
  146.         {
  147.             result = step2(c);
  148.  
  149.             if (j == 0)
  150.             {
  151.                 /* retain first letter */
  152.                 code[j++] = c;
  153.             }
  154.             else if ( result != NIL && result != prev )
  155.             {
  156.                 /* store soundex code */
  157.                 code[j++] = result;
  158.             }
  159.  
  160.             prev = result;
  161.         }
  162.     }
  163.  
  164.  
  165.     /* right fill with zeros */
  166.     while (j < SOUNDEX_LENGTH)
  167.         code[j++] = '0';
  168.  
  169.  
  170.     return (code);
  171. }
  172.  
  173.  
  174. /***
  175. *   SOUNDEX()
  176. *   Convert a string to a "Soundex" code (Clipper-callable).
  177. *
  178. *   cSoundexCode := SOUNDEX(cString)
  179. */
  180.  
  181. CLIPPER SOUNDEX(void)
  182.  
  183. {
  184.     char *code;
  185.  
  186.  
  187.     if ( PCOUNT >= 1 && ISCHAR(1) )
  188.     {
  189.         code = SoundexC( _parc(1), _parclen(1) );
  190.     }
  191.     else
  192.     {
  193.         code = "0000";
  194.     }
  195.  
  196.  
  197.     _retclen(code, SOUNDEX_LENGTH);
  198. }
  199.  
  200.  
  201.  
  202.  
  203. /***
  204. *    bcopy()
  205. *    shift 'count' bytes of memory
  206. */
  207.  
  208. static void bcopy(byte *to, byte *from, quant count)
  209.  
  210. {
  211.     while ( count-- )
  212.         *to++ = *from++;
  213. }
  214.  
  215.  
  216.  
  217.  
  218. /***
  219. *   StuffC()
  220. *   Remove characters from a string and insert characters
  221. *    from a second string (C callable).
  222. *
  223. *    StuffC( str, len, pos, del, iStr, iLen )
  224. *
  225. *    Remove 'del' characters from 'str' starting at 'pos',
  226. *    insert all characters from 'iStr' in their place.  'len'
  227. *    is the logical length of 'str' and 'iLen' is the logical
  228. *    length of 'iStr'.  The lengths need not be the same and
  229. *    either can be zero.
  230. */
  231.  
  232. static void StuffC( byte *str, quant len, quant pos, quant del,
  233.                     byte *iStr, quant iLen )
  234.  
  235. {
  236.     long oLen;
  237.     byte *result;
  238.  
  239.  
  240.     /* convert origin */
  241.     if ( pos > 0 )
  242.         pos--;
  243.  
  244.     /* limit params */
  245.     if ( pos > len )
  246.         pos = len;
  247.  
  248.     if ( del > len - pos )
  249.         del = len - pos;
  250.  
  251.     /* use long to verify size without overflow */
  252.     oLen = (long)len + (long)iLen - (long)del;
  253.     if ( oLen > 0L && oLen < 65500L )
  254.     {
  255.         /* allocate workspace */
  256.         result = _xgrab((quant)oLen + 1);
  257.  
  258.         /* build the result string */
  259.         bcopy(result, str, pos);
  260.         bcopy(&result[pos], iStr, iLen);
  261.         bcopy(&result[pos + iLen], &str[pos + del], len - (pos + del));
  262.         result[oLen] = NIL;
  263.  
  264.         /* return string to Clipper */
  265.         _retclen(result, (quant)oLen);
  266.         _xfree(result);
  267.     }
  268.     else
  269.         _retc("");
  270. }
  271.  
  272.  
  273.  
  274.  
  275. /***
  276. *    STUFF()
  277. *    Replace 'del' number of characters in 'str' starting at 'pos'
  278. *        with the entire 'iStr' string.
  279. *
  280. *    result = STUFF(str, pos, del, iStr)
  281. *
  282. *        result      -   character string.       
  283. *        str         -   character string.
  284. *        pos         -   numeric.
  285. *        del         -   numeric.
  286. *        iStr        -   character string.
  287. *
  288. **/
  289.  
  290. CLIPPER STUFF(void)
  291.  
  292. {
  293.     if (PCOUNT == 4 && ISCHAR(1) &&
  294.         ISNUM(2) && ISNUM(3) && ISCHAR(4) )
  295.     {
  296.         StuffC(_parc(1), _parclen(1), _parni(2),
  297.                _parni(3), _parc(4), _parclen(4));
  298.     }
  299.     else
  300.         _retc("");
  301. }
  302.  
  303.