1
  
2
  
3
  
4
  
5
  
6
  
7
  
8
  
9
  
10
  
11
  
12
  
13
  
14
  
15
  
16
  
17
  
18
  
19
  
20
  
21
  
22
  
23
  
24
  
25
  
26
  
27
  
28
  
29
  
30
  
31
  
32
  
33
  
34
  
35
  
36
  
37
  
38
  
39
  
40
  
41
  
42
  
43
  
44
  
45
  
46
  
47
  
48
  
49
  
50
  
51
  
52
  
53
  
54
  
55
  
56
  
57
  
58
  
59
  
60
  
61
  
62
  
63
  
64
  
65
  
66
  
67
  
68
  
69
  
70
  
71
  
72
  
73
  
74
  
75
  
76
  
77
  
78
  
79
  
80
  
81
  
82
  
83
  
84
  
85
  
86
  
87
  
88
  
89
  
90
  
91
  
92
  
93
  
94
  
95
  
96
  
97
  
98
  
99
  
100
  
101
  
102
  
103
  
104
  
105
  
106
  
107
  
108
  
109
  
110
  
111
  
112
  
113
  
114
  
115
  
116
  
117
  
118
  
119
  
120
  
121
  
122
  
123
  
124
  
125
  
126
  
127
  
128
  
129
  
130
  
131
  
132
  
133
  
134
  
135
  
136
  
137
  
138
  
139
  
140
  
141
  
142
  
143
  
144
  
145
  
146
  
147
  
148
  
149
  
150
  
151
  
152
  
153
  
154
  
155
  
156
  
157
  
158
  
159
  
160
  
161
  
#ifndef CB_KEY_PIKESTRING_H 
#define CB_KEY_PIKESTRING_H 
#include "bitvector.h" 
#include "pike_int_types.h" 
 
typedef struct pike_string * CB_NAME(string); 
typedef unsigned INT32 CB_NAME(char); 
 
#ifdef cb_string 
# undef cb_string 
#endif 
#define cb_string CB_NAME(string) 
 
#ifdef cb_char 
# undef cb_char 
#endif 
#define cb_char CB_NAME(char) 
 
#define hton8(x) (x) 
#define get_unaligned_be8(x) ((unsigned INT8 *)x)[0] 
 
#ifdef CB_SOURCE 
#define CB_ADD_KEY_REF(x)     do { if ((x).str) add_ref((x).str); } while(0) 
#define CB_FREE_KEY(x)                do { if ((x).str) free_string((x).str); } while(0) 
#define CB_SET_KEY(node, x)                           \ 
        do { CB_ADD_KEY_REF(x);                         \ 
            CB_FREE_KEY((node)->key); (node)->key = (x); } while(0) 
 
#define CB_KEY_EQ(k1, k2)     (CB_S_EQ((k1).len, (k2).len) && (k1).str == (k2).str) 
#define CB_KEY_LT(k1, k2)                             \ 
        (CB_LT((k1).len, (k2).len) && my_quick_strcmp((k1).str, (k2).str) < 0) 
 
#define CB_GET_CHAR(s, n)     ((cb_char)INDEX_CHARP((s)->str, (n), (s)->size_shift)) 
#define CB_WIDTH(s)   (1 << (3 + (s)->size_shift)) /* width in bits */ 
#define CB_LENGTH(str)        ((str)->len) 
#define CB_SIZE(key)  ((key).len) 
#define CB_GET_BIT(str, pos)                          \ 
        (BITN(cb_char, CB_GET_CHAR((str), (pos).chars), (pos).bits)) 
static inline unsigned INT32 CB_COUNT_PREFIX(const cb_string s1, const cb_string s2, const size_t n) { 
    cb_char c; 
    c = CB_GET_CHAR(s1, n); 
    c ^= CB_GET_CHAR(s2, n); 
 
    return clz32(c); 
} 
 
 
static inline cb_size cb_prefix_count_fallback(const cb_string, 
                                            const cb_string, 
                                            const cb_size, 
                                            cb_size); 
 
