Advertisement
Guest User

fts3_porter_ext.c

a guest
Oct 21st, 2011
782
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 18.98 KB | None | 0 0
  1. #include "sqlite3.h"
  2. #include "fts3_tokenizer.h"
  3.  
  4. #include <assert.h>
  5. #include <stdlib.h>
  6. #include <stdio.h>
  7. #include <string.h>
  8. #include <ctype.h>
  9. #include <stdbool.h>
  10.  
  11. #define utf8letterA 0xB0D0U
  12. #define utf8letterB 0xB1D0U
  13. #define utf8letterV 0xB2D0U
  14. #define utf8letterG 0xB3D0U
  15. #define utf8letterD 0xB4D0U
  16. #define utf8letterE 0xB5D0U
  17. #define utf8letterYO 0x91D1U
  18. #define utf8letterZH 0xB6D0U
  19. #define utf8letterZ 0xB7D0U
  20. #define utf8letterI 0xB8D0U
  21. #define utf8letterIY 0xB9D0U
  22. #define utf8letterK 0xBAD0U
  23. #define utf8letterL 0xBBD0U
  24. #define utf8letterM 0xBCD0U
  25. #define utf8letterN 0xBDD0U
  26. #define utf8letterO 0xBED0U
  27. #define utf8letterP 0xBFD0U
  28. #define utf8letterR 0x80D1U
  29. #define utf8letterS 0x81D1U
  30. #define utf8letterT 0x82D1U
  31. #define utf8letterU 0x83D1U
  32. #define utf8letterF 0x84D1U
  33. #define utf8letterH 0x85D1U
  34. #define utf8letterTS 0x86D1U
  35. #define utf8letterCH 0x87D1U
  36. #define utf8letterSH 0x88D1U
  37. #define utf8letterSCH 0x89D1U
  38. #define utf8letterTVY 0x8AD1U // TVYordiy znak
  39. #define utf8letterY 0x8BD1U
  40. #define utf8letterMYA 0x8CD1U // MYAgkiy znak
  41. #define utf8letterEE 0x8DD1U
  42. #define utf8letterYU 0x8ED1U
  43. #define utf8letterYA 0x8FD1U
  44.  
  45. #define LOC_CHAR_TYPE unsigned short
  46. #define LOC_PREFIX(_a) _a##_utf8
  47.  
  48. #undef LOC_TABLE_ENTRY
  49. #undef LOC_TABLE_INDEX
  50. #define LOC_TABLE_ENTRY struct LOC_PREFIX(stem_table_entry_)
  51. #define LOC_TABLE_INDEX struct LOC_PREFIX(stem_table_index_)
  52.  
  53.  
  54. LOC_TABLE_ENTRY
  55. {
  56.     LOC_CHAR_TYPE   suffix[8];
  57.     int             remove, len;
  58. };
  59.  
  60.  
  61. LOC_TABLE_INDEX
  62. {
  63.     LOC_CHAR_TYPE   first;
  64.     int             count;
  65. };
  66.  
  67.  
  68. // TableStringN, where N is a number of chars
  69. #undef TS1
  70. #undef TS2
  71. #undef TS3
  72. #undef TS4
  73. #undef TS5
  74. #define TS1(c1) { utf8letter##c1 }
  75. #define TS2(c1,c2) { utf8letter##c1, utf8letter##c2 }
  76. #define TS3(c1,c2,c3) { utf8letter##c1, utf8letter##c2, utf8letter##c3 }
  77. #define TS4(c1,c2,c3,c4) { utf8letter##c1, utf8letter##c2, utf8letter##c3, utf8letter##c4 }
  78. #define TS5(c1,c2,c3,c4,c5) { utf8letter##c1, utf8letter##c2, utf8letter##c3, utf8letter##c4, utf8letter##c5 }
  79.  
  80.  
  81. static LOC_TABLE_INDEX LOC_PREFIX(ru_adj_i)[] =
  82. {
  83.     { utf8letterE,  4 },
  84.     { utf8letterI,  2 },
  85.     { utf8letterIY, 4 },
  86.     { utf8letterM,  7 },
  87.     { utf8letterO,  2 },
  88.     { utf8letterU,  2 },
  89.     { utf8letterH,  2 },
  90.     { utf8letterYU, 4 },
  91.     { utf8letterYA, 4 },
  92. };
  93.  
  94.  
  95. static LOC_TABLE_ENTRY LOC_PREFIX(ru_adj)[] =
  96. {
  97.     { TS2(E,E),     2, 0 },
  98.     { TS2(I,E),     2, 0 },
  99.     { TS2(Y,E),     2, 0 },
  100.     { TS2(O,E),     2, 0 },
  101.  
  102.     { TS3(I,M,I),   3, 0 },
  103.     { TS3(Y,M,I),   3, 0 },
  104.  
  105.     { TS2(E,IY),    2, 0 },
  106.     { TS2(I,IY),    2, 0 },
  107.     { TS2(Y,IY),    2, 0 },
  108.     { TS2(O,IY),    2, 0 },
  109.  
  110.     { TS3(A,E,M),   0, 0 },
  111.     { TS3(U,E,M),   0, 0 },
  112.     { TS3(YA,E,M),  0, 0 },
  113.     { TS2(E,M),     2, 0 },
  114.     { TS2(I,M),     2, 0 },
  115.     { TS2(Y,M),     2, 0 },
  116.     { TS2(O,M),     2, 0 },
  117.  
  118.     { TS3(E,G,O),   3, 0 },
  119.     { TS3(O,G,O),   3, 0 },
  120.  
  121.     { TS3(E,M,U),   3, 0 },
  122.     { TS3(O,M,U),   3, 0 },
  123.  
  124.     { TS2(I,H),     2, 0 },
  125.     { TS2(Y,H),     2, 0 },
  126.  
  127.     { TS2(E,YU),    2, 0 },
  128.     { TS2(O,YU),    2, 0 },
  129.     { TS2(U,YU),    2, 0 },
  130.     { TS2(YU,YU),   2, 0 },
  131.  
  132.     { TS2(A,YA),    2, 0 },
  133.     { TS2(YA,YA),   2, 0 }
  134. };
  135.  
  136.  
  137. static LOC_TABLE_INDEX LOC_PREFIX(ru_part_i)[] =
  138. {
  139.     { utf8letterA,  3 },
  140.     { utf8letterM,  1 },
  141.     { utf8letterN,  3 },
  142.     { utf8letterO,  3 },
  143.     { utf8letterY,  3 },
  144.     { utf8letterSH, 4 },
  145.     { utf8letterSCH,    5 }
  146. };
  147.  
  148.  
  149. static LOC_TABLE_ENTRY LOC_PREFIX(ru_part)[] =
  150. {
  151.     { TS4(A,N,N,A),     2, 0 },
  152.     { TS4(E,N,N,A),     2, 0 },
  153.     { TS4(YA,N,N,A),    2, 0 },
  154.  
  155.     { TS3(YA,E,M),      2, 0 },
  156.  
  157.     { TS3(A,N,N),       1, 0 },
  158.     { TS3(E,N,N),       1, 0 },
  159.     { TS3(YA,N,N),      1, 0 },
  160.  
  161.     { TS4(A,N,N,O),     2, 0 },
  162.     { TS4(E,N,N,O),     2, 0 },
  163.     { TS4(YA,N,N,O),    2, 0 },
  164.  
  165.     { TS4(A,N,N,Y),     2, 0 },
  166.     { TS4(E,N,N,Y),     2, 0 },
  167.     { TS4(YA,N,N,Y),    2, 0 },
  168.  
  169.     { TS3(A,V,SH),      2, 0 },
  170.     { TS3(I,V,SH),      3, 0 },
  171.     { TS3(Y,V,SH),      3, 0 },
  172.     { TS3(YA,V,SH),     2, 0 },
  173.  
  174.     { TS3(A,YU,SCH),    2, 0 },
  175.     { TS2(A,SCH),       1, 0 },
  176.     { TS3(YA,YU,SCH),   2, 0 },
  177.     { TS2(YA,SCH),      1, 0 },
  178.     { TS3(U,YU,SCH),    3, 0 }
  179. };
  180.  
  181.  
  182. static LOC_TABLE_INDEX LOC_PREFIX(ru_verb_i)[] =
  183. {
  184.     { utf8letterA,  7 },
  185.     { utf8letterE,  9 },
  186.     { utf8letterI,  4 },
  187.     { utf8letterIY, 4 },
  188.     { utf8letterL,  4 },
  189.     { utf8letterM,  5 },
  190.     { utf8letterO,  7 },
  191.     { utf8letterT,  9 },
  192.     { utf8letterY,  3 },
  193.     { utf8letterMYA,    10 },
  194.     { utf8letterYU, 4 },
  195.     { utf8letterYA, 1 }
  196. };
  197.  
  198.  
  199. static LOC_TABLE_ENTRY LOC_PREFIX(ru_verb)[] =
  200. {
  201.     { TS3(A,L,A),   3, 0 },
  202.     { TS3(A,N,A),   3, 0 },
  203.     { TS3(YA,L,A),  3, 0 },
  204.     { TS3(YA,N,A),  3, 0 },
  205.     { TS3(I,L,A),   3, 0 },
  206.     { TS3(Y,L,A),   3, 0 },
  207.     { TS3(E,N,A),   3, 0 },
  208.  
  209.     { TS4(A,E,T,E),     4, 0 },
  210.     { TS4(A,IY,T,E),    4, 0 },
  211.     { TS3(MYA,T,E),     3, 0 },
  212.     { TS4(U,E,T,E),     4, 0 },
  213.     { TS4(YA,E,T,E),    4, 0 },
  214.     { TS4(YA,IY,T,E),   4, 0 },
  215.     { TS4(E,IY,T,E),    4, 0 },
  216.     { TS4(U,IY,T,E),    4, 0 },
  217.     { TS3(I,T,E),       3, 0 },
  218.  
  219.     { TS3(A,L,I),   3, 0 },
  220.     { TS3(YA,L,I),  3, 0 },
  221.     { TS3(I,L,I),   3, 0 },
  222.     { TS3(Y,L,I),   3, 0 },
  223.  
  224.     { TS2(A,IY),    2, 0 },
  225.     { TS2(YA,IY),   2, 0 },
  226.     { TS2(E,IY),    2, 0 },
  227.     { TS2(U,IY),    2, 0 },
  228.  
  229.     { TS2(A,L),     2, 0 },
  230.     { TS2(YA,L),    2, 0 },
  231.     { TS2(I,L),     2, 0 },
  232.     { TS2(Y,L),     2, 0 },
  233.  
  234.     { TS3(A,E,M),   3, 0 },
  235.     { TS3(YA,E,M),  3, 0 },
  236.     { TS3(U,E,M),   3, 0 },
  237.     { TS2(I,M),     2, 0 },
  238.     { TS2(Y,M),     2, 0 },
  239.  
  240.     { TS3(A,L,O),   3, 0 },
  241.     { TS3(A,N,O),   3, 0 },
  242.     { TS3(YA,L,O),  3, 0 },
  243.     { TS3(YA,N,O),  3, 0 },
  244.     { TS3(I,L,O),   3, 0 },
  245.     { TS3(Y,L,O),   3, 0 },
  246.     { TS3(E,N,O),   3, 0 },
  247.  
  248.     { TS3(A,E,T),   3, 0 },
  249.     { TS3(A,YU,T),  3, 0 },
  250.     { TS3(YA,E,T),  3, 0 },
  251.     { TS3(YA,YU,T), 3, 0 },
  252.     { TS2(YA,T),    2, 0 },
  253.     { TS3(U,E,T),   3, 0 },
  254.     { TS3(U,YU,T),  3, 0 },
  255.     { TS2(I,T),     2, 0 },
  256.     { TS2(Y,T),     2, 0 },
  257.  
  258.     { TS3(A,N,Y),   3, 0 },
  259.     { TS3(YA,N,Y),  3, 0 },
  260.     { TS3(E,N,Y),   3, 0 },
  261.  
  262.     { TS4(A,E,SH,MYA),  4, 0 },
  263.     { TS4(U,E,SH,MYA),  4, 0 },
  264.     { TS4(YA,E,SH,MYA), 4, 0 },
  265.     { TS3(A,T,MYA),     3, 0 },
  266.     { TS3(E,T,MYA),     3, 0 },
  267.     { TS3(I,T,MYA),     3, 0 },
  268.     { TS3(U,T,MYA),     3, 0 },
  269.     { TS3(Y,T,MYA),     3, 0 },
  270.     { TS3(I,SH,MYA),    3, 0 },
  271.     { TS3(YA,T,MYA),    3, 0 },
  272.  
  273.     { TS2(A,YU),    2, 0 },
  274.     { TS2(U,YU),    2, 0 },
  275.     { TS2(YA,YU),   2, 0 },
  276.     { TS1(YU),      1, 0 },
  277.  
  278.     { TS2(U,YA),    2, 0 }
  279. };
  280.  
  281.  
  282. static LOC_TABLE_INDEX LOC_PREFIX(ru_dear_i)[] =
  283. {
  284.     { utf8letterK,  3 },
  285.     { utf8letterA,  2 },
  286.     { utf8letterV,  2 },
  287.     { utf8letterE,  2 },
  288.     { utf8letterI,  4 },
  289.     { utf8letterIY, 2 },
  290.     { utf8letterM,  4 },
  291.     { utf8letterO,  2 },
  292.     { utf8letterU,  2 },
  293.     { utf8letterH,  2 },
  294.     { utf8letterYU, 2 }
  295. };
  296.  
  297.  
  298. static LOC_TABLE_ENTRY LOC_PREFIX(ru_dear)[] =
  299. {
  300.     { TS3(CH,E,K),      3, 0 },
  301.     { TS3(CH,O,K),      3, 0 },
  302.     { TS3(N,O,K),       3, 0 },
  303.  
  304.     { TS3(CH,K,A),      3, 0 },
  305.     { TS3(N, K,A),      3, 0 },
  306.     { TS4(CH,K,O,V),    4, 0 },
  307.     { TS4(N, K,O,V),    4, 0 },
  308.     { TS3(CH,K,E),      3, 0 },
  309.     { TS3(N, K,E),      3, 0 },
  310.     { TS3(CH,K,I),      3, 0 },
  311.     { TS3(N, K,I),      3, 0 },
  312.     { TS5(CH,K,A,M,I),  5, 0 },
  313.     { TS5(N, K,A,M,I),  5, 0 },
  314.     { TS4(CH,K,O,IY),   4, 0 },
  315.     { TS4(N, K,O,IY),   4, 0 },
  316.     { TS4(CH,K,A,M),    4, 0 },
  317.     { TS4(N, K,A,M),    4, 0 },
  318.     { TS4(CH,K,O,M),    4, 0 },
  319.     { TS4(N, K,O,M),    4, 0 },
  320.     { TS3(CH,K,O),      3, 0 },
  321.     { TS3(N, K,O),      3, 0 },
  322.     { TS3(CH,K,U),      3, 0 },
  323.     { TS3(N, K,U),      3, 0 },
  324.     { TS4(CH,K,A,H),    4, 0 },
  325.     { TS4(N, K,A,H),    4, 0 },
  326.     { TS4(CH,K,O,YU),   4, 0 },
  327.     { TS4(N, K,O,YU),   4, 0 }
  328. };
  329.  
  330.  
  331. static LOC_TABLE_INDEX LOC_PREFIX(ru_noun_i)[] =
  332. {
  333.     { utf8letterA,  1 },
  334.     { utf8letterV,  2 },
  335.     { utf8letterE,  3 },
  336.     { utf8letterI,  6 },
  337.     { utf8letterIY, 4 },
  338.     { utf8letterM,  5 },
  339.     { utf8letterO,  1 },
  340.     { utf8letterU,  1 },
  341.     { utf8letterH,  3 },
  342.     { utf8letterY,  1 },
  343.     { utf8letterMYA,    1 },
  344.     { utf8letterYU, 3 },
  345.     { utf8letterYA, 3 }
  346. };
  347.  
  348.  
  349. static LOC_TABLE_ENTRY LOC_PREFIX(ru_noun)[] =
  350. {
  351.     { TS1(A),       1, 0 },
  352.  
  353.     { TS2(E,V),     2, 0 },
  354.     { TS2(O,V),     2, 0 },
  355.  
  356.     { TS2(I,E),     2, 0 },
  357.     { TS2(MYA,E),   2, 0 },
  358.     { TS1(E),       1, 0 },
  359.  
  360.     { TS4(I,YA,M,I),4, 0 },
  361.     { TS3(YA,M,I),  3, 0 },
  362.     { TS3(A,M,I),   3, 0 },
  363.     { TS2(E,I),     2, 0 },
  364.     { TS2(I,I),     2, 0 },
  365.     { TS1(I),       1, 0 },
  366.  
  367.     { TS3(I,E,IY),  3, 0 },
  368.     { TS2(E,IY),    2, 0 },
  369.     { TS2(O,IY),    2, 0 },
  370.     { TS2(I,IY),    2, 0 },
  371.  
  372.     { TS3(I,YA,M),  3, 0 },
  373.     { TS2(YA,M),    2, 0 },
  374.     { TS3(I,E,M),   3, 0 },
  375.     { TS2(A,M),     2, 0 },
  376.     { TS2(O,M),     2, 0 },
  377.  
  378.     { TS1(O),       1, 0 },
  379.  
  380.     { TS1(U),       1, 0 },
  381.  
  382.     { TS2(A,H),     2, 0 },
  383.     { TS3(I,YA,H),  3, 0 },
  384.     { TS2(YA,H),    2, 0 },
  385.  
  386.     { TS1(Y),       1, 0 },
  387.  
  388.     { TS1(MYA),     1, 0 },
  389.  
  390.     { TS2(I,YU),    2, 0 },
  391.     { TS2(MYA,YU),  2, 0 },
  392.     { TS1(YU),      1, 0 },
  393.  
  394.     { TS2(I,YA),    2, 0 },
  395.     { TS2(MYA,YA),  2, 0 },
  396.     { TS1(YA),      1, 0 }
  397. };
  398.  
  399.  
  400. int stem_ru_table_i ( LOC_CHAR_TYPE * word, int len, LOC_TABLE_ENTRY * table, LOC_TABLE_INDEX * itable, int icount )
  401. {
  402.     int i, j, k, m;
  403.     LOC_CHAR_TYPE l = word[--len];
  404.  
  405.     for ( i=0, j=0; i<icount; i++ )
  406.     {
  407.         if ( l==itable[i].first )
  408.         {
  409.             m = itable[i].count;
  410.             i = j-1;
  411.             while ( m-- )
  412.             {
  413.                 i++;
  414.                 j = table[i].len;
  415.                 k = len;
  416.                 if ( j>k )
  417.                     continue;
  418.                 for ( ; j>=0; k--, j-- )
  419.                     if ( word[k]!=table[i].suffix[j] )
  420.                         break;
  421.                 if ( j>=0 )
  422.                     continue;
  423.                 return table[i].remove;
  424.             }
  425.             return 0;
  426.         }
  427.         j += itable[i].count;
  428.     }
  429.     return 0;
  430. }
  431.  
  432.  
  433. #undef STEM_RU_FUNC
  434. #define STEM_RU_FUNC(func,table) \
  435.     int func ( LOC_CHAR_TYPE * word, int len ) \
  436.     { \
  437.         return stem_ru_table ( word, len, LOC_PREFIX(table), \
  438.             sizeof(LOC_PREFIX(table))/sizeof(LOC_TABLE_ENTRY) ); \
  439.     }
  440.  
  441. #undef STEM_RU_FUNC_I
  442. #define STEM_RU_FUNC_I(table) \
  443.     int LOC_PREFIX(stem_##table##_i) ( LOC_CHAR_TYPE * word, int len ) \
  444.     { \
  445.         return stem_ru_table_i ( word, len, LOC_PREFIX(table), LOC_PREFIX(table##_i), \
  446.             sizeof(LOC_PREFIX(table##_i))/sizeof(LOC_TABLE_INDEX) ); \
  447.     }
  448.  
  449.  
  450. STEM_RU_FUNC_I(ru_adj)
  451. STEM_RU_FUNC_I(ru_part)
  452. STEM_RU_FUNC_I(ru_dear)
  453. STEM_RU_FUNC_I(ru_verb)
  454. STEM_RU_FUNC_I(ru_noun)
  455.  
  456.  
  457. static int LOC_PREFIX(stem_ru_adjectival) ( LOC_CHAR_TYPE * word, int len )
  458. {
  459.     register int i = LOC_PREFIX(stem_ru_adj_i) ( word, len );
  460.     if ( i )
  461.         i += LOC_PREFIX(stem_ru_part_i) ( word, len-i );
  462.     return i;
  463. }
  464.  
  465.  
  466. static int LOC_PREFIX(stem_ru_verb_ov) ( LOC_CHAR_TYPE * word, int len )
  467. {
  468.     register int i = LOC_PREFIX(stem_ru_verb_i) ( word, len );
  469.     if ( i && (len>=i+2) && word[len-i-2] == utf8letterO && word[len-i-1] == utf8letterV )
  470.         return i+2;
  471.     return i;
  472. }
  473.  
  474.  
  475. void LOC_PREFIX(stem_ru_init) ()
  476. {
  477.     unsigned int i;
  478.  
  479.     #undef STEM_RU_INIT_TABLE
  480.     #define STEM_RU_INIT_TABLE(table) \
  481.         for ( i=0; i<(sizeof(LOC_PREFIX(table))/sizeof(LOC_TABLE_ENTRY)); i++ ) \
  482.             LOC_PREFIX(table)[i].len = ((int)strlen((char*)LOC_PREFIX(table)[i].suffix)/sizeof(LOC_CHAR_TYPE))- 1;
  483.  
  484.     STEM_RU_INIT_TABLE(ru_adj)
  485.     STEM_RU_INIT_TABLE(ru_part)
  486.     STEM_RU_INIT_TABLE(ru_verb)
  487.     STEM_RU_INIT_TABLE(ru_noun)
  488.     STEM_RU_INIT_TABLE(ru_dear)
  489. }
  490.  
  491.  
  492. size_t LOC_PREFIX(stem_ru) ( LOC_CHAR_TYPE * word )
  493. {
  494.     size_t startWordAddr = (size_t)word;
  495.     int r1, r2;
  496.     int i, len;
  497.  
  498.     // IsVowel
  499.     #undef IV
  500.     #define IV(c) ( \
  501.         c==utf8letterA || c==utf8letterE || c==utf8letterYO || c==utf8letterI || c==utf8letterO || \
  502.         c==utf8letterU || c==utf8letterY || c==utf8letterEE || c==utf8letterYU || c==utf8letterYA )
  503.  
  504.     // EndOfWord
  505.     #undef EOW
  506.     #define EOW(_arg) (!(*((unsigned char*)(_arg))))
  507.  
  508.     while ( !EOW(word) ) if ( IV(*word) ) break; else word++;
  509.     if ( !EOW(word) ) word++; else return -1;
  510.     len = 0; while ( !EOW(word+len) ) len++;
  511.  
  512.     r1 = r2 = len;
  513.     for ( i=-1; i<len-1; i++ ) if ( IV(word[i]) && !IV(word[i+1]) ) { r1 = i+2; break; }
  514.     for ( i=r1; i<len-1; i++ ) if ( IV(word[i]) && !IV(word[i+1]) ) { r2 = i+2; break; }
  515.  
  516.     #define C(p) word[len-p]
  517.     #define W(p,c) ( C(p)==c )
  518.     #define XSUFF2(c2,c1) ( W(1,c1) && W(2,c2) )
  519.     #define XSUFF3(c3,c2,c1) ( W(1,c1) && W(2,c2) && W(3,c3) )
  520.     #define XSUFF4(c4,c3,c2,c1) ( W(1,c1) && W(2,c2) && W(3,c3) && W(4,c4) )
  521.     #define XSUFF5(c5,c4,c3,c2,c1) ( W(1,c1) && W(2,c2) && W(3,c3) && W(4,c4) && W(5,c5) )
  522.     #define BRK(_arg) { len -= _arg; break; }
  523.     #define CHK(_func) { i = LOC_PREFIX(_func) ( word, len ); if ( i ) BRK ( i ); }
  524.  
  525.     for ( ;; )
  526.     {
  527.         CHK ( stem_ru_dear_i );
  528.  
  529.         if ( C(1)==utf8letterV && len>=2 )
  530.         {
  531.             if ( C(2)==utf8letterI || C(2)==utf8letterY || C(2)==utf8letterYA )
  532.                 BRK(2);
  533.  
  534.             if ( C(2)==utf8letterA )
  535.             {
  536.                 if ( C(3)==utf8letterV && C(4)==utf8letterA )
  537.                     BRK(4);
  538.                 BRK(2);
  539.             }
  540.         }
  541.  
  542.         if ( len>=3 && XSUFF3 ( utf8letterV, utf8letterSH, utf8letterI )
  543.             && ( C(4)==utf8letterA || C(4)==utf8letterI || C(4)==utf8letterY || C(4)==utf8letterYA ) )
  544.                 BRK(4);
  545.  
  546.         if ( len>=5 && XSUFF5 ( utf8letterV, utf8letterSH, utf8letterI, utf8letterS, utf8letterMYA )
  547.             && ( C(6)==utf8letterA || C(6)==utf8letterI || C(6)==utf8letterY || C(6)==utf8letterYA ) )
  548.                 BRK(6);
  549.  
  550.         CHK ( stem_ru_adjectival );
  551.  
  552.         if ( len>=2 && ( XSUFF2 ( utf8letterS, utf8letterMYA ) || XSUFF2 ( utf8letterS, utf8letterYA ) ) )
  553.         {
  554.             len -= 2;
  555.             CHK ( stem_ru_adjectival );
  556.             CHK ( stem_ru_verb_ov );
  557.         } else
  558.         {
  559.             CHK ( stem_ru_verb_ov );
  560.         }
  561.  
  562.         CHK ( stem_ru_noun_i );
  563.         break;
  564.     }
  565.  
  566.     if ( len && ( W(1,utf8letterIY) || W(1,utf8letterI) ) )
  567.         len--;
  568.  
  569.     if ( len-r2>=3 && XSUFF3 ( utf8letterO, utf8letterS, utf8letterT ) )
  570.         len -= 3;
  571.     else if ( len-r2>=4 && XSUFF4 ( utf8letterO, utf8letterS, utf8letterT, utf8letterMYA ) )
  572.         len -= 4;
  573.  
  574.     if ( len>=3 && XSUFF3 ( utf8letterE, utf8letterIY, utf8letterSH ) )
  575.         len -= 3;
  576.     else if ( len>=4 && XSUFF4 ( utf8letterE, utf8letterIY, utf8letterSH, utf8letterE ) )
  577.         len -= 4;
  578.  
  579.     if ( len>=2 && XSUFF2 ( utf8letterN, utf8letterN ) )
  580.         len--;
  581.  
  582.     if ( len && W(1,utf8letterMYA) )
  583.         len--;
  584.  
  585.     return ((size_t) ((unsigned char*)(word+len)) - startWordAddr);
  586. //  return  ((int) (word + len)) - startWordAddr  - 2;
  587. }
  588.  
  589. // undefine externally defined stuff
  590. #undef LOC_CHAR_TYPE
  591. #undef LOC_PREFIX
  592. #undef RUS
  593.  
  594. /////////////////////////////////////////////////////////////////////////////
  595.  
  596. void stem_ru_init ()
  597. {
  598.     stem_ru_init_utf8 ();
  599. }
  600.  
  601.  
  602. static inline bool isUnicode(const char *zIn, int nIn) {
  603.     if (nIn <= 0) {
  604.         return false;
  605.     }
  606.  
  607.     if ((nIn & 1) == 1) {
  608.         return false;
  609.     }
  610.  
  611.     return *((unsigned char * )zIn) >0x80U;
  612. }
  613.  
  614.  
  615. static void copyEnsuredLowerCase(unsigned short * res, unsigned short * symbol) {
  616.  
  617.     switch (*symbol) {
  618.     case 0x90d0:
  619.         *res = 0xb0d0;
  620.         return;
  621.     case 0x91d0:
  622.         *res = 0xb1d0;
  623.         return;
  624.     case 0x92d0:
  625.         *res = 0xb2d0;
  626.         return;
  627.     case 0x93d0:
  628.         *res = 0xb3d0;
  629.         return;
  630.     case 0x94d0:
  631.         *res = 0xb4d0;
  632.         return;
  633.     case 0x95d0:
  634.         *res = 0xb5d0;
  635.         return;
  636.     case 0x81d0:
  637.         *res = 0x91d1;
  638.         return;
  639.     case 0x96d0:
  640.         *res = 0xb6d0;
  641.         return;
  642.     case 0x97d0:
  643.         *res = 0xb7d0;
  644.         return;
  645.     case 0x98d0:
  646.         *res = 0xb8d0;
  647.         return;
  648.     case 0x99d0:
  649.         *res = 0xb9d0;
  650.         return;
  651.     case 0x9ad0:
  652.         *res = 0xbad0;
  653.         return;
  654.     case 0x9bd0:
  655.         *res = 0xbbd0;
  656.         return;
  657.     case 0x9cd0:
  658.         *res = 0xbcd0;
  659.         return;
  660.     case 0x9dd0:
  661.         *res = 0xbdd0;
  662.         return;
  663.     case 0x9ed0:
  664.         *res = 0xbed0;
  665.         return;
  666.     case 0x9fd0:
  667.         *res = 0xbfd0;
  668.         return;
  669.     case 0xa0d0:
  670.         *res = 0x80d1;
  671.         return;
  672.     case 0xa1d0:
  673.         *res = 0x81d1;
  674.         return;
  675.     case 0xa2d0:
  676.         *res = 0x82d1;
  677.         return;
  678.     case 0xa3d0:
  679.         *res = 0x83d1;
  680.         return;
  681.     case 0xa4d0:
  682.         *res = 0x84d1;
  683.         return;
  684.     case 0xa5d0:
  685.         *res = 0x85d1;
  686.         return;
  687.     case 0xa6d0:
  688.         *res = 0x86d1;
  689.         return;
  690.     case 0xa7d0:
  691.         *res = 0x87d1;
  692.         return;
  693.     case 0xa8d0:
  694.         *res = 0x88d1;
  695.         return;
  696.     case 0xa9d0:
  697.         *res = 0x89d1;
  698.         return;
  699.     case 0xacd0:
  700.         *res = 0x8cd1;
  701.         return;
  702.     case 0xabd0:
  703.         *res = 0x8bd1;
  704.         return;
  705.     case 0xaad0:
  706.         *res = 0x8ad1;
  707.         return;
  708.     case 0xadd0:
  709.         *res = 0x8dd1;
  710.         return;
  711.     case 0xaed0:
  712.         *res = 0x8ed1;
  713.         return;
  714.     case 0xafd0:
  715.         *res = 0x8fd1;
  716.         return;
  717.     default:
  718.         *res = *symbol;
  719.         return;
  720.     }
  721. }
  722.  
  723. /*
  724.  *  FOR RUSSIAN
  725.  */
  726. static void porter_stemmer_unicode(const char *zIn, int nIn, char *zOut, int *pnOut){
  727.   int i;
  728.   static const int UNICODE_LIMIT = 40; //20 symbols
  729.  
  730.   //limit to
  731.   int limit = nIn > UNICODE_LIMIT ? UNICODE_LIMIT : nIn;
  732.  
  733.   i = 0;
  734.   while (i<limit) {
  735.       bool isNextUtfSymbol = *((unsigned char*)&zIn[i]) > 0x80U;
  736.  
  737.       if (isNextUtfSymbol) {
  738.  
  739.           bool isNotLastPos = i < limit-1;
  740.           if (isNotLastPos) {
  741.               copyEnsuredLowerCase( (unsigned short*) &zOut[i],
  742.                       (unsigned short*) &zIn[i]);
  743.           }
  744.           i += 2;
  745.       } else {
  746.           //Напр. Грузовозоff. Либо можно не копировать
  747.           zOut[i] = zIn[i];
  748.           i++;
  749.       }
  750.   }
  751.  
  752.   //Запас есть всгеда. См. выделение памяти для zOut
  753.   zOut[limit] = '\0';
  754.  
  755.  
  756.   int len = stem_ru_utf8((unsigned short *) zOut); //Two byte in symbol
  757.  
  758.   if (len <= 0 || len > limit ) {
  759.       len = limit;
  760.   }
  761.  
  762.  
  763.   *pnOut = len;
  764.  
  765.   return;
  766.  
  767. }
  768.  
  769. static int porterOpen1(
  770.   sqlite3_tokenizer *pTokenizer,         /* The tokenizer */
  771.   const char *zInput, int nInput,        /* String to be tokenized */
  772.   sqlite3_tokenizer_cursor **ppCursor    /* OUT: Tokenization cursor */
  773. ) {
  774.   stem_ru_init();
  775.   return porterOpen(pTokenizer, zInput, nInput, ppCursor);
  776. }
  777.  
  778. static int porterNext1(
  779.   sqlite3_tokenizer_cursor *pCursor,  /* Cursor returned by porterOpen */
  780.   const char **pzToken,               /* OUT: *pzToken is the token text */
  781.   int *pnBytes,                       /* OUT: Number of bytes in token */
  782.   int *piStartOffset,                 /* OUT: Starting offset of token */
  783.   int *piEndOffset,                   /* OUT: Ending offset of token */
  784.   int *piPosition                     /* OUT: Position integer of token */
  785. ){
  786.   porter_tokenizer_cursor *c = (porter_tokenizer_cursor *) pCursor;
  787.   const char *z = c->zInput;
  788.  
  789.   while( c->iOffset<c->nInput ){
  790.     int iStartOffset, ch;
  791.  
  792.     /* Scan past delimiter characters */
  793.     while( c->iOffset<c->nInput && isDelim(z[c->iOffset]) ){
  794.       c->iOffset++;
  795.     }
  796.  
  797.     /* Count non-delimiter characters. */
  798.     iStartOffset = c->iOffset;
  799.     while( c->iOffset<c->nInput && !isDelim(z[c->iOffset]) ){
  800.       c->iOffset++;
  801.     }
  802.  
  803.     if( c->iOffset>iStartOffset ){
  804.       int n = c->iOffset-iStartOffset;
  805.  
  806.       const char *zIn = &z[iStartOffset];
  807.       //printf("%s \n", zIn);
  808.  
  809.       bool unicode = isUnicode(zIn, n);
  810.  
  811. //      int minLength = unicode ? 2 : 1;
  812.  
  813.       //Можно еще проверить на stop-words.
  814.       //Вообще эта проверка необязательна. Алгоритм по умолчанию не использовал ни ограничения ни стоп слова
  815. //      if (n <= minLength) {
  816. //          //printf("skipped \n");
  817. //        continue;
  818. //      }
  819.  
  820.       if( n>=c->nAllocated ){
  821.         char *pNew;
  822.         c->nAllocated = n+20;
  823.         pNew = (char*) sqlite3_realloc(c->zToken, c->nAllocated);
  824.         if( !pNew ) return SQLITE_NOMEM;
  825.         c->zToken = pNew;
  826.       }
  827.  
  828.       if (unicode) {
  829.           porter_stemmer_unicode(zIn, n, c->zToken, pnBytes);
  830.       } else {
  831.           porter_stemmer(zIn, n, c->zToken, pnBytes);
  832.       }
  833.  
  834.       //printf("%d \n", *pnBytes);
  835.  
  836.       *pzToken = c->zToken;
  837.       *piStartOffset = iStartOffset;
  838.       *piEndOffset = c->iOffset;
  839.       *piPosition = c->iToken++;
  840.       return SQLITE_OK;
  841.     }
  842.   }
  843.   return SQLITE_DONE;
  844. }
  845.  
  846. /*
  847. ** The set of routines that implement the porter-stemmer tokenizer
  848. */
  849. static const sqlite3_tokenizer_module porterTokenizerModule1 = {
  850.   0,
  851.   porterCreate,
  852.   porterDestroy,
  853.   porterOpen1,
  854.   porterClose,
  855.   porterNext1,
  856. };
  857.  
  858. /*
  859. ** Allocate a new porter tokenizer.  Return a pointer to the new
  860. ** tokenizer in *ppModule
  861. */
  862. void sqlite3Fts3PorterTokenizerModule1(
  863.   sqlite3_tokenizer_module const**ppModule
  864. ){
  865.   *ppModule = &porterTokenizerModule1;
  866. }
  867.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement