Advertisement
CSenshi

GABOOO

Oct 6th, 2019
2,336
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. using namespace std;
  2. #include <sys/types.h>
  3. #include <sys/stat.h>
  4. #include <sys/mman.h>
  5. #include <fcntl.h>
  6. #include <unistd.h>
  7. #include <string.h>
  8. #include "imdb.h"
  9.  
  10. const char *const imdb::kActorFileName = "actordata";
  11. const char *const imdb::kMovieFileName = "moviedata";
  12.  
  13. imdb::imdb(const string &directory)
  14. {
  15.   const string actorFileName = directory + "/" + kActorFileName;
  16.   const string movieFileName = directory + "/" + kMovieFileName;
  17.  
  18.   actorFile = acquireFileMap(actorFileName, actorInfo);
  19.   movieFile = acquireFileMap(movieFileName, movieInfo);
  20. }
  21.  
  22. bool imdb::good() const
  23. {
  24.   return !((actorInfo.fd == -1) ||
  25.            (movieInfo.fd == -1));
  26. }
  27.  
  28. struct key_credits
  29. {
  30.   string player;
  31.   const void *data;
  32. };
  33.  
  34. struct key_cast
  35. {
  36.   film movie;
  37.   const void *data;
  38. };
  39.  
  40. static int cmp_credits(const void *m1, const void *m2)
  41. {
  42.   // elem1
  43.   struct key_credits kc = *(key_credits *)m1;
  44.   string elem1 = kc.player;
  45.  
  46.   // elem2
  47.   int offset = *(int *)m2;
  48.   string elem2 = string((char *)kc.data + offset);
  49.  
  50.   return elem1.compare(elem2);
  51. }
  52.  
  53. static int cmp_cast(const void *m1, const void *m2)
  54. {
  55.   // elem1
  56.   struct key_cast kc = *(key_cast *)m1;
  57.   film elem1 = kc.movie;
  58.  
  59.   // elem2
  60.   int offset = *(int *)m2;
  61.   string movie_name = string((char *)kc.data + offset);
  62.   char year_byte = *((char *)kc.data + offset + movie_name.size() + 1);
  63.   int year = 1900 + year_byte;
  64.   film elem2 = {movie_name, year};
  65.  
  66.   if (elem1 == elem2)
  67.     return 0;
  68.   if (elem1 < elem2)
  69.     return -1;
  70.   return 1;
  71. }
  72.  
  73. // you should be implementing these two methods right here...
  74. bool imdb::getCredits(const string &player, vector<film> &films) const
  75. {
  76.   // binary search
  77.   int total_actors = *(int *)actorFile;
  78.   key_credits kc = {player, actorFile};
  79.   void *base = (char *)actorFile + sizeof(int);
  80.   void *res = bsearch(&kc, base, total_actors, sizeof(int), cmp_credits);
  81.  
  82.   if (!res)
  83.     return false;
  84.  
  85.   // actor info
  86.   int off = *(int *)res;
  87.   void *base_act = (char *)actorFile + off;
  88.  
  89.   // actor name
  90.   char *actor_name = (char *)base_act;
  91.   int cur_off = strlen(actor_name) + 1;
  92.   cur_off += cur_off % 2;
  93.  
  94.   // movie count
  95.   short count = *(short *)((char *)base_act + cur_off);
  96.   cur_off += 2;
  97.   cur_off += (cur_off) % 4;
  98.  
  99.   // movie iteration
  100.   int *movie_offsets = (int *)((char *)base_act + cur_off);
  101.  
  102.   for (int i = 0; i < count; i++)
  103.   {
  104.     int off = movie_offsets[i];
  105.  
  106.     // name
  107.     char *movie_name = (char *)movieFile + off;
  108.     off += strlen(movie_name) + 1;
  109.  
  110.     // year
  111.     char year_byte = *((char *)movieFile + off);
  112.     int year = 1900 + year_byte;
  113.  
  114.     film cur_film = {string(movie_name), year};
  115.  
  116.     films.push_back(cur_film);
  117.   }
  118.   return true;
  119. }
  120. bool imdb::getCast(const film &movie, vector<string> &players) const
  121. {
  122.   // binary search
  123.   int total_movies = *(int *)movieFile;
  124.   key_cast kc = {movie, movieFile};
  125.   void *base = (char *)movieFile + sizeof(int);
  126.   void *res = bsearch(&kc, base, total_movies, sizeof(int), cmp_cast);
  127.  
  128.   // check if exists
  129.   if (!res)
  130.   {
  131.     players.clear();
  132.     return false;
  133.   }
  134.  
  135.   // movie info
  136.   int off = *(int *)res;
  137.   void *base_movie = (char *)movieFile + off;
  138.  
  139.   // movie name
  140.   char *movie_name = (char *)base_movie;
  141.   int cur_off = strlen(movie_name) + 1;
  142.  
  143.   // movie year
  144.   char year_byte = *((char *)base_movie + cur_off);
  145.   cur_off += 1;
  146.   cur_off += cur_off % 2;
  147.  
  148.   // actor count
  149.   short count = *(short *)((char *)base_movie + cur_off);
  150.   cur_off += 2;
  151.   cur_off += (cur_off) % 4;
  152.  
  153.   // actor iteration
  154.   int *actor_offsets = (int *)((char *)base_movie + cur_off);
  155.   for (int i = 0; i < count; i++)
  156.   {
  157.     int off = actor_offsets[i];
  158.  
  159.     //name
  160.     char *actor_name = (char *)actorFile + off;
  161.     players.push_back(string(actor_name));
  162.   }
  163.   return true;
  164. }
  165.  
  166. imdb::~imdb()
  167. {
  168.   releaseFileMap(actorInfo);
  169.   releaseFileMap(movieInfo);
  170. }
  171.  
  172. // ignore everything below... it's all UNIXy stuff in place to make a file look like
  173. // an array of bytes in RAM..
  174. const void *imdb::acquireFileMap(const string &fileName, struct fileInfo &info)
  175. {
  176.   struct stat stats;
  177.   stat(fileName.c_str(), &stats);
  178.   info.fileSize = stats.st_size;
  179.   info.fd = open(fileName.c_str(), O_RDONLY);
  180.   return info.fileMap = mmap(0, info.fileSize, PROT_READ, MAP_SHARED, info.fd, 0);
  181. }
  182.  
  183. void imdb::releaseFileMap(struct fileInfo &info)
  184. {
  185.   if (info.fileMap != NULL)
  186.     munmap((char *)info.fileMap, info.fileSize);
  187.   if (info.fd != -1)
  188.     close(info.fd);
  189. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement