1 /******************************************************************************
2 *
3 * Copyright (C) 2009, The Gentee Group. All rights reserved.
4 * This file is part of the Gentee open source project - http://www.gentee.com.
5 *
6 * THIS FILE IS PROVIDED UNDER THE TERMS OF THE GENTEE LICENSE ("AGREEMENT").
7 * ANY USE, REPRODUCTION OR DISTRIBUTION OF THIS FILE CONSTITUTES RECIPIENTS
8 * ACCEPTANCE OF THE AGREEMENT.
9 *
10 * Author: Alexey Krivonogov ( gentee )
11 *
12 ******************************************************************************/
13
14 #include "ged.h"
15
16 cmpfunc fcmp[] = { 0, &cmpbyte, &cmpubyte, &cmpshort, &cmpushort, &cmpint,
17 &cmpuint, 0, 0, 0, 0, &cmpstr, &cmpustr };
18
19 /* Filter format
20 uint size of data
21 cmd - SF_
22 uint - number of the field from 0
23 uint - len [for string fields]
24 uint - value
25 */
26
27 /* Index format
28 uint - size of data
29 uint - number of the field
30 uint - flags & len
31 */
32
33 int ges_compare( pvoid left, pvoid right, uint param )
34 {
35 pgedfield pfield;
36 pubyte lrec, rrec;
37 pgedsel psel = (pgedsel)param;
38 puint pind = ( puint )buf_ptr( PINDEX );
39 puint pend = ( puint )(( pubyte )pind + buf_len( PINDEX ));
40 uint len, flag;
41 int ok = 0;
42
43 lrec = psel->pdb->db + ( *(pubyte)left - 1 ) * psel->pdb->fsize;
44 rrec = psel->pdb->db + ( *(pubyte)right - 1 ) * psel->pdb->fsize;
45
46 while ( pind < pend && !ok )
47 {
48 pfield = psel->pdb->fields + *pind++;
49 flag = *pind++;
50
51 len = flag & 0xFFFF;
52 if ( !len )
53 len = pfield->width;
54 ok = fcmp[ pfield->ftype ]( lrec + pfield->offset,
55 rrec + pfield->offset, len );
56 if ( flag & IF_DESC )
57 ok = -ok;
58 }
59 return ok;
60 }
61
62 BOOL ges_updateindex( pgedsel psel )
63 {
64 if ( buf_len( PINDEX ))
65 {
66 quicksort( buf_ptr( PSELECT ), psel->reccount, sizeof( uint ),
67 (cmpfunc)&ges_compare, (uint)psel );
68 }
69 return TRUE;
70 }
71
72 BOOL ges_reverse( pgedsel psel )
73 {
74 uint i, itemp, count = psel->reccount >> 1;
75 puint pi = ( puint )buf_ptr( PSELECT );
76
77 for (i = 0; i < count; i++ )
78 {
79 itemp = pi[i];
80 pi[i] = pi[ psel->reccount - i - 1 ];
81 pi[ psel->reccount - i - 1 ] = itemp;
82 }
83 ges_goto( psel, psel->reccount - psel->reccur + 1 );
84 return TRUE;
85 }
86
87 BOOL ges_index( pgedsel psel, puint index )
88 {
89 buf_copy( PINDEX, (pubyte)index + sizeof( uint ), *index );
90
91 return ges_updateindex( psel );
92 }
93
94 BOOL ges_update( pgedsel psel )
95 {
96 uint i;
97 pubyte prec;
98 pged pdb;
99 puint pstart = ( puint )buf_ptr( PFILTER );
100 puint pend = ( puint )(( pubyte )pstart + buf_len( PFILTER ));
101
102 pdb = psel->pdb;
103 prec = pdb->db;
104 buf_clear( PSELECT );
105 for ( i = 0; i < pdb->reccount; i++ )
106 {
107 puint pflt = pstart;
108 uint ok = 0;
109 uint ifield, cmd, not, or, len, type;
110
111 if ( *prec ) // Deleted mark
112 continue;
113 while ( pflt < pend )
114 {
115 cmd = *pflt & 0xFFFFFF;
116 not = *pflt & SF_NOT;
117 or = *pflt & SF_OR;
118
119 if ( cmd > SF_ALL )
120 {
121 ifield = *++pflt;
122 pflt++;
123 type = pdb->fields[ ifield ].ftype;
124 if ( type == FT_STR )
125 len = *pflt++;
126 else
127 if ( type == FT_USTR )
128 len = *pflt++;
129 }
130 switch ( cmd )
131 {
132 case SF_ALL:
133 ok = !*prec;
134 break;
135 case SF_EQ:
136 ok = !fcmp[ type ]( pflt,
137 prec + pdb->fields[ ifield ].offset, len );
138 break;
139 case SF_LESS:
140 ok = fcmp[ type ](
141 prec + pdb->fields[ ifield ].offset, pflt, len ) < 0;
142 break;
143 case SF_GREAT:
144 ok = fcmp[ type ](
145 prec + pdb->fields[ ifield ].offset, pflt, len ) > 0;
146 break;
147 case SF_END:
148 break;
149 }
150 if ( not )
151 ok = !ok;
152 if ( or )
153 {
154 if ( ok ) break;
155 }
156 else
157 if ( !ok ) break;
158 switch ( type )
159 {
160 case FT_STR:
161 pflt = ( puint )((pubyte)pflt + len );
162 break;
163 case FT_USTR:
164 pflt = ( puint )((pubyte)pflt + ( len << 1 ));
165 break;
166 default:
167 pflt++;
168 }
169 }
170 if ( ok )
171 {
172 buf_appenduint( PSELECT, i + 1 );
173 }
174 prec += pdb->fsize;
175 }
176 psel->reccount = buf_len( PSELECT ) >> 2;
177
178 ges_updateindex( psel );
179 ges_goto( psel, 1 );
180 return TRUE;
181 }
182
183 BOOL ges_select( pgedsel psel, pged pdb, puint filter, puint index )
184 {
185 psel->sm = mem_alloc( sizeof( selmem ));
186
187 mem_zero( psel->sm, sizeof( selmem ));
188 buf_init( PSELECT );
189 buf_init( PINDEX );
190 buf_init( PFILTER );
191
192 psel->pdb = pdb;
193 buf_copy( PFILTER, (pubyte)filter + sizeof( uint ), *filter );
194 ges_update( psel );
195 ges_index( psel, index );
196 ges_goto( psel, 1 );
197
198 return TRUE;
199 }
200
201 BOOL ges_close( pgedsel psel )
202 {
203 buf_delete( PSELECT );
204 buf_delete( PINDEX );
205 buf_delete( PFILTER );
206 mem_free( psel->sm );
207
208 return TRUE;
209 }
210
211 uint ges_goto( pgedsel psel, uint pos )
212 {
213 if ( pos > psel->reccount )
214 pos = 0;
215 psel->reccur = pos;
216 return psel->reccur;
217 }
218
219 uint ges_recno( pgedsel psel )
220 {
221 if ( !psel->reccur )
222 return 0;
223
224 return *( ( puint )buf_ptr( PSELECT ) + psel->reccur - 1 );
225 }
226
227 BOOL ges_eof( pgedsel psel )
228 {
229 return !psel->reccur;
230 }
231
232 /*
233 pgedsel ged_select( pgedsel psel, pged pdb )
234 {
235 return psel;
236 }
237
238 pubyte ged_goto( pgedsel psel, uint pos )
239 {
240 pged pdb = psel->pdb;
241
242 if ( pos > pdb->reccount && !pos )
243 {
244 psel->reccur = 0;
245 psel->recptr = buf_ptr( &psel->record );
246 mem_zero( psel->recptr, pdb->fsize + 1 );
247 }
248 else
249 {
250 psel->reccur = pos;
251 psel->recptr = ( pubyte )buf_ptr( &pdb->data ) + pdb->head->oversize +
252 ( pos - 1 ) * pdb->fsize;
253 }
254 return psel->recptr;
255 }
256 */