void DBCursor::string_field(FILE *fp, char **out, int *lenOut) { int len = 0; int io; /* fscanf is wierd, so we do it ourselves... */ while(isdigit(io = fgetc(fp))){ len = len * 10 + (io - '0'); } FRIENDLY_ASSERT(io == '\t'); char *str = new char[len + 1]; io = fread(str, sizeof(str[0]), len+1, fp); /* read \n also */ FRIENDLY_ASSERT(io == len+1); str[len] = 0; /* replace \n with 0 (just in case...) */ if(out){ f_fields->add(str); *out = str; if(lenOut) *lenOut = len; }else{ delete str; } }
void DBCursor::short_list(FILE *fp, int *qout, int ltype, void *out) { int c; int ret; c = fgetc(fp); FRIENDLY_ASSERT(c == '#'); c = fgetc(fp); FRIENDLY_ASSERT(c == '\n'); switch(ltype){ case STRING_CODE: { typedef const char** ccpp; ccpp *cpout = (ccpp*)out; assert(f_list == NULL); /* only one SHORT_LIST per record supported */ f_list = new StringList; while((c = fgetc(fp)) != '#'){ char *item; int ftype; ungetc(c, fp); ret = fscanf(fp, "%d\n", &ftype); if(ret == 0) throw(PosixError(errno, "Unable to fscanf\n")); FRIENDLY_ASSERT(ftype == STRING_CODE); string_field(fp, &item, NULL); f_list->append(item); } *cpout = f_list->array(); *qout = f_list->qty(); } break; default: abort(); /* only strings supported */ } c = fgetc(fp); FRIENDLY_ASSERT(c == '\n'); }
void DBCursor::int_field(FILE *fp, int *out) { int an_int; int io; io = fscanf(fp, "%d\n", &an_int); FRIENDLY_ASSERT(io == 1); if(out) *out = an_int; }
int DBCursor::next(int typeCode, ...) { int ret = 1; FILE *fp = f_table->file(DB::READ); int io; int recordClass; if(f_start < 0){ /* on first call to next(), reset the file */ rewind(fp); } f_start = ftell(fp); io = fscanf(fp, "%d\n", &recordClass); /* get record code */ if(io != EOF){ /* got any data? */ FRIENDLY_ASSERT(io == 1); // clean up previous fields first if they exist f_fields->reset(); delete f_list; f_list = NULL; va_list ap; va_start(ap, typeCode); int fieldQty; io = fscanf(fp, "%d\n", &fieldQty); /* get field count */ FRIENDLY_ASSERT(io == 1); /* iterate over fields in the input stream... */ while(fieldQty--){ int fieldCode; io = fscanf(fp, "%d\n", &fieldCode); /* get field type */ FRIENDLY_ASSERT(io == 1); assert(typeCode); /* make sure caller didn't give too few args */ switch(fieldCode){ case STRING_CODE: { char **data = NULL; int *len = NULL; if (fieldCode == typeCode || (fieldCode + typeCode) == 0) { data = va_arg(ap, char**); if (fieldCode != typeCode) { len = va_arg(ap, int*); } } string_field(fp, data, len); } break; case INTEGER_CODE: int_field(fp, fieldCode == typeCode ? va_arg(ap, int*) : 0); break; case SHORT_LIST_CODE: { int *qout = va_arg(ap, int *); int ltype = va_arg(ap, int); void *out = va_arg(ap, void*); short_list(fp, qout, ltype, out); } break; default: abort(); }