SAGA API v9.10
Loading...
Searching...
No Matches
table_dbase.cpp
Go to the documentation of this file.
1/**********************************************************
2 * Version $Id$
3 *********************************************************/
4
6// //
7// SAGA //
8// //
9// System for Automated Geoscientific Analyses //
10// //
11// Application Programming Interface //
12// //
13// Library: SAGA_API //
14// //
15//-------------------------------------------------------//
16// //
17// table_dbase.cpp //
18// //
19// Copyright (C) 2005 by Olaf Conrad //
20// //
21//-------------------------------------------------------//
22// //
23// This file is part of 'SAGA - System for Automated //
24// Geoscientific Analyses'. //
25// //
26// This library is free software; you can redistribute //
27// it and/or modify it under the terms of the GNU Lesser //
28// General Public License as published by the Free //
29// Software Foundation, either version 2.1 of the //
30// License, or (at your option) any later version. //
31// //
32// This library is distributed in the hope that it will //
33// be useful, but WITHOUT ANY WARRANTY; without even the //
34// implied warranty of MERCHANTABILITY or FITNESS FOR A //
35// PARTICULAR PURPOSE. See the GNU Lesser General Public //
36// License for more details. //
37// //
38// You should have received a copy of the GNU Lesser //
39// General Public License along with this program; if //
40// not, see <http://www.gnu.org/licenses/>. //
41// //
42//-------------------------------------------------------//
43// //
44// contact: Olaf Conrad //
45// Institute of Geography //
46// University of Goettingen //
47// Goldschmidtstr. 5 //
48// 37077 Goettingen //
49// Germany //
50// //
51// e-mail: oconrad@saga-gis.org //
52// //
54
55//---------------------------------------------------------
56
57
59// //
60// //
61// //
63
64//---------------------------------------------------------
65#include <stdlib.h>
66#include <string.h>
67#include <time.h>
68
69#include "api_core.h"
70#include "table_dbase.h"
71#include "table.h"
72#include "datetime.h"
73
74
76// //
77// //
78// //
80
81//---------------------------------------------------------
83{
84 m_hFile = NULL;
85 m_Record = NULL;
86 m_Fields = NULL;
87 m_nFields = 0;
88 m_Encoding = Encoding;
89}
90
91//---------------------------------------------------------
96
97//---------------------------------------------------------
99{
100 if( m_hFile )
101 {
102 Flush_Record();
103 Header_Write();
104
105 fclose(m_hFile);
106 m_hFile = NULL;
107 }
108
109 SG_FREE_SAFE(m_Record);
110 SG_FREE_SAFE(m_Fields);
111
112 m_nFields = 0;
113 m_nRecords = 0;
114 m_nHeaderBytes = 0;
115 m_nRecordBytes = 0;
116 m_nFileBytes = 0;
117
118 m_bModified = false;
119}
120
121
123// //
125
126//---------------------------------------------------------
127bool CSG_Table_DBase::Open_Read(const SG_Char *FileName, CSG_Table *pTable, bool bRecords_Load)
128{
129 Close();
130
131 if( (m_hFile = fopen(CSG_String(FileName), "rb")) == NULL )
132 {
133 SG_UI_Msg_Add_Error(_TL("dbf read: could not open file"));
134
135 return( false );
136 }
137
138 m_bReadOnly = true;
139
140 if( !Header_Read() )
141 {
142 SG_UI_Msg_Add_Error(_TL("dbf read: could not read header"));
143
144 Close();
145
146 return( false );
147 }
148
149 fseek(m_hFile, 0, SEEK_END);
150 m_nFileBytes = ftell(m_hFile);
151 fseek(m_hFile, 0, SEEK_SET);
152
153 //-----------------------------------------------------
154 if( pTable )
155 {
156 int iField;
157
158 pTable->Destroy();
159
160 for(iField=0; iField<Get_Field_Count(); iField++)
161 {
162 switch( Get_Field_Type(iField) )
163 {
164 case DBF_FT_LOGICAL:
165 pTable->Add_Field(Get_Field_Name(iField), SG_DATATYPE_Char);
166 break;
167
168 case DBF_FT_CHARACTER: default:
170 break;
171
172 case DBF_FT_DATE:
173 pTable->Add_Field(Get_Field_Name(iField), SG_DATATYPE_Date);
174 break;
175
176 case DBF_FT_FLOAT:
178 break;
179
180 case DBF_FT_NUMERIC:
181 pTable->Add_Field(Get_Field_Name(iField), Get_Field_Decimals(iField) > 0
184 );
185 }
186 }
187
188 //-------------------------------------------------
189 if( bRecords_Load && Get_Count() > 0 && Move_First() )
190 {
191 for(int iRecord=0; iRecord<Get_Count() && SG_UI_Process_Set_Progress(iRecord, Get_Count()); iRecord++)
192 {
193 CSG_Table_Record *pRecord = pTable->Add_Record();
194
195 for(iField=0; iField<Get_Field_Count(); iField++)
196 {
197 switch( Get_Field_Type(iField) )
198 {
199 default:
200 pRecord->Set_Value(iField, asString(iField));
201 break;
202
203 case DBF_FT_FLOAT:
204 case DBF_FT_NUMERIC:
205 {
206 double Value;
207
208 if( asDouble(iField, Value) )
209 pRecord->Set_Value(iField, Value);
210 else
211 pRecord->Set_NoData(iField);
212 }
213 break;
214 }
215 }
216
217 Move_Next();
218 }
219
221 }
222 }
223
224 return( true );
225}
226
227//---------------------------------------------------------
228inline bool CSG_Table_DBase::Read(void *buffer, size_t size, size_t count)
229{
230 return( m_hFile && fread(buffer, size, count, m_hFile) == size * count );
231}
232
233//---------------------------------------------------------
234inline bool CSG_Table_DBase::Write(void *buffer, size_t size, size_t count)
235{
236 return( m_hFile && fwrite(buffer, size, count, m_hFile) == size * count );
237}
238
239//---------------------------------------------------------
240bool CSG_Table_DBase::Header_Read(void)
241{
242 if( !m_hFile )
243 {
244 return( false );
245 }
246
247 //-----------------------------------------------------
248 char buffer[16]; TDBF_Header h;
249
250 fseek(m_hFile, 0, SEEK_SET);
251
252 //-----------------------------------------------------
253 // Bytes 0-31: File Header...
254 Read(&h.FileType , sizeof(char), 1); // 00 FoxBase+, FoxPro, dBaseIII+, dBaseIV, no memo - 0x03
255 // FoxBase+, dBaseIII+ with memo - 0x83
256 // FoxPro with memo - 0xF5
257 // dBaseIV with memo - 0x8B
258 // dBaseIV with SQL Table - 0x8E
259 Read(&h.LastUpdate , sizeof(char), 3); // 01-03 Last update, format YYYYMMDD **correction: it is YYMMDD**
260 Read(&m_nRecords , sizeof(char), 4); // 04-07 Number of records in file (32-bit number)
261 Read(&m_nHeaderBytes , sizeof(char), 2); // 08-09 Number of bytes in header (16-bit number)
262 Read(&m_nRecordBytes , sizeof(char), 2); // 10-11 Number of bytes in record (16-bit number)
263 Read(buffer , sizeof(char), 2); // 12-13 Reserved, fill with 0x00
264 Read(&h.Transaction , sizeof(char), 1); // 14 dBaseIV flag, incomplete transaction
265 // Begin Transaction sets it to - 0x01
266 // End Transaction or RollBack reset it to - 0x00
267 Read(&h.bEncrypted , sizeof(char), 1); // 15 Encryption flag, encrypted 0x01 else 0x00
268 // Changing the flag does not encrypt or decrypt the records
269 Read(buffer , sizeof(char), 12); // 16-27 dBaseIV multi-user environment use
270 Read(&h.ProductionIdx, sizeof(char), 1); // 28 Production index exists - 0x01 else 0x00
271 Read(&h.LanguageDrvID, sizeof(char), 1); // 29 dBaseIV language driver ID
272 Read(buffer , sizeof(char), 2); // 30-31 Reserved fill with - 0x00
273
274 //-----------------------------------------------------
275 // Bytes 32-n: Field Descriptor Array...
276 while( ftell(m_hFile) < (long)m_nHeaderBytes - 1 && !feof(m_hFile) )
277 {
278 m_Fields = (TDBF_Field *)SG_Realloc(m_Fields, (m_nFields + 1) * sizeof(TDBF_Field));
279
280 Read( m_Fields[m_nFields].Name , sizeof(char), 11); // 0-10 Field Name ASCII padded with 0x00
281 Read(&m_Fields[m_nFields].Type , sizeof(char), 1); // 11 Field Type Identifier (see table)
282 Read(&m_Fields[m_nFields].Displacement , sizeof(char), 4); // 12-15 Displacement of field in record
283 Read(&m_Fields[m_nFields].Width , sizeof(char), 1); // 16 Field length in bytes
284 Read(&m_Fields[m_nFields].Decimals , sizeof(char), 1); // 17 Field decimal places
285 Read(buffer , sizeof(char), 2); // 18-19 Reserved
286 Read(&m_Fields[m_nFields].WorkAreaID , sizeof(char), 1); // 20 dBaseIV work area ID
287 Read(buffer , sizeof(char), 10); // 21-30 Reserved
288 Read(&m_Fields[m_nFields].ProductionIdx, sizeof(char), 1); // 31 Field is part of production index - 0x01 else 0x00
289
290 m_Fields[m_nFields].Name[11] = '\0';
291
292 m_nFields++;
293 }
294
295 //-----------------------------------------------------
296 // Byte n+1: Header m_Record Terminator (0x0D)...
297 Read(buffer, sizeof(char), 1);
298
299 if( buffer[0] == 0x0d )
300 {
301 Init_Record();
302 Move_First();
303
304 return( true );
305 }
306
307 Close();
308
309 return( false );
310}
311
312
314// //
316
317//---------------------------------------------------------
318bool CSG_Table_DBase::Open_Write(const SG_Char *FileName, CSG_Table *pTable, bool bRecords_Save)
319{
320 Close();
321
322 if( pTable == NULL || pTable->Get_Field_Count() <= 0 )
323 {
324 SG_UI_Msg_Add_Error(_TL("dbf write: invalid table"));
325
326 return( false );
327 }
328
329 if( (m_hFile = fopen(CSG_String(FileName), "w+b")) == NULL )
330 {
331 SG_UI_Msg_Add_Error(_TL("dbf write: could open file"));
332
333 return( false );
334 }
335
336 m_bReadOnly = false;
337
338 //-----------------------------------------------------
339 m_nFields = pTable->Get_Field_Count();
340 m_Fields = (TDBF_Field *)SG_Calloc(m_nFields, sizeof(TDBF_Field)); // init all bytes with 0x00
341
342 for(int iField=0; iField<Get_Field_Count(); iField++)
343 {
344 CSG_String Name(pTable->Get_Field_Name(iField)); int nBytes;
345
346 for(int j=0; j<11 && j<(int)Name.Length(); j++)
347 {
348 m_Fields[iField].Name[j] = Name.b_str()[j];
349 }
350
351 switch( pTable->Get_Field_Type(iField) )
352 {
353 case SG_DATATYPE_String: default:
354 m_Fields[iField].Type = DBF_FT_CHARACTER;
355 m_Fields[iField].Width = (BYTE)((nBytes = pTable->Get_Field_Length(iField, m_Encoding)) > 255 ? 255 : nBytes < 1 ? 1 : nBytes);
356 break;
357
358 case SG_DATATYPE_Date :
359 m_Fields[iField].Type = DBF_FT_DATE;
360 m_Fields[iField].Width = (BYTE)8;
361 break;
362
363 case SG_DATATYPE_Char :
364 m_Fields[iField].Type = DBF_FT_CHARACTER;
365 m_Fields[iField].Width = (BYTE)1;
366 break;
367
368 case SG_DATATYPE_Bit :
369 m_Fields[iField].Type = DBF_FT_NUMERIC;
370 m_Fields[iField].Width = (BYTE)1;
371 break;
372
373 case SG_DATATYPE_Byte :
374 m_Fields[iField].Type = DBF_FT_NUMERIC;
375 m_Fields[iField].Width = (BYTE)3;
376 break;
377
378 case SG_DATATYPE_Word :
379 case SG_DATATYPE_Short :
380 m_Fields[iField].Type = DBF_FT_NUMERIC;
381 m_Fields[iField].Width = (BYTE)6;
382 break;
383
384 case SG_DATATYPE_DWord :
385 case SG_DATATYPE_Int :
386 case SG_DATATYPE_ULong :
387 case SG_DATATYPE_Long :
388 case SG_DATATYPE_Color :
389 m_Fields[iField].Type = DBF_FT_NUMERIC;
390 m_Fields[iField].Width = (BYTE)16;
391 break;
392
394 m_Fields[iField].Type = DBF_FT_NUMERIC;
395 m_Fields[iField].Width = (BYTE)16;
396 m_Fields[iField].Decimals = (BYTE)8;
397 break;
398
400 m_Fields[iField].Type = DBF_FT_FLOAT;
401 m_Fields[iField].Width = (BYTE)19;
402 m_Fields[iField].Decimals = (BYTE)10;
403 break;
404 }
405 }
406
407 Header_Write();
408
409 m_nFileBytes = m_nHeaderBytes;
410
411 //-----------------------------------------------------
412 if( bRecords_Save )
413 {
414 for(sLong iRecord=0; iRecord<pTable->Get_Count() && SG_UI_Process_Set_Progress(iRecord, pTable->Get_Count()); iRecord++)
415 {
416 CSG_Table_Record *pRecord = pTable->Get_Record(iRecord);
417
418 Add_Record();
419
420 for(int iField=0; iField<Get_Field_Count(); iField++)
421 {
422 if( pRecord->is_NoData(iField) )
423 {
424 Set_NoData(iField);
425 }
426 else switch( Get_Field_Type(iField) )
427 {
428 default:
429 Set_Value(iField, pRecord->asString(iField));
430 break;
431
432 case DBF_FT_FLOAT:
433 case DBF_FT_NUMERIC:
434 Set_Value(iField, pRecord->asDouble(iField));
435 break;
436 }
437 }
438
439 Flush_Record();
440 }
441
443 }
444
445 return( true );
446}
447
448//---------------------------------------------------------
449void CSG_Table_DBase::Header_Write(void)
450{
451 if( !m_hFile || m_bReadOnly )
452 {
453 return;
454 }
455
456 //-----------------------------------------------------
457 char buffer[16]; TDBF_Header h;
458
459 time_t ltime; time(&ltime); struct tm *pTime = localtime(&ltime);
460
461 h.FileType = 0x03;
462 h.Transaction = 0;
463 h.bEncrypted = 0;
464 h.LanguageDrvID = 0;
465 h.ProductionIdx = 0;
466 h.LastUpdate[0] = (unsigned char)pTime->tm_year;
467 h.LastUpdate[1] = (unsigned char)pTime->tm_mon + 1;
468 h.LastUpdate[2] = (unsigned char)pTime->tm_mday;
469
470 m_nHeaderBytes = (m_nFields + 1) * 32 + 1;
471 m_nRecordBytes = 1; // Delete-Flag = Byte 0...
472
473 for(int iField=0; iField<m_nFields; iField++)
474 {
475 if( m_Fields[iField].Type == DBF_FT_CHARACTER )
476 {
477 if( m_Fields[iField].Width < 1 )
478 {
479 m_Fields[iField].Width = 1;
480 }
481 else if( m_Fields[iField].Width > 255 )
482 {
483 m_Fields[iField].Width = 255;
484 }
485 }
486
487 m_nRecordBytes += m_Fields[iField].Width;
488 }
489
490 Init_Record();
491
492 fseek(m_hFile, 0, SEEK_SET);
493
494 memset(buffer, 0, 16 * sizeof(char));
495
496 //-----------------------------------------------------
497 // Bytes 0-31: File Header...
498 Write(&h.FileType , sizeof(char), 1); // 00 FoxBase+, FoxPro, dBaseIII+, dBaseIV, no memo - 0x03
499 // FoxBase+, dBaseIII+ with memo - 0x83
500 // FoxPro with memo - 0xF5
501 // dBaseIV with memo - 0x8B
502 // dBaseIV with SQL Table - 0x8E
503 Write(&h.LastUpdate , sizeof(char), 3); // 01-03 Last update, format YYYYMMDD **correction: it is YYMMDD**
504 Write(&m_nRecords , sizeof(char), 4); // 04-07 Number of records in file (32-bit number)
505 Write(&m_nHeaderBytes , sizeof(char), 2); // 08-09 Number of bytes in header (16-bit number)
506 Write(&m_nRecordBytes , sizeof(char), 2); // 10-11 Number of bytes in record (16-bit number)
507 Write(buffer , sizeof(char), 2); // 12-13 Reserved, fill with 0x00
508 Write(&h.Transaction , sizeof(char), 1); // 14 dBaseIV flag, incomplete transaction
509 // Begin Transaction sets it to - 0x01
510 // End Transaction or RollBack reset it to - 0x00
511 Write(&h.bEncrypted , sizeof(char), 1); // 15 Encryption flag, encrypted 0x01 else 0x00
512 // Changing the flag does not encrypt or decrypt the records
513 Write(buffer , sizeof(char), 12); // 16-27 dBaseIV multi-user environment use
514 Write(&h.ProductionIdx, sizeof(char), 1); // 28 Production index exists 0x01 else 0x00
515 Write(&h.LanguageDrvID, sizeof(char), 1); // 29 dBaseIV language driver ID
516 Write(buffer , sizeof(char), 2); // 30-31 Reserved fill with 0x00
517
518 //-----------------------------------------------------
519 // Bytes 32-n: Field Descriptor Array...
520 for(int iField=0; iField<m_nFields; iField++)
521 {
522 Write( m_Fields[iField].Name , sizeof(char), 11); // 00-10 Field Name ASCII padded with 0x00
523 Write(&m_Fields[iField].Type , sizeof(char), 1); // 11 Field Type Identifier (see table)
524 Write(&m_Fields[iField].Displacement , sizeof(char), 4); // 12-15 Displacement of field in record
525 Write(&m_Fields[iField].Width , sizeof(char), 1); // 16 Field length in bytes
526 Write(&m_Fields[iField].Decimals , sizeof(char), 1); // 17 Field decimal places
527 Write(buffer , sizeof(char), 2); // 18-19 Reserved
528 Write(&m_Fields[iField].WorkAreaID , sizeof(char), 1); // 20 dBaseIV work area ID
529 Write(buffer , sizeof(char), 10); // 21-30 Reserved
530 Write(&m_Fields[iField].ProductionIdx, sizeof(char), 1); // 31 Field is part of production index - 0x01 else 0x00
531 }
532
533 //-----------------------------------------------------
534 // Byte n+1: Header m_Record Terminator (0x0D)...
535 buffer[0] = 0x0D;
536 Write(buffer, sizeof(char), 1);
537}
538
539
541// //
543
544//---------------------------------------------------------
545void CSG_Table_DBase::Init_Record(void)
546{
547 m_Record = (char *)SG_Realloc(m_Record, m_nRecordBytes * sizeof(char));
548 m_Record[0] = ' '; // Data records are preceded by one byte, that is, a space (0x20) if the record is not deleted, an asterisk (0x2A) if the record is deleted.
549
550 for(int iField=0, iPos=1; iField<m_nFields; iPos+=m_Fields[iField++].Width)
551 {
552 m_Fields[iField].Offset = iPos;
553 }
554}
555
556//---------------------------------------------------------
558{
559 return( m_hFile ? ftell(m_hFile) : 0 );
560}
561
562
564// //
566
567//---------------------------------------------------------
569{
570 bool Result = false;
571
572 if( m_hFile )
573 {
574 Flush_Record();
575
576 fseek(m_hFile, m_nHeaderBytes, SEEK_SET);
577
578 if( Read(m_Record, sizeof(char), (size_t)m_nRecordBytes) )
579 {
580 Result = true;
581 }
582
583 fseek(m_hFile, m_nHeaderBytes, SEEK_SET);
584 }
585
586 return( Result );
587}
588
589//---------------------------------------------------------
591{
592 bool Result = false;
593
594 if( m_hFile )
595 {
596 Flush_Record();
597
598 fseek(m_hFile, m_nRecordBytes, SEEK_CUR);
599
600 if( Read(m_Record, sizeof(char), (size_t)m_nRecordBytes) )
601 {
602 Result = true;
603 }
604
605 fseek(m_hFile, -m_nRecordBytes, SEEK_CUR);
606 }
607
608 return( Result );
609}
610
611
613// //
615
616//---------------------------------------------------------
618{
619 if( m_hFile )
620 {
621 m_bModified = true;
622
623 memset(m_Record, ' ', m_nRecordBytes);
624
625 fseek(m_hFile, 0, SEEK_END);
626 Write(m_Record, m_nRecordBytes, sizeof(char));
627 fseek(m_hFile, -m_nRecordBytes, SEEK_END);
628
629 m_nRecords ++;
630 m_nFileBytes += m_nRecordBytes;
631 }
632}
633
634//---------------------------------------------------------
636{
637 if( m_hFile && !m_bReadOnly && m_bModified )
638 {
639 m_bModified = false;
640 Write(m_Record, m_nRecordBytes, sizeof(char));
641 fseek(m_hFile, -m_nRecordBytes, SEEK_CUR);
642 }
643}
644
645
647// //
649
650//---------------------------------------------------------
652{
653 return( m_hFile && *m_Record == '*' );
654}
655
656//---------------------------------------------------------
657bool CSG_Table_DBase::asInt(int iField, int &Value)
658{
659 double d;
660
661 if( asDouble(iField, d) )
662 {
663 Value = (int)d;
664
665 return( true );
666 }
667
668 return( false );
669}
670
671//---------------------------------------------------------
672bool CSG_Table_DBase::asDouble(int iField, double &Value)
673{
674 if( !m_hFile || iField < 0 || iField >= m_nFields )
675 {
676 return( false );
677 }
678
679 //-----------------------------------------------------
680 CSG_String s;
681
682 char *c = m_Record + m_Fields[iField].Offset;
683
684 for(int i=0; i<m_Fields[iField].Width && *c; i++, c++)
685 {
686 s += *c;
687 }
688
689 //-----------------------------------------------------
690 if( m_Fields[iField].Type == DBF_FT_FLOAT
691 || m_Fields[iField].Type == DBF_FT_NUMERIC )
692 {
693 s.Replace(",", ".");
694
695 return( s.asDouble(Value) );
696 }
697
698 //-----------------------------------------------------
699 if( m_Fields[iField].Type == DBF_FT_DATE )
700 {
701 if( s.Length() < 8 )
702 {
703 return( false );
704 }
705
706 int d = s.Mid(6, 2).asInt(); if( d < 1 ) d = 1; else if( d > 31 ) d = 31;
707 int m = s.Mid(4, 2).asInt(); if( m < 1 ) m = 1; else if( m > 12 ) m = 12;
708 int y = s.Mid(0, 4).asInt();
709
710 Value = 10000 * y + 100 * m + d;
711 }
712
713 //-----------------------------------------------------
714 return( true );
715}
716
717//---------------------------------------------------------
719{
720 CSG_String Value;
721
722 if( !m_hFile || iField < 0 || iField >= m_nFields )
723 {
724 return( Value );
725 }
726
727 //-----------------------------------------------------
728 if( m_Fields[iField].Type != DBF_FT_DATE )
729 {
730 switch( m_Encoding )
731 {
732 case SG_FILE_ENCODING_ANSI: default:
733 { char *s = m_Record + m_Fields[iField].Offset;
734
735 for(int i=0; i<m_Fields[iField].Width && *s; i++, s++)
736 {
737 Value += *s > 0 ? *s : '?';
738 }
739 } break;
740
742 Value = CSG_String::from_UTF8(m_Record + m_Fields[iField].Offset, m_Fields[iField].Width);
743 break;
744 }
745
746 Value.Trim(true);
747 }
748
749 //-----------------------------------------------------
750 if( m_Fields[iField].Type == DBF_FT_DATE ) // SAGA(DD.MM.YYYY) from DBASE(YYYYMMDD)
751 {
752 char *s = m_Record + m_Fields[iField].Offset;
753
754 Value += s[0]; // Y1
755 Value += s[1]; // Y2
756 Value += s[2]; // Y3
757 Value += s[3]; // Y4
758 Value += '-';
759 Value += s[4]; // M1
760 Value += s[5]; // M2
761 Value += '-';
762 Value += s[6]; // D1
763 Value += s[7]; // D2
764 }
765
766 //-----------------------------------------------------
767 return( Value );
768}
769
770
772// //
774
775//---------------------------------------------------------
776bool CSG_Table_DBase::Set_Value(int iField, double Value)
777{
778 if( !m_hFile || iField < 0 || iField >= m_nFields || m_Fields[iField].Width < 1 )
779 {
780 return( false );
781 }
782
783 //-----------------------------------------------------
784 if( m_Fields[iField].Type == DBF_FT_DATE )
785 { // Value is expected to be Julian Day Number
786 CSG_DateTime d(Value);
787
788 return( Set_Value(iField, CSG_String::Format("%04d-%02d-%02d",
789 d.Get_Year (),
790 1 + (int)d.Get_Month(),
791 1 + d.Get_Day ()
792 )));
793 }
794
795 //-----------------------------------------------------
796 if( m_Fields[iField].Type == DBF_FT_FLOAT )
797 { // Number stored as a string, right justified, and padded with blanks to the width of the field.
798 char s[256];
799
800 sprintf(s, "%*.*e", m_Fields[iField].Width, m_Fields[iField].Decimals, Value);
801
802 size_t n = strlen(s); if( n > m_Fields[iField].Width ) { n = m_Fields[iField].Width; }
803
804 memset(m_Record + m_Fields[iField].Offset, ' ', m_Fields[iField].Width);
805 memcpy(m_Record + m_Fields[iField].Offset, s , M_GET_MIN(strlen(s), m_Fields[iField].Width));
806
807 m_bModified = true;
808
809 return( true );
810 }
811
812 //-----------------------------------------------------
813 if( m_Fields[iField].Type == DBF_FT_NUMERIC )
814 { // Number stored as a string, right justified, and padded with blanks to the width of the field.
815 char s[256];
816
817 if( m_Fields[iField].Decimals > 0 )
818 {
819 sprintf(s, "%*.*f", m_Fields[iField].Width, m_Fields[iField].Decimals, Value);
820 }
821 else
822 {
823 sprintf(s, "%*d" , m_Fields[iField].Width, (int)Value);
824 }
825
826 memset(m_Record + m_Fields[iField].Offset, ' ', m_Fields[iField].Width);
827 memcpy(m_Record + m_Fields[iField].Offset, s , M_GET_MIN(strlen(s), m_Fields[iField].Width));
828
829 m_bModified = true;
830
831 return( true );
832 }
833
834 //-----------------------------------------------------
835 return( false );
836}
837
838//---------------------------------------------------------
839bool CSG_Table_DBase::Set_Value(int iField, const CSG_String &Value)
840{
841 if( !m_hFile || iField < 0 || iField >= m_nFields || m_Fields[iField].Width < 1 )
842 {
843 return( false );
844 }
845
846 //-----------------------------------------------------
847 if( m_Fields[iField].Type == DBF_FT_CHARACTER )
848 { // All OEM code page characters - padded with blanks to the width of the field.
849 if( Value.Length() < 1 )
850 {
851 memset(m_Record + m_Fields[iField].Offset, ' ', m_Fields[iField].Width);
852
853 m_bModified = true;
854
855 return( true );
856 }
857
858 CSG_Buffer s;
859
860 switch( m_Encoding )
861 {
862 case SG_FILE_ENCODING_ANSI: default:
863 s = Value.to_ASCII();
864 break;
865
867 s = Value.to_UTF8 ();
868 break;
869 }
870
871 if( s.Get_Size() >= Value.Length() )
872 {
873 memset(m_Record + m_Fields[iField].Offset, ' ', m_Fields[iField].Width);
874 memcpy(m_Record + m_Fields[iField].Offset, s.Get_Data(), M_GET_MIN(s.Get_Size(), m_Fields[iField].Width));
875
876 m_bModified = true;
877
878 return( true );
879 }
880 }
881
882 //-----------------------------------------------------
883 if( m_Fields[iField].Type == DBF_FT_DATE ) // SAGA(YYYY-MM-DD) to DBASE(YYYYMMDD)
884 { // 8 bytes - date stored as a string in the format YYYYMMDD
885 if( Value.Length() >= 10 )
886 {
887 char *s = m_Record + m_Fields[iField].Offset;
888
889 s[0] = Value.b_str()[0]; // Y1
890 s[1] = Value.b_str()[1]; // Y2
891 s[2] = Value.b_str()[2]; // Y3
892 s[3] = Value.b_str()[3]; // Y4
893 s[4] = Value.b_str()[5]; // M1
894 s[5] = Value.b_str()[6]; // M2
895 s[6] = Value.b_str()[8]; // D1
896 s[7] = Value.b_str()[9]; // D2
897
898 m_bModified = true;
899
900 return( true );
901 }
902 }
903
904 //-----------------------------------------------------
905 return( false );
906}
907
908//---------------------------------------------------------
910{
911 if( !m_hFile || iField < 0 || iField >= m_nFields || m_Fields[iField].Width < 1 )
912 {
913 return( false );
914 }
915
916 //-----------------------------------------------------
917 memset(m_Record + m_Fields[iField].Offset, ' ', m_Fields[iField].Width);
918
919 m_bModified = true;
920
921 return( true );
922}
923
924
926// //
927// //
928// //
930
931//---------------------------------------------------------
void SG_UI_Msg_Add_Error(const char *Message)
bool SG_UI_Process_Set_Ready(void)
bool SG_UI_Process_Set_Progress(int Position, int Range)
signed long long sLong
Definition api_core.h:158
SAGA_API_DLL_EXPORT void * SG_Realloc(void *memblock, size_t size)
SAGA_API_DLL_EXPORT void * SG_Calloc(size_t num, size_t size)
#define SG_FREE_SAFE(PTR)
Definition api_core.h:205
@ SG_DATATYPE_Long
Definition api_core.h:1006
@ SG_DATATYPE_Byte
Definition api_core.h:999
@ SG_DATATYPE_Bit
Definition api_core.h:998
@ SG_DATATYPE_Short
Definition api_core.h:1002
@ SG_DATATYPE_Word
Definition api_core.h:1001
@ SG_DATATYPE_ULong
Definition api_core.h:1005
@ SG_DATATYPE_Float
Definition api_core.h:1007
@ SG_DATATYPE_Double
Definition api_core.h:1008
@ SG_DATATYPE_Color
Definition api_core.h:1011
@ SG_DATATYPE_Int
Definition api_core.h:1004
@ SG_DATATYPE_Char
Definition api_core.h:1000
@ SG_DATATYPE_String
Definition api_core.h:1009
@ SG_DATATYPE_DWord
Definition api_core.h:1003
@ SG_DATATYPE_Date
Definition api_core.h:1010
#define SG_Char
Definition api_core.h:536
#define _TL(s)
Definition api_core.h:1568
@ SG_FILE_ENCODING_UTF8
Definition api_core.h:552
@ SG_FILE_ENCODING_ANSI
Definition api_core.h:550
size_t Get_Size(void) const
Definition api_core.h:241
char * Get_Data(int Offset=0) const
Definition api_core.h:244
Month Get_Month(void) const
Definition datetime.cpp:379
int Get_Year(void) const
Definition datetime.cpp:384
unsigned short Get_Day(void) const
Definition datetime.cpp:377
size_t Length(void) const
const char * b_str(void) const
size_t to_UTF8(char **pString) const
size_t Replace(const CSG_String &Old, const CSG_String &New, bool bReplaceAll=true)
static CSG_String Format(const char *Format,...)
int Trim(bool fromRight=false)
int asInt(void) const
bool to_ASCII(char **pString, char Replace='_') const
CSG_String Mid(size_t first, size_t count=0) const
static CSG_String from_UTF8(const char *String, size_t Length=0)
double asDouble(void) const
virtual ~CSG_Table_DBase(void)
bool asInt(int iField, int &Value)
void Close(void)
int Get_Count(void)
int Get_File_Position(void)
bool Move_First(void)
bool asDouble(int iField, double &Value)
void Flush_Record(void)
const char * Get_Field_Name(int iField)
bool Set_Value(int iField, double Value)
int Get_Field_Count(void)
bool isDeleted(void)
bool Open_Write(const SG_Char *FileName, class CSG_Table *pTable, bool bRecords_Save=true)
void Add_Record(void)
int Get_Field_Decimals(int iField)
char Get_Field_Type(int iField)
CSG_String asString(int iField)
CSG_Table_DBase(int Encoding=SG_FILE_ENCODING_ANSI)
bool Set_NoData(int iField)
bool Move_Next(void)
bool Open_Read(const SG_Char *FileName, class CSG_Table *pTable, bool bRecords_Load=true)
bool Set_Value(int Field, const CSG_String &Value)
bool is_NoData(int Field) const
bool Set_NoData(int Field)
double asDouble(int Field) const
const SG_Char * asString(int Field, int Decimals=-99) const
const SG_Char * Get_Field_Name(int Field) const
Definition table.h:362
sLong Get_Count(void) const
Definition table.h:400
virtual bool Destroy(void)
Definition table.cpp:314
virtual CSG_Table_Record * Add_Record(CSG_Table_Record *pCopy=NULL)
Definition table.cpp:823
virtual CSG_Table_Record * Get_Record(sLong Index) const
Definition table.h:402
virtual int Get_Field_Length(int Field, int Encoding=SG_FILE_ENCODING_UNDEFINED) const
Definition table.cpp:674
int Get_Field_Count(void) const
Definition table.h:361
virtual bool Add_Field(const CSG_String &Name, TSG_Data_Type Type, int Position=-1)
Definition table.cpp:479
TSG_Data_Type Get_Field_Type(int Field) const
Definition table.h:363
#define M_GET_MIN(a, b)
Definition mat_tools.h:141
#define DBF_FT_NUMERIC
Definition table_dbase.h:78
#define DBF_FT_DATE
Definition table_dbase.h:76
#define DBF_FT_FLOAT
Definition table_dbase.h:77
#define DBF_FT_CHARACTER
Definition table_dbase.h:75
#define DBF_FT_LOGICAL
Definition table_dbase.h:79