1 | /************* TabFix C++ Program Source Code File (.CPP) **************/ |
2 | /* PROGRAM NAME: TABFIX */ |
3 | /* ------------- */ |
4 | /* Version 4.9.2 */ |
5 | /* */ |
6 | /* COPYRIGHT: */ |
7 | /* ---------- */ |
8 | /* (C) Copyright to the author Olivier BERTRAND 1998-2017 */ |
9 | /* */ |
10 | /* WHAT THIS PROGRAM DOES: */ |
11 | /* ----------------------- */ |
12 | /* This program are the TDBFIX class DB routines. */ |
13 | /* */ |
14 | /***********************************************************************/ |
15 | |
16 | /***********************************************************************/ |
17 | /* Include relevant section of system dependant header files. */ |
18 | /***********************************************************************/ |
19 | #include "my_global.h" |
20 | #if defined(__WIN__) |
21 | #include <io.h> |
22 | #include <fcntl.h> |
23 | #include <errno.h> |
24 | #if defined(__BORLANDC__) |
25 | #define __MFC_COMPAT__ // To define min/max as macro |
26 | #endif // __BORLANDC__ |
27 | //#include <windows.h> |
28 | #else // !__WIN__ |
29 | #if defined(UNIX) |
30 | #include <sys/types.h> |
31 | #include <sys/stat.h> |
32 | #include <unistd.h> |
33 | #include <errno.h> |
34 | #else // !UNIX |
35 | #include <io.h> |
36 | #endif // !UNIX |
37 | #include <fcntl.h> |
38 | #endif // !__WIN__ |
39 | |
40 | /***********************************************************************/ |
41 | /* Include application header files: */ |
42 | /***********************************************************************/ |
43 | #include "global.h" // global declares |
44 | #include "plgdbsem.h" // DB application declares |
45 | #include "filamfix.h" |
46 | #include "filamdbf.h" |
47 | #include "tabfix.h" // TDBFIX, FIXCOL classes declares |
48 | #include "array.h" |
49 | #include "blkfil.h" |
50 | |
51 | /***********************************************************************/ |
52 | /* DB static variables. */ |
53 | /***********************************************************************/ |
54 | extern int num_read, num_there, num_eq[2]; // Statistics |
55 | static const longlong M2G = 0x80000000; |
56 | static const longlong M4G = (longlong)2 * M2G; |
57 | char BINCOL::Endian = 'H'; |
58 | |
59 | /***********************************************************************/ |
60 | /* External function. */ |
61 | /***********************************************************************/ |
62 | USETEMP UseTemp(void); |
63 | |
64 | /* ------------------------------------------------------------------- */ |
65 | |
66 | /***********************************************************************/ |
67 | /* Implementation of the TDBFIX class. */ |
68 | /***********************************************************************/ |
69 | TDBFIX::TDBFIX(PDOSDEF tdp, PTXF txfp) : TDBDOS(tdp, txfp) |
70 | { |
71 | Teds = tdp->Teds; // For BIN tables |
72 | } // end of TDBFIX standard constructor |
73 | |
74 | TDBFIX::TDBFIX(PGLOBAL g, PTDBFIX tdbp) : TDBDOS(g, tdbp) |
75 | { |
76 | Teds = tdbp->Teds; |
77 | } // end of TDBFIX copy constructor |
78 | |
79 | // Method |
80 | PTDB TDBFIX::Clone(PTABS t) |
81 | { |
82 | PTDB tp; |
83 | PGLOBAL g = t->G; |
84 | |
85 | tp = new(g) TDBFIX(g, this); |
86 | |
87 | if (Ftype < 2) { |
88 | // File is text |
89 | PDOSCOL cp1, cp2; |
90 | |
91 | for (cp1 = (PDOSCOL)Columns; cp1; cp1 = (PDOSCOL)cp1->GetNext()) { |
92 | cp2 = new(g) DOSCOL(cp1, tp); // Make a copy |
93 | NewPointer(t, cp1, cp2); |
94 | } // endfor cp1 |
95 | |
96 | } else { |
97 | // File is binary |
98 | PBINCOL cp1, cp2; |
99 | |
100 | for (cp1 = (PBINCOL)Columns; cp1; cp1 = (PBINCOL)cp1->GetNext()) { |
101 | cp2 = new(g) BINCOL(cp1, tp); // Make a copy |
102 | NewPointer(t, cp1, cp2); |
103 | } // endfor cp1 |
104 | |
105 | } // endif Ftype |
106 | |
107 | return tp; |
108 | } // end of Clone |
109 | |
110 | /***********************************************************************/ |
111 | /* Reset read/write position values. */ |
112 | /***********************************************************************/ |
113 | void TDBFIX::ResetDB(void) |
114 | { |
115 | TDBDOS::ResetDB(); |
116 | } // end of ResetDB |
117 | |
118 | /***********************************************************************/ |
119 | /* Allocate FIX (DOS) or BIN column description block. */ |
120 | /***********************************************************************/ |
121 | PCOL TDBFIX::MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n) |
122 | { |
123 | if (Ftype == RECFM_BIN) |
124 | return new(g) BINCOL(g, cdp, this, cprec, n); |
125 | else |
126 | return new(g) DOSCOL(g, cdp, this, cprec, n); |
127 | |
128 | } // end of MakeCol |
129 | |
130 | /***********************************************************************/ |
131 | /* Remake the indexes after the table was modified. */ |
132 | /***********************************************************************/ |
133 | int TDBFIX::ResetTableOpt(PGLOBAL g, bool dop, bool dox) |
134 | { |
135 | int prc, rc = RC_OK; |
136 | |
137 | To_Filter = NULL; // Disable filtering |
138 | //To_BlkIdx = NULL; // and block filtering |
139 | To_BlkFil = NULL; // and index filtering |
140 | Cardinality(g); // If called by create |
141 | RestoreNrec(); // May have been modified |
142 | MaxSize = -1; // Size must be recalculated |
143 | Cardinal = -1; // as well as Cardinality |
144 | |
145 | // After the table was modified the indexes |
146 | // are invalid and we should mark them as such... |
147 | rc = ((PDOSDEF)To_Def)->InvalidateIndex(g); |
148 | |
149 | if (dop) { |
150 | Columns = NULL; // Not used anymore |
151 | Txfp->Reset(); |
152 | // OldBlk = CurBlk = -1; |
153 | // ReadBlks = CurNum = Rbuf = Modif = 0; |
154 | Use = USE_READY; // So the table can be reopened |
155 | Mode = MODE_ANY; // Just to be clean |
156 | rc = MakeBlockValues(g); // Redo optimization |
157 | } // endif dop |
158 | |
159 | if (dox && (rc == RC_OK || rc == RC_INFO)) { |
160 | // Remake eventual indexes |
161 | Columns = NULL; // Not used anymore |
162 | Txfp->Reset(); // New start |
163 | Use = USE_READY; // So the table can be reopened |
164 | Mode = MODE_READ; // New mode |
165 | prc = rc; |
166 | |
167 | if (PlgGetUser(g)->Check & CHK_OPT) |
168 | // We must remake indexes. |
169 | rc = MakeIndex(g, NULL, FALSE); |
170 | |
171 | rc = (rc == RC_INFO) ? prc : rc; |
172 | } // endif dox |
173 | |
174 | return rc; |
175 | } // end of ResetTableOpt |
176 | |
177 | /***********************************************************************/ |
178 | /* Reset the Nrec and BlkSize values that can have been modified. */ |
179 | /***********************************************************************/ |
180 | void TDBFIX::RestoreNrec(void) |
181 | { |
182 | if (!Txfp->Padded) { |
183 | Txfp->Nrec = (To_Def && To_Def->GetElemt()) ? To_Def->GetElemt() |
184 | : DOS_BUFF_LEN; |
185 | Txfp->Blksize = Txfp->Nrec * Txfp->Lrecl; |
186 | |
187 | if (Cardinal >= 0) |
188 | Txfp->Block = (Cardinal > 0) |
189 | ? (Cardinal + Txfp->Nrec - 1) / Txfp->Nrec : 0; |
190 | |
191 | } // endif Padded |
192 | |
193 | } // end of RestoreNrec |
194 | |
195 | /***********************************************************************/ |
196 | /* FIX Cardinality: returns table cardinality in number of rows. */ |
197 | /* This function can be called with a null argument to test the */ |
198 | /* availability of Cardinality implementation (1 yes, 0 no). */ |
199 | /***********************************************************************/ |
200 | int TDBFIX::Cardinality(PGLOBAL g) |
201 | { |
202 | if (!g) |
203 | return Txfp->Cardinality(g); |
204 | |
205 | if (Cardinal < 0) |
206 | Cardinal = Txfp->Cardinality(g); |
207 | |
208 | return Cardinal; |
209 | } // end of Cardinality |
210 | |
211 | /***********************************************************************/ |
212 | /* FIX GetMaxSize: returns file size in number of lines. */ |
213 | /***********************************************************************/ |
214 | int TDBFIX::GetMaxSize(PGLOBAL g) |
215 | { |
216 | if (MaxSize < 0) { |
217 | MaxSize = Cardinality(g); |
218 | |
219 | if (MaxSize > 0 && (To_BlkFil = InitBlockFilter(g, To_Filter)) |
220 | && !To_BlkFil->Correlated()) { |
221 | // Use BlockTest to reduce the estimated size |
222 | MaxSize = Txfp->MaxBlkSize(g, MaxSize); |
223 | ResetBlockFilter(g); |
224 | } // endif To_BlkFil |
225 | |
226 | } // endif MaxSize |
227 | |
228 | return MaxSize; |
229 | } // end of GetMaxSize |
230 | |
231 | /***********************************************************************/ |
232 | /* FIX ResetSize: Must reset Headlen for DBF tables only. */ |
233 | /***********************************************************************/ |
234 | void TDBFIX::ResetSize(void) |
235 | { |
236 | if (Txfp->GetAmType() == TYPE_AM_DBF) |
237 | Txfp->Headlen = 0; |
238 | |
239 | MaxSize = Cardinal = -1; |
240 | } // end of ResetSize |
241 | |
242 | /***********************************************************************/ |
243 | /* FIX GetProgMax: get the max value for progress information. */ |
244 | /***********************************************************************/ |
245 | int TDBFIX::GetProgMax(PGLOBAL g) |
246 | { |
247 | return Cardinality(g); |
248 | } // end of GetProgMax |
249 | |
250 | /***********************************************************************/ |
251 | /* RowNumber: return the ordinal number of the current row. */ |
252 | /***********************************************************************/ |
253 | int TDBFIX::RowNumber(PGLOBAL g, bool b) |
254 | { |
255 | if (Txfp->GetAmType() == TYPE_AM_DBF) { |
256 | if (!b && To_Kindex) { |
257 | /*****************************************************************/ |
258 | /* Don't know how to retrieve Rows from DBF file address */ |
259 | /* because of eventual deleted lines still in the file. */ |
260 | /*****************************************************************/ |
261 | sprintf(g->Message, MSG(NO_ROWID_FOR_AM), |
262 | GetAmName(g, Txfp->GetAmType())); |
263 | return 0; |
264 | } // endif To_Kindex |
265 | |
266 | if (!b) |
267 | return Txfp->GetRows(); |
268 | |
269 | } // endif DBF |
270 | |
271 | return Txfp->GetRowID(); |
272 | } // end of RowNumber |
273 | |
274 | /***********************************************************************/ |
275 | /* FIX tables don't use temporary files except if specified as do it. */ |
276 | /***********************************************************************/ |
277 | bool TDBFIX::IsUsingTemp(PGLOBAL) |
278 | { |
279 | // Not ready yet to handle using a temporary file with mapping |
280 | // or while deleting from DBF files. |
281 | return ((UseTemp() == TMP_YES && Txfp->GetAmType() != TYPE_AM_MAP && |
282 | !(Mode == MODE_DELETE && Txfp->GetAmType() == TYPE_AM_DBF)) || |
283 | UseTemp() == TMP_FORCE || UseTemp() == TMP_TEST); |
284 | } // end of IsUsingTemp |
285 | |
286 | /***********************************************************************/ |
287 | /* FIX Access Method opening routine (also used by the BIN a.m.) */ |
288 | /* New method now that this routine is called recursively (last table */ |
289 | /* first in reverse order): index blocks are immediately linked to */ |
290 | /* join block of next table if it exists or else are discarted. */ |
291 | /***********************************************************************/ |
292 | bool TDBFIX::OpenDB(PGLOBAL g) |
293 | { |
294 | if (trace(1)) |
295 | htrc("FIX OpenDB: tdbp=%p tdb=R%d use=%d key=%p mode=%d Ftype=%d\n" , |
296 | this, Tdb_No, Use, To_Key_Col, Mode, Ftype); |
297 | |
298 | if (Use == USE_OPEN) { |
299 | /*******************************************************************/ |
300 | /* Table already open, just replace it at its beginning. */ |
301 | /*******************************************************************/ |
302 | if (To_Kindex) |
303 | /*****************************************************************/ |
304 | /* Table is to be accessed through a sorted index table. */ |
305 | /*****************************************************************/ |
306 | To_Kindex->Reset(); |
307 | else |
308 | Txfp->Rewind(); // see comment in Work.log |
309 | |
310 | ResetBlockFilter(g); |
311 | return false; |
312 | } // endif use |
313 | |
314 | if (Mode == MODE_DELETE && Txfp->GetAmType() == TYPE_AM_MAP && |
315 | (!Next || UseTemp() == TMP_FORCE)) { |
316 | // Delete all lines or using temp. Not handled in MAP mode |
317 | Txfp = new(g) FIXFAM((PDOSDEF)To_Def); |
318 | Txfp->SetTdbp(this); |
319 | } // endif Mode |
320 | |
321 | /*********************************************************************/ |
322 | /* Call Cardinality to calculate Block in the case of Func queries. */ |
323 | /* and also in the case of multiple tables. */ |
324 | /*********************************************************************/ |
325 | if (Cardinality(g) < 0) |
326 | return true; |
327 | |
328 | /*********************************************************************/ |
329 | /* Open according to required logical input/output mode. */ |
330 | /* Use conventionnal input/output functions. */ |
331 | /* Treat fixed length text files as binary. */ |
332 | /*********************************************************************/ |
333 | if (Txfp->OpenTableFile(g)) |
334 | return true; |
335 | |
336 | Use = USE_OPEN; // Do it now in case we are recursively called |
337 | |
338 | /*********************************************************************/ |
339 | /* Initialize To_Line at the beginning of the block buffer. */ |
340 | /*********************************************************************/ |
341 | To_Line = Txfp->GetBuf(); // For WriteDB |
342 | |
343 | /*********************************************************************/ |
344 | /* Allocate the block filter tree if evaluation is possible. */ |
345 | /*********************************************************************/ |
346 | To_BlkFil = InitBlockFilter(g, To_Filter); |
347 | |
348 | if (trace(1)) |
349 | htrc("OpenFix: R%hd mode=%d BlkFil=%p\n" , Tdb_No, Mode, To_BlkFil); |
350 | |
351 | /*********************************************************************/ |
352 | /* Reset buffer access according to indexing and to mode. */ |
353 | /*********************************************************************/ |
354 | Txfp->ResetBuffer(g); |
355 | |
356 | /*********************************************************************/ |
357 | /* Reset statistics values. */ |
358 | /*********************************************************************/ |
359 | num_read = num_there = num_eq[0] = num_eq[1] = 0; |
360 | return false; |
361 | } // end of OpenDB |
362 | |
363 | /***********************************************************************/ |
364 | /* WriteDB: Data Base write routine for FIX access method. */ |
365 | /***********************************************************************/ |
366 | int TDBFIX::WriteDB(PGLOBAL g) |
367 | { |
368 | return Txfp->WriteBuffer(g); |
369 | } // end of WriteDB |
370 | |
371 | // ------------------------ BINCOL functions ---------------------------- |
372 | |
373 | /***********************************************************************/ |
374 | /* BINCOL public constructor. */ |
375 | /***********************************************************************/ |
376 | BINCOL::BINCOL(PGLOBAL g, PCOLDEF cdp, PTDB tp, PCOL cp, int i, PCSZ am) |
377 | : DOSCOL(g, cdp, tp, cp, i, am) |
378 | { |
379 | char c, *fmt = cdp->GetFmt(); |
380 | |
381 | Fmt = GetDomain() ? 'C' : 'X'; |
382 | Buff = NULL; |
383 | Eds = ((PTDBFIX)tp)->Teds; |
384 | N = 0; |
385 | M = GetTypeSize(Buf_Type, sizeof(longlong)); |
386 | Lim = 0; |
387 | |
388 | if (fmt) { |
389 | for (N = 0, i = 0; fmt[i]; i++) { |
390 | c = toupper(fmt[i]); |
391 | |
392 | if (isdigit(c)) |
393 | N = (N * 10 + (c - '0')); |
394 | else if (c == 'L' || c == 'B' || c == 'H') |
395 | Eds = c; |
396 | else |
397 | Fmt = c; |
398 | |
399 | } // endfor i |
400 | |
401 | // M is the size of the source value |
402 | switch (Fmt) { |
403 | case 'C': Eds = 0; break; |
404 | case 'X': break; |
405 | case 'S': M = sizeof(short); break; |
406 | case 'T': M = sizeof(char); break; |
407 | case 'I': M = sizeof(int); break; |
408 | case 'G': M = sizeof(longlong); break; |
409 | case 'R': // Real |
410 | case 'F': M = sizeof(float); break; |
411 | case 'D': M = sizeof(double); break; |
412 | default: |
413 | sprintf(g->Message, MSG(BAD_BIN_FMT), Fmt, Name); |
414 | throw 11; |
415 | } // endswitch Fmt |
416 | |
417 | } else if (IsTypeChar(Buf_Type)) |
418 | Eds = 0; |
419 | |
420 | if (Eds) { |
421 | // This is a byte order specification |
422 | if (!N) |
423 | N = M; |
424 | |
425 | if (Eds != 'L' && Eds != 'B') |
426 | Eds = Endian; |
427 | |
428 | if (N != M || Eds != Endian || IsTypeChar(Buf_Type)) { |
429 | Buff = (char*)PlugSubAlloc(g, NULL, M); |
430 | memset(Buff, 0, M); |
431 | Lim = MY_MIN(N, M); |
432 | } else |
433 | Eds = 0; // New format is a no op |
434 | |
435 | } // endif Eds |
436 | |
437 | } // end of BINCOL constructor |
438 | |
439 | /***********************************************************************/ |
440 | /* BINCOL constructor used for copying columns. */ |
441 | /* tdbp is the pointer to the new table descriptor. */ |
442 | /***********************************************************************/ |
443 | BINCOL::BINCOL(BINCOL *col1, PTDB tdbp) : DOSCOL(col1, tdbp) |
444 | { |
445 | Eds = col1->Eds; |
446 | Fmt = col1->Fmt; |
447 | N = col1->N; |
448 | M = col1->M; |
449 | Lim = col1->Lim; |
450 | } // end of BINCOL copy constructor |
451 | |
452 | /***********************************************************************/ |
453 | /* Set Endian according to the host setting. */ |
454 | /***********************************************************************/ |
455 | void BINCOL::SetEndian(void) |
456 | { |
457 | union { |
458 | short S; |
459 | char C[sizeof(short)]; |
460 | }; |
461 | |
462 | S = 1; |
463 | Endian = (C[0] == 1) ? 'L' : 'B'; |
464 | } // end of SetEndian |
465 | |
466 | /***********************************************************************/ |
467 | /* ReadColumn: what this routine does is to access the last line */ |
468 | /* read from the corresponding table and extract from it the field */ |
469 | /* corresponding to this column. */ |
470 | /***********************************************************************/ |
471 | void BINCOL::ReadColumn(PGLOBAL g) |
472 | { |
473 | char *p = NULL; |
474 | int rc; |
475 | PTDBFIX tdbp = (PTDBFIX)To_Tdb; |
476 | |
477 | if (trace(2)) |
478 | htrc("BIN ReadColumn: col %s R%d coluse=%.4X status=%.4X buf_type=%d\n" , |
479 | Name, tdbp->GetTdb_No(), ColUse, Status, Buf_Type); |
480 | |
481 | /*********************************************************************/ |
482 | /* If physical reading of the line was deferred, do it now. */ |
483 | /*********************************************************************/ |
484 | if (!tdbp->IsRead()) |
485 | if ((rc = tdbp->ReadBuffer(g)) != RC_OK) { |
486 | if (rc == RC_EF) |
487 | sprintf(g->Message, MSG(INV_DEF_READ), rc); |
488 | |
489 | throw 11; |
490 | } // endif |
491 | |
492 | p = tdbp->To_Line + Deplac; |
493 | |
494 | /*********************************************************************/ |
495 | /* Set Value from the line field. */ |
496 | /*********************************************************************/ |
497 | if (Eds) { |
498 | for (int i = 0; i < Lim; i++) |
499 | if (Eds == 'B' && Endian == 'L') |
500 | Buff[i] = p[N - i - 1]; |
501 | else if (Eds == 'L' && Endian == 'B') |
502 | Buff[M - i - 1] = p[i]; |
503 | else if (Endian == 'B') |
504 | Buff[M - i - 1] = p[N - i - 1]; |
505 | else |
506 | Buff[i] = p[i]; |
507 | |
508 | p = Buff; |
509 | } // endif Eds |
510 | |
511 | switch (Fmt) { |
512 | case 'X': // Standard not converted values |
513 | if (Eds && IsTypeChar(Buf_Type)) |
514 | Value->SetValueNonAligned<longlong>(p); |
515 | else |
516 | Value->SetBinValue(p); |
517 | |
518 | break; |
519 | case 'S': // Short integer |
520 | Value->SetValueNonAligned<short>(p); |
521 | break; |
522 | case 'T': // Tiny integer |
523 | Value->SetValue(*p); |
524 | break; |
525 | case 'I': // Integer |
526 | Value->SetValueNonAligned<int>(p); |
527 | break; |
528 | case 'G': // Large (great) integer |
529 | Value->SetValueNonAligned<longlong>(p); |
530 | break; |
531 | case 'F': // Float |
532 | case 'R': // Real |
533 | Value->SetValueNonAligned<float>(p); |
534 | break; |
535 | case 'D': // Double |
536 | Value->SetValueNonAligned<double>(p); |
537 | break; |
538 | case 'C': // Text |
539 | if (Value->SetValue_char(p, Long)) { |
540 | sprintf(g->Message, "Out of range value for column %s at row %d" , |
541 | Name, tdbp->RowNumber(g)); |
542 | PushWarning(g, tdbp); |
543 | } // endif SetValue_char |
544 | |
545 | break; |
546 | default: |
547 | sprintf(g->Message, MSG(BAD_BIN_FMT), Fmt, Name); |
548 | throw 11; |
549 | } // endswitch Fmt |
550 | |
551 | // Set null when applicable |
552 | if (Nullable) |
553 | Value->SetNull(Value->IsZero()); |
554 | |
555 | } // end of ReadColumn |
556 | |
557 | /***********************************************************************/ |
558 | /* WriteColumn: what this routine does is to access the last line */ |
559 | /* read from the corresponding table, and rewrite the field */ |
560 | /* corresponding to this column from the column buffer. */ |
561 | /***********************************************************************/ |
562 | void BINCOL::WriteColumn(PGLOBAL g) |
563 | { |
564 | char *p, *s; |
565 | longlong n; |
566 | PTDBFIX tdbp = (PTDBFIX)To_Tdb; |
567 | |
568 | if (trace(1)) { |
569 | htrc("BIN WriteColumn: col %s R%d coluse=%.4X status=%.4X" , |
570 | Name, tdbp->GetTdb_No(), ColUse, Status); |
571 | htrc(" Lrecl=%d\n" , tdbp->Lrecl); |
572 | htrc("Long=%d deplac=%d coltype=%d ftype=%c\n" , |
573 | Long, Deplac, Buf_Type, *Format.Type); |
574 | } // endif trace |
575 | |
576 | /*********************************************************************/ |
577 | /* Check whether the new value has to be converted to Buf_Type. */ |
578 | /*********************************************************************/ |
579 | if (Value != To_Val) |
580 | Value->SetValue_pval(To_Val, false); // Convert the updated value |
581 | |
582 | p = (Eds) ? Buff : tdbp->To_Line + Deplac; |
583 | |
584 | /*********************************************************************/ |
585 | /* Check whether updating is Ok, meaning col value is not too long. */ |
586 | /* Updating will be done only during the second pass (Status=true) */ |
587 | /* Conversion occurs if the external format Fmt is specified. */ |
588 | /*********************************************************************/ |
589 | switch (Fmt) { |
590 | case 'X': |
591 | // Standard not converted values |
592 | if (Eds && IsTypeChar(Buf_Type)) { |
593 | if (Status) |
594 | Value->GetValueNonAligned<longlong>(p, Value->GetBigintValue()); |
595 | } else if (Value->GetBinValue(p, Long, Status)) { |
596 | sprintf(g->Message, MSG(BIN_F_TOO_LONG), |
597 | Name, Value->GetSize(), Long); |
598 | throw 31; |
599 | } // endif p |
600 | |
601 | break; |
602 | case 'S': // Short integer |
603 | n = Value->GetBigintValue(); |
604 | |
605 | if (n > 32767LL || n < -32768LL) { |
606 | sprintf(g->Message, MSG(VALUE_TOO_BIG), n, Name); |
607 | throw 31; |
608 | } else if (Status) |
609 | Value->GetValueNonAligned<short>(p, (short)n); |
610 | |
611 | break; |
612 | case 'T': // Tiny integer |
613 | n = Value->GetBigintValue(); |
614 | |
615 | if (n > 255LL || n < -256LL) { |
616 | sprintf(g->Message, MSG(VALUE_TOO_BIG), n, Name); |
617 | throw 31; |
618 | } else if (Status) |
619 | *p = (char)n; |
620 | |
621 | break; |
622 | case 'I': // Integer |
623 | n = Value->GetBigintValue(); |
624 | |
625 | if (n > INT_MAX || n < INT_MIN) { |
626 | sprintf(g->Message, MSG(VALUE_TOO_BIG), n, Name); |
627 | throw 31; |
628 | } else if (Status) |
629 | Value->GetValueNonAligned<int>(p, (int)n); |
630 | |
631 | break; |
632 | case 'G': // Large (great) integer |
633 | if (Status) |
634 | *(longlong *)p = Value->GetBigintValue(); |
635 | |
636 | break; |
637 | case 'F': // Float |
638 | case 'R': // Real |
639 | if (Status) |
640 | Value->GetValueNonAligned<float>(p, (float)Value->GetFloatValue()); |
641 | |
642 | break; |
643 | case 'D': // Double |
644 | if (Status) |
645 | Value->GetValueNonAligned<double>(p, Value->GetFloatValue()); |
646 | |
647 | break; |
648 | case 'C': // Characters |
649 | if ((n = (signed)strlen(Value->GetCharString(Buf))) > Long) { |
650 | sprintf(g->Message, MSG(BIN_F_TOO_LONG), Name, (int) n, Long); |
651 | throw 31; |
652 | } // endif n |
653 | |
654 | if (Status) { |
655 | s = Value->GetCharString(Buf); |
656 | memset(p, ' ', Long); |
657 | memcpy(p, s, strlen(s)); |
658 | } // endif Status |
659 | |
660 | break; |
661 | default: |
662 | sprintf(g->Message, MSG(BAD_BIN_FMT), Fmt, Name); |
663 | throw 31; |
664 | } // endswitch Fmt |
665 | |
666 | if (Eds && Status) { |
667 | p = tdbp->To_Line + Deplac; |
668 | |
669 | for (int i = 0; i < Lim; i++) |
670 | if (Eds == 'B' && Endian == 'L') |
671 | p[N - i - 1] = Buff[i]; |
672 | else if (Eds == 'L' && Endian == 'B') |
673 | p[i] = Buff[M - i - 1]; |
674 | else if (Endian == 'B') |
675 | p[N - i - 1] = Buff[M - i - 1]; |
676 | else |
677 | p[i] = Buff[i]; |
678 | |
679 | } // endif Eds |
680 | |
681 | } // end of WriteColumn |
682 | |
683 | /* ------------------------ End of TabFix ---------------------------- */ |
684 | |