Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using namespace std;
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <sys/mman.h>
- #include <fcntl.h>
- #include <unistd.h>
- #include <string.h>
- #include "imdb.h"
- const char *const imdb::kActorFileName = "actordata";
- const char *const imdb::kMovieFileName = "moviedata";
- imdb::imdb(const string &directory)
- {
- const string actorFileName = directory + "/" + kActorFileName;
- const string movieFileName = directory + "/" + kMovieFileName;
- actorFile = acquireFileMap(actorFileName, actorInfo);
- movieFile = acquireFileMap(movieFileName, movieInfo);
- }
- bool imdb::good() const
- {
- return !((actorInfo.fd == -1) ||
- (movieInfo.fd == -1));
- }
- struct key_credits
- {
- string player;
- const void *data;
- };
- struct key_cast
- {
- film movie;
- const void *data;
- };
- static int cmp_credits(const void *m1, const void *m2)
- {
- // elem1
- struct key_credits kc = *(key_credits *)m1;
- string elem1 = kc.player;
- // elem2
- int offset = *(int *)m2;
- string elem2 = string((char *)kc.data + offset);
- return elem1.compare(elem2);
- }
- static int cmp_cast(const void *m1, const void *m2)
- {
- // elem1
- struct key_cast kc = *(key_cast *)m1;
- film elem1 = kc.movie;
- // elem2
- int offset = *(int *)m2;
- string movie_name = string((char *)kc.data + offset);
- char year_byte = *((char *)kc.data + offset + movie_name.size() + 1);
- int year = 1900 + year_byte;
- film elem2 = {movie_name, year};
- if (elem1 == elem2)
- return 0;
- if (elem1 < elem2)
- return -1;
- return 1;
- }
- // you should be implementing these two methods right here...
- bool imdb::getCredits(const string &player, vector<film> &films) const
- {
- // binary search
- int total_actors = *(int *)actorFile;
- key_credits kc = {player, actorFile};
- void *base = (char *)actorFile + sizeof(int);
- void *res = bsearch(&kc, base, total_actors, sizeof(int), cmp_credits);
- if (!res)
- return false;
- // actor info
- int off = *(int *)res;
- void *base_act = (char *)actorFile + off;
- // actor name
- char *actor_name = (char *)base_act;
- int cur_off = strlen(actor_name) + 1;
- cur_off += cur_off % 2;
- // movie count
- short count = *(short *)((char *)base_act + cur_off);
- cur_off += 2;
- cur_off += (cur_off) % 4;
- // movie iteration
- int *movie_offsets = (int *)((char *)base_act + cur_off);
- for (int i = 0; i < count; i++)
- {
- int off = movie_offsets[i];
- // name
- char *movie_name = (char *)movieFile + off;
- off += strlen(movie_name) + 1;
- // year
- char year_byte = *((char *)movieFile + off);
- int year = 1900 + year_byte;
- film cur_film = {string(movie_name), year};
- films.push_back(cur_film);
- }
- return true;
- }
- bool imdb::getCast(const film &movie, vector<string> &players) const
- {
- // binary search
- int total_movies = *(int *)movieFile;
- key_cast kc = {movie, movieFile};
- void *base = (char *)movieFile + sizeof(int);
- void *res = bsearch(&kc, base, total_movies, sizeof(int), cmp_cast);
- // check if exists
- if (!res)
- {
- players.clear();
- return false;
- }
- // movie info
- int off = *(int *)res;
- void *base_movie = (char *)movieFile + off;
- // movie name
- char *movie_name = (char *)base_movie;
- int cur_off = strlen(movie_name) + 1;
- // movie year
- char year_byte = *((char *)base_movie + cur_off);
- cur_off += 1;
- cur_off += cur_off % 2;
- // actor count
- short count = *(short *)((char *)base_movie + cur_off);
- cur_off += 2;
- cur_off += (cur_off) % 4;
- // actor iteration
- int *actor_offsets = (int *)((char *)base_movie + cur_off);
- for (int i = 0; i < count; i++)
- {
- int off = actor_offsets[i];
- //name
- char *actor_name = (char *)actorFile + off;
- players.push_back(string(actor_name));
- }
- return true;
- }
- imdb::~imdb()
- {
- releaseFileMap(actorInfo);
- releaseFileMap(movieInfo);
- }
- // ignore everything below... it's all UNIXy stuff in place to make a file look like
- // an array of bytes in RAM..
- const void *imdb::acquireFileMap(const string &fileName, struct fileInfo &info)
- {
- struct stat stats;
- stat(fileName.c_str(), &stats);
- info.fileSize = stats.st_size;
- info.fd = open(fileName.c_str(), O_RDONLY);
- return info.fileMap = mmap(0, info.fileSize, PROT_READ, MAP_SHARED, info.fd, 0);
- }
- void imdb::releaseFileMap(struct fileInfo &info)
- {
- if (info.fileMap != NULL)
- munmap((char *)info.fileMap, info.fileSize);
- if (info.fd != -1)
- close(info.fd);
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement