1 /*
2  * Copyright (C) 2018 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.xsdc.cpp;
18 
19 import java.util.Arrays;
20 import java.util.HashSet;
21 
22 class Utils {
23     private static final String[] keywords = {
24         "alignas", "alignof", "and", "and_eq", "asm", "atomic_cancel", "atomic_commit",
25         "atomic_noexcept", "auto", "bitand", "bitor", "bool", "break", "case", "catch",
26         "char", "char16_t", "char32_t", "class", "compl", "concept", "const", "constexpr",
27         "const_cast", "continue", "decltype", "default", "delete", "do", "double",
28         "dynamic_cast", "else", "enum", "explicit", "export", "extern", "false", "float",
29         "for", "friend", "goto", "if", "inline", "int", "import", "long", "module", "mutable",
30         "namespace", "new", "noexcept", "not", "not_eq", "nullptr", "operator", "or", "or_eq",
31         "private", "protected", "public", "register", "reinterpret_cast", "requires", "return",
32         "short", "signed", "sizeof", "static", "static_assert", "static_cast", "struct",
33         "switch", "synchronized", "template", "this", "thread_local", "throw", "true", "try",
34         "typedef", "typeid", "typename", "union", "unsigned", "using", "virtual", "void",
35         "volatile", "wchar_t", "while", "xor", "xor_eq",
36     };
37     private static final HashSet<String> keywordSet = new HashSet<>(Arrays.asList(keywords));
38 
toCamelCase(String[] words)39     private static String toCamelCase(String[] words) {
40         String res = words[0];
41         for (int idx = 1; idx < words.length; ++idx) {
42             res += capitalize(words[idx]);
43         }
44         return res;
45     }
46 
capitalize(String input)47     static String capitalize(String input) {
48         return input.substring(0, 1).toUpperCase() + input.substring(1);
49     }
50 
lowerize(String input)51     static String lowerize(String input) {
52         return input.substring(0, 1).toLowerCase() + input.substring(1);
53     }
54 
toVariableName(String name)55     static String toVariableName(String name) throws CppCodeGeneratorException {
56         String trimmed = toCamelCase(name.replaceAll("[^A-Za-z0-9_-]", "").split("-"));
57         if (trimmed.isEmpty()) {
58             throw new CppCodeGeneratorException(
59                     String.format("cannot convert to a variable name : %s", name));
60         }
61         String lowered = Character.isDigit(trimmed.charAt(0)) ? "_" + trimmed
62                 : lowerize(trimmed);
63         // always starts with a lowercase or underscore character.
64         return (keywordSet.contains(lowered)) ? "_" + lowered : lowered;
65     }
66 
toClassName(String name)67     static String toClassName(String name) throws CppCodeGeneratorException {
68         String trimmed = toCamelCase(
69                 name.replaceAll("[^A-Za-z0-9_-]", "").replaceAll("[\\.-]", "_").split("_"));
70         if (trimmed.isEmpty() || Character.isDigit(trimmed.charAt(0))) {
71             throw new CppCodeGeneratorException(
72                     String.format("cannot convert to a class name : %s", name));
73         }
74         return capitalize(trimmed);
75     }
76 
toEnumName(String name)77     static String toEnumName(String name) throws CppCodeGeneratorException {
78         if ("".equals(name)) {
79             name = "EMPTY";
80         }
81         String trimmed = name.replace(".", "_").replaceAll("[^A-Za-z0-9_]", "");
82         if (trimmed.isEmpty()) {
83             throw new CppCodeGeneratorException(
84                     String.format("cannot convert to a variable name : %s", name));
85         }
86         String enumName = Character.isDigit(trimmed.charAt(0)) ? "_" + trimmed : trimmed;
87         return (keywordSet.contains(enumName)) ? "_" + enumName : enumName;
88     }
89 
toAssignmentName(String typeName, String variableName, boolean isMultipleType)90     static String toAssignmentName(String typeName, String variableName, boolean isMultipleType) {
91         if (isMultipleType || typeName.equals("std::string")) {
92             return String.format("std::move(%s)", variableName);
93         }
94         return variableName;
95     }
96 
elementTypeName(String name, boolean isMultipleType)97     static String elementTypeName(String name, boolean isMultipleType) {
98         String res;
99         if (isMultipleType) {
100             res = "std::vector<" + name + ">";
101         } else {
102             res = "std::optional<" + name + ">";
103         }
104         return res;
105     }
106 }
107