| // Copyright (c) 2021, the R8 project authors. Please see the AUTHORS file | |
| // for details. All rights reserved. Use of this source code is governed by a | |
| // BSD-style license that can be found in the LICENSE file. | |
| package com.android.tools.r8.utils; | |
| import com.android.tools.r8.DiagnosticsHandler; | |
| import com.android.tools.r8.MapIdEnvironment; | |
| import com.android.tools.r8.MapIdProvider; | |
| import com.google.common.collect.ImmutableMap; | |
| import java.util.Map; | |
| public class MapIdTemplateProvider implements MapIdProvider { | |
| private static final char VARIABLE_PREFIX = '%'; | |
| private static final Map<String, MapIdProvider> HANDLERS = | |
| ImmutableMap.<String, MapIdProvider>builder() | |
| .put(var("MAP_HASH"), MapIdEnvironment::getMapHash) | |
| .build(); | |
| private static String var(String name) { | |
| return VARIABLE_PREFIX + name; | |
| } | |
| private static int getMaxVariableLength() { | |
| int max = 0; | |
| for (String key : HANDLERS.keySet()) { | |
| max = Math.max(max, key.length()); | |
| } | |
| return max; | |
| } | |
| public static MapIdProvider create(String template, DiagnosticsHandler handler) { | |
| String cleaned = template; | |
| for (String variable : HANDLERS.keySet()) { | |
| // Maintain the same size as template so indexing remains valid for error reporting. | |
| cleaned = cleaned.replace(variable, ' ' + variable.substring(1)); | |
| } | |
| assert template.length() == cleaned.length(); | |
| int unhandled = cleaned.indexOf(VARIABLE_PREFIX); | |
| if (unhandled >= 0) { | |
| while (unhandled >= 0) { | |
| int endIndex = Math.min(unhandled + getMaxVariableLength(), template.length()); | |
| String variablePrefix = template.substring(unhandled, endIndex); | |
| handler.error( | |
| new StringDiagnostic("Invalid template variable starting with " + variablePrefix)); | |
| unhandled = cleaned.indexOf(VARIABLE_PREFIX, unhandled + 1); | |
| } | |
| return null; | |
| } | |
| return new MapIdTemplateProvider(template); | |
| } | |
| private final String template; | |
| private String cachedValue = null; | |
| private MapIdTemplateProvider(String template) { | |
| this.template = template; | |
| } | |
| @Override | |
| public String get(MapIdEnvironment environment) { | |
| if (cachedValue == null) { | |
| cachedValue = template; | |
| HANDLERS.forEach( | |
| (variable, getter) -> { | |
| cachedValue = cachedValue.replace(variable, getter.get(environment)); | |
| }); | |
| } | |
| return cachedValue; | |
| } | |
| } |