관리-도구
편집 파일: AutoGeneratedCode.h.cxxcodebuilder
# Phusion Passenger - https://www.phusionpassenger.com/ # Copyright (c) 2017 Phusion Holding B.V. # # "Passenger", "Phusion Passenger" and "Union Station" are registered # trademarks of Phusion Holding B.V. # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. require 'build/support/vendor/cxx_hinted_parser/lib/cxx_hinted_parser' def main fields = parse_config_class_fields comment copyright_header_for(__FILE__), 1 separator comment %q{ SpawningKit/Config/AutoGeneratedCode.h is automatically generated from SpawningKit/Config/AutoGeneratedCode.h.cxxcodebuilder by the build system. It uses the comment hints from SpawningKit/Config.h. To force regenerating this file: rm -f src/agent/Core/SpawningKit/Config/AutoGeneratedCode.h rake src/agent/Core/SpawningKit/Config/AutoGeneratedCode.h } separator function 'inline void Passenger::SpawningKit::Config::internStrings()' do add_code %Q{ size_t totalSize = 0; size_t tmpSize; char *newStorage, *pos, *end; } separator comment 'Calculated required storage size' fields.each do |field| case field.type when 'StaticString' add_code %Q{ totalSize += #{field.name}.size() + 1; } when 'StringKeyTable<StaticString>' add_code %Q{ { StringKeyTable<StaticString>::ConstIterator it(#{field.name}); while (*it != NULL) { totalSize += it.getValue().size() + 1; it.next(); } } } end end separator comment 'Allocate new storage' add_code %Q{ newStorage = pos = new char[totalSize]; end = newStorage + totalSize; } separator comment 'Fill new storage' fields.each do |field| case field.type when 'StaticString' add_code %Q{ pos = appendData(pos, end, #{field.name}); pos = appendData(pos, end, "\\0", 1); } when 'StringKeyTable<StaticString>' add_code %Q{ { StringKeyTable<StaticString>::Iterator it(#{field.name}); while (*it != NULL) { pos = appendData(pos, end, it.getValue()); pos = appendData(pos, end, "\\0", 1); it.next(); } } } end end separator comment 'Move over pointers to new storage' add_code %Q{ pos = newStorage; } fields.each do |field| case field.type when 'StaticString' add_code %Q{ tmpSize = #{field.name}.size(); #{field.name} = StaticString(pos, tmpSize); pos += tmpSize + 1; } separator when 'StringKeyTable<StaticString>' add_code %Q{ { StringKeyTable<StaticString>::Iterator it(#{field.name}); while (*it != NULL) { tmpSize = it.getValue().size(); it.getValue() = StaticString(pos, tmpSize); pos += tmpSize + 1; it.next(); } } } separator end end separator comment 'Commit current storage' add_code %Q{ storage.reset(newStorage); } end function 'inline bool Passenger::SpawningKit::Config::validate(vector<StaticString> &errors) const' do add_code %q{ bool ok = true; const Config &config = *this; } separator excluded_field_names = [] fields.each do |field| if field.metadata[:only_meaningful_if] meaningfulness_check = "#{field.metadata[:only_meaningful_if]} && " end if field.metadata[:require_non_empty] add_code %Q{ if (#{meaningfulness_check}OXT_UNLIKELY(#{field.name}.empty())) { ok = false; errors.push_back(P_STATIC_STRING("#{key_for(field)} may not be empty")); } } elsif field.metadata[:require] add_code %Q{ if (#{meaningfulness_check}OXT_UNLIKELY(!(#{field.metadata[:require]}))) { ok = false; errors.push_back(P_STATIC_STRING("#{key_for(field)} does not satisfy requirement: " #{field.metadata[:require].inspect})); } } else excluded_field_names << field.name end end separator comment "Excluded:\n\n#{excluded_field_names.join("\n")}" separator add_code %Q{ return ok; } end function 'inline Json::Value Passenger::SpawningKit::Config::getConfidentialFieldsToPassToApp() const' do add_code %q{ Json::Value doc; const Config &config = *this; } separator excluded_field_names = [] fields.each do |field| if field.metadata[:pass_during_handshake] setter_code = %Q{ doc["#{key_for(field)}"] = #{value_expression_for(field)}; } if field.metadata[:only_meaningful_if] || field.metadata[:only_pass_during_handshake_if] conditions = [ field.metadata[:only_meaningful_if], field.metadata[:only_pass_during_handshake_if] ].compact add_code %Q[ if (#{conditions.join(" && ")}) { ] indent do add_code(setter_code) end add_code %Q[ } ] else add_code(setter_code) end else excluded_field_names << field.name end end separator comment "Excluded:\n\n#{excluded_field_names.join("\n")}" separator add_code %q{ return doc; } end function 'inline Json::Value Passenger::SpawningKit::Config::getNonConfidentialFieldsToPassToApp() const' do add_code %q{ Json::Value doc; const Config &config = *this; } separator excluded_field_names = [] fields.each do |field| if field.metadata[:pass_during_handshake] if field.metadata[:non_confidential] setter_code = %Q{ doc["#{key_for(field)}"] = #{value_expression_for(field)}; } else setter_code = %Q{ doc["#{key_for(field)}"] = "<SECRET>"; } end if field.metadata[:only_meaningful_if] || field.metadata[:only_pass_during_handshake_if] conditions = [ field.metadata[:only_meaningful_if], field.metadata[:only_pass_during_handshake_if] ].compact add_code %Q[ if (#{conditions.join(" && ")}) { ] indent do add_code(setter_code) end add_code %Q[ } ] else add_code(setter_code) end else excluded_field_names << field.name end end separator comment "Excluded:\n\n#{excluded_field_names.join("\n")}" separator add_code %q{ return doc; } end end def key_for(field) key = field.metadata[:pass_during_handshake] if key.is_a?(String) key else field.name.gsub(/([A-Z])/, '_\1').downcase end end def value_expression_for(field) case field.type when 'StaticString' "#{field.name}.toString()" when 'int', 'unsigned int', 'bool' field.name when 'StringKeyTable<StaticString>' "tableToJson(#{field.name})" else raise "Unsupported field type '#{field.type}' for field #{field.name}" end end def parse_config_class_fields config_h = File.dirname(__FILE__) + '/../Config.h' parser = CxxHintedParser::Parser.load_file(config_h).parse parser.structs['Config'] end main