Skip to content

Instantly share code, notes, and snippets.

@ktnyt
Created March 17, 2016 04:43
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ktnyt/857ead5eee8c0014f88d to your computer and use it in GitHub Desktop.
Save ktnyt/857ead5eee8c0014f88d to your computer and use it in GitHub Desktop.
Personal CPP include/source generation script.
#!/usr/bin/env python
from os.path import isfile
from datetime import date
import argparse
parser = argparse.ArgumentParser(description='HPP/CPP generator')
parser.add_argument('module', type=str, help='Module')
parser.add_argument('--author', default='', help='Author')
parser.add_argument('--basename', default='', help='Basename')
parser.add_argument('--define', default=False, help='Define', action='store_true')
parser.add_argument('--empty' , default=False, help='Empty', action='store_true')
parser.add_argument('--hpponly', default=False, help='Hpp Only', action='store_true')
parser.add_argument('--implement', default=False, help='Implement', action='store_true')
parser.add_argument('--include', default=[], help='Include', nargs='*')
parser.add_argument('--namespace', default=[], help='Namespace', nargs='*')
parser.add_argument('--overwrite', default=False, help='Overwrite', action='store_true')
parser.add_argument('--path', default='.', help='Path')
parser.add_argument('--pimpl', default=False, help='Pimpl', action='store_true')
parser.add_argument('--template', default=False, help='Template', action='store_true')
parser.add_argument('--version', default='1.0.0', help='Version')
args = parser.parse_args()
module = args.module
author = args.author
basename = args.basename
define = args.define
empty = args.empty
implement = args.implement
include = args.include
hpponly = args.hpponly
namespace = args.namespace
overwrite = args.overwrite
path = args.path
pimpl = args.pimpl
template = args.template
version = args.version
if len(basename) == 0:
basename = module
today = date.today()
year = today.year
month = today.month
day = today.day
preamble = '\n'.join(map(lambda s: s.rstrip(), [
'/******************************************************************************',
' * ',
' * {{0}} ',
' * ',
' * @author Copyright (C) {2} {0} ',
' * @version {1} ',
' * @created {2:02d}/{3:02d}/{4:02d} {0} -- Created! ',
' * @@ ',
' * ',
' * Licensed to the Apache Software Foundation (ASF) under one ',
' * or more contributor license agreements. See the NOTICE file ',
' * distributed with this work for additional information ',
' * regarding copyright ownership. The ASF licenses this file ',
' * to you under the Apache License, Version 2.0 (the ',
' * "License"); you may not use this file except in compliance ',
' * with the License. You may obtain a copy of the License at ',
' * ',
' * http://www.apache.org/licenses/LICENSE-2.0 ',
' * ',
' * Unless required by applicable law or agreed to in writing, ',
' * software distributed under the License is distributed on an ',
' * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY ',
' * KIND, either express or implied. See the License for the ',
' * specific language governing permissions and limitations ',
' * under the License. ',
' * ',
' *****************************************************************************/'
])).format(author, version, year, month, day)
if not empty:
guard = '__{0}__'
if len(namespace) > 0:
guard = guard.format('{0}_{1}'.format('_'.join(namespace), module)).upper()
else:
guard = guard.format(module).upper()
definition = '\n'.join(filter(lambda x: x is not None, [
'template<typename T>' if template else None,
'class {0} {{'.format(module),
'public:',
' {0}();'.format(module),
' {0}(const {0}& other);'.format(module),
' {0}({0}&& other) noexcept;'.format(module),
' {0}& operator =(const {0}& other);'.format(module),
' {0}& operator =({0}&& other) noexcept;'.format(module),
' friend void swap({0}& a, {0}& b);'.format(module),
' {0} clone();'.format(module) if pimpl else None,
'private:',
' struct impl; std::shared_ptr<impl> pimpl;' if pimpl else ' ',
'};'
]))
struct = '\n'.join(filter(lambda x: x is not None, [
'template<typename T>' if template else None,
'struct {0}::impl {{'.format(module if not template else '{}<T>'.format(module)),
' ',
'};'
]))
default_constructor = '\n'.join(filter(lambda x: x is not None, [
'template<typename T>' if template else None,
'{0}::{1}(){2} {{}}'.format(module if not template else '{}<T>'.format(module), module, ' : pimpl(std::make_shared<impl>())' if pimpl else '')
]))
copy_constructor = '\n'.join(filter(lambda x: x is not None, [
'template<typename T>' if template else None,
'{0}::{1}(const {0}& other){2} {{}}'.format(module if not template else '{}<T>'.format(module), module, ' : pimpl(other.pimpl)' if pimpl else '')
]))
move_constructor = '\n'.join(filter(lambda x: x is not None, [
'template<typename T>' if template else None,
'{0}::{1}({0}&& other) noexcept{2} {{'.format(module if not template else '{}<T>'.format(module), module, ' : pimpl(other.pimpl)' if pimpl else ''),
' other.pimpl = nullptr;' if pimpl else ' ',
'}'
]))
copy_assignment = '\n'.join(filter(lambda x: x is not None, [
'template<typename T>' if template else None,
'{0}& {0}::operator =(const {0}& other) {{'.format(module if not template else '{}<T>'.format(module)),
' {0} another(other);'.format(module if not template else '{}<T>'.format(module)),
' *this = std::move(another);',
' return *this;',
'}'
]))
move_assignment = '\n'.join(filter(lambda x: x is not None, [
'template<typename T>' if template else None,
'{0}& {0}::operator =({0}&& other) noexcept {{'.format(module if not template else '{}<T>'.format(module)),
' swap(*this, other);',
' return *this;',
'}'
]))
swap_function = '\n'.join(filter(lambda x: x is not None, [
'template<typename T>' if template else None,
'void swap({0}& a, {0}& b) {{'.format(module if not template else '{}<T>'.format(module)),
' std::swap(a.pimpl, b.pimpl);' if pimpl else ' ',
'}'
]))
clone_function = '\n'.join(filter(lambda x: x is not None, [
'template<typename T>' if template else None,
'{0} {0}::clone() {{'.format(module if not template else '{}<T>'.format(module)),
' ',
'}'
]))
implementation = '\n'.join(filter(lambda x: x is not None, [
struct,
'',
default_constructor,
'',
copy_constructor,
'',
move_constructor,
'',
copy_assignment,
'',
move_assignment,
'',
swap_function,
'' if pimpl else None,
clone_function if pimpl else None
]))
indented_definition = '\n'.join(map(lambda x: '{0}{1}'.format(''.join([' ']*len(namespace)), x), definition.split('\n')))
indented_implementation = '\n'.join(map(lambda x: '{0}{1}'.format(''.join([' ']*len(namespace)), x), implementation.split('\n')))
definition_filename = '{0}.hpp'
if len(namespace) > 0:
definition_filename = definition_filename.format('{0}/{1}/{2}'.format(path, '/'.join(namespace), basename))
else:
definition_filename = definition_filename.format('{0}/{1}'.format(path, basename))
definition_filename = definition_filename.lower()
implementation_filename = '{{0}}{0}'.format('_impl.hpp' if template or hpponly else '.cpp')
if len(namespace) > 0:
implementation_filename = implementation_filename.format('{0}/{1}/{2}'.format(path, '/'.join(namespace), basename))
else:
implementation_filename = implementation_filename.format('{0}/{1}'.format(path, basename))
implementation_filename = implementation_filename.lower()
test_filename = '{0}.cpp'
if len(namespace) > 0:
test_filename = test_filename.format('tests/{0}/{1}/{2}'.format(path, '/'.join(namespace), basename))
else:
test_filename = test_filename.format('{0}/{1}'.format(path, basename))
test_filename = test_filename.lower()
if pimpl:
include.append('memory')
includes = '\n'.join(map(lambda i: '#include <{}>'.format(i), sorted(list(set(include)))))
definition_content = '\n'.join(filter(lambda x: x is not None, [
preamble.format(definition_filename),
'',
'#ifndef {0}'.format(guard),
'#define {0}'.format(guard),
'',
includes if len(include) > 0 else None,
'' if len(include) > 0 else None,
'\n'.join(map(lambda p: '{0}namespace {1} {{'.format(''.join([' ']*p[0]), p[1]), enumerate(namespace))),
indented_definition,
'\n'.join(map(lambda i: '{0}}}'.format(''.join([' ']*i)), reversed(range(len(namespace))))),
'',
'#include "{0}"'.format(implementation_filename) if template or hpponly else None,
'' if template or hpponly else None,
'#endif',
''
]))
implementation_content = '\n'.join(filter(lambda x: x is not None, [
preamble.format(implementation_filename),
'',
'#include "{0}"'.format(definition_filename) if not template and not hpponly else None,
'' if not template and not hpponly else None,
'\n'.join(map(lambda p: '{0}namespace {1} {{'.format(''.join([' ']*p[0]), p[1]), enumerate(namespace))),
indented_implementation,
'\n'.join(map(lambda i: '{0}}}'.format(''.join([' ']*i)), reversed(range(len(namespace))))),
''
]))
test_content = '\n'.join(filter(lambda x: x is not None,[
preamble.format(test_filename),
'',
'#include "gtest/gtest.h"',
'#include "{0}"'.format(definition_filename),
'',
'\n'.join(map(lambda p: '{0}namespace {1} {{'.format(''.join([' ']*p[0]), p[1]), enumerate(namespace + ['test']))),
'',
'\n'.join(map(lambda i: '{0}}}'.format(''.join([' ']*i)), reversed(range(len(namespace + ['test']))))),
''
]))
if (not isfile(definition_filename)) or overwrite:
f = open(definition_filename, 'w')
f.write(definition_content)
f.close()
if (not isfile(implementation_filename)) or overwrite:
f = open(implementation_filename, 'w')
f.write(implementation_content)
f.close()
if (not isfile(test_filename)) or overwrite:
f = open(test_filename, 'w')
f.write(test_content)
f.close()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment