1 /*-----------------------------------------------------------------------------
2 * Id: dbf_f_count F3
3 *
4 * Summary: Number of fields.
5 *
6 * Return: Returns the number of fields.
7 *
8 -----------------------------------------------------------------------------*/
9
10 method uint dbf.f_count()
11 {
12 return *this.fields
13 }
14
15 /*-----------------------------------------------------------------------------
16 * Id: dbf_f_decimal F2
17 *
18 * Summary: Getting the size of the fractional part in a numerical field.
19 *
20 * Params: num - Field number beginning with 1.
21 *
22 * Return: The size of the fractional part.
23 *
24 -----------------------------------------------------------------------------*/
25
26 method uint dbf.f_decimal( uint num )
27 {
28 return this.fields[ num - 1 ].decimals
29 }
30
31 /*-----------------------------------------------------------------------------
32 * Id: dbf_f_name F2
33 *
34 * Summary: Get the name of the specified field.
35 *
36 * Params: num - Field number beginning with 1.
37 *
38 * Return: Returns the name of the specified field.
39 *
40 -----------------------------------------------------------------------------*/
41
42 method str dbf.f_name( uint num )
43 {
44 return this.fields[ num - 1 ].name
45 }
46
47 /*-----------------------------------------------------------------------------
48 * Id: dbf_f_width F2
49 *
50 * Summary: Get the width of the specified field.
51 *
52 * Params: num - Field number beginning with 1.
53 *
54 * Return: Returns the width of the field.
55 *
56 -----------------------------------------------------------------------------*/
57
58 method uint dbf.f_width( uint num )
59 {
60 return this.fields[ num - 1 ].width
61 }
62
63 /*-----------------------------------------------------------------------------
64 * Id: dbf_f_find F2
65 *
66 * Summary: Getting the number of a field by its name.
67 *
68 * Params: name - The name of the field.
69 *
70 * Return: The number of the field with the specified name or
71 0 in case of an error.
72 *
73 -----------------------------------------------------------------------------*/
74
75 method uint dbf.f_find( str name )
76 {
77 uint i
78
79 fornum i, *this.fields
80 {
81 if name %== this.fields[ i ].name : return i + 1
82 }
83 return 0
84 }
85
86 /*-----------------------------------------------------------------------------
87 * Id: dbf_f_offset F2
88 *
89 * Summary: Get the offset of the field.
90 *
91 * Params: num - Field number beginning with 1.
92 *
93 * Return: Returns the offset of this field.
94 *
95 -----------------------------------------------------------------------------*/
96
97 method uint dbf.f_offset( uint num )
98 {
99 return this.fields[ num - 1 ].offset
100 }
101
102 /*-----------------------------------------------------------------------------
103 * Id: dbf_f_type F2
104 *
105 * Summary: Get the field type.
106 *
107 * Params: num - Field number beginning with 1.
108 *
109 * Return: Returns the type of this field. It can be one of the following
110 values. $$[dbftypes]
111 *
112 -----------------------------------------------------------------------------*/
113
114 method uint dbf.f_type( uint num )
115 {
116 return this.fields[ num - 1 ].ftype
117 }
118
119 /*-----------------------------------------------------------------------------
120 * Id: dbf_f_ptr F2
121 *
122 * Summary: Pointer to data. Get the pointer to the contents of this field
123 from the current record.
124 *
125 * Params: num - Field number beginning with 1.
126 *
127 * Return: Returns the pointer to this field.
128 *
129 -----------------------------------------------------------------------------*/
130
131 method uint dbf.f_ptr( uint num )
132 {
133 return this.ptr + this.fields[ num - 1 ].offset
134 }
135
136 /*-----------------------------------------------------------------------------
137 * Id: dbf_f_str F2
138 *
139 * Summary: Getting a value. Get the value of the field from the current
140 record as a string.
141 *
142 * Params: val - The string for getting the value.
143 num - Field number beginning with 1.
144 *
145 * Return: #lng/retpar( val )
146 *
147 -----------------------------------------------------------------------------*/
148
149 method str dbf.f_str( str val, uint num )
150 {
151 uint width = this.fields[ num - 1 ].width
152
153 val.reserve( width )
154 val.copy( this.f_ptr( num ), width )
155 // val.setlen( width )
156 return val.trimrspace()
157 }
158
159 /*-----------------------------------------------------------------------------
160 * Id: dbf_f_logic F2
161 *
162 * Summary: Getting a logical value. Get the value of the logical field from
163 the current record.
164 *
165 * Params: num - Field number beginning with 1.
166 *
167 * Return: Returns the value of the logical field.$$[dbflogic]
168 *
169 -----------------------------------------------------------------------------*/
170
171 method uint dbf.f_logic( uint num )
172 {
173 uint val = this.f_ptr( num )->byte
174
175 switch val
176 {
177 case 'Y', 'y', 'T', 't' : return $DBF_LTRUE
178 case 'N', 'n', 'F', 'f' : return $DBF_LFALSE
179 }
180 return $DBF_LUNKNOWN
181 }
182
183 /*-----------------------------------------------------------------------------
184 * Id: dbf_f_date F2
185 *
186 * Summary: Getting a date. Getting the date from the specified field of the
187 current record into the structure #a(tdatetime).
188 *
189 * Params: dt - The structure for getting the date.
190 num - Field number beginning with 1.
191 *
192 * Return: #lng/retpar(dt)
193 *
194 -----------------------------------------------------------------------------*/
195
196 method datetime dbf.f_date( datetime dt, uint num )
197 {
198 // mzero( &dt, sizeof( datetime ))
199 str st
200 str stemp
201 uint cur
202
203 this.f_str( st, num )
204
205 stemp.substr( st, 6, 2 )
206 dt.day = stemp.int()//str2int( stemp )
207 stemp.substr( st, 4, 2 )
208 dt.month = stemp.int()//str2int( stemp )
209 st.setlen( 4 )
210 dt.year = st.int()//str2int( st )
211
212 return dt
213 }
214
215 /*-----------------------------------------------------------------------------
216 * Id: dbf_f_date_1 FA
217 *
218 * Summary: Getting the date from the specified field of the current record as
219 a string.
220 *
221 * Params: val - The string for getting the date.
222 num - Field number beginning with 1.
223 *
224 * Return: #lng/retpar(val)
225 *
226 -----------------------------------------------------------------------------*/
227
228 method str dbf.f_date( str val, uint num )
229 {
230 datetime dt
231
232 this.f_date( dt, num )
233 getdatetime( dt, val, 0->str )
234 return val
235 }
236
237 /*-----------------------------------------------------------------------------
238 * Id: dbf_f_double F2
239 *
240 * Summary: Getting a numerical value. Get a numerical value of the double
241 type from the specified field of the current record.
242 *
243 * Params: num - Field number beginning with 1.
244 *
245 * Return: A value of the double type.
246 *
247 -----------------------------------------------------------------------------*/
248
249 method double dbf.f_double( uint num )
250 {
251 str val
252
253 this.f_str( val, num ).trimspace()
254 return double( val )
255 }
256
257 /*-----------------------------------------------------------------------------
258 * Id: dbf_f_int F2
259 *
260 * Summary: Getting an integer value. Get a numerical value of the int type
261 from the specified field of the current record.
262 *
263 * Params: num - Field number beginning with 1.
264 *
265 * Return: A number of the int type is returned.
266 *
267 -----------------------------------------------------------------------------*/
268
269 method int dbf.f_int( uint num )
270 {
271 str val
272
273 this.f_str( val, num ).trimspace()
274 return int( val )
275 }
276
277 /*-----------------------------------------------------------------------------
278 * Id: dbf_f_memo F2
279 *
280 * Summary: Get the value of a memo field. Get the value of the memo field from
281 the current record.
282 *
283 * Params: val - The string for writing the value.
284 num - Field number beginning with 1.
285 *
286 * Return: #lng/retf#
287 *
288 -----------------------------------------------------------------------------*/
289
290 method uint dbf.f_memo( str val, uint num )
291 {
292 uint id = this.f_int( num )
293 uint pos
294
295 val.clear()
296 if this.f_type( num ) != $DBFF_MEMO || !id : return 1
297
298 pos = id * this.mblock
299 if this.dbtfile.setpos( pos, $FILE_BEGIN ) != pos
300 {
301 return this.error( $ERRDBT_POS )
302 }
303
304 val->buf.use = 0
305 uint i
306
307 if this.head.version == 0x83 // dBase III
308 {
309 uint prev
310
311 while this.dbtfile.read( val->buf, this.mblock )
312 {
313 fornum i = prev, *val->buf
314 {
315 if val->buf[i] == 0x1A && val->buf[i + 1] == 0x1A
316 {
317 break
318 }
319 }
320 prev = *val->buf
321 if i < *val->buf : break
322 }
323 }
324 else // 0x8B dBase IV
325 {
326 this.dbtfile.read( val->buf, this.mblock )
327 i = ( val.ptr() + 4 )->uint
328 val->buf.del( 0, 8 )
329 if i > this.mblock
330 {
331 if this.dbtfile.read( val->buf, i - this.mblock ) != i - this.mblock
332 {
333 return this.error( $ERRDBT_READ )
334 }
335 }
336 i -= 8
337 }
338 val->buf[i] = 0
339 val.setlenptr()
340 return 1
341 }
342
343 /*-----------------------------------------------------------------------------
344 * Id: dbf_fw_str F2
345 *
346 * Summary: Writing a value. Write a value into the specified field of
347 the current record.
348 *
349 * Params: val - The string being written.
350 num - Field number beginning with 1.
351 *
352 * Return: #lng/retf#
353 *
354 -----------------------------------------------------------------------------*/
355
356 method uint dbf.fw_str( str val, uint num )
357 {
358 fordata fd
359 if this.eof( fd ) : return this.error( $ERRDBF_EOF )
360
361 uint width = this.f_width( num )
362
363 if *val > width
364 {
365 return this.error( $ERRDBF_FOVER )
366 }
367
368 uint pos = this.head.header_len +
369 this.cur * this.head.record_width + this.f_offset( num )
370 uint off = this.ptr + this.f_offset( num ) - this.page.data
371
372 if this.f_type( num ) == $DBFF_CHAR
373 {
374 val.fillspacer( width )
375 }
376 else : val.fillspacel( width )
377
378 mcopy( this.page.ptr() + off, val.ptr(), width )
379 //if !this.page.write( this.dbffile, pos, off, width )
380 if !this.dbffile.writepos( pos, this.page.ptr() + off, width )
381 {
382 return this.error( $ERRDBF_WRITE )
383 }
384 if this.getdate()
385 {
386 uint size
387
388 /*setpos( this.dbffile, 1, $FILE_BEGIN )
389 // Записываем дату и количество записей
390 WriteFile( this.dbffile, &this.head.yy, 3, &size, 0 )*/
391 this.dbffile.writepos( pos, &this.head.yy, 3 )
392 }
393 return 1
394 }
395
396 /*-----------------------------------------------------------------------------
397 * Id: dbf_fw_logic F2
398 *
399 * Summary: Writing a logical value. Write a logical value into the specified
400 field of the current record.
401 *
402 * Params: val - Number 1 or 0.
403 num - Field number beginning with 1.
404 *
405 * Return: #lng/retf#
406 *
407 -----------------------------------------------------------------------------*/
408
409 method uint dbf.fw_logic( uint val, uint num )
410 {
411 return this.fw_str( ?( val, "T", "F" ), num )
412 }
413
414 /*-----------------------------------------------------------------------------
415 * Id: dbf_fw_date F2
416 *
417 * Summary: Writing a date. Write a date into the specified field of the
418 current record.
419 *
420 * Params: dt - The structure #a(tdatetime) containing the date.
421 num - Field number beginning with 1.
422 *
423 * Return: #lng/retf#
424 *
425 -----------------------------------------------------------------------------*/
426
427 method uint dbf.fw_date( datetime dt, uint num )
428 {
429 str val
430
431 val += dt.year
432 //int2str( val, "%02i", dt.month )
433 //int2str( val, "%02i", dt.day )
434 val.out4( "%02i", dt.month )
435 val.out4( "%02i", dt.day )
436 return this.fw_str( val, num )
437 }
438
439 /*-----------------------------------------------------------------------------
440 * Id: dbf_fw_double F2
441 *
442 * Summary: Writing a numerical value. Write a numerical value into the
443 specified field of the current record.
444 *
445 * Params: dval - The number being written.
446 num - Field number beginning with 1.
447 *
448 * Return: #lng/retf#
449 *
450 -----------------------------------------------------------------------------*/
451
452 method uint dbf.fw_double( double dval, uint num )
453 {
454 str val
455 uint width = this.f_width( num )
456
457 //double2str( val, "%\(width).\(this.f_decimal( num ))f", dval )
458 val.out8( "%\(width).\(this.f_decimal( num ))f", (&dval)->ulong )
459
460 return this.fw_str( val, num )
461 }
462
463 /*-----------------------------------------------------------------------------
464 * Id: dbf_fw_int F2
465 *
466 * Summary: Writing an integer value. Write a value of the int type into
467 the specified field of the current record.
468 *
469 * Params: ival - The number being written.
470 num - Field number beginning with 1.
471 *
472 * Return: #lng/retf#
473 *
474 -----------------------------------------------------------------------------*/
475
476 method uint dbf.fw_int( int ival, uint num )
477 {
478 str val
479 uint width = this.f_decimal( num )
480
481 val += ival
482 if width
483 {
484 val.appendch( '.' )
485 val.fill( "0", width, 0 )
486 }
487 return this.fw_str( val, num )
488 }
489
490 /*method uint dbf.fw_int( uint ival, uint num )
491 {
492 return this.fw_int( int( ival ), num )
493 }*/
494
495 /*-----------------------------------------------------------------------------
496 ** Id: dbf_fw_memo F2
497 *
498 * Summary: Writing a value into a memo field. Write a value into the
499 specified memo field of the current record.
500 *
501 * Params: val - The string being written.
502 num - Field number beginning with 1.
503 *
504 * Return: #lng/retf#
505 *
506 -----------------------------------------------------------------------------*/
507
508 method uint dbf.fw_memo( str val, uint num )
509 {
510 uint size
511 uint idmem iread fsize vlen
512 str cur
513
514 subfunc uint reqblock( uint rsize )
515 {
516 rsize += ?( this.head.version == 0x83, 2, 8 )
517 return rsize / this.mblock + ?( rsize % this.mblock, 1, 0 )
518 }
519
520 if this.f_type( num ) != $DBFF_MEMO : return this.error( $ERRDBF_TYPE )
521 this.f_memo( cur, num )
522
523 if *cur && reqblock( *cur ) >= reqblock( *val )
524 {
525 // Записываем поверх старого
526 this.dbtfile.setpos( this.f_int( num ) * this.mblock, $FILE_BEGIN )
527 if this.head.version == 0x8B &&
528 //!'ff ff 08 00 \i4 \( *val + 8 )'.write( this.dbtfile )
529 !this.dbtfile.write( 'ff ff 08 00 \i4 \( *val + 8 )' )
530
531 {
532 return this.error( $ERRDBT_WRITE )
533 }
534
535 if !this.dbtfile.write( val ) : return this.error( $ERRDBT_WRITE )
536
537 if this.head.version == 0x83 && //!'1a 1a'.write( this.dbtfile )
538 !this.dbtfile.write( '1a 1a' )
539 {
540 return this.error( $ERRDBT_WRITE )
541 }
542 return 1
543 }
544 // Записываем в новом месте
545 this.dbtfile.setpos( 0, $FILE_BEGIN )
546 //ReadFile( this.dbtfile, &idmem, 4, &iread, 0 )
547 this.dbtfile.read( &idmem, 4 )
548 fsize = this.dbtfile.getsize( )
549 this.dbtfile.setpos( 0, $FILE_END )
550 if !idmem : idmem = 1
551
552 if idmem * this.mblock > fsize
553 {
554 // Заполняем до начала записи недостающим размером
555 cur.clear()
556 cur.fill( "\01A", idmem * this.mblock - fsize, $FILL_LEN )
557 if !this.dbtfile.write( cur )
558 {
559 return this.error( $ERRDBT_WRITE )
560 }
561 }
562 if this.head.version == 0x83
563 {
564 vlen = *val
565 val.fill( "\01A", reqblock( vlen ) * this.mblock, $FILL_LEN )
566 }
567 else // dBase IV
568 {
569 //if //! 'ff ff 08 00 \i4 \( *val + 8 )'.write( this.dbtfile )
570 if !this.dbtfile.write( 'ff ff 08 00 \i4 \( *val + 8 )' )
571 {
572 return this.error( $ERRDBT_WRITE )
573 }
574 }
575
576 if !this.dbtfile.write( val )
577 {
578 return this.error( $ERRDBT_WRITE )
579 }
580 if this.head.version == 0x83 : val.setlen( vlen )
581
582 size = reqblock( this.dbtfile.getsize( ) )
583 this.dbtfile.setpos( 0, $FILE_BEGIN )
584 //WriteFile( this.dbtfile, &size, 4, &iread, 0 )
585 this.dbtfile.write( &size, 4 )
586
587 return this.fw_int( idmem, num )
588 }
589