int dbf_find_next(dbf_handle_t dbf) { if (dbf->last_find_use_index) { if (!dbf->index) { set_error(ERR_DBF_NO_INDEX, dbf, NULL); return ERROR; } if (!dbf->index->last_search) { set_error(ERR_DBF_FIND_NEXT, dbf, NULL); return ERROR; } int pos; do { EW(pos = dbf_idx_next(dbf->index)); if (pos == NOT_FOUND) { dbf->pos = -1; return FALSE; } dbf_seek(dbf, pos - 1); } while (dbf_is_deleted(dbf)); return TRUE; } else { if (dbf->last_find_col_id == -1) { set_error(ERR_DBF_FIND_NEXT, dbf, NULL); return ERROR; } else { return dbf_full_table_scan(dbf, dbf->last_find_col_id, dbf->last_find_value); } } }
int dbf_find(dbf_handle_t dbf, int id, bool use_index, const void* value) { if (use_index) { if (!dbf->index) { set_error(ERR_DBF_NO_INDEX, dbf, NULL); return ERROR; } if (id < 0 || id > dbf->index->index_count) { set_error(ERR_DBF_INVALID_INDEX_ID, dbf, "index=%i", id); return ERROR; } int pos; dbf->last_find_use_index = true; EW(pos = dbf_idx_find(dbf->index, id, value)); if (pos == NOT_FOUND) { dbf->pos = -1; return FALSE; } dbf_seek(dbf, pos - 1); if (dbf_is_deleted(dbf)) { return dbf_find_next(dbf); } else return TRUE; } else { dbf->last_find_col_id = id; if (dbf->last_find_value) free(dbf->last_find_value); dbf->last_find_value = strdup(value); dbf->last_find_use_index = false; dbf->pos = -1; return dbf_full_table_scan(dbf, id, value); } }
int dbf_full_table_scan(dbf_handle_t dbf, int col_id, const void* value) { char buf[BUFSIZE]; for (int i = dbf->pos + 1; i < dbf->row_count; i++) { EW(dbf_seek(dbf, i)); if (!dbf_is_deleted(dbf)) { EW(dbf_read(dbf, col_id, buf, BUFSIZE)); if (strcmp(buf, value) == 0) { return TRUE; } } } dbf->pos = -1; return FALSE; }
int _dbf_read_header(DBF *dbf) { DBF_FIELD *field; int i; ssize_t count; char temp[32]; DBUG_ENTER("_dbf_read_header"); dbf_seek(dbf, DBF_POS_FILE_HEADER); if((count=read(dbf->fd, dbf->header, DBF_LEN_FILE_HEADER)) < DBF_LEN_FILE_HEADER) { fprintf(stderr, "DBF: Error reading header: read only %d bytes, expected %i bytes\n", count, DBF_LEN_FILE_HEADER); close(dbf->fd); DBUG_RETURN(-2); } dbf->numfields = (DBF_HDR_LENHEADER(dbf->header)-33)/32; dbf->version = DBF_HDR_VERSION(dbf->header); dbf->numrecords = DBF_HDR_NUMRECORDS(dbf->header); dbf->record_length = 0; if(dbf->version != 0x03) { fprintf(stderr, "DBF: Unsupported dBase file version 0x%02x\n", dbf->version); close(dbf->fd); DBUG_RETURN(-3); } field = dbf->fields = DBF_FIELD_INIT(dbf->numfields); for(i=0; i<dbf->numfields; i++, field++) { if((count=read(dbf->fd, temp, DBF_LEN_FIELD)) < DBF_LEN_FIELD) { fprintf(stderr, "DBF: Error reading field!\n"); DBUG_RETURN(-3); } strncpy(field->name, DBF_FLD_NAME(temp), 10); field->name[10] = '\0'; field->format[0] = '\0'; field->metadata.name = field->name; field->metadata.format = field->format; field->type = DBF_FLD_TYPE(temp); field->length = DBF_FLD_LEN(temp); field->decimals = DBF_FLD_DECIMALS(temp); switch(field->type) { case DBF_CHARACTER: dbf->record_length += field->size = field->length; strcpy(field->format, "%s"); field->metadata.data_type = CHARACTER; break; case DBF_NUMBER: /* if field->decimals >0, fall through to FLOATING */ if(field->decimals == 0) { dbf->record_length += field->size = field->length; strcpy(field->format, "%lld"); field->metadata.data_type = NUMBER; break; } case DBF_FLOATING: dbf->record_length += field->size = field->length; sprintf(field->format, "%%.%if", field->decimals); field->metadata.data_type = FLOATING; break; case DBF_LOGICAL: dbf->record_length += field->size = 1; strcpy(field->format, "%c"); field->metadata.data_type = LOGICAL; break; case DBF_DATE: dbf->record_length += field->size = 8; strcpy(field->format, "%8s"); field->metadata.data_type = DATE; break; case DBF_GENERAL: case DBF_MEMO: case DBF_PICTURE: fprintf(stderr, "DBF: Unsupported field type %c! Please ask for support from the author!\n", field->type); DBUG_RETURN(-4); default: fprintf(stderr, "DBF: Unknown field type %c!\n", field->type); DBUG_RETURN(-4); } } if(!(dbf->record_buffer = (char *)malloc(dbf->record_length+2))) DBUG_RETURN(-5); /* set the last byte to \0 so that e.g. strndup doesn't over-read */ dbf->record_buffer[dbf->record_length+1] = '\0'; DBUG_RETURN(0); }