29 #define fetch_metadata(name) \ 
   30   item = metadata->GetItem(name, false); \ 
   31   if (item == NULL || StrEmpty(item->value)) { \ 
   32     DEBUG(grf, 0, "Base " SET_TYPE "set detail loading: %s field missing.", name); \ 
   33     DEBUG(grf, 0, "  Is %s readable for the user running OpenTTD?", full_filename); \ 
   45 template <
class T, 
size_t Tnum_files, 
bool Tsearch_in_tars>
 
   48   memset(
this, 0, 
sizeof(*
this));
 
   60   for (
const IniItem *item = metadata->
item; item != NULL; item = item->
next) {
 
   61     if (strncmp(
"description.", item->
name, 12) != 0) 
continue;
 
   67   for (uint i = 0; item->
value[i] != 
'\0' && i < 4; i++) {
 
   68     this->shortname |= ((uint8)item->
value[i]) << (i * 8);
 
   72   this->version = atoi(item->
value);
 
   74   item = metadata->
GetItem(
"fallback", 
false);
 
   75   this->fallback = (item != NULL && strcmp(item->
value, 
"0") != 0 && strcmp(item->
value, 
"false") != 0);
 
   81   for (uint i = 0; i < Tnum_files; i++) {
 
   82     MD5File *file = &this->files[i];
 
   85     if (item == NULL || (item->
value == NULL && !allow_empty_filename)) {
 
   90     const char *filename = item->
value;
 
   91     if (filename == NULL) {
 
  102     item = md5s->
GetItem(filename, 
false);
 
  103     if (item == NULL || item->
value == NULL) {
 
  104       DEBUG(grf, 0, 
"No MD5 checksum specified for: %s (in %s)", filename, full_filename);
 
  107     char *c = item->
value;
 
  108     for (uint i = 0; i < 
sizeof(file->
hash) * 2; i++, c++) {
 
  110       if (
'0' <= *c && *c <= 
'9') {
 
  112       } 
else if (
'a' <= *c && *c <= 
'f') {
 
  114       } 
else if (
'A' <= *c && *c <= 
'F') {
 
  117         DEBUG(grf, 0, 
"Malformed MD5 checksum specified for: %s (in %s)", filename, full_filename);
 
  121         file->
hash[i / 2] = j << 4;
 
  123         file->
hash[i / 2] |= j;
 
  128     item = origin->
GetItem(filename, 
false);
 
  129     if (item == NULL) item = origin->
GetItem(
"default", 
false);
 
  131       DEBUG(grf, 1, 
"No origin warning message specified for: %s", filename);
 
  144         DEBUG(grf, 1, 
"MD5 checksum mismatch for: %s (in %s)", filename, full_filename);
 
  149         DEBUG(grf, 1, 
"The file %s specified in %s is missing", filename, full_filename);
 
  157 template <
class Tbase_set>
 
  161   DEBUG(grf, 1, 
"Checking %s for base " SET_TYPE " set", filename);
 
  163   Tbase_set *
set = 
new Tbase_set();
 
  167   char *path = 
stredup(filename + basepath_length);
 
  168   char *psep = strrchr(path, PATHSEPCHAR);
 
  175   if (set->FillSetDetails(ini, path, filename)) {
 
  176     Tbase_set *duplicate = NULL;
 
  178       if (strcmp(c->name, set->name) == 0 || c->shortname == 
set->shortname) {
 
  183     if (duplicate != NULL) {
 
  185       if ((duplicate->valid_files == set->valid_files && duplicate->version >= set->version) ||
 
  186           duplicate->valid_files > 
set->valid_files) {
 
  187         DEBUG(grf, 1, 
"Not adding %s (%i) as base " SET_TYPE " set (duplicate, %s)", set->name, set->version,
 
  188             duplicate->valid_files > set->valid_files ? 
"less valid files" : 
"lower version");
 
  193         while (*prev != duplicate) prev = &(*prev)->next;
 
  196         set->next = duplicate->next;
 
  203         DEBUG(grf, 1, 
"Removing %s (%i) as base " SET_TYPE " set (duplicate, %s)", duplicate->name, duplicate->version,
 
  204             duplicate->valid_files < set->valid_files ? 
"less valid files" : 
"lower version");
 
  211       while (*last != NULL) last = &(*last)->next;
 
  217       DEBUG(grf, 1, 
"Adding %s (%i) as base " SET_TYPE " set", set->name, set->version);
 
  233 template <
class Tbase_set>
 
  245     if (strcmp(name, s->name) == 0) {
 
  260 template <
class Tbase_set>
 
  265     p += 
seprintf(p, last, 
"%18s: %s", s->name, s->GetDescription());
 
  266     int invalid = s->GetNumInvalid();
 
  268       int missing = s->GetNumMissing();
 
  270         p += 
seprintf(p, last, 
" (%i corrupt file%s)\n", invalid, invalid == 1 ? 
"" : 
"s");
 
  272         p += 
seprintf(p, last, 
" (unusable: %i missing file%s)\n", missing, missing == 1 ? 
"" : 
"s");
 
  283 #if defined(ENABLE_NETWORK) 
  288   for (; s != NULL; s = s->next) {
 
  289     if (s->GetNumMissing() != 0) 
continue;
 
  291     if (s->shortname != ci->
unique_id) 
continue;
 
  292     if (!md5sum) 
return  s->files[0].filename;
 
  295     memset(md5, 0, 
sizeof(md5));
 
  296     for (uint i = 0; i < Tbase_set::NUM_FILES; i++) {
 
  297       for (uint j = 0; j < 
sizeof(md5); j++) {
 
  298         md5[j] ^= s->files[i].hash[j];
 
  301     if (memcmp(md5, ci->
md5sum, 
sizeof(md5)) == 0) 
return s->files[0].filename;
 
  306 template <
class Tbase_set>
 
  315 template <
class Tbase_set>
 
  321 template <
class Tbase_set>
 
  333 template <
class Tbase_set>
 
  348 template <
class Tbase_set>
 
  354     if (s->GetNumMissing() != 0) 
continue;
 
  364 template <
class Tbase_set>
 
  369     if (index == 0) 
return s;
 
  372   error(
"Base" SET_TYPE "::GetSet(): index %d out of range", index);
 
  379 template <
class Tbase_set>
 
  389 template <
class Tbase_set>
 
  400 #define INSTANTIATE_BASE_MEDIA_METHODS(repl_type, set_type) \ 
  401   template const char *repl_type::ini_set; \ 
  402   template const char *repl_type::GetExtension(); \ 
  403   template bool repl_type::AddFile(const char *filename, size_t pathlength, const char *tar_filename); \ 
  404   template bool repl_type::HasSet(const struct ContentInfo *ci, bool md5sum); \ 
  405   template bool repl_type::SetSet(const char *name); \ 
  406   template char *repl_type::GetSetsList(char *p, const char *last); \ 
  407   template int repl_type::GetNumSets(); \ 
  408   template int repl_type::GetIndexOfUsedSet(); \ 
  409   template const set_type *repl_type::GetSet(int index); \ 
  410   template const set_type *repl_type::GetUsedSet(); \ 
  411   template bool repl_type::DetermineBestSet(); \ 
  412   template set_type *repl_type::GetAvailableSets(); \ 
  413   template const char *TryGetBaseSetFile(const ContentInfo *ci, bool md5sum, const set_type *s);