📄 flatfileold.c,v
字号:
sizeof(null_title),
&null_title);
}
int dvd_title_search(char *title, char *name, int *result_ids[], int *count)
{
/* Search for title in title_text, or name in director and actors
Note this a case sensitive match as there is
no case insensitive strstr!
*/
dvd_title a_title;
int id = 1;
int matches = 0;
int *results = NULL;
int results_size = 0;
int err;
*count = 0;
while(err = dvd_title_get(id, &a_title),
err == DVD_SUCCESS || err == DVD_ERR_NOT_FOUND) {
if(err == DVD_SUCCESS && a_title.title_id != 0) {
/* Valid record */
if((title && strstr(a_title.title_text, title)) ||
(name && strstr(a_title.director, name)) ||
(name && strstr(a_title.actor1, name)) ||
(name && strstr(a_title.actor2, name))) {
/* Add a result to the list */
/* Increase capacity if required */
if(matches >= results_size) {
results_size += 4;
results = (int *)realloc(results, sizeof(int)*results_size);
if(results == NULL)
return DVD_ERR_NO_MEMORY;
}
results[matches] = a_title.title_id;
matches++;
}
}
id++;
}
*result_ids = results;
*count = matches;
return DVD_SUCCESS;
}
int dvd_disk_set(dvd_disk *disk_record_to_update)
{
if(disk_record_to_update == NULL)
return DVD_ERR_NULL_POINTER;
return
file_set(disk_file,
sizeof(dvd_disk) * (disk_record_to_update -> disk_id),
sizeof(dvd_disk),
(void *) disk_record_to_update);
}
int dvd_disk_get(int disk_id, dvd_disk *disk_record_to_complete)
{
int err = DVD_SUCCESS;
if(disk_record_to_complete == NULL)
return DVD_ERR_NULL_POINTER;
err = file_get(disk_file,
sizeof(dvd_disk) * disk_id,
sizeof(dvd_disk),
(void *) disk_record_to_complete);
/* If we cannot get the disk there may be an error
with the data, or the title may not exist */
if(err != DVD_SUCCESS)
return err;
/* If the retrieved disk id is not as expected there
may be an error, or the disk may be deleted */
if(disk_record_to_complete -> disk_id == 0)
return DVD_ERR_NOT_FOUND;
if(disk_id != disk_record_to_complete -> disk_id)
return DVD_ERR_BAD_MEMBER_TABLE;
return DVD_SUCCESS;
}
int dvd_disk_create(dvd_disk *disk_record_to_add, int *disk_id)
{
int err;
dvd_disk new_disk;
dvd_rental null_rental;
/* Make a new disk record. See also notes in member_create.
Ought really to check that the title_id is valid, but
then again it can be invalidated independently anyway.
*/
/* Take a copy of the passed member, in case it is static */
new_disk = *disk_record_to_add;
/* The new disk_id is the next available id */
new_disk.disk_id = disk_count;
/* Add the new disk to the disk file and the rentals file */
err = dvd_disk_set(&new_disk);
if(err != DVD_SUCCESS)
return err;
memset((void *) &null_rental, 0, sizeof(dvd_rental));
null_rental.disk_id = new_disk.disk_id;
null_rental.member_id = 0;
err = dvd_rental_set(null_rental.disk_id, &null_rental);
if(err != DVD_SUCCESS)
return err;
/* Update disk file state */
*disk_id = disk_count;
disk_count++;
return DVD_SUCCESS;
}
int dvd_disk_delete(int disk_id)
{
/* Delete a disk by setting the disk_id to zero */
dvd_disk null_disk;
memset((void *)&null_disk, 0, sizeof(null_disk));
return file_set(disk_file,
disk_id * sizeof(null_disk),
sizeof(null_disk),
&null_disk);
}
int dvd_disk_search(int title_id, int *result_ids[], int *count)
{
/* Search for disks of a particular title */
dvd_disk a_disk;
int id = 1;
int matches = 0;
int *results = NULL;
int results_size = 0;
int err;
*count = 0;
while(err = dvd_disk_get(id, &a_disk),
err == DVD_SUCCESS || err == DVD_ERR_NOT_FOUND) {
if(err == DVD_SUCCESS && a_disk.disk_id != 0) {
/* Valid record */
if(title_id == a_disk.title_id) {
/* Add a result to the list */
/* Increase capacity if required */
if(matches >= results_size) {
results_size += 4;
results = (int *)realloc(results, sizeof(int)*results_size);
if(results == NULL)
return DVD_ERR_NO_MEMORY;
}
results[matches] = a_disk.disk_id;
matches++;
}
}
id++;
}
*result_ids = results;
*count = matches;
return DVD_SUCCESS;
}
int dvd_get_genre_list(char **genre_list[], int *count)
{
static char *genres[] = {
"Action",
"Education",
"Comedy",
"Thriller",
"Foreign",
"Romance",
"Science Fiction"
};
*genre_list = genres;
*count = sizeof(genres)/sizeof(char *);
return DVD_SUCCESS;
}
int dvd_get_classification_list(char **class_list[], int *count)
{
static char *classes[] = {
"E", "U", "PG", "12", "15", "18"
};
*class_list = classes;
*count = sizeof(classes)/sizeof(char *);
return DVD_SUCCESS;
}
int dvd_err_text(int err_number, char **message_to_show)
{
static char default_msg[80];
char *msg = default_msg;
sprintf(default_msg,"unknown error type: %d", err_number);
switch(err_number) {
case DVD_SUCCESS: msg = "no error"; break;
case DVD_ERR_NO_FILE: msg = "cannot open file"; break;
case DVD_ERR_BAD_TABLE: msg = "corrupt table file"; break;
case DVD_ERR_NO_MEMBER_TABLE: msg = "no member table"; break;
case DVD_ERR_BAD_MEMBER_TABLE: msg = "corrupt member table"; break;
case DVD_ERR_BAD_TITLE_TABLE: msg = "corrupt title table"; break;
case DVD_ERR_BAD_DISK_TABLE: msg = "corrupt disk table"; break;
case DVD_ERR_BAD_RENTAL_TABLE: msg = "corrupt rental table"; break;
case DVD_ERR_BAD_RESERVE_TABLE: msg = "corrupt reserve table"; break;
case DVD_ERR_BAD_SEEK: msg = "cannot seek in file"; break;
case DVD_ERR_NULL_POINTER: msg = "null data pointer"; break;
case DVD_ERR_BAD_WRITE: msg = "cannot write to file"; break;
case DVD_ERR_BAD_READ: msg = "cannot read file"; break;
case DVD_ERR_NOT_FOUND: msg = "no match found"; break;
case DVD_ERR_NO_MEMORY: msg = "out of memory"; break;
}
*message_to_show = msg;
return DVD_SUCCESS;
}
int dvd_today(char **date)
{
static char today[9];
time_t the_ticks = time(NULL);
struct tm *the_time = localtime(&the_ticks);
sprintf(today, "%04d%02d%02d",
the_time -> tm_year + 1900,
the_time -> tm_mon + 1,
the_time -> tm_mday);
*date = today;
return DVD_SUCCESS;
}
/*
Rentals and Reservation Scheme
Add another table that mirrors the disk table, but contains
a member_id field (if rented) and a date rented.
*/
/* Helper functions */
static int dvd_rental_set(int disk_id, dvd_rental *rental)
{
if(rental == NULL)
return DVD_ERR_NULL_POINTER;
return
file_set(rental_file,
sizeof(dvd_rental) * (rental -> disk_id),
sizeof(dvd_rental),
(void *) rental);
}
static int dvd_rental_get(int disk_id, dvd_rental *rental)
{
int err = DVD_SUCCESS;
if(rental == NULL)
return DVD_ERR_NULL_POINTER;
err = file_get(rental_file,
sizeof(dvd_rental) * disk_id,
sizeof(dvd_rental),
(void *) rental);
if(err != DVD_SUCCESS)
return err;
if(disk_id != rental -> disk_id)
return DVD_ERR_BAD_RENTAL_TABLE;
return DVD_SUCCESS;
}
static int dvd_reserve_set(int member_id, dvd_reserve *reserve)
{
if(reserve == NULL)
return DVD_ERR_NULL_POINTER;
return
file_set(reserve_file,
sizeof(dvd_reserve) * (reserve -> member_id),
sizeof(dvd_reserve),
(void *) reserve);
}
static int dvd_reserve_get(int member_id, dvd_reserve *reserve)
{
int err = DVD_SUCCESS;
if(reserve == NULL)
return DVD_ERR_NULL_POINTER;
err = file_get(reserve_file,
sizeof(dvd_reserve) * member_id,
sizeof(dvd_reserve),
(void *) reserve);
if(err != DVD_SUCCESS)
return err;
if(member_id != reserve -> member_id)
return DVD_ERR_BAD_RENTAL_TABLE;
return DVD_SUCCESS;
}
/*
To rent a single title we need to find a disk of that title
and tell the owner which one to give the customer. BUT, we
must ensure that we do not have too many reservations for
this date for that title already.
*/
int dvd_rent_title(int member_id, int title_id, int *disk_id_to_rent)
{
int count;
char *date;
int err;
dvd_disk disk;
dvd_rental rental;
dvd_reserve reserve;
int disk_id;
(void) dvd_today(&date);
/* See if there is a reservation for today, and clear it */
err = dvd_reserve_get(member_id, &reserve);
if(err != DVD_SUCCESS)
return err;
if(reserve.title_id == title_id &&
strcmp(date, reserve.date)) {
reserve.title_id = 0;
dvd_reserve_set(member_id, &reserve);
}
/* Check that there is a copy available (including reservations) */
err = dvd_title_available(title_id, date, &count);
if(err != DVD_SUCCESS)
return err;
if(count <= 0)
return DVD_ERR_NOT_FOUND;
/* Add an entry to the rental table and return allocated disk id */
for(disk_id = 1; disk_id < disk_count; disk_id++) {
err = dvd_disk_get(disk_id, &disk);
if(err == DVD_SUCCESS && title_id == disk.title_id) {
/* See if this copy is already out */
err = dvd_rental_get(disk_id, &rental);
if(err != DVD_SUCCESS)
return err;
if(rental.member_id == 0) {
rental.member_id = member_id;
strcpy(rental.date, date);
err = dvd_rental_set(disk_id, &rental);
if(err != DVD_SUCCESS)
return err;
*disk_id_to_rent = disk_id;
return DVD_SUCCESS;
}
}
}
return DVD_ERR_NOT_FOUND;
}
int dvd_rented_disk_info(int disk_id, int *member_id, char *date_rented)
{
/* Lookup the disk in the rental table and return the details */
/* The user can get the title from dvd_disk_get */
dvd_rental rental;
int err;
err = dvd_rental_get(disk_id, &rental);
if(err != DVD_SUCCESS)
return err;
if(rental.member_id == 0)
return DVD_ERR_NOT_FOUND;
*member_id = rental.member_id;
strcpy(date_rented, rental.date);
return DVD_SUCCESS;
}
/*
To return a disk we erase the record for that disk in the rental
table, but also return the date the disk was rented, so that the
store owner can charge a fine if needed.
*/
int dvd_disk_return(int disk_id, int *member_id, char *date)
{
dvd_rental rental;
int err;
err = dvd_rental_get(disk_id, &rental);
if(err != DVD_SUCCESS)
return err;
strcpy(date, rental.date);
/* Clear the entry in the rental table for this disk */
memset((void *) &rental, 0, sizeof(dvd_rental));
rental.disk_id = disk_id;
return dvd_rental_set(disk_id, &rental);
}
/*
Reservations
Another table that mirrors the member table - we allow
each member to reserve one title at a time, for one date.
A record is kept of titles and requested date of hire.
We can allow only as many reservations for any one date as
we have disks of that title.
When a member comes into the store and tries to rent a video
the application should check to see if the title he wants to rent
has a reservation for today. Then the reservation must be cancelled
before an attempt is made to rent an actual disk.
*/
int dvd_title_available(int title_id, char *date, int *count)
{
int copies = 0;
int disk_id, member_id;
dvd_disk disk;
dvd_rental rental;
dvd_reserve reserve;
int err;
/* Find out how many copies of this title we have */
for(disk_id = 1; disk_id < disk_count; disk_id++) {
err = dvd_disk_get(disk_id, &disk);
if(err == DVD_ERR_NOT_FOUND)
continue;
if(err != DVD_SUCCESS)
return err;
if(title_id == disk.title_id) {
copies++;
/* Check the rental table to disregard copies already rented */
err = dvd_rental_get(disk_id, &rental);
if(err != DVD_SUCCESS)
return err;
if(rental.member_id != 0)
copies--;
}
}
/* Scan the reservation table and count the times
this title appears at this date */
for(member_id = 1; member_id < member_count; member_id++) {
err = dvd_reserve_get(member_id, &reserve);
if(err != DVD_SUCCESS)
return err;
if(title_id == reserve.title_id &&
strcmp(date, reserve.date) == 0)
copies--;
}
/* All done */
*count = copies;
return DVD_SUCCESS;
}
int dvd_reserve_title(char *date, int title_id, int member_id)
{
int count;
dvd_reserve reserve;
reserve.member_id = member_id;
reserve.title_id = title_id;
strcpy(reserve.date, date);
/* Check title is available on this date */
if(dvd_title_available(title_id, date, &count) == DVD_SUCCESS &&
count > 0) {
/* Make entry in the reservation table */
return dvd_reserve_set(member_id, &reserve);
}
return DVD_ERR_NOT_FOUND;
}
int dvd_reserve_title_cancel(int member_id)
{
/* Clear out entry in the reservation table */
dvd_reserve reserve;
memset((void *) &reserve, 0, sizeof(dvd_reserve));
reserve.member_id = member_id;
return dvd_reserve_set(member_id, &reserve);
}
int dvd_reserve_title_query_by_member(int member_id, int *title_id)
{
/* Retrieve a reservation for this member (if any) */
dvd_reserve reserve;
int err;
err = dvd_reserve_get(member_id, &reserve);
if(err != DVD_SUCCESS)
return err;
*title_id = reserve.title_id;
return DVD_SUCCESS;
}
int dvd_reserve_title_query_by_titledate(int title_id, char *date, int *member_ids[])
{
/* Return a list of members who have reserved this title on this date */
/* Null date means any date */
return DVD_ERR_NOT_FOUND;
}
int dvd_overdue_disks(char *date1, char *date2, int *disk_ids[], int *count)
{
/* Scan the rental table for disks whose rented date is after date1
and before date2. Null dates mean beginning of epoch and tomorrow */
return DVD_ERR_NOT_FOUND;
@
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -