1927c5d5fdc46eb60c28e569a922659733d927adaTom Cherry// 2927c5d5fdc46eb60c28e569a922659733d927adaTom Cherry// Copyright (C) 2017 The Android Open Source Project 3927c5d5fdc46eb60c28e569a922659733d927adaTom Cherry// 4927c5d5fdc46eb60c28e569a922659733d927adaTom Cherry// Licensed under the Apache License, Version 2.0 (the "License"); 5927c5d5fdc46eb60c28e569a922659733d927adaTom Cherry// you may not use this file except in compliance with the License. 6927c5d5fdc46eb60c28e569a922659733d927adaTom Cherry// You may obtain a copy of the License at 7927c5d5fdc46eb60c28e569a922659733d927adaTom Cherry// 8927c5d5fdc46eb60c28e569a922659733d927adaTom Cherry// http://www.apache.org/licenses/LICENSE-2.0 9927c5d5fdc46eb60c28e569a922659733d927adaTom Cherry// 10927c5d5fdc46eb60c28e569a922659733d927adaTom Cherry// Unless required by applicable law or agreed to in writing, software 11927c5d5fdc46eb60c28e569a922659733d927adaTom Cherry// distributed under the License is distributed on an "AS IS" BASIS, 12927c5d5fdc46eb60c28e569a922659733d927adaTom Cherry// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13927c5d5fdc46eb60c28e569a922659733d927adaTom Cherry// See the License for the specific language governing permissions and 14927c5d5fdc46eb60c28e569a922659733d927adaTom Cherry// limitations under the License. 15927c5d5fdc46eb60c28e569a922659733d927adaTom Cherry// 16927c5d5fdc46eb60c28e569a922659733d927adaTom Cherry 17919458c350563e578e2d55852fbae187756c130aTom Cherry#include <property_info_serializer/property_info_serializer.h> 18919458c350563e578e2d55852fbae187756c130aTom Cherry 19919458c350563e578e2d55852fbae187756c130aTom Cherry#include <android-base/strings.h> 20919458c350563e578e2d55852fbae187756c130aTom Cherry 21919458c350563e578e2d55852fbae187756c130aTom Cherry#include "space_tokenizer.h" 22919458c350563e578e2d55852fbae187756c130aTom Cherry 23927c5d5fdc46eb60c28e569a922659733d927adaTom Cherryusing android::base::Join; 24919458c350563e578e2d55852fbae187756c130aTom Cherryusing android::base::Split; 25919458c350563e578e2d55852fbae187756c130aTom Cherryusing android::base::StartsWith; 26919458c350563e578e2d55852fbae187756c130aTom Cherryusing android::base::Trim; 27919458c350563e578e2d55852fbae187756c130aTom Cherry 28919458c350563e578e2d55852fbae187756c130aTom Cherrynamespace android { 29919458c350563e578e2d55852fbae187756c130aTom Cherrynamespace properties { 30919458c350563e578e2d55852fbae187756c130aTom Cherry 31927c5d5fdc46eb60c28e569a922659733d927adaTom Cherrynamespace { 32927c5d5fdc46eb60c28e569a922659733d927adaTom Cherry 33927c5d5fdc46eb60c28e569a922659733d927adaTom Cherrybool IsTypeValid(const std::vector<std::string>& type_strings) { 34927c5d5fdc46eb60c28e569a922659733d927adaTom Cherry if (type_strings.empty()) { 35927c5d5fdc46eb60c28e569a922659733d927adaTom Cherry return false; 36927c5d5fdc46eb60c28e569a922659733d927adaTom Cherry } 37927c5d5fdc46eb60c28e569a922659733d927adaTom Cherry 38927c5d5fdc46eb60c28e569a922659733d927adaTom Cherry // There must be at least one string following 'enum' 39927c5d5fdc46eb60c28e569a922659733d927adaTom Cherry if (type_strings[0] == "enum") { 40927c5d5fdc46eb60c28e569a922659733d927adaTom Cherry return type_strings.size() > 1; 41927c5d5fdc46eb60c28e569a922659733d927adaTom Cherry } 42927c5d5fdc46eb60c28e569a922659733d927adaTom Cherry 43927c5d5fdc46eb60c28e569a922659733d927adaTom Cherry // There should not be any string following any other types. 44927c5d5fdc46eb60c28e569a922659733d927adaTom Cherry if (type_strings.size() != 1) { 45927c5d5fdc46eb60c28e569a922659733d927adaTom Cherry return false; 46927c5d5fdc46eb60c28e569a922659733d927adaTom Cherry } 47927c5d5fdc46eb60c28e569a922659733d927adaTom Cherry 48927c5d5fdc46eb60c28e569a922659733d927adaTom Cherry // Check that the type matches one of remaining valid types. 49927c5d5fdc46eb60c28e569a922659733d927adaTom Cherry static const char* const no_parameter_types[] = {"string", "bool", "int", 50927c5d5fdc46eb60c28e569a922659733d927adaTom Cherry "uint", "double", "size"}; 51927c5d5fdc46eb60c28e569a922659733d927adaTom Cherry for (const auto& type : no_parameter_types) { 52927c5d5fdc46eb60c28e569a922659733d927adaTom Cherry if (type_strings[0] == type) { 53927c5d5fdc46eb60c28e569a922659733d927adaTom Cherry return true; 54927c5d5fdc46eb60c28e569a922659733d927adaTom Cherry } 55927c5d5fdc46eb60c28e569a922659733d927adaTom Cherry } 56927c5d5fdc46eb60c28e569a922659733d927adaTom Cherry return false; 57927c5d5fdc46eb60c28e569a922659733d927adaTom Cherry} 58927c5d5fdc46eb60c28e569a922659733d927adaTom Cherry 59919458c350563e578e2d55852fbae187756c130aTom Cherrybool ParsePropertyInfoLine(const std::string& line, PropertyInfoEntry* out, std::string* error) { 60919458c350563e578e2d55852fbae187756c130aTom Cherry auto tokenizer = SpaceTokenizer(line); 61919458c350563e578e2d55852fbae187756c130aTom Cherry 62919458c350563e578e2d55852fbae187756c130aTom Cherry auto property = tokenizer.GetNext(); 63919458c350563e578e2d55852fbae187756c130aTom Cherry if (property.empty()) { 64919458c350563e578e2d55852fbae187756c130aTom Cherry *error = "Did not find a property entry in '" + line + "'"; 65919458c350563e578e2d55852fbae187756c130aTom Cherry return false; 66919458c350563e578e2d55852fbae187756c130aTom Cherry } 67919458c350563e578e2d55852fbae187756c130aTom Cherry 68919458c350563e578e2d55852fbae187756c130aTom Cherry auto context = tokenizer.GetNext(); 69919458c350563e578e2d55852fbae187756c130aTom Cherry if (context.empty()) { 70919458c350563e578e2d55852fbae187756c130aTom Cherry *error = "Did not find a context entry in '" + line + "'"; 71919458c350563e578e2d55852fbae187756c130aTom Cherry return false; 72919458c350563e578e2d55852fbae187756c130aTom Cherry } 73919458c350563e578e2d55852fbae187756c130aTom Cherry 74927c5d5fdc46eb60c28e569a922659733d927adaTom Cherry // It is not an error to not find exact_match or a type, as older files will not contain them. 75919458c350563e578e2d55852fbae187756c130aTom Cherry auto exact_match = tokenizer.GetNext(); 76927c5d5fdc46eb60c28e569a922659733d927adaTom Cherry // We reformat type to be space deliminated regardless of the input whitespace for easier storage 77927c5d5fdc46eb60c28e569a922659733d927adaTom Cherry // and subsequent parsing. 78927c5d5fdc46eb60c28e569a922659733d927adaTom Cherry auto type_strings = std::vector<std::string>{}; 79927c5d5fdc46eb60c28e569a922659733d927adaTom Cherry auto type = tokenizer.GetNext(); 80927c5d5fdc46eb60c28e569a922659733d927adaTom Cherry while (!type.empty()) { 81927c5d5fdc46eb60c28e569a922659733d927adaTom Cherry type_strings.emplace_back(type); 82927c5d5fdc46eb60c28e569a922659733d927adaTom Cherry type = tokenizer.GetNext(); 83927c5d5fdc46eb60c28e569a922659733d927adaTom Cherry } 84919458c350563e578e2d55852fbae187756c130aTom Cherry 85927c5d5fdc46eb60c28e569a922659733d927adaTom Cherry if (!type_strings.empty() && !IsTypeValid(type_strings)) { 86927c5d5fdc46eb60c28e569a922659733d927adaTom Cherry *error = "Type '" + Join(type_strings, " ") + "' is not valid"; 87927c5d5fdc46eb60c28e569a922659733d927adaTom Cherry return false; 88927c5d5fdc46eb60c28e569a922659733d927adaTom Cherry } 89927c5d5fdc46eb60c28e569a922659733d927adaTom Cherry 90927c5d5fdc46eb60c28e569a922659733d927adaTom Cherry *out = {property, context, Join(type_strings, " "), exact_match == "exact"}; 91919458c350563e578e2d55852fbae187756c130aTom Cherry return true; 92919458c350563e578e2d55852fbae187756c130aTom Cherry} 93919458c350563e578e2d55852fbae187756c130aTom Cherry 94927c5d5fdc46eb60c28e569a922659733d927adaTom Cherry} // namespace 95927c5d5fdc46eb60c28e569a922659733d927adaTom Cherry 96919458c350563e578e2d55852fbae187756c130aTom Cherryvoid ParsePropertyInfoFile(const std::string& file_contents, 97919458c350563e578e2d55852fbae187756c130aTom Cherry std::vector<PropertyInfoEntry>* property_infos, 98919458c350563e578e2d55852fbae187756c130aTom Cherry std::vector<std::string>* errors) { 99919458c350563e578e2d55852fbae187756c130aTom Cherry // Do not clear property_infos to allow this function to be called on multiple files, with 100919458c350563e578e2d55852fbae187756c130aTom Cherry // their results concatenated. 101919458c350563e578e2d55852fbae187756c130aTom Cherry errors->clear(); 102919458c350563e578e2d55852fbae187756c130aTom Cherry 103919458c350563e578e2d55852fbae187756c130aTom Cherry for (const auto& line : Split(file_contents, "\n")) { 104919458c350563e578e2d55852fbae187756c130aTom Cherry auto trimmed_line = Trim(line); 105919458c350563e578e2d55852fbae187756c130aTom Cherry if (trimmed_line.empty() || StartsWith(trimmed_line, "#")) { 106919458c350563e578e2d55852fbae187756c130aTom Cherry continue; 107919458c350563e578e2d55852fbae187756c130aTom Cherry } 108919458c350563e578e2d55852fbae187756c130aTom Cherry 109919458c350563e578e2d55852fbae187756c130aTom Cherry auto property_info_entry = PropertyInfoEntry{}; 110919458c350563e578e2d55852fbae187756c130aTom Cherry auto parse_error = std::string{}; 111919458c350563e578e2d55852fbae187756c130aTom Cherry if (!ParsePropertyInfoLine(trimmed_line, &property_info_entry, &parse_error)) { 112919458c350563e578e2d55852fbae187756c130aTom Cherry errors->emplace_back(parse_error); 113919458c350563e578e2d55852fbae187756c130aTom Cherry continue; 114919458c350563e578e2d55852fbae187756c130aTom Cherry } 115919458c350563e578e2d55852fbae187756c130aTom Cherry 116919458c350563e578e2d55852fbae187756c130aTom Cherry property_infos->emplace_back(property_info_entry); 117919458c350563e578e2d55852fbae187756c130aTom Cherry } 118919458c350563e578e2d55852fbae187756c130aTom Cherry} 119919458c350563e578e2d55852fbae187756c130aTom Cherry 120919458c350563e578e2d55852fbae187756c130aTom Cherry} // namespace properties 121919458c350563e578e2d55852fbae187756c130aTom Cherry} // namespace android 122