static inline cb_size cb_prefix_count_wide0(const cb_string s1, 
                                            const cb_string s2, 
                                            const cb_size len, 
                                            cb_size start) { 
    size_t j = start.chars; 
    const unsigned char * p1, * p2; 
 
    p1 = STR0(s1); 
    p2 = STR0(s2); 
 
#if 0 
    asm volatile( 
    "pushf\t\n" 
    "orl $(1<<18), (%esp)\t\n" 
    "popf\t\n" 
  ); 
#endif 
 
#define PREFIX(n) do {                                                \ 
    size_t k = j/sizeof(unsigned INT ##n );                             \ 
    for (;k < len.chars/sizeof(unsigned INT ##n );k++) {                \ 
        unsigned INT ##n x = get_unaligned_be ##n (p1 + k * sizeof(unsigned INT ##n))\ 
                           ^ get_unaligned_be ##n (p2 + k * sizeof(unsigned INT ##n));\ 
        if (x) {                                                \ 
            unsigned INT32 a;                                           \ 
            a = clz ##n(x);                             \ 
            start.chars = k*sizeof(unsigned INT ##n ) + a/8;    \ 
            start.bits = 24 + a % 8;                            \ 
            return start;                                       \ 
        }                                                       \ 
    }                                                           \ 
    j = k*sizeof(unsigned INT ##n);                             \ 
    } while(0) 
#ifdef lzc64 
   PREFIX(64); 
#endif 
   PREFIX(32); 
    PREFIX(8); 
 
#if 0 
    asm volatile( 
    "pushf\t\n" 
    "andl $(~(1<<18)), (%esp)\t\n" 
    "popf\t\n" 
  ); 
#endif 
 
    start.chars = j; 
 
    if (len.bits) { 
        unsigned INT32 a = clz8(((p_wchar0*)p1)[j]^((p_wchar0*)p2)[j]); 
        start.bits = MINIMUM(len.bits, 24+a); 
        return start; 
    } 
 
    start.bits = 0; 
    return start; 
} 
 
static inline cb_size cb_prefix_count_widestring(const cb_string s1, 
                                                 const cb_string s2, 
                                                 const cb_size len, 
                                                 const cb_size start) { 
#if 0 
    size_t i; 
    cb_size t, r; 
    unsigned char* chrptr = s1->str;; 
    static volatile cb_string n1, n2; 
    static volatile void* zero = NULL; 
    static volatile cb_size *rp, *tp; 
 
    n1 = s1; 
    n2 = s2; 
 
#endif 
    if (CB_WIDTH(s1) == 8 && 8 == CB_WIDTH(s2)) 
        return cb_prefix_count_wide0(s1, s2, len, start); 
#if 0 
        if (!CB_S_EQ(r, t)) { 
            rp = &r; 
            tp = &t; 
            fprintf(stderr, "%p(%p) and %p(%p) have prefix %lu,%lu. should " 
                    + "have %lu,%lu (len: %lu, %lu  start: %lu, %lu)\n", 
                    s1->str, s1, s2->str, s2, t.chars, t.bits, r.chars, 
                    r.bits, len.chars, len.bits, start.chars, start.bits); 
            fprintf(stderr, "here you die: %p, %lu\n", chrptr, 
                    r.bits/(UINT64)zero); 
            fprintf(stderr, "%p %p %p", zero, n1, n2); 
            n1 = n2 = (void*)(zero = (UINT64)chrptr ^ (UINT64)n1 
                              ^ (UINT64)n2); 
            fprintf(stderr, "%p %p %p %p %p %p", zero, n1, n2, rp, (void*)rp, 
                    tp, (void*)tp); 
        } 
#endif 
 
 
    return cb_prefix_count_fallback(s1, s2, len, start); 
} 
 
#define       cb_prefix_count cb_prefix_count_widestring 
 
#undef CB_WIDTH 
#define CB_WIDTH(s)   (32) 
 
#endif /* CB_SOURCE */ 
 
#endif