unit uRODLCppConverters; {----------------------------------------------------------------------------} { RemObjects SDK Library - CodeGen2 } { } { compiler: Delphi 5 and up, Kylix 2 and up } { platform: Win32, Linux } { } { (c)opyright RemObjects Software. all rights reserved. } { } { Using this code requires a valid license of the RemObjects SDK } { which can be obtained at http://www.remobjects.com. } {----------------------------------------------------------------------------} {$IFDEF LINUX} {$I ../RemObjects.inc} {$ELSE} {$I ..\RemObjects.inc} {$ENDIF LINUX} interface uses uRODLTemplateBasedConverter, uRODLImplConverter, uRODLIntfConverter, uRODLInvkConverter, uRODLAsyncConverter, uRODL, Classes; type TRODLCppImplConverter = class(TRODLImplConverter) protected function GetParamFrontModifier(flag: TRODLParamFlag): string; override; function GetParamBackModifier(flag: TRODLParamFlag): string; override; function GetTypeIdentifier(const originalType: string): string; override; public constructor Create(const aLibrary: TRODLLibrary; const aTemplateFileName: string; const aUnitName: string; const aServerClassName: string; const aTargetEntity: string = ''; const aRequiredUnits: string = ''); override; end; TRODLCppIntfConverter = class(TRODLIntfConverter) private FSimpleTypes: TStringList; procedure PreProcessLibrary(const aLibrary: TRODLLibrary); protected function GetParamFrontModifier(flag: TRODLParamFlag): string; override; function GetParamBackModifier(flag: TRODLParamFlag): string; override; function GetTypeIdentifier(const originalType: string): string; override; function GetServicesSectionClass: TServicesSectionClass; override; function GetEventSinksSectionClass: TEventSinksSectionClass; override; public constructor Create(const aLibrary: TRODLLibrary; const aTemplateFileName: string; const aUnitName: string; const Split: Boolean = False; const AOutputDir: string = ''; const AWrapperTemplateName: string = ''; const aTargetEntity: string = ''); override; destructor Destroy; override; procedure SaveResultToFile(const FileName: string); override; end; TRODLCppInvkConverter = class(TRODLInvkConverter) protected function GetParamFrontModifier(flag: TRODLParamFlag): string; override; function GetParamBackModifier(flag: TRODLParamFlag): string; override; function GetTypeIdentifier(const originalType: string): string; override; function GetServicesSectionClass: TServicesSectionClass; override; public constructor Create(const aLibrary: TRODLLibrary; const aTemplateFileName: string; const aUnitName: string; const ASplit: Boolean = False; const AOutputDir: string = ''; const AWrapperTemplateName: string = ''; const aTargetEntity: string = ''); override; procedure SaveResultToFile(const FileName: string); override; end; TRODLCppAsyncConverter = class(TRODLAsyncConverter) protected function GetParamFrontModifier(flag: TRODLParamFlag): string; override; function GetParamBackModifier(flag: TRODLParamFlag): string; override; function GetTypeIdentifier(const originalType: string): string; override; function GetServicesSectionClass: TServicesSectionClass; override; public constructor Create(const aLibrary: TRODLLibrary; const aTemplateFileName: string; const aUnitName: string; const Split: Boolean = False; const AOutputDir: string = ''; const AWrapperTemplateName: string = ''; const aTargetEntity: string = ''); override; procedure SaveResultToFile(const FileName: string); override; end; implementation uses SysUtils, uRODLTemplateBasedConverterUtils, uROTypes; const CppFrontFlagNames : array[TRODLParamFlag] of string = ( 'const', '', '', 'result'); CppBackFlagNames : array[TRODLParamFlag] of string = ( '', '&', '&', 'result'); DEFAULT_CPP_INTF_SERVICE_ANCESTOR = 'IInterface'; DEFAULT_CPP_INVK_SERVICE_ANCESTOR = 'System::TObject'; DEFAULT_CPP_INTF_EVENT_SINK_ANCESTOR = 'IInterface'; DEFAULT_CPP_ASYNC_SERVICE_ANCESTOR = 'IInterface'; type TCppIntfServicesSection = class (TIntfServicesSection) protected function GetAncestorName(const aService: TRODLBaseService): string; override; end; TCppIntfEventSinksSection = class (TIntfEventSinksSection) protected function GetAncestorName(const aService: TRODLBaseService): string; override; end; TCppInvkServicesSection = class (TServicesSection) protected function GetAncestorName(const aService: TRODLBaseService): string; override; end; TCppAsyncServicesSection = class (TAsyncServicesSection) protected function GetAncestorName(const aService: TRODLBaseService): string; override; end; // SIMPLE_TYPES TSimpleTypesSection = class (TRODLGeneratorSection) protected procedure DoReplacements(var curLine: string; const TypeName: string; const aLibrary: TRODLLibrary); dynamic; public constructor Create(AParent: TRODLCppIntfConverter); reintroduce; virtual; procedure Process(const sectionText: string; const aLibrary: TRODLLibrary); override; end; { TRODLCppImplConverter } constructor TRODLCppImplConverter.Create(const aLibrary: TRODLLibrary; const aTemplateFileName, aUnitName, aServerClassName, aTargetEntity: string; const aRequiredUnits: string); begin FileExtension := '.cpp'; inherited Create(aLibrary, aTemplateFileName, aUnitName, aServerClassName, aTargetEntity, aRequiredUnits); end; function TRODLCppImplConverter.GetParamBackModifier( flag: TRODLParamFlag): string; begin Result := CppBackFlagNames[Flag]; end; function TRODLCppImplConverter.GetParamFrontModifier( flag: TRODLParamFlag): string; begin Result := CppFrontFlagNames[Flag]; end; function TRODLCppImplConverter.GetTypeIdentifier( const originalType: string): string; begin Result := CachedDataTypeToCppType(originalType, FLibrary); end; { TRODLCppIntfConverter } constructor TRODLCppIntfConverter.Create(const aLibrary: TRODLLibrary; const aTemplateFileName, aUnitName: string; const Split: Boolean = False; const AOutputDir: string = ''; const AWrapperTemplateName: string = ''; const aTargetEntity: string = ''); begin // Call inherited with nil so that convert is not called, allowing us // to setup the optional sections. Setting up the optional sections before // calling the inherited Create is not an option, the section list would // not have been created inherited Create(nil, aTemplateFileName, aUnitName, Split, AOutputDir, AWrapperTemplateName, aTargetEntity); FileExtension := '.cpp'; FSimpleTypes := TStringList.Create; FSimpleTypes.Sorted := True; FSimpleTypes.Duplicates := dupIgnore; PreProcessLibrary(aLibrary); Sections.Add(TSimpleTypesSection.Create(Self)); // Now that everything is done, call convert if need be. if (aLibrary <> nil) then Convert(aLibrary); end; destructor TRODLCppIntfConverter.Destroy; begin FSimpleTypes.Free; inherited Destroy; end; function TRODLCppIntfConverter.GetEventSinksSectionClass: TEventSinksSectionClass; begin Result := TCppIntfEventSinksSection; end; function TRODLCppIntfConverter.GetParamBackModifier( flag: TRODLParamFlag): string; begin Result := CppBackFlagNames[Flag]; end; function TRODLCppIntfConverter.GetParamFrontModifier( flag: TRODLParamFlag): string; begin Result := CppFrontFlagNames[Flag]; end; function TRODLCppIntfConverter.GetServicesSectionClass: TServicesSectionClass; begin Result := TCppIntfServicesSection; end; function TRODLCppIntfConverter.GetTypeIdentifier( const originalType: string): string; begin Result := CachedDataTypeToCppType(originalType, FLibrary); end; procedure TRODLCppIntfConverter.PreProcessLibrary(const aLibrary: TRODLLibrary); var I, J, K: Integer; DataType: string; CurInterface: TRODLServiceInterface; CurOp: TRODLOperation; begin // In order to fill the SIMPLE_TYPES section, we need to go through all // potential types and note if they are simple or complex (implemented as // a class). for I := 0 to aLibrary.StructCount - 1 do begin for J := 0 to aLibrary.Structs[I].Count - 1 do begin DataType := aLibrary.Structs[I].Items[J].DataType; if not SameText(DataType, DataTypeNames[rtXML]) and not CachedIsImplementedAsClass(DataType, aLibrary) then FSimpleTypes.Add(DataType); end; end; for I := 0 to aLibrary.ArrayCount - 1 do begin DataType := aLibrary.Arrays[I].ElementType; if not CachedIsImplementedAsClass(DataType, aLibrary) then FSimpleTypes.Add(DataType); end; for I := 0 to aLibrary.ServiceCount - 1 do begin CurInterface := aLibrary.Services[I].Default; for J := 0 to CurInterface.Count - 1 do begin CurOp := CurInterface.Items[J]; if Assigned(CurOp.Result) and (Length(CurOp.Result.DataType) > 0) then begin DataType := CurOp.Result.DataType; if not CachedIsImplementedAsClass(DataType, aLibrary) then FSimpleTypes.Add(DataType); end; for K := 0 to CurOp.Count - 1 do begin DataType := CurOp.Items[K].DataType; if not CachedIsImplementedAsClass(DataType, aLibrary) then FSimpleTypes.Add(DataType); end; end; end; for I := 0 to aLibrary.ExceptionCount - 1 do begin for J := 0 to aLibrary.Exceptions[I].Count - 1 do begin DataType := aLibrary.Exceptions[I].Items[J].DataType; if not CachedIsImplementedAsClass(DataType, aLibrary) then FSimpleTypes.Add(DataType); end; end; for I := 0 to aLibrary.EventSinkCount - 1 do begin CurInterface := aLibrary.EventSinks[I].Default; for J := 0 to CurInterface.Count - 1 do begin CurOp := CurInterface.Items[J]; if Assigned(CurOp.Result) and (Length(CurOp.Result.DataType) > 0) then begin DataType := CurOp.Result.DataType; if not CachedIsImplementedAsClass(DataType, aLibrary) then FSimpleTypes.Add(DataType); end; for K := 0 to CurOp.Count - 1 do begin DataType := CurOp.Items[K].DataType; if not CachedIsImplementedAsClass(DataType, aLibrary) then FSimpleTypes.Add(DataType); end; end; end; end; procedure TRODLCppIntfConverter.SaveResultToFile(const FileName: string); begin if Split then inherited SaveResultToFile(ChangeFileExt(FileName, '.h')) else inherited SaveResultToFile(FileName); end; { TRODLCppInvkConverter } constructor TRODLCppInvkConverter.Create(const aLibrary: TRODLLibrary; const aTemplateFileName, aUnitName: string; const ASplit: Boolean = False; const AOutputDir: string = ''; const AWrapperTemplateName: string = ''; const aTargetEntity: string = ''); begin FileExtension := '.cpp'; inherited Create(aLibrary, aTemplateFileName, aUnitName, ASplit, AOutputDir, AWrapperTemplateName, aTargetEntity); end; function TRODLCppInvkConverter.GetParamBackModifier( flag: TRODLParamFlag): string; begin Result := CppBackFlagNames[Flag]; end; function TRODLCppInvkConverter.GetParamFrontModifier( flag: TRODLParamFlag): string; begin Result := CppFrontFlagNames[Flag]; end; function TRODLCppInvkConverter.GetServicesSectionClass: TServicesSectionClass; begin Result := TCppInvkServicesSection; end; function TRODLCppInvkConverter.GetTypeIdentifier( const originalType: string): string; begin Result := CachedDataTypeToCppType(originalType, FLibrary); end; procedure TRODLCppInvkConverter.SaveResultToFile(const FileName: string); begin if Split then inherited SaveResultToFile(ChangeFileExt(FileName, '.h')) else inherited SaveResultToFile(FileName); end; { TCppIntfServicesSection } function TCppIntfServicesSection.GetAncestorName( const aService: TRODLBaseService): string; begin Result := inherited GetAncestorName(aService); if Length(Result) = 0 then Result := DEFAULT_CPP_INTF_SERVICE_ANCESTOR; end; { TCppInvkServicesSection } function TCppInvkServicesSection.GetAncestorName( const aService: TRODLBaseService): string; begin Result := inherited GetAncestorName(aService); if Length(Result) = 0 then Result := DEFAULT_CPP_INVK_SERVICE_ANCESTOR; end; { TCppEventSinksSection } function TCppIntfEventSinksSection.GetAncestorName( const aService: TRODLBaseService): string; begin Result := inherited GetAncestorName(aService); if Length(Result) = 0 then Result := DEFAULT_CPP_INTF_EVENT_SINK_ANCESTOR; end; { TRODLCppAsyncConverter } constructor TRODLCppAsyncConverter.Create(const aLibrary: TRODLLibrary; const aTemplateFileName, aUnitName: string; const Split: Boolean; const AOutputDir, AWrapperTemplateName, aTargetEntity: string); begin FileExtension := '.cpp'; inherited Create(aLibrary, aTemplateFileName, aUnitName, Split, AOutputDir, AWrapperTemplateName, aTargetEntity); end; function TRODLCppAsyncConverter.GetParamBackModifier( flag: TRODLParamFlag): string; begin Result := CppBackFlagNames[Flag]; end; function TRODLCppAsyncConverter.GetParamFrontModifier( flag: TRODLParamFlag): string; begin Result := CppFrontFlagNames[Flag]; end; function TRODLCppAsyncConverter.GetServicesSectionClass: TServicesSectionClass; begin Result := TCppAsyncServicesSection; end; function TRODLCppAsyncConverter.GetTypeIdentifier( const originalType: string): string; begin Result := CachedDataTypeToCppType(originalType, FLibrary); end; procedure TRODLCppAsyncConverter.SaveResultToFile(const FileName: string); begin if Split then inherited SaveResultToFile(ChangeFileExt(FileName, '.h')) else inherited SaveResultToFile(FileName); end; { TCppAsyncServicesSection } function TCppAsyncServicesSection.GetAncestorName( const aService: TRODLBaseService): string; begin Result := inherited GetAncestorName(aService); if Length(Result) = 0 then Result := DEFAULT_CPP_ASYNC_SERVICE_ANCESTOR; end; { TSimpleTypesSection } constructor TSimpleTypesSection.Create(AParent: TRODLCppIntfConverter); begin inherited Create(AParent, 'SIMPLE_TYPES'); end; procedure TSimpleTypesSection.DoReplacements(var curLine: string; const TypeName: string; const aLibrary: TRODLLibrary); begin MacroReplace(curLine, '%', ['TYPE_NAME', CachedDataTypeToCppType(TypeName, aLibrary) ]); end; procedure TSimpleTypesSection.Process(const sectionText: string; const aLibrary: TRODLLibrary); var I: Integer; curLine: string; begin for I := 0 to (Parent as TRODLCppIntfConverter).FSimpleTypes.Count - 1 do begin curLine := sectionText; DoReplacements(curLine, (Parent as TRODLCppIntfConverter).FSimpleTypes[I], aLibrary); Write(curLine); end; end; end.