Coverage Report

Created: 2022-02-19 20:27

/src/php-src/ext/standard/soundex.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
   +----------------------------------------------------------------------+
3
   | Copyright (c) The PHP Group                                          |
4
   +----------------------------------------------------------------------+
5
   | This source file is subject to version 3.01 of the PHP license,      |
6
   | that is bundled with this package in the file LICENSE, and is        |
7
   | available through the world-wide-web at the following url:           |
8
   | http://www.php.net/license/3_01.txt                                  |
9
   | If you did not receive a copy of the PHP license and are unable to   |
10
   | obtain it through the world-wide-web, please send a note to          |
11
   | license@php.net so we can mail you a copy immediately.               |
12
   +----------------------------------------------------------------------+
13
   | Author: Bjørn Borud - Guardian Networks AS <borud@guardian.no>       |
14
   +----------------------------------------------------------------------+
15
 */
16
17
#include "php.h"
18
#include <stdlib.h>
19
#include <errno.h>
20
#include <ctype.h>
21
#include "php_string.h"
22
23
/* Simple soundex algorithm as described by Knuth in TAOCP, vol 3 */
24
/* {{{ Calculate the soundex key of a string */
25
PHP_FUNCTION(soundex)
26
0
{
27
0
  char  *str;
28
0
  size_t  i, _small, str_len, code, last;
29
0
  char  soundex[4 + 1];
30
31
0
  static char soundex_table[26] =
32
0
  {0,             /* A */
33
0
   '1',           /* B */
34
0
   '2',           /* C */
35
0
   '3',           /* D */
36
0
   0,             /* E */
37
0
   '1',           /* F */
38
0
   '2',           /* G */
39
0
   0,             /* H */
40
0
   0,             /* I */
41
0
   '2',           /* J */
42
0
   '2',           /* K */
43
0
   '4',           /* L */
44
0
   '5',           /* M */
45
0
   '5',           /* N */
46
0
   0,             /* O */
47
0
   '1',           /* P */
48
0
   '2',           /* Q */
49
0
   '6',           /* R */
50
0
   '2',           /* S */
51
0
   '3',           /* T */
52
0
   0,             /* U */
53
0
   '1',           /* V */
54
0
   0,             /* W */
55
0
   '2',           /* X */
56
0
   0,             /* Y */
57
0
   '2'};            /* Z */
58
59
0
  ZEND_PARSE_PARAMETERS_START(1, 1)
60
0
    Z_PARAM_STRING(str, str_len)
61
0
  ZEND_PARSE_PARAMETERS_END();
62
63
0
  if (str_len == 0) {
64
0
    RETURN_FALSE;
65
0
  }
66
67
  /* build soundex string */
68
0
  last = -1;
69
0
  for (i = 0, _small = 0; i < str_len && _small < 4; i++) {
70
    /* convert chars to upper case and strip non-letter chars */
71
    /* BUG: should also map here accented letters used in non */
72
    /* English words or names (also found in English text!): */
73
    /* esstsett, thorn, n-tilde, c-cedilla, s-caron, ... */
74
0
    code = toupper((int)(unsigned char)str[i]);
75
0
    if (code >= 'A' && code <= 'Z') {
76
0
      if (_small == 0) {
77
        /* remember first valid char */
78
0
        soundex[_small++] = (char)code;
79
0
        last = soundex_table[code - 'A'];
80
0
      }
81
0
      else {
82
        /* ignore sequences of consonants with same soundex */
83
        /* code in trail, and vowels unless they separate */
84
        /* consonant letters */
85
0
        code = soundex_table[code - 'A'];
86
0
        if (code != last) {
87
0
          if (code != 0) {
88
0
            soundex[_small++] = (char)code;
89
0
          }
90
0
          last = code;
91
0
        }
92
0
      }
93
0
    }
94
0
  }
95
  /* pad with '0' and terminate with 0 ;-) */
96
0
  while (_small < 4) {
97
0
    soundex[_small++] = '0';
98
0
  }
99
0
  soundex[_small] = '\0';
100
101
0
  RETURN_STRINGL(soundex, _small);
102
0
}
103
/* }}} */