| 180 | } |
| 181 | |
| 182 | char* parse(char* ptr) |
| 183 | { |
| 184 | while(argCount < maxArgs) { |
| 185 | /* |
| 186 | * Parse either: |
| 187 | * varname name:12... -> valueof(name) |
| 188 | * raw value 15:18... -> 15 |
| 189 | * quoted value "text":arg... -> text |
| 190 | * |
| 191 | * ptr is left at separator |
| 192 | */ |
| 193 | if(*ptr == '\0' || *ptr == '}') { |
| 194 | break; |
| 195 | } |
| 196 | |
| 197 | auto& arg = args[argCount++]; |
| 198 | if(*ptr == '"') { |
| 199 | ++ptr; |
| 200 | arg.type = Arg::Type::string; |
| 201 | arg.ptr = ptr; |
| 202 | auto endQuote = strchr(ptr, '"'); |
| 203 | if(endQuote == nullptr) { |
| 204 | // Malformed {cmd:"value} |
| 205 | ptr += strlen(ptr); |
| 206 | } else { |
| 207 | *endQuote = '\0'; |
| 208 | ptr = endQuote + 1; |
| 209 | } |
| 210 | } else { |
| 211 | if(*ptr == '{') { |
| 212 | ++ptr; |
| 213 | arg.type = Arg::Type::expression; |
| 214 | arg.ptr = new String(tmpl.evaluate(ptr)); |
| 215 | } else if(isNumber(ptr)) { |
| 216 | arg.type = Arg::Type::number; |
| 217 | arg.ptr = ptr; |
| 218 | } else { |
| 219 | arg.type = Arg::Type::variable; |
| 220 | arg.ptr = ptr; |
| 221 | } |
| 222 | ptr = findSep(ptr); |
| 223 | } |
| 224 | |
| 225 | char c = *ptr; |
| 226 | *ptr++ = '\0'; |
| 227 | if(c != ':') { |
| 228 | break; |
| 229 | } |
| 230 | } |
| 231 | |
| 232 | return ptr; |
| 233 | } |
| 234 | |
| 235 | uint8_t count() const |
| 236 | { |