159ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn#!/usr/bin/python2 259ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn 33daa5a0d71ba8facd8be9370df54c20c23be6d8dUtkarsh Sanghi# 43daa5a0d71ba8facd8be9370df54c20c23be6d8dUtkarsh Sanghi# Copyright (C) 2015 The Android Open Source Project 53daa5a0d71ba8facd8be9370df54c20c23be6d8dUtkarsh Sanghi# 63daa5a0d71ba8facd8be9370df54c20c23be6d8dUtkarsh Sanghi# Licensed under the Apache License, Version 2.0 (the "License"); 73daa5a0d71ba8facd8be9370df54c20c23be6d8dUtkarsh Sanghi# you may not use this file except in compliance with the License. 83daa5a0d71ba8facd8be9370df54c20c23be6d8dUtkarsh Sanghi# You may obtain a copy of the License at 93daa5a0d71ba8facd8be9370df54c20c23be6d8dUtkarsh Sanghi# 103daa5a0d71ba8facd8be9370df54c20c23be6d8dUtkarsh Sanghi# http://www.apache.org/licenses/LICENSE-2.0 113daa5a0d71ba8facd8be9370df54c20c23be6d8dUtkarsh Sanghi# 123daa5a0d71ba8facd8be9370df54c20c23be6d8dUtkarsh Sanghi# Unless required by applicable law or agreed to in writing, software 133daa5a0d71ba8facd8be9370df54c20c23be6d8dUtkarsh Sanghi# distributed under the License is distributed on an "AS IS" BASIS, 143daa5a0d71ba8facd8be9370df54c20c23be6d8dUtkarsh Sanghi# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 153daa5a0d71ba8facd8be9370df54c20c23be6d8dUtkarsh Sanghi# See the License for the specific language governing permissions and 163daa5a0d71ba8facd8be9370df54c20c23be6d8dUtkarsh Sanghi# limitations under the License. 173daa5a0d71ba8facd8be9370df54c20c23be6d8dUtkarsh Sanghi# 1859ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn 1959ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn"""A C++ code generator for printing protobufs which use the LITE_RUNTIME. 2059ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn 2159ea81cf9e7b293ec3241e5d442092b0278a3643Darren KrahnNormally printing a protobuf would be done with Message::DebugString(). However, 2259ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahnthis is not available when using only MessageLite. This script generates code to 2359ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahnemulate Message::DebugString() without using reflection. The input must be a 2459ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahnvalid .proto file. 2559ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn 2659ea81cf9e7b293ec3241e5d442092b0278a3643Darren KrahnUsage: proto_print.py [--subdir=foo] <bar.proto> 2759ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn 2859ea81cf9e7b293ec3241e5d442092b0278a3643Darren KrahnFiles named print_bar_proto.h and print_bar_proto.cc will be created in the 2959ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahncurrent working directory. 3059ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn""" 3159ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn 3259ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahnfrom __future__ import print_function 3359ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn 3459ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahnimport argparse 3559ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahnimport collections 3659ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahnfrom datetime import date 3759ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahnimport os 3859ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahnimport re 3959ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahnimport subprocess 4059ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn 4159ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn 4259ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn# Holds information about a protobuf message field. 4359ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn# 4459ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn# Attributes: 4559ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn# repeated: Whether the field is a repeated field. 4659ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn# type_: The type of the field. E.g. int32. 4759ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn# name: The name of the field. 4859ea81cf9e7b293ec3241e5d442092b0278a3643Darren KrahnField = collections.namedtuple('Field', 'repeated type_ name') 4959ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn 5059ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn 5159ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahnclass Message(object): 5259ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn """Holds information about a protobuf message. 5359ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn 5459ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn Attributes: 5559ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn name: The name of the message. 5659ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn fields: A list of Field tuples. 5759ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn """ 5859ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn 5959ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn def __init__(self, name): 6059ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn """Initializes a Message instance. 6159ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn 6259ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn Args: 6359ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn name: The protobuf message name. 6459ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn """ 6559ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn self.name = name 6659ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn self.fields = [] 6759ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn 6859ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn def AddField(self, attribute, field_type, field_name): 6959ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn """Adds a new field to the message. 7059ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn 7159ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn Args: 7259ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn attribute: This should be 'optional', 'required', or 'repeated'. 7359ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn field_type: The type of the field. E.g. int32. 7459ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn field_name: The name of the field. 7559ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn """ 7659ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn self.fields.append(Field(repeated=attribute == 'repeated', 7759ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn type_=field_type, name=field_name)) 7859ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn 7959ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn 8059ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahnclass Enum(object): 8159ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn """Holds information about a protobuf enum. 8259ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn 8359ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn Attributes: 8459ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn name: The name of the enum. 8559ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn values: A list of enum value names. 8659ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn """ 8759ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn 8859ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn def __init__(self, name): 8959ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn """Initializes a Enum instance. 9059ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn 9159ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn Args: 9259ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn name: The protobuf enum name. 9359ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn """ 9459ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn self.name = name 9559ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn self.values = [] 9659ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn 9759ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn def AddValue(self, value_name): 9859ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn """Adds a new value to the enum. 9959ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn 10059ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn Args: 10159ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn value_name: The name of the value. 10259ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn """ 10359ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn self.values.append(value_name) 10459ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn 10559ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn 10659ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahndef ParseProto(input_file): 10759ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn """Parses a proto file and returns a tuple of parsed information. 10859ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn 10959ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn Args: 11059ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn input_file: The proto file to parse. 11159ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn 11259ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn Returns: 11359ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn A tuple in the form (package, imports, messages, enums) where 11459ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn package: A string holding the proto package. 11559ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn imports: A list of strings holding proto imports. 11659ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn messages: A list of Message objects; one for each message in the proto. 11759ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn enums: A list of Enum objects; one for each enum in the proto. 11859ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn """ 11959ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn package = '' 12059ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn imports = [] 12159ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn messages = [] 12259ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn enums = [] 12359ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn current_message_stack = [] 12459ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn current_enum = None 12559ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn package_re = re.compile(r'package\s+(\w+);') 126c3fcde6097f2793fd09c6c529c8d13fa3fc61ebcDarren Krahn import_re = re.compile(r'import\s+"([\w]*/)*(\w+).proto";') 12759ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn message_re = re.compile(r'message\s+(\w+)\s*{') 12859ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn field_re = re.compile(r'(optional|required|repeated)\s+(\w+)\s+(\w+)\s*=') 12959ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn enum_re = re.compile(r'enum\s+(\w+)\s*{') 13059ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn enum_value_re = re.compile(r'(\w+)\s*=') 13159ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn for line in input_file: 13259ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn line = line.strip() 13359ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn if not line or line.startswith('//'): 13459ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn continue 13559ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn # Close off the current scope. Enums first because they can't be nested. 13659ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn if line == '}': 13759ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn if current_enum: 13859ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn enums.append(current_enum) 13959ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn current_enum = None 14059ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn if current_message_stack: 14159ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn messages.append(current_message_stack.pop()) 14259ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn continue 14359ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn # Look for a message definition. 14459ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn match = message_re.search(line) 14559ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn if match: 14659ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn prefix = '' 14759ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn if current_message_stack: 14859ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn prefix = '::'.join([m.name for m in current_message_stack]) + '::' 14959ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn current_message_stack.append(Message(prefix + match.group(1))) 15059ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn continue 15159ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn # Look for a message field definition. 15259ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn if current_message_stack: 15359ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn match = field_re.search(line) 15459ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn if match: 15559ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn current_message_stack[-1].AddField(match.group(1), 15659ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn match.group(2), 15759ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn match.group(3)) 15859ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn continue 15959ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn # Look for an enum definition. 16059ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn match = enum_re.search(line) 16159ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn if match: 16259ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn current_enum = Enum(match.group(1)) 16359ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn continue 16459ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn # Look for an enum value. 16559ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn if current_enum: 16659ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn match = enum_value_re.search(line) 16759ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn if match: 16859ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn current_enum.AddValue(match.group(1)) 16959ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn continue 17059ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn # Look for a package statement. 17159ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn match = package_re.search(line) 17259ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn if match: 17359ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn package = match.group(1) 17459ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn # Look for an import statement. 17559ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn match = import_re.search(line) 17659ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn if match: 177c3fcde6097f2793fd09c6c529c8d13fa3fc61ebcDarren Krahn imports.append(match.group(2)) 17859ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn return package, imports, messages, enums 17959ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn 18059ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn 18159ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahndef GenerateFileHeaders(proto_name, package, imports, subdir, header_file_name, 18259ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn header_file, impl_file): 18359ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn """Generates and prints file headers. 18459ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn 18559ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn Args: 18659ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn proto_name: The name of the proto file. 18759ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn package: The protobuf package. 18859ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn imports: A list of imported protos. 18959ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn subdir: The --subdir arg. 19059ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn header_file_name: The header file name. 19159ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn header_file: The header file handle, open for writing. 19259ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn impl_file: The implementation file handle, open for writing. 19359ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn """ 19459ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn if subdir: 19559ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn guard_name = '%s_%s_PRINT_%s_PROTO_H_' % (package.upper(), 19659ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn subdir.upper(), 19759ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn proto_name.upper()) 19859ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn package_with_subdir = '%s/%s' % (package, subdir) 19959ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn else: 20059ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn guard_name = '%s_PRINT_%s_PROTO_H_' % (package.upper(), proto_name.upper()) 20159ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn package_with_subdir = package 20259ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn includes = '\n'.join( 20359ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn ['#include "%(package_with_subdir)s/print_%(import)s_proto.h"' % { 20459ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn 'package_with_subdir': package_with_subdir, 20559ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn 'import': current_import} for current_import in imports]) 20659ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn header = """\ 20759ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn// Copyright %(year)s The Chromium OS Authors. All rights reserved. 20859ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn// Use of this source code is governed by a BSD-style license that can be 20959ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn// found in the LICENSE file. 21059ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn 21159ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn// THIS CODE IS GENERATED. 21259ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn 21359ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn#ifndef %(guard_name)s 21459ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn#define %(guard_name)s 21559ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn 21659ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn#include <string> 21759ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn 21859ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn#include "%(package_with_subdir)s/%(proto)s.pb.h" 21959ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn 22059ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahnnamespace %(package)s { 22159ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn""" % {'year': date.today().year, 22259ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn 'guard_name': guard_name, 22359ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn 'package': package, 22459ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn 'proto': proto_name, 22559ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn 'package_with_subdir': package_with_subdir} 22659ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn impl = """\ 22759ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn// Copyright %(year)s The Chromium OS Authors. All rights reserved. 22859ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn// Use of this source code is governed by a BSD-style license that can be 22959ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn// found in the LICENSE file. 23059ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn 23159ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn// THIS CODE IS GENERATED. 23259ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn 23359ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn#include "%(package_with_subdir)s/%(header_file_name)s" 23459ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn 23559ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn#include <string> 23659ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn 23759ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn#include <base/strings/string_number_conversions.h> 23859ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn#include <base/strings/stringprintf.h> 23959ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn 24059ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn%(includes)s 24159ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn 24259ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahnnamespace %(package)s { 24359ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn""" % {'year': date.today().year, 24459ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn 'package': package, 24559ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn 'package_with_subdir': package_with_subdir, 24659ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn 'header_file_name': header_file_name, 24759ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn 'includes': includes} 24859ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn 24959ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn header_file.write(header) 25059ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn impl_file.write(impl) 25159ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn 25259ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn 25359ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahndef GenerateFileFooters(proto_name, package, subdir, header_file, impl_file): 25459ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn """Generates and prints file footers. 25559ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn 25659ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn Args: 25759ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn proto_name: The name of the proto file. 25859ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn package: The protobuf package. 25959ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn subdir: The --subdir arg. 26059ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn header_file: The header file handle, open for writing. 26159ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn impl_file: The implementation file handle, open for writing. 26259ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn """ 26359ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn if subdir: 26459ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn guard_name = '%s_%s_PRINT_%s_PROTO_H_' % (package.upper(), 26559ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn subdir.upper(), 26659ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn proto_name.upper()) 26759ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn else: 26859ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn guard_name = '%s_PRINT_%s_PROTO_H_' % (package.upper(), proto_name.upper()) 26959ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn header = """ 27059ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn 27159ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn} // namespace %(package)s 27259ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn 27359ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn#endif // %(guard_name)s 27459ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn""" % {'guard_name': guard_name, 'package': package} 27559ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn impl = """ 27659ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn} // namespace %(package)s 27759ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn""" % {'package': package} 27859ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn 27959ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn header_file.write(header) 28059ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn impl_file.write(impl) 28159ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn 28259ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn 28359ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahndef GenerateEnumPrinter(enum, header_file, impl_file): 28459ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn """Generates and prints a function to print an enum value. 28559ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn 28659ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn Args: 28759ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn enum: An Enum instance. 28859ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn header_file: The header file handle, open for writing. 28959ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn impl_file: The implementation file handle, open for writing. 29059ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn """ 29159ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn declare = """ 29259ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahnstd::string GetProtoDebugStringWithIndent(%(name)s value, int indent_size); 29359ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahnstd::string GetProtoDebugString(%(name)s value);""" % {'name': enum.name} 29459ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn define_begin = """ 29559ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahnstd::string GetProtoDebugString(%(name)s value) { 29659ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn return GetProtoDebugStringWithIndent(value, 0); 29759ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn} 29859ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn 29959ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahnstd::string GetProtoDebugStringWithIndent(%(name)s value, int indent_size) { 30059ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn""" % {'name': enum.name} 30159ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn define_end = """ 30259ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn return "<unknown>"; 30359ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn} 30459ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn""" 30559ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn condition = """ 30659ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn if (value == %(value_name)s) { 30759ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn return "%(value_name)s"; 30859ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn }""" 30959ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn 31059ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn header_file.write(declare) 31159ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn impl_file.write(define_begin) 31259ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn for value_name in enum.values: 31359ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn impl_file.write(condition % {'value_name': value_name}) 31459ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn impl_file.write(define_end) 31559ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn 31659ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn 31759ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahndef GenerateMessagePrinter(message, header_file, impl_file): 31859ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn """Generates and prints a function to print a message. 31959ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn 32059ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn Args: 32159ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn message: A Message instance. 32259ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn header_file: The header file handle, open for writing. 32359ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn impl_file: The implementation file handle, open for writing. 32459ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn """ 32559ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn declare = """ 32659ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahnstd::string GetProtoDebugStringWithIndent(const %(name)s& value, 32759ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn int indent_size); 32859ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahnstd::string GetProtoDebugString(const %(name)s& value);""" % {'name': 32959ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn message.name} 33059ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn define_begin = """ 33159ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahnstd::string GetProtoDebugString(const %(name)s& value) { 33259ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn return GetProtoDebugStringWithIndent(value, 0); 33359ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn} 33459ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn 33559ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahnstd::string GetProtoDebugStringWithIndent(const %(name)s& value, 33659ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn int indent_size) { 33759ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn std::string indent(indent_size, ' '); 33859ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn std::string output = base::StringPrintf("[%%s] {\\n", 33959ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn value.GetTypeName().c_str()); 34059ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn""" % {'name': message.name} 34159ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn define_end = """ 34259ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn output += indent + "}\\n"; 34359ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn return output; 34459ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn} 34559ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn""" 34659ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn singular_field = """ 34759ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn if (value.has_%(name)s()) { 34859ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn output += indent + " %(name)s: "; 34959ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn base::StringAppendF(&output, %(format)s); 35059ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn output += "\\n"; 35159ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn }""" 35259ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn repeated_field = """ 35359ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn output += indent + " %(name)s: {"; 35459ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn for (int i = 0; i < value.%(name)s_size(); ++i) { 355c3fcde6097f2793fd09c6c529c8d13fa3fc61ebcDarren Krahn if (i > 0) { 356c3fcde6097f2793fd09c6c529c8d13fa3fc61ebcDarren Krahn base::StringAppendF(&output, ", "); 357c3fcde6097f2793fd09c6c529c8d13fa3fc61ebcDarren Krahn } 35859ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn base::StringAppendF(&output, %(format)s); 35959ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn } 36059ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn output += "}\\n";""" 36159ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn singular_field_get = 'value.%(name)s()' 36259ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn repeated_field_get = 'value.%(name)s(i)' 36359ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn formats = {'bool': '"%%s", %(value)s ? "true" : "false"', 36459ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn 'int32': '"%%d", %(value)s', 36559ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn 'int64': '"%%ld", %(value)s', 366c3fcde6097f2793fd09c6c529c8d13fa3fc61ebcDarren Krahn 'uint32': '"%%u (0x%%08X)", %(value)s, %(value)s', 367c3fcde6097f2793fd09c6c529c8d13fa3fc61ebcDarren Krahn 'uint64': '"%%lu (0x%%016X)", %(value)s, %(value)s', 36859ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn 'string': '"%%s", %(value)s.c_str()', 36959ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn 'bytes': """"%%s", base::HexEncode(%(value)s.data(), 37059ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn %(value)s.size()).c_str()"""} 37159ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn subtype_format = ('"%%s", GetProtoDebugStringWithIndent(%(value)s, ' 37259ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn 'indent_size + 2).c_str()') 37359ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn 37459ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn header_file.write(declare) 37559ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn impl_file.write(define_begin) 37659ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn for field in message.fields: 37759ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn if field.repeated: 37859ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn value_get = repeated_field_get % {'name': field.name} 37959ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn field_code = repeated_field 38059ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn else: 38159ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn value_get = singular_field_get % {'name': field.name} 38259ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn field_code = singular_field 38359ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn if field.type_ in formats: 38459ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn value_format = formats[field.type_] % {'value': value_get} 38559ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn else: 38659ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn value_format = subtype_format % {'value': value_get} 38759ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn impl_file.write(field_code % {'name': field.name, 38859ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn 'format': value_format}) 38959ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn impl_file.write(define_end) 39059ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn 39159ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn 39259ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahndef FormatFile(filename): 39359ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn subprocess.call(['clang-format', '-i', '-style=Chromium', filename]) 39459ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn 39559ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn 39659ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahndef main(): 39759ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn parser = argparse.ArgumentParser(description='print proto code generator') 39859ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn parser.add_argument('input_file') 39959ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn parser.add_argument('--subdir', default='') 40059ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn args = parser.parse_args() 40159ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn with open(args.input_file) as input_file: 40259ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn package, imports, messages, enums = ParseProto(input_file) 40359ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn proto_name = os.path.basename(args.input_file).rsplit('.', 1)[0] 40459ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn header_file_name = 'print_%s_proto.h' % proto_name 40559ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn impl_file_name = 'print_%s_proto.cc' % proto_name 40659ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn with open(header_file_name, 'w') as header_file: 40759ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn with open(impl_file_name, 'w') as impl_file: 40859ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn GenerateFileHeaders(proto_name, package, imports, args.subdir, 40959ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn header_file_name, header_file, impl_file) 41059ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn for enum in enums: 41159ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn GenerateEnumPrinter(enum, header_file, impl_file) 41259ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn for message in messages: 41359ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn GenerateMessagePrinter(message, header_file, impl_file) 41459ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn GenerateFileFooters(proto_name, package, args.subdir, header_file, 41559ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn impl_file) 41659ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn FormatFile(header_file_name) 41759ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn FormatFile(impl_file_name) 41859ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn 41959ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahnif __name__ == '__main__': 42059ea81cf9e7b293ec3241e5d442092b0278a3643Darren Krahn main() 421