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 HINSTANCE handledll;
17
18 // See ged.h -> Type of fields
19
20 uint fsizes[] = { 0, 1, 1, 2, 2, 4, 4, 8, 8, 4, 8, 0, 0 };
21
22 BOOL WINAPI DllMain( HINSTANCE hinstDll, DWORD fdwReason,
23 LPVOID lpReserved )
24 //BOOL WINAPI _DllMainCRTStartup( HINSTANCE hinstDll, DWORD fdwReason,
25 // LPVOID lpReserved )
26 {
27 if ( fdwReason == DLL_PROCESS_ATTACH )
28 {
29 handledll = hinstDll;
30 mem_init();
31 }
32 return ( TRUE );
33 }
34
35 pged ged_init( pged pdb )
36 {
37 pdb->gm = mem_alloc( sizeof( gedmem ));
38
39 mem_zero( pdb->gm, sizeof( gedmem ));
40 buf_init( &pdb->gm->record );
41 buf_init( &pdb->gm->data );
42 buf_init( &pdb->gm->head );
43 str_init( &pdb->gm->dbname );
44 str_init( &pdb->gm->dbfile );
45
46 str_copyzero( &pdb->gm->dbname, pdb->filename );
47 os_filefullname( &pdb->gm->dbname, &pdb->gm->dbfile );
48 return pdb;
49 }
50
51 BOOL ged_delete( pged pdb )
52 {
53 buf_delete( &pdb->gm->head );
54 buf_delete( &pdb->gm->data );
55 buf_delete( &pdb->gm->record );
56 str_delete( &pdb->gm->dbname );
57 str_delete( &pdb->gm->dbfile );
58 mem_free( pdb->gm );
59 return TRUE;
60 }
61
62 uint ged_error( pged pdb, uint code )
63 {
64 uint ret;
65
66 pdb->error = code;
67 pdb->filename = buf_ptr( PFILE );
68 if ( pdb->call )
69 {
70 pdb->call( pdb->nfyparam, &ret, ( puint )pdb );
71 pdb->error = ret;
72 }
73 return !pdb->error;
74 }
75
76 BOOL ged_read( pged pdb, pbuf ret, long64 pos, uint size )
77 {
78 if ( !size )
79 size = ( uint )os_filesize( pdb->handle );
80
81 buf_reserve( ret, size );
82
83 os_filepos( pdb->handle, pos, pos < 0 ? FSET_END : FSET_BEGIN );
84
85 if ( size && !os_fileread( pdb->handle, buf_ptr( ret ), size ))
86 ged_error( pdb, GDE_READFILE );
87
88 buf_setlen( ret, size );
89
90 return !pdb->error;
91 }
92
93 BOOL ged_write( pged pdb, pubyte data, long64 pos, uint size )
94 {
95 os_filepos( pdb->handle, pos, pos < 0 ? FSET_END : FSET_BEGIN );
96
97 if ( !os_filewrite( pdb->handle, data, size ))
98 ged_error( pdb, GDE_WRITEFILE );
99
100 return !pdb->error;
101 }
102
103 BOOL ged_close( pged pdb )
104 {
105 os_fileclose( pdb->handle );
106 return ged_delete( pdb );
107 }
108
109 BOOL ged_create( pged pdb, pgedfieldinit pfi )
110 {
111 gedhead head;
112 pbuf out;
113 pubyte genteeinfo = "Open source Gentee database format http://www.gentee.com";
114
115 ged_init( pdb );
116 mem_zero( &head, sizeof( gedhead ));
117 out = PDATA;
118 head.ext = GED_STRING;
119 head.size = sizeof( gedhead );
120
121 buf_append( out, ( pubyte )&head, sizeof( gedhead ) );
122
123 if ( os_fileexist( PFILE ) && !ged_error( pdb, GDE_GEDEXIST ))
124 return !pdb->error;
125
126 pdb->handle = os_fileopen( PFILE, FOP_CREATE );
127
128 if ( !pdb->handle )
129 return ged_error( pdb, GDE_OPENFILE );
130
131 while ( pfi->ftype )
132 {
133 buf_appendch( out, ( ubyte )( pfi->ftype & 0xFF ));
134 if ( !fsizes[ pfi->ftype & 0xFF ] )
135 buf_appendch( out, ( ubyte )min( 255, pfi->ftype >> 16 ));
136 buf_append( out, pfi->name, lstrlen( pfi->name ) + 1 );
137 head.numfields++;
138 pfi++;
139 }
140 buf_appendch( out, GEI_GENTEE );
141 buf_appendushort( out, (ushort)( lstrlen( genteeinfo ) + 1 ));
142 buf_append( out, genteeinfo, lstrlen( genteeinfo ) + 1 );
143 head.oversize = ( ushort )buf_len( out );
144
145 if ( pdb->autoid )
146 {
147 head.autoid = ( ushort )pdb->autoid;
148 buf_appenduint( out, 0 );
149 }
150 mem_copy( buf_ptr( out ), ( pubyte )&head, sizeof( gedhead ));
151 if ( !os_filewrite( pdb->handle, buf_ptr( out ), buf_len( out )))
152 return ged_error( pdb, GDE_WRITEFILE );
153
154 os_fileclose( pdb->handle );
155
156 ged_delete( pdb );
157
158 return !pdb->error;
159 }
160
161 BOOL ged_open( pged pdb )
162 {
163 uint i;
164 pubyte ptr;
165
166 ged_init( pdb );
167
168 pdb->handle = os_fileopen( PFILE, 0 );
169
170 if ( !pdb->handle )
171 return ged_error( pdb, GDE_OPENFILE );
172
173 ged_read( pdb, PDATA, 0, 0 );
174
175 pdb->db = buf_ptr( PDATA );
176 pdb->head = ( pgedhead )pdb->db;
177 buf_reserve( PHEAD, pdb->head->oversize + pdb->head->numfields * sizeof( gedfield ));
178 buf_copy( PHEAD, pdb->db, pdb->head->oversize );
179 pdb->head = ( pgedhead )buf_ptr( PHEAD );
180
181 if ( pdb->head->ext != GED_STRING )
182 return ged_error( pdb, GDE_FORMAT );
183
184 pdb->fields = ( pgedfield )( ( pubyte )pdb->head + pdb->head->oversize );
185 pdb->fsize = 1; // The first byte is the deleted mark
186 ptr = ( pubyte )pdb->head + sizeof( gedhead );
187 for ( i = 0; i < pdb->head->numfields; i++ )
188 {
189 pdb->fields[ i ].ftype = *ptr++;
190 pdb->fields[ i ].width = fsizes[ pdb->fields[ i ].ftype ] ?
191 fsizes[ pdb->fields[ i ].ftype ] : *ptr++;
192 pdb->fields[ i ].offset = ( ushort )pdb->fsize;
193
194 if ( pdb->fields[ i ].ftype == FT_USTR )
195 pdb->fields[ i ].width <<= 1;
196 pdb->fields[ i ].name = ptr;
197 ptr += lstrlen( ptr ) + 1;
198 pdb->fsize += pdb->fields[ i ].width;
199 }
200 if ( pdb->head->autoid )
201 pdb->autoid = *( puint )( pdb->db + buf_len( PDATA ) - sizeof( uint ));
202
203 pdb->reccount = ( buf_len( PDATA ) - pdb->head->oversize -
204 ( pdb->head->autoid ? sizeof( uint ) : 0 )) / pdb->fsize;
205 pdb->db += pdb->head->oversize;
206 buf_reserve( PRECORD, pdb->fsize + sizeof( uint ));
207 ged_goto( pdb, 1 );
208
209 return !pdb->error;
210 }
211
212 uint ged_goto( pged pdb, uint pos )
213 {
214 if ( pos > pdb->reccount )
215 pos = 0;
216 pdb->reccur = pos;
217 pdb->recptr = ( pos ? pdb->db + ( pos - 1 ) * pdb->fsize : buf_ptr( PRECORD ));
218 return pdb->reccur;
219 }
220
221 uint ged_recno( pged pdb )
222 {
223 return pdb->reccur;
224 }
225
226 BOOL ged_eof( pged pdb )
227 {
228 return !pdb->reccur;
229 }
230