while (sscanf(remainder, "%s%n", buf, &consumed) == 1) { string value; string flag = buf; size_t eqAt = flag.find('='); if (eqAt != string::npos) { value = flag.substr(eqAt + 1); flag.erase(eqAt); } switch (hash(flag)) { case str_case(flag, "Blends") { tileProp.blends = true; break; } case str_case(flag, "Framed") { tileProp.isFramed = true; break; } case str_case(flag, "UnFramed") { break; } case str_case(flag, "Solid") { tileProp.isSolid = true; break; } case str_case(flag, "SolidTop") { tileProp.topIsSolid = true; break; } case str_case(flag, "Platform") { tileProp.isPlatform = true; break; } case str_case(flag, "Merge") { tileProp.blendWith = atol(value.c_str()); break; } case str_case(flag, "Stone") { tileProp.isStone = true; break; } case str_case(flag, "Grass") { tileProp.isGrass = true; break; } case str_case(flag, "OnCeil") { tileProp.placement = TilePlacement::ON_CEILING; break; } case str_case(flag, "OnFaces") { tileProp.placement = TilePlacement::ON_FACES; break; } case str_case(flag, "OnFloorSurf") { tileProp.placement = TilePlacement::ON_FACES; break; } case str_case(flag, "OnFloor") { tileProp.placement = TilePlacement::ON_FLOOR; break; } case str_case(flag, "OnSurf") { tileProp.placement = TilePlacement::ON_SURFACES; break; } case str_case(flag, "OnTorch") { tileProp.placement = TilePlacement::ON_TORCH_PTS; break; } case str_case(flag, "OnWall") { tileProp.placement = TilePlacement::ON_WALLS; break; } case str_case(flag, "AsDoor") { tileProp.placement = TilePlacement::AS_DOOR; break; } case str_case(flag, "Light") { tileProp.isLightSource = true; break; } case str_case(flag, "TX") { tileProp.tX = atol(value.c_str()); break; } case str_case(flag, "TY") { tileProp.tY = atol(value.c_str()); break; } default: fprintf(stderr, "Unknown flag %s\n", flag.c_str()); return 2; } remainder += consumed; } // The magic constexpr int filthyHash(const char *x, int y, int z, int res) { return z < y ? filthyHash(x, y, z + 1, (int)((long)res * 31 + x[z])) : res; } constexpr int cleanHash(const char* x, int y) { return filthyHash(x, y, 0, 0) << 4 | (y & ((1 << 4) - 1)); } template constexpr int dirtyHash(const char (&x)[N]) { return cleanHash(x, N - 1); } int hash(string x) { return cleanHash(x.c_str(), x.length()); } #define str_case(key, x) dirtyHash(x): if ((key) == (x))