@ -36,10 +36,12 @@
# include <google/protobuf/descriptor.pb.h>
# include <google/protobuf/io/printer.h>
# include <google/protobuf/io/zero_copy_stream.h>
# include <google/protobuf/stubs/strutil.h>
# include <google/protobuf/compiler/csharp/csharp_generator.h>
# include <google/protobuf/compiler/csharp/csharp_umbrella_class.h>
# include <google/protobuf/compiler/csharp/csharp_helpers.h>
# include <google/protobuf/compiler/csharp/csharp_names.h>
# include <google/protobuf/compiler/csharp/csharp_umbrella_class.h>
using google : : protobuf : : internal : : scoped_ptr ;
@ -48,9 +50,39 @@ namespace protobuf {
namespace compiler {
namespace csharp {
std : : string GetOutputFile ( const google : : protobuf : : FileDescriptor * file , const std : : string file_extension )
{
return GetUmbrellaClassUnqualifiedName ( file ) + file_extension ;
std : : string GetOutputFile (
const google : : protobuf : : FileDescriptor * file ,
const std : : string file_extension ,
const bool generate_directories ,
const std : : string base_namespace ,
string * error ) {
string relative_filename = GetUmbrellaClassUnqualifiedName ( file ) + file_extension ;
if ( ! generate_directories ) {
return relative_filename ;
}
string ns = GetFileNamespace ( file ) ;
string namespace_suffix = ns ;
if ( ! base_namespace . empty ( ) ) {
// Check that the base_namespace is either equal to or a leading part of
// the file namespace. This isn't just a simple prefix; "Foo.B" shouldn't
// be regarded as a prefix of "Foo.Bar". The simplest option is to add "."
// to both.
string extended_ns = ns + " . " ;
if ( extended_ns . find ( base_namespace + " . " ) ! = 0 ) {
* error = " Namespace " + ns + " is not a prefix namespace of base namespace " + base_namespace ;
return " " ; // This will be ignored, because we've set an error.
}
namespace_suffix = ns . substr ( base_namespace . length ( ) ) ;
if ( namespace_suffix . find ( " . " ) = = 0 ) {
namespace_suffix = namespace_suffix . substr ( 1 ) ;
}
}
string namespace_dir = StringReplace ( namespace_suffix , " . " , " / " , true ) ;
if ( ! namespace_dir . empty ( ) ) {
namespace_dir + = " / " ;
}
return namespace_dir + relative_filename ;
}
void GenerateFile ( const google : : protobuf : : FileDescriptor * file ,
@ -75,16 +107,26 @@ bool Generator::Generate(
}
std : : string file_extension = " .cs " ;
std : : string base_namespace = " " ;
bool generate_directories = false ;
for ( int i = 0 ; i < options . size ( ) ; i + + ) {
if ( options [ i ] . first = = " file_extension " ) {
file_extension = options [ i ] . second ;
} else if ( options [ i ] . first = = " base_namespace " ) {
base_namespace = options [ i ] . second ;
generate_directories = true ;
} else {
* error = " Unknown generator option: " + options [ i ] . first ;
return false ;
}
}
std : : string filename = GetOutputFile ( file , file_extension ) ;
string filename_error = " " ;
std : : string filename = GetOutputFile ( file , file_extension , generate_directories , base_namespace , & filename_error ) ;
if ( ! filename_error . empty ( ) ) {
* error = filename_error ;
return false ;
}
scoped_ptr < io : : ZeroCopyOutputStream > output (
generator_context - > Open ( filename ) ) ;
io : : Printer printer ( output . get ( ) , ' $ ' ) ;