1 /*****************************************************************************
2  * Copyright (c) 2014-2020 OpenRCT2 developers
3  *
4  * For a complete list of all authors, please refer to contributors.md
5  * Interested in contributing? Visit https://github.com/OpenRCT2/OpenRCT2
6  *
7  * OpenRCT2 is licensed under the GNU General Public License version 3.
8  *****************************************************************************/
9 
10 #include "FormatCodes.h"
11 
12 #include "../core/EnumMap.hpp"
13 
14 #include <mutex>
15 #include <string>
16 #include <vector>
17 
18 // clang-format off
19 static const EnumMap<FormatToken> FormatTokenMap = {
20     { "MOVE_X",               FormatToken::Move,                },
21     { "NEWLINE",              FormatToken::Newline,             },
22     { "NEWLINE_SMALLER",      FormatToken::NewlineSmall,        },
23     { "TINYFONT",             FormatToken::FontTiny,            },
24     { "MEDIUMFONT",           FormatToken::FontMedium,          },
25     { "SMALLFONT",            FormatToken::FontSmall,           },
26     { "OUTLINE",              FormatToken::OutlineEnable,       },
27     { "OUTLINE_OFF",          FormatToken::OutlineDisable,      },
28     { "WINDOW_COLOUR_1",      FormatToken::ColourWindow1,       },
29     { "WINDOW_COLOUR_2",      FormatToken::ColourWindow2,       },
30     { "WINDOW_COLOUR_3",      FormatToken::ColourWindow3,       },
31     { "INLINE_SPRITE",        FormatToken::InlineSprite,        },
32     { "COMMA32",              FormatToken::Comma32,             },
33     { "INT32",                FormatToken::Int32,               },
34     { "COMMA1DP16",           FormatToken::Comma1dp16,          },
35     { "COMMA2DP32",           FormatToken::Comma2dp32,          },
36     { "COMMA16",              FormatToken::Comma16,             },
37     { "UINT16",               FormatToken::UInt16,              },
38     { "CURRENCY2DP",          FormatToken::Currency2dp,         },
39     { "CURRENCY",             FormatToken::Currency,            },
40     { "STRINGID",             FormatToken::StringId,            },
41     { "STRING",               FormatToken::String,              },
42     { "MONTHYEAR",            FormatToken::MonthYear,           },
43     { "MONTH",                FormatToken::Month,               },
44     { "VELOCITY",             FormatToken::Velocity,            },
45     { "POP16",                FormatToken::Pop16,               },
46     { "PUSH16",               FormatToken::Push16,              },
47     { "DURATION",             FormatToken::DurationShort,       },
48     { "REALTIME",             FormatToken::DurationLong,        },
49     { "LENGTH",               FormatToken::Length,              },
50     { "SPRITE",               FormatToken::Sprite,              },
51     { "BLACK",                FormatToken::ColourBlack,         },
52     { "GREY",                 FormatToken::ColourGrey,          },
53     { "WHITE",                FormatToken::ColourWhite,         },
54     { "RED",                  FormatToken::ColourRed,           },
55     { "GREEN",                FormatToken::ColourGreen,         },
56     { "YELLOW",               FormatToken::ColourYellow,        },
57     { "TOPAZ",                FormatToken::ColourTopaz,         },
58     { "CELADON",              FormatToken::ColourCeladon,       },
59     { "BABYBLUE",             FormatToken::ColourBabyBlue,      },
60     { "PALELAVENDER",         FormatToken::ColourPaleLavender,  },
61     { "PALEGOLD",             FormatToken::ColourPaleGold,      },
62     { "LIGHTPINK",            FormatToken::ColourLightPink,     },
63     { "PEARLAQUA",            FormatToken::ColourPearlAqua,     },
64     { "PALESILVER",           FormatToken::ColourPaleSilver,    },
65 };
66 // clang-format on
67 
GetFormatTokenStringWithBraces(FormatToken token)68 std::string_view GetFormatTokenStringWithBraces(FormatToken token)
69 {
70     // Ensure cache is thread safe
71     static std::mutex mutex;
72     std::lock_guard<std::mutex> guard(mutex);
73 
74     static std::vector<std::string> cache;
75     auto index = static_cast<size_t>(token);
76     if (cache.size() <= index)
77     {
78         cache.resize(index + 1);
79     }
80     if (cache[index].empty())
81     {
82         cache[index] = "{" + std::string(FormatTokenToString(token)) + "}";
83     }
84     return cache[index];
85 }
86 
FormatTokenFromString(std::string_view token)87 FormatToken FormatTokenFromString(std::string_view token)
88 {
89     auto result = FormatTokenMap.find(token);
90     return result != std::end(FormatTokenMap) ? result->second : FormatToken::Unknown;
91 }
92 
FormatTokenToString(FormatToken token,bool withBraces)93 std::string_view FormatTokenToString(FormatToken token, bool withBraces)
94 {
95     if (withBraces)
96     {
97         return GetFormatTokenStringWithBraces(token);
98     }
99 
100     auto it = FormatTokenMap.find(token);
101     if (it != FormatTokenMap.end())
102         return it->first;
103 
104     return {};
105 }
106 
FormatTokenTakesArgument(FormatToken token)107 bool FormatTokenTakesArgument(FormatToken token)
108 {
109     switch (token)
110     {
111         case FormatToken::Comma32:
112         case FormatToken::Int32:
113         case FormatToken::Comma1dp16:
114         case FormatToken::Comma2dp32:
115         case FormatToken::Comma16:
116         case FormatToken::UInt16:
117         case FormatToken::Currency2dp:
118         case FormatToken::Currency:
119         case FormatToken::StringId:
120         case FormatToken::String:
121         case FormatToken::MonthYear:
122         case FormatToken::Month:
123         case FormatToken::Velocity:
124         case FormatToken::DurationShort:
125         case FormatToken::DurationLong:
126         case FormatToken::Length:
127         case FormatToken::Sprite:
128             return true;
129         default:
130             return false;
131     }
132 }
133 
FormatTokenIsColour(FormatToken token)134 bool FormatTokenIsColour(FormatToken token)
135 {
136     switch (token)
137     {
138         case FormatToken::ColourBlack:
139         case FormatToken::ColourGrey:
140         case FormatToken::ColourWhite:
141         case FormatToken::ColourRed:
142         case FormatToken::ColourGreen:
143         case FormatToken::ColourYellow:
144         case FormatToken::ColourTopaz:
145         case FormatToken::ColourCeladon:
146         case FormatToken::ColourBabyBlue:
147         case FormatToken::ColourPaleLavender:
148         case FormatToken::ColourPaleGold:
149         case FormatToken::ColourLightPink:
150         case FormatToken::ColourPearlAqua:
151         case FormatToken::ColourPaleSilver:
152             return true;
153         default:
154             return false;
155     }
156 }
157 
FormatTokenGetTextColourIndex(FormatToken token)158 size_t FormatTokenGetTextColourIndex(FormatToken token)
159 {
160     switch (token)
161     {
162         case FormatToken::ColourBlack:
163             return 0;
164         case FormatToken::ColourGrey:
165             return 1;
166         case FormatToken::ColourWhite:
167             return 2;
168         case FormatToken::ColourRed:
169             return 3;
170         case FormatToken::ColourGreen:
171             return 4;
172         case FormatToken::ColourYellow:
173             return 5;
174         case FormatToken::ColourTopaz:
175             return 6;
176         case FormatToken::ColourCeladon:
177             return 7;
178         case FormatToken::ColourBabyBlue:
179             return 8;
180         case FormatToken::ColourPaleLavender:
181             return 9;
182         case FormatToken::ColourPaleGold:
183             return 10;
184         case FormatToken::ColourLightPink:
185             return 11;
186         case FormatToken::ColourPearlAqua:
187             return 12;
188         case FormatToken::ColourPaleSilver:
189             return 13;
190         default:
191             return 0;
192     }
193 }
194 
FormatTokenFromTextColour(size_t textColour)195 FormatToken FormatTokenFromTextColour(size_t textColour)
196 {
197     static constexpr const FormatToken tokens[] = {
198         FormatToken::ColourBlack,        FormatToken::ColourGrey,       FormatToken::ColourWhite,
199         FormatToken::ColourRed,          FormatToken::ColourGreen,      FormatToken::ColourYellow,
200         FormatToken::ColourTopaz,        FormatToken::ColourCeladon,    FormatToken::ColourBabyBlue,
201         FormatToken::ColourPaleLavender, FormatToken::ColourPaleGold,   FormatToken::ColourLightPink,
202         FormatToken::ColourPearlAqua,    FormatToken::ColourPaleSilver,
203     };
204     if (textColour > std::size(tokens))
205         return FormatToken::ColourBlack;
206     return tokens[textColour];
207 }
208