int DBMFAM::Cardinality(PGLOBAL g) { if (!g) return 1; if (!Headlen) if ((Headlen = ScanHeader(g, To_File, Lrecl, Tdbp->GetPath())) < 0) return -1; // Error in ScanHeader // Set number of blocks for later use Block = (Records > 0) ? (Records + Nrec - 1) / Nrec : 0; return Records; } // end of Cardinality
void VfkStream::ScanFile(int fx) { RTIMING("VfkStream::ScanFile"); Stream& strm = streams[fx]; int64 last_line = strm.GetSize(); while(last_line > 0) { strm.Seek(last_line - 1); if(strm.Get() == '\n') break; last_line--; } strm.Seek(0); try { int c; int64 rowpos = strm.GetPos(); while((c = strm.Get()) == '&' && ((c = strm.Get()) == 'H' || c == 'D') && IsAlpha(strm.Term())) { char type = c; int64 begin = strm.GetPos(); SkipRow(strm); rowpos = strm.GetPos(); int len = (int)(strm.GetPos() - begin); StringBuffer linebuf(len + 1); strm.Seek(begin); strm.Get(linebuf, len); linebuf[len] = 0; const char *b = linebuf; const char *id = b; while(IsIdent(*++b)) ; String ident(id, b); if(*b++ != ';') throw Exc(NFormat("';' expected after '%s' (found: '%c', %2:02x)", ident, *b)); if(type == 'D') { String fident = "X_" + ident; int f = tables.Find(fident); if(f < 0) throw Exc(NFormat("unexpected data for filter table '%s'", ident)); // b = ScanRow(b, tables[f]); } else if(IsAlpha(*b)) { String fident = "X_" + ident; Table& tbl = tables.GetAdd(fident); tbl.name = tbl.rawname = fident; tbl.row_count = 0; ScanHeader(b, tbl); } else { do { Vector<Value> row; row.SetCount(HDR_COUNT); if(*b == '\"') { WString text = ReadString(b, &b); if(IsDateTime(ident) && !IsNull(text)) { Time dt = VfkReadTime(text.ToString(), NULL); if(IsNull(dt)) throw Exc(NFormat("invalid date/time value %s", AsCString(text.ToString()))); row[HDR_DTM] = dt; } else { row[HDR_STR] = text; if(ident == "CODEPAGE") if(text == WString("EE8MSWIN1250")) charset = CHARSET_WIN1250; } } else { double num = ScanDouble(b, &b); if(IsNull(num)) throw Exc("invalid numeric value"); row[HDR_NUM] = num; } int l = header.FindLast(ident); row[HDR_ID] = ident; row[HDR_ORD] = (l >= 0 ? (int)header[l][HDR_ORD] + 1 : 0); header.Add(ident) = row; } while(*b++ == ';'); b--; } } strm.Seek(rowpos); while(strm.Get() == '&' && strm.Get() == 'B' && IsAlpha(strm.Term())) { int64 header_offset = strm.GetPos(); SkipRow(strm); int64 begin_offset = strm.GetPos(); int len = (int)(begin_offset - header_offset); Buffer<char> linebuf(len + 1); strm.Seek(header_offset); strm.Get(linebuf, len); linebuf[len] = 0; const char *b = linebuf; const char *id = b; while(IsIdent(*++b)) ; int idlen = b - id; String ident(id, b); if(*b++ != ';') throw Exc(NFormat("';' expected after '%s' (found: '%c', %2:02x)", ident, *b)); String name = ident; for(const VFKLongName *ln = vfk_long_names; ln->shortname; ln++) if(name == ln->shortname) { name = ln->longname; break; } Table& tbl = tables.GetAdd(name); tbl.name = name; tbl.rawname = ident; ScanHeader(b, tbl); int64 p = begin_offset, e = last_line; Buffer<char> idbuf(idlen + 3); while(p < e) { int64 m = (p + e) >> 1; while(m > p) { char part[100]; int partsize = (int)min<int64>(m - p, sizeof(part)); strm.Seek(m - partsize); strm.Get(part, partsize); const char *x = &part[partsize]; while(x > part && x[-1] != '\n') x--; int lfpos = x - part; if(x > part && --x > part && x[-1] == '\r') x--; m -= partsize - lfpos; if(x <= part) continue; if(*--x != '\xA4') break; m -= lfpos - (x - part); } strm.Seek(m); if(strm.Get(idbuf, idlen + 3) != idlen + 3 || idbuf[0] != '&' || idbuf[1] != 'D' || memcmp(~idbuf + 2, id, idlen) || idbuf[idlen + 2] != ';') e = m; else { SkipRow(strm); p = strm.GetPos(); } } int xgrp = file_groups.GetKey(fx); int f; for(f = 0; f < tbl.file_index.GetCount(); f++) if(file_groups.GetKey(tbl.file_index[f]) == xgrp) break; if(f >= tbl.file_index.GetCount()) { tbl.file_index.Add(fx); tbl.begin_offset.Add(begin_offset); tbl.end_offset.Add(p); } strm.Seek(p); } } catch(Exc e) { throw Exc(NFormat("%s (offset %n): %s", file_groups[fx], strm.GetPos(), e)); } }