collection.c 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. #include "collection.h"
  2. #include "common.h"
  3. enum CollectionOpenResult collectionChainOpen(struct ICollection *collection,
  4. const char *name, enum FileType type, struct IFile **out_file) {
  5. while (collection) {
  6. enum CollectionOpenResult result = collection->open(collection, name, type, out_file);
  7. if (result == CollectionOpen_Success) return result;
  8. if (result == CollectionOpen_NotFound) {
  9. collection = collection->next;
  10. } else {
  11. /* TODO print error */
  12. return result;
  13. }
  14. }
  15. return CollectionOpen_NotFound;
  16. }
  17. static enum AFileResult filesystemCollectionFile_Open(struct FilesystemCollectionFile_ *f, const char *filename) {
  18. const enum AFileResult result = aFileOpen(&f->file, filename);
  19. f->opened = result == AFile_Success;
  20. f->head.size = f->file.size;
  21. return result;
  22. }
  23. static size_t filesystemCollectionFile_Read(struct IFile *file, size_t offset, size_t size, void *buffer) {
  24. struct FilesystemCollectionFile_ *f = (void*)file;
  25. const size_t result = aFileReadAtOffset(&f->file, offset, size, buffer);
  26. return result != AFileError ? result : 0;
  27. }
  28. static void filesystemCollectionFile_Close(struct IFile *file) {
  29. struct FilesystemCollectionFile_ *f = (void*)file;
  30. aFileClose(&f->file);
  31. f->head.size = 0;
  32. f->opened = 0;
  33. }
  34. static void filesystemCollectionClose(struct ICollection *collection) {
  35. (void)(collection);
  36. /* TODO ensure all files are closed */
  37. }
  38. static enum CollectionOpenResult filesystemCollectionOpen(struct ICollection *collection,
  39. const char *name, enum FileType type, struct IFile **out_file) {
  40. struct FilesystemCollection *fsc = (struct FilesystemCollection*)collection;
  41. char buffer[512];
  42. const char *subdir = "/";
  43. const char *suffix = "";
  44. *out_file = 0;
  45. int fileslot = 0;
  46. for(; fileslot < FilesystemCollectionFileSlots; ++fileslot)
  47. if (fsc->files[fileslot].head.read) break;
  48. if (fileslot >= FilesystemCollectionFileSlots)
  49. return CollectionOpen_TooManyFiles;
  50. struct FilesystemCollectionFile_ *f = fsc->files + fileslot;
  51. switch (type) {
  52. case File_Map: subdir = "/maps/"; suffix = ".bsp"; break;
  53. case File_Material: subdir = "/materials/"; suffix = ".vmt"; break;
  54. case File_Texture: subdir = "/materials/"; suffix = ".vtf"; break;
  55. case File_Model: subdir = "/models/"; suffix = ".mdl"; break;
  56. }
  57. const int subdir_len = strlen(subdir);
  58. const int name_len = strlen(name);
  59. const int suffix_len = strlen(suffix);
  60. if (fsc->path_len + subdir_len + name_len + suffix_len >= (int)sizeof(buffer)) {
  61. PRINTF("Resource \"%s\" path is too long", name);
  62. return CollectionOpen_NotFound;
  63. }
  64. char *c = buffer;
  65. for (int i = 0; i < fsc->path_len; ++i) *c++ = fsc->path[i];
  66. for (int i = 0; i < subdir_len; ++i) *c++ = subdir[i];
  67. for (int i = 0; i < name_len; ++i) {
  68. char C = tolower(name[i]);
  69. *c++ = (C == '\\') ? '/' : C;
  70. }
  71. for (int i = 0; i < suffix_len; ++i) *c++ = suffix[i];
  72. *c = '\0';
  73. if (AFile_Success != filesystemCollectionFile_Open(f, buffer))
  74. return CollectionOpen_NotFound;
  75. *out_file = &f->head;
  76. return CollectionOpen_Success;
  77. }
  78. void filesystemCollectionCreate(struct FilesystemCollection *collection, const char *dir) {
  79. memset(collection, 0, sizeof *collection);
  80. /* TODO length check? dir exists check? */
  81. collection->path_len = strlen(dir);
  82. strncpy(collection->path, dir, sizeof(collection->path) - 1);
  83. for (int i = 0; i < FilesystemCollectionFileSlots; ++i) {
  84. struct FilesystemCollectionFile_ *f = collection->files + i;
  85. aFileReset(&f->file);
  86. f->head.read = filesystemCollectionFile_Read;
  87. f->head.close = filesystemCollectionFile_Close;
  88. }
  89. collection->head.open = filesystemCollectionOpen;
  90. collection->head.close = filesystemCollectionClose;
  91. }