diff --git a/main/DDF/DefaultEscherRecordFactory.cs b/main/DDF/DefaultEscherRecordFactory.cs index fb91c6719..57fb71a10 100644 --- a/main/DDF/DefaultEscherRecordFactory.cs +++ b/main/DDF/DefaultEscherRecordFactory.cs @@ -19,7 +19,6 @@ limitations under the License. namespace NPOI.DDF { using System; - using System.Reflection; using NPOI.Util; using System.Collections.Generic; @@ -30,16 +29,6 @@ namespace NPOI.DDF /// public class DefaultEscherRecordFactory : IEscherRecordFactory { - private static Type[] escherRecordClasses = { - - typeof(EscherBSERecord), typeof(EscherOptRecord), typeof(EscherTertiaryOptRecord), - typeof(EscherClientAnchorRecord), - typeof(EscherDgRecord), typeof(EscherSpgrRecord), typeof(EscherSpRecord), - typeof(EscherClientDataRecord), typeof(EscherDggRecord), - typeof(EscherSplitMenuColorsRecord), typeof(EscherChildAnchorRecord), typeof(EscherTextboxRecord) - }; - private static Dictionary recordsMap = RecordsToMap(escherRecordClasses); - /// /// Initializes a new instance of the class. /// @@ -96,26 +85,10 @@ public virtual EscherRecord CreateRecord(byte[] data, int offset) return r; } - //ConstructorInfo recordConstructor = (ConstructorInfo) recordsMap[header.RecordId]; - ConstructorInfo recordConstructor = null; - if (recordsMap.ContainsKey(recordId)) - recordConstructor = recordsMap[recordId]; - - EscherRecord escherRecord = null; - if (recordConstructor == null) - { + var escherRecord = CreateRecordById(recordId); + if (escherRecord is null) return new UnknownEscherRecord(); - } - try - { - escherRecord = (EscherRecord)recordConstructor.Invoke(new object[] { }); - //escherRecord = (EscherRecord)Activator.CreateInstance(recordConstructor); - } - catch - { - return new UnknownEscherRecord(); - } escherRecord.RecordId = recordId; escherRecord.Options = options; return escherRecord; @@ -123,45 +96,27 @@ public virtual EscherRecord CreateRecord(byte[] data, int offset) } /// - /// Converts from a list of classes into a map that Contains the record id as the key and - /// the Constructor in the value part of the map. It does this by using reflection to look up - /// the RECORD_ID field then using reflection again to find a reference to the constructor. + /// REMOVE-REFLECTION: Change reflection-based to a lookup. /// - /// The records to convert - /// The map containing the id/constructor pairs. - private static Dictionary RecordsToMap(Type[] records) - { - Dictionary result = new Dictionary(); - //ConstructorInfo constructor; - Type[] EMPTY_CLASS_ARRAY = new Type[0]; - for (int i = 0; i < records.Length; i++) + /// + /// + private static EscherRecord CreateRecordById(short id) + => id switch { - Type recordType = records[i]; - short sid = 0; - - try - { - sid = (short)recordType.GetField("RECORD_ID").GetValue(null); - } - catch - { - throw new RecordFormatException( - "Unable to determine record types"); - } - ConstructorInfo ci; - try - { - ci = recordType.GetConstructor(EMPTY_CLASS_ARRAY); - } - catch(Exception e) - { - throw new RuntimeException(e); - } - //result[sid] = recordType; //constructor; - result.Add(sid, ci); - } - return result; - } + EscherBSERecord.RECORD_ID => new EscherBSERecord(), + EscherOptRecord.RECORD_ID => new EscherOptRecord(), + EscherTertiaryOptRecord.RECORD_ID => new EscherTertiaryOptRecord(), + EscherClientAnchorRecord.RECORD_ID => new EscherClientAnchorRecord(), + EscherDgRecord.RECORD_ID => new EscherDgRecord(), + EscherSpgrRecord.RECORD_ID => new EscherSpgrRecord(), + EscherSpRecord.RECORD_ID => new EscherSpRecord(), + EscherClientDataRecord.RECORD_ID => new EscherClientDataRecord(), + EscherDggRecord.RECORD_ID => new EscherDggRecord(), + EscherSplitMenuColorsRecord.RECORD_ID => new EscherSplitMenuColorsRecord(), + EscherChildAnchorRecord.RECORD_ID => new EscherChildAnchorRecord(), + EscherTextboxRecord.RECORD_ID => new EscherTextboxRecord(), + _ => null + }; public static bool IsContainer(short options, short recordId) { diff --git a/main/HSSF/Record/CFHeader12Record.cs b/main/HSSF/Record/CFHeader12Record.cs index c2501965f..b6cfcdce4 100644 --- a/main/HSSF/Record/CFHeader12Record.cs +++ b/main/HSSF/Record/CFHeader12Record.cs @@ -29,7 +29,7 @@ namespace NPOI.HSSF.Record */ public class CFHeader12Record : CFHeaderBase, IFutureRecord, ICloneable { - public static short sid = 0x0879; + public const short sid = 0x0879; private FtrHeader futureHeader; diff --git a/main/HSSF/Record/CFHeaderRecord.cs b/main/HSSF/Record/CFHeaderRecord.cs index d816bb236..839106948 100644 --- a/main/HSSF/Record/CFHeaderRecord.cs +++ b/main/HSSF/Record/CFHeaderRecord.cs @@ -28,7 +28,7 @@ namespace NPOI.HSSF.Record */ public class CFHeaderRecord : CFHeaderBase, ICloneable { - public static short sid = 0x01B0; + public const short sid = 0x01B0; /** Creates new CFHeaderRecord */ public CFHeaderRecord() diff --git a/main/HSSF/Record/CFRule12Record.cs b/main/HSSF/Record/CFRule12Record.cs index c11e2e769..db96fd1b0 100644 --- a/main/HSSF/Record/CFRule12Record.cs +++ b/main/HSSF/Record/CFRule12Record.cs @@ -41,7 +41,7 @@ namespace NPOI.HSSF.Record */ public class CFRule12Record : CFRuleBase, IFutureRecord, ICloneable { - public static short sid = 0x087A; + public const short sid = 0x087A; private FtrHeader futureHeader; private int ext_formatting_length; diff --git a/main/HSSF/Record/CFRuleRecord.cs b/main/HSSF/Record/CFRuleRecord.cs index 3947c5404..2f28ff565 100644 --- a/main/HSSF/Record/CFRuleRecord.cs +++ b/main/HSSF/Record/CFRuleRecord.cs @@ -34,7 +34,7 @@ namespace NPOI.HSSF.Record */ public class CFRuleRecord : CFRuleBase, ICloneable { - public static short sid = 0x01B1; + public const short sid = 0x01B1; /** Creates new CFRuleRecord */ private CFRuleRecord(byte conditionType, byte comparisonOperation) diff --git a/main/HSSF/Record/Chart/LinkedDataRecord.cs b/main/HSSF/Record/Chart/LinkedDataRecord.cs index a1a9609b2..2faf38c25 100644 --- a/main/HSSF/Record/Chart/LinkedDataRecord.cs +++ b/main/HSSF/Record/Chart/LinkedDataRecord.cs @@ -32,7 +32,7 @@ namespace NPOI.HSSF.Record.Chart */ public class LinkedDataRecord : StandardRecord, ICloneable { - public static short sid = 0x1051; + public const short sid = 0x1051; private static BitField customNumberFormat = BitFieldFactory.GetInstance(0x1); diff --git a/main/HSSF/Record/Chart/StartBlockRecord.cs b/main/HSSF/Record/Chart/StartBlockRecord.cs index e13f3893b..317ac75d6 100644 --- a/main/HSSF/Record/Chart/StartBlockRecord.cs +++ b/main/HSSF/Record/Chart/StartBlockRecord.cs @@ -28,7 +28,7 @@ namespace NPOI.HSSF.Record.Chart */ public class StartBlockRecord : StandardRecord { - public static short sid = 0x0852; + public const short sid = 0x0852; private short rt; private short grbitFrt; diff --git a/main/HSSF/Record/RecordFactory.cs b/main/HSSF/Record/RecordFactory.cs index cda2eb9b2..7b866df8b 100644 --- a/main/HSSF/Record/RecordFactory.cs +++ b/main/HSSF/Record/RecordFactory.cs @@ -26,14 +26,14 @@ namespace NPOI.HSSF.Record { using System; using System.IO; - using System.Reflection; - using System.Collections; + using System.Collections; using System.Collections.Generic; using NPOI.HSSF.Record.Chart; using NPOI.HSSF.Record.PivotTable; using NPOI.HSSF.Record.AutoFilter; using NPOI.Util; using System.Globalization; + using System.Linq; /** * Title: Record Factory @@ -47,79 +47,19 @@ namespace NPOI.HSSF.Record * @author Csaba Nagy (ncsaba at yahoo dot com) */ + // REMOVE-REFLECTION: Reflection is removed by turning into a lookup. public class RecordFactory { private static int NUM_RECORDS = 512; private static Type[] recordClasses; - #region inner Record Creater - private interface I_RecordCreator - { - Record Create(RecordInputStream in1); - - Type GetRecordClass(); - } - private class ReflectionConstructorRecordCreator : I_RecordCreator - { - - private ConstructorInfo _c; - public ReflectionConstructorRecordCreator(ConstructorInfo c) - { - _c = c; - } - public Record Create(RecordInputStream in1) - { - Object[] args = { in1 }; - try - { - return (Record)_c.Invoke(args); - } - catch (Exception e) - { - throw new RecordFormatException("Unable to construct record instance", e.InnerException); - } - } - public Type GetRecordClass() - { - return _c.DeclaringType; - } - } - /** - * A "create" method is used instead of the usual constructor if the created record might - * be of a different class to the declaring class. - */ - private class ReflectionMethodRecordCreator : I_RecordCreator - { - - private MethodInfo _m; - public ReflectionMethodRecordCreator(MethodInfo m) - { - _m = m; - } - public Record Create(RecordInputStream in1) - { - Object[] args = { in1 }; - try - { - return (Record)_m.Invoke(null, args); - } - catch (Exception e) - { - throw new RecordFormatException("Unable to construct record instance", e.InnerException); - } - } - public Type GetRecordClass() - { - return _m.DeclaringType; - } - } - #endregion - - private static Type[] CONSTRUCTOR_ARGS = new Type[] { typeof(RecordInputStream), }; + private static Dictionary _recordTypes; static RecordFactory() { - recordClasses = new Type[] + // For reference only + + /*recordClasses = new Type[] { typeof(ArrayRecord), typeof(AutoFilterInfoRecord), @@ -401,15 +341,431 @@ static RecordFactory() typeof(FilterModeRecord), typeof(Excel9FileRecord) + };*/ + + _recordTypes = new Dictionary + { + { ArrayRecord.sid, typeof(ArrayRecord) }, + { AutoFilterInfoRecord.sid, typeof(AutoFilterInfoRecord) }, + { BackupRecord.sid, typeof(BackupRecord) }, + { BlankRecord.sid, typeof(BlankRecord) }, + { BOFRecord.sid, typeof(BOFRecord) }, + { BookBoolRecord.sid, typeof(BookBoolRecord) }, + { BoolErrRecord.sid, typeof(BoolErrRecord) }, + { BottomMarginRecord.sid, typeof(BottomMarginRecord) }, + { BoundSheetRecord.sid, typeof(BoundSheetRecord) }, + { CalcCountRecord.sid, typeof(CalcCountRecord) }, + { CalcModeRecord.sid, typeof(CalcModeRecord) }, + { CFHeaderRecord.sid, typeof(CFHeaderRecord) }, + { CFHeader12Record.sid, typeof(CFHeader12Record) }, + { CFRuleRecord.sid, typeof(CFRuleRecord) }, + { CFRule12Record.sid, typeof(CFRule12Record) }, + { ChartRecord.sid, typeof(ChartRecord) }, + { AlRunsRecord.sid, typeof(AlRunsRecord) }, + { CodepageRecord.sid, typeof(CodepageRecord) }, + { ColumnInfoRecord.sid, typeof(ColumnInfoRecord) }, + { ContinueRecord.sid, typeof(ContinueRecord) }, + { CountryRecord.sid, typeof(CountryRecord) }, + { CRNCountRecord.sid, typeof(CRNCountRecord) }, + { CRNRecord.sid, typeof(CRNRecord) }, + { DateWindow1904Record.sid, typeof(DateWindow1904Record) }, + { DBCellRecord.sid, typeof(DBCellRecord) }, + { DConRefRecord.sid, typeof(DConRefRecord) }, + { DefaultColWidthRecord.sid, typeof(DefaultColWidthRecord) }, + { DefaultRowHeightRecord.sid, typeof(DefaultRowHeightRecord) }, + { DeltaRecord.sid, typeof(DeltaRecord) }, + { DimensionsRecord.sid, typeof(DimensionsRecord) }, + { DrawingGroupRecord.sid, typeof(DrawingGroupRecord) }, + { DrawingRecord.sid, typeof(DrawingRecord) }, + { DrawingSelectionRecord.sid, typeof(DrawingSelectionRecord) }, + { DSFRecord.sid, typeof(DSFRecord) }, + { DVALRecord.sid, typeof(DVALRecord) }, + { DVRecord.sid, typeof(DVRecord) }, + { EOFRecord.sid, typeof(EOFRecord) }, + { ExtendedFormatRecord.sid, typeof(ExtendedFormatRecord) }, + { ExternalNameRecord.sid, typeof(ExternalNameRecord) }, + { ExternSheetRecord.sid, typeof(ExternSheetRecord) }, + { ExtSSTRecord.sid, typeof(ExtSSTRecord) }, + { FilePassRecord.sid, typeof(FilePassRecord) }, + { FileSharingRecord.sid, typeof(FileSharingRecord) }, + { FnGroupCountRecord.sid, typeof(FnGroupCountRecord) }, + { FontRecord.sid, typeof(FontRecord) }, + { FooterRecord.sid, typeof(FooterRecord) }, + { FormatRecord.sid, typeof(FormatRecord) }, + { FormulaRecord.sid, typeof(FormulaRecord) }, + { GridsetRecord.sid, typeof(GridsetRecord) }, + { GutsRecord.sid, typeof(GutsRecord) }, + { HCenterRecord.sid, typeof(HCenterRecord) }, + { HeaderRecord.sid, typeof(HeaderRecord) }, + { HeaderFooterRecord.sid, typeof(HeaderFooterRecord) }, + { HideObjRecord.sid, typeof(HideObjRecord) }, + { HorizontalPageBreakRecord.sid, typeof(HorizontalPageBreakRecord) }, + { HyperlinkRecord.sid, typeof(HyperlinkRecord) }, + { IndexRecord.sid, typeof(IndexRecord) }, + { InterfaceEndRecord.sid, typeof(InterfaceEndRecord) }, + { InterfaceHdrRecord.sid, typeof(InterfaceHdrRecord) }, + { IterationRecord.sid, typeof(IterationRecord) }, + { LabelRecord.sid, typeof(LabelRecord) }, + { LabelSSTRecord.sid, typeof(LabelSSTRecord) }, + { LeftMarginRecord.sid, typeof(LeftMarginRecord) }, + { MergeCellsRecord.sid, typeof(MergeCellsRecord) }, + { MMSRecord.sid, typeof(MMSRecord) }, + { MulBlankRecord.sid, typeof(MulBlankRecord) }, + { MulRKRecord.sid, typeof(MulRKRecord) }, + { NameRecord.sid, typeof(NameRecord) }, + { NameCommentRecord.sid, typeof(NameCommentRecord) }, + { NoteRecord.sid, typeof(NoteRecord) }, + { NumberRecord.sid, typeof(NumberRecord) }, + { ObjectProtectRecord.sid, typeof(ObjectProtectRecord) }, + { ObjRecord.sid, typeof(ObjRecord) }, + { PaletteRecord.sid, typeof(PaletteRecord) }, + { PaneRecord.sid, typeof(PaneRecord) }, + { PasswordRecord.sid, typeof(PasswordRecord) }, + { PasswordRev4Record.sid, typeof(PasswordRev4Record) }, + { PrecisionRecord.sid, typeof(PrecisionRecord) }, + { PrintGridlinesRecord.sid, typeof(PrintGridlinesRecord) }, + { PrintHeadersRecord.sid, typeof(PrintHeadersRecord) }, + { PrintSetupRecord.sid, typeof(PrintSetupRecord) }, + { PrintSizeRecord.sid, typeof(PrintSizeRecord) }, + { ProtectionRev4Record.sid, typeof(ProtectionRev4Record) }, + { ProtectRecord.sid, typeof(ProtectRecord) }, + { RecalcIdRecord.sid, typeof(RecalcIdRecord) }, + { RefModeRecord.sid, typeof(RefModeRecord) }, + { RefreshAllRecord.sid, typeof(RefreshAllRecord) }, + { RightMarginRecord.sid, typeof(RightMarginRecord) }, + { RKRecord.sid, typeof(RKRecord) }, + { RowRecord.sid, typeof(RowRecord) }, + { SaveRecalcRecord.sid, typeof(SaveRecalcRecord) }, + { ScenarioProtectRecord.sid, typeof(ScenarioProtectRecord) }, + { SCLRecord.sid, typeof(SCLRecord) }, + { SelectionRecord.sid, typeof(SelectionRecord) }, + { SeriesRecord.sid, typeof(SeriesRecord) }, + { SeriesTextRecord.sid, typeof(SeriesTextRecord) }, + { SharedFormulaRecord.sid, typeof(SharedFormulaRecord) }, + { SSTRecord.sid, typeof(SSTRecord) }, + { StringRecord.sid, typeof(StringRecord) }, + { StyleRecord.sid, typeof(StyleRecord) }, + { SupBookRecord.sid, typeof(SupBookRecord) }, + { TabIdRecord.sid, typeof(TabIdRecord) }, + { TableRecord.sid, typeof(TableRecord) }, + { TableStylesRecord.sid, typeof(TableStylesRecord) }, + { TextObjectRecord.sid, typeof(TextObjectRecord) }, + { TopMarginRecord.sid, typeof(TopMarginRecord) }, + { UncalcedRecord.sid, typeof(UncalcedRecord) }, + { UseSelFSRecord.sid, typeof(UseSelFSRecord) }, + { UserSViewBegin.sid, typeof(UserSViewBegin) }, + { UserSViewEnd.sid, typeof(UserSViewEnd) }, + { ValueRangeRecord.sid, typeof(ValueRangeRecord) }, + { VCenterRecord.sid, typeof(VCenterRecord) }, + { VerticalPageBreakRecord.sid, typeof(VerticalPageBreakRecord) }, + { WindowOneRecord.sid, typeof(WindowOneRecord) }, + { WindowProtectRecord.sid, typeof(WindowProtectRecord) }, + { WindowTwoRecord.sid, typeof(WindowTwoRecord) }, + { WriteAccessRecord.sid, typeof(WriteAccessRecord) }, + { WriteProtectRecord.sid, typeof(WriteProtectRecord) }, + { WSBoolRecord.sid, typeof(WSBoolRecord) }, + { SheetExtRecord.sid, typeof(SheetExtRecord) }, + { AreaFormatRecord.sid, typeof(AreaFormatRecord) }, + { AreaRecord.sid, typeof(AreaRecord) }, + { AttachedLabelRecord.sid, typeof(AttachedLabelRecord) }, + { AxcExtRecord.sid, typeof(AxcExtRecord) }, + { AxisLineFormatRecord.sid, typeof(AxisLineFormatRecord) }, + { AxisParentRecord.sid, typeof(AxisParentRecord) }, + { AxisRecord.sid, typeof(AxisRecord) }, + { AxesUsedRecord.sid, typeof(AxesUsedRecord) }, + { BarRecord.sid, typeof(BarRecord) }, + { BeginRecord.sid, typeof(BeginRecord) }, + { BopPopCustomRecord.sid, typeof(BopPopCustomRecord) }, + { BopPopRecord.sid, typeof(BopPopRecord) }, + { CatLabRecord.sid, typeof(CatLabRecord) }, + { CatSerRangeRecord.sid, typeof(CatSerRangeRecord) }, + { Chart3DBarShapeRecord.sid, typeof(Chart3DBarShapeRecord) }, + { Chart3dRecord.sid, typeof(Chart3dRecord) }, + { ChartEndObjectRecord.sid, typeof(ChartEndObjectRecord) }, + { ChartFormatRecord.sid, typeof(ChartFormatRecord) }, + { ChartFRTInfoRecord.sid, typeof(ChartFRTInfoRecord) }, + { ChartStartObjectRecord.sid, typeof(ChartStartObjectRecord) }, + { CrtLayout12ARecord.sid, typeof(CrtLayout12ARecord) }, + { CrtLayout12Record.sid, typeof(CrtLayout12Record) }, + { CrtLineRecord.sid, typeof(CrtLineRecord) }, + { CrtLinkRecord.sid, typeof(CrtLinkRecord) }, + { CrtMlFrtContinueRecord.sid, typeof(CrtMlFrtContinueRecord) }, + { CrtMlFrtRecord.sid, typeof(CrtMlFrtRecord) }, + { DataFormatRecord.sid, typeof(DataFormatRecord) }, + { DataLabExtContentsRecord.sid, typeof(DataLabExtContentsRecord) }, + { DataLabExtRecord.sid, typeof(DataLabExtRecord) }, + { DatRecord.sid, typeof(DatRecord) }, + { DefaultTextRecord.sid, typeof(DefaultTextRecord) }, + { DropBarRecord.sid, typeof(DropBarRecord) }, + { EndBlockRecord.sid, typeof(EndBlockRecord) }, + { EndRecord.sid, typeof(EndRecord) }, + { LinkedDataRecord.sid, typeof(LinkedDataRecord) }, + { Fbi2Record.sid, typeof(Fbi2Record) }, + { FbiRecord.sid, typeof(FbiRecord) }, + { FontIndexRecord.sid, typeof(FontIndexRecord) }, + { FrameRecord.sid, typeof(FrameRecord) }, + { FrtFontListRecord.sid, typeof(FrtFontListRecord) }, + { GelFrameRecord.sid, typeof(GelFrameRecord) }, + { IFmtRecordRecord.sid, typeof(IFmtRecordRecord) }, + { LegendExceptionRecord.sid, typeof(LegendExceptionRecord) }, + { LegendRecord.sid, typeof(LegendRecord) }, + { LineFormatRecord.sid, typeof(LineFormatRecord) }, + { MarkerFormatRecord.sid, typeof(MarkerFormatRecord) }, + { ObjectLinkRecord.sid, typeof(ObjectLinkRecord) }, + { PicFRecord.sid, typeof(PicFRecord) }, + { PieFormatRecord.sid, typeof(PieFormatRecord) }, + { PieRecord.sid, typeof(PieRecord) }, + { PlotAreaRecord.sid, typeof(PlotAreaRecord) }, + { PlotGrowthRecord.sid, typeof(PlotGrowthRecord) }, + { PosRecord.sid, typeof(PosRecord) }, + { RadarAreaRecord.sid, typeof(RadarAreaRecord) }, + { RadarRecord.sid, typeof(RadarRecord) }, + { RichTextStreamRecord.sid, typeof(RichTextStreamRecord) }, + { ScatterRecord.sid, typeof(ScatterRecord) }, + { SerAuxErrBarRecord.sid, typeof(SerAuxErrBarRecord) }, + { SerAuxTrendRecord.sid, typeof(SerAuxTrendRecord) }, + { SerFmtRecord.sid, typeof(SerFmtRecord) }, + { SeriesIndexRecord.sid, typeof(SeriesIndexRecord) }, + { SeriesListRecord.sid, typeof(SeriesListRecord) }, + { SerParentRecord.sid, typeof(SerParentRecord) }, + { SerToCrtRecord.sid, typeof(SerToCrtRecord) }, + { ShapePropsStreamRecord.sid, typeof(ShapePropsStreamRecord) }, + { ShtPropsRecord.sid, typeof(ShtPropsRecord) }, + { StartBlockRecord.sid, typeof(StartBlockRecord) }, + { SurfRecord.sid, typeof(SurfRecord) }, + { TextPropsStreamRecord.sid, typeof(TextPropsStreamRecord) }, + { TextRecord.sid, typeof(TextRecord) }, + { TickRecord.sid, typeof(TickRecord) }, + { UnitsRecord.sid, typeof(UnitsRecord) }, + { YMultRecord.sid, typeof(YMultRecord) }, + { DataItemRecord.sid, typeof(DataItemRecord) }, + { ExtendedPivotTableViewFieldsRecord.sid, typeof(ExtendedPivotTableViewFieldsRecord) }, + { PageItemRecord.sid, typeof(PageItemRecord) }, + { StreamIDRecord.sid, typeof(StreamIDRecord) }, + { ViewDefinitionRecord.sid, typeof(ViewDefinitionRecord) }, + { ViewFieldsRecord.sid, typeof(ViewFieldsRecord) }, + { ViewSourceRecord.sid, typeof(ViewSourceRecord) }, + { AutoFilterRecord.sid, typeof(AutoFilterRecord) }, + { FilterModeRecord.sid, typeof(FilterModeRecord) }, + { Excel9FileRecord.sid, typeof(Excel9FileRecord) } }; + // recordTypes.Add() + } - _recordCreatorsById = RecordsToMap(recordClasses); + private static Record CreateBySid(short sid, RecordInputStream stream) + { + return sid switch + { + ArrayRecord.sid => new ArrayRecord(stream), + AutoFilterInfoRecord.sid => new AutoFilterInfoRecord(stream), + BackupRecord.sid => new BackupRecord(stream), + BlankRecord.sid => new BlankRecord(stream), + BOFRecord.sid => new BOFRecord(stream), + BookBoolRecord.sid => new BookBoolRecord(stream), + BoolErrRecord.sid => new BoolErrRecord(stream), + BottomMarginRecord.sid => new BottomMarginRecord(stream), + BoundSheetRecord.sid => new BoundSheetRecord(stream), + CalcCountRecord.sid => new CalcCountRecord(stream), + CalcModeRecord.sid => new CalcModeRecord(stream), + CFHeaderRecord.sid => new CFHeaderRecord(stream), + CFHeader12Record.sid => new CFHeader12Record(stream), + CFRuleRecord.sid => new CFRuleRecord(stream), + CFRule12Record.sid => new CFRule12Record(stream), + ChartRecord.sid => new ChartRecord(stream), + AlRunsRecord.sid => new AlRunsRecord(stream), + CodepageRecord.sid => new CodepageRecord(stream), + ColumnInfoRecord.sid => new ColumnInfoRecord(stream), + ContinueRecord.sid => new ContinueRecord(stream), + CountryRecord.sid => new CountryRecord(stream), + CRNCountRecord.sid => new CRNCountRecord(stream), + CRNRecord.sid => new CRNRecord(stream), + DateWindow1904Record.sid => new DateWindow1904Record(stream), + DBCellRecord.sid => new DBCellRecord(stream), + DConRefRecord.sid => new DConRefRecord(stream), + DefaultColWidthRecord.sid => new DefaultColWidthRecord(stream), + DefaultRowHeightRecord.sid => new DefaultRowHeightRecord(stream), + DeltaRecord.sid => new DeltaRecord(stream), + DimensionsRecord.sid => new DimensionsRecord(stream), + DrawingGroupRecord.sid => new DrawingGroupRecord(stream), + DrawingRecord.sid => new DrawingRecord(stream), + DrawingSelectionRecord.sid => new DrawingSelectionRecord(stream), + DSFRecord.sid => new DSFRecord(stream), + DVALRecord.sid => new DVALRecord(stream), + DVRecord.sid => new DVRecord(stream), + EOFRecord.sid => new EOFRecord(stream), + ExtendedFormatRecord.sid => new ExtendedFormatRecord(stream), + ExternalNameRecord.sid => new ExternalNameRecord(stream), + ExternSheetRecord.sid => new ExternSheetRecord(stream), + ExtSSTRecord.sid => new ExtSSTRecord(stream), + FilePassRecord.sid => new FilePassRecord(stream), + FileSharingRecord.sid => new FileSharingRecord(stream), + FnGroupCountRecord.sid => new FnGroupCountRecord(stream), + FontRecord.sid => new FontRecord(stream), + FooterRecord.sid => new FooterRecord(stream), + FormatRecord.sid => new FormatRecord(stream), + FormulaRecord.sid => new FormulaRecord(stream), + GridsetRecord.sid => new GridsetRecord(stream), + GutsRecord.sid => new GutsRecord(stream), + HCenterRecord.sid => new HCenterRecord(stream), + HeaderRecord.sid => new HeaderRecord(stream), + HeaderFooterRecord.sid => new HeaderFooterRecord(stream), + HideObjRecord.sid => new HideObjRecord(stream), + HorizontalPageBreakRecord.sid => new HorizontalPageBreakRecord(stream), + HyperlinkRecord.sid => new HyperlinkRecord(stream), + IndexRecord.sid => new IndexRecord(stream), + InterfaceEndRecord.sid => InterfaceEndRecord.Create(stream), + InterfaceHdrRecord.sid => new InterfaceHdrRecord(stream), + IterationRecord.sid => new IterationRecord(stream), + LabelRecord.sid => new LabelRecord(stream), + LabelSSTRecord.sid => new LabelSSTRecord(stream), + LeftMarginRecord.sid => new LeftMarginRecord(stream), + MergeCellsRecord.sid => new MergeCellsRecord(stream), + MMSRecord.sid => new MMSRecord(stream), + MulBlankRecord.sid => new MulBlankRecord(stream), + MulRKRecord.sid => new MulRKRecord(stream), + NameRecord.sid => new NameRecord(stream), + NameCommentRecord.sid => new NameCommentRecord(stream), + NoteRecord.sid => new NoteRecord(stream), + NumberRecord.sid => new NumberRecord(stream), + ObjectProtectRecord.sid => new ObjectProtectRecord(stream), + ObjRecord.sid => new ObjRecord(stream), + PaletteRecord.sid => new PaletteRecord(stream), + PaneRecord.sid => new PaneRecord(stream), + PasswordRecord.sid => new PasswordRecord(stream), + PasswordRev4Record.sid => new PasswordRev4Record(stream), + PrecisionRecord.sid => new PrecisionRecord(stream), + PrintGridlinesRecord.sid => new PrintGridlinesRecord(stream), + PrintHeadersRecord.sid => new PrintHeadersRecord(stream), + PrintSetupRecord.sid => new PrintSetupRecord(stream), + PrintSizeRecord.sid => new PrintSizeRecord(stream), + ProtectionRev4Record.sid => new ProtectionRev4Record(stream), + ProtectRecord.sid => new ProtectRecord(stream), + RecalcIdRecord.sid => new RecalcIdRecord(stream), + RefModeRecord.sid => new RefModeRecord(stream), + RefreshAllRecord.sid => new RefreshAllRecord(stream), + RightMarginRecord.sid => new RightMarginRecord(stream), + RKRecord.sid => new RKRecord(stream), + RowRecord.sid => new RowRecord(stream), + SaveRecalcRecord.sid => new SaveRecalcRecord(stream), + ScenarioProtectRecord.sid => new ScenarioProtectRecord(stream), + SCLRecord.sid => new SCLRecord(stream), + SelectionRecord.sid => new SelectionRecord(stream), + SeriesRecord.sid => new SeriesRecord(stream), + SeriesTextRecord.sid => new SeriesTextRecord(stream), + SharedFormulaRecord.sid => new SharedFormulaRecord(stream), + SSTRecord.sid => new SSTRecord(stream), + StringRecord.sid => new StringRecord(stream), + StyleRecord.sid => new StyleRecord(stream), + SupBookRecord.sid => new SupBookRecord(stream), + TabIdRecord.sid => new TabIdRecord(stream), + TableRecord.sid => new TableRecord(stream), + TableStylesRecord.sid => new TableStylesRecord(stream), + TextObjectRecord.sid => new TextObjectRecord(stream), + TopMarginRecord.sid => new TopMarginRecord(stream), + UncalcedRecord.sid => new UncalcedRecord(stream), + UseSelFSRecord.sid => new UseSelFSRecord(stream), + UserSViewBegin.sid => new UserSViewBegin(stream), + UserSViewEnd.sid => new UserSViewEnd(stream), + ValueRangeRecord.sid => new ValueRangeRecord(stream), + VCenterRecord.sid => new VCenterRecord(stream), + VerticalPageBreakRecord.sid => new VerticalPageBreakRecord(stream), + WindowOneRecord.sid => new WindowOneRecord(stream), + WindowProtectRecord.sid => new WindowProtectRecord(stream), + WindowTwoRecord.sid => new WindowTwoRecord(stream), + WriteAccessRecord.sid => new WriteAccessRecord(stream), + WriteProtectRecord.sid => new WriteProtectRecord(stream), + WSBoolRecord.sid => new WSBoolRecord(stream), + SheetExtRecord.sid => new SheetExtRecord(stream), + AreaFormatRecord.sid => new AreaFormatRecord(stream), + AreaRecord.sid => new AreaRecord(stream), + AttachedLabelRecord.sid => new AttachedLabelRecord(stream), + AxcExtRecord.sid => new AxcExtRecord(stream), + AxisLineFormatRecord.sid => new AxisLineFormatRecord(stream), + AxisParentRecord.sid => new AxisParentRecord(stream), + AxisRecord.sid => new AxisRecord(stream), + AxesUsedRecord.sid => new AxesUsedRecord(stream), + BarRecord.sid => new BarRecord(stream), + BeginRecord.sid => new BeginRecord(stream), + BopPopCustomRecord.sid => new BopPopCustomRecord(stream), + BopPopRecord.sid => new BopPopRecord(stream), + CatLabRecord.sid => new CatLabRecord(stream), + CatSerRangeRecord.sid => new CatSerRangeRecord(stream), + Chart3DBarShapeRecord.sid => new Chart3DBarShapeRecord(stream), + Chart3dRecord.sid => new Chart3dRecord(stream), + ChartEndObjectRecord.sid => new ChartEndObjectRecord(stream), + ChartFormatRecord.sid => new ChartFormatRecord(stream), + ChartFRTInfoRecord.sid => new ChartFRTInfoRecord(stream), + ChartStartObjectRecord.sid => new ChartStartObjectRecord(stream), + CrtLayout12ARecord.sid => new CrtLayout12ARecord(stream), + CrtLayout12Record.sid => new CrtLayout12Record(stream), + CrtLineRecord.sid => new CrtLineRecord(stream), + CrtLinkRecord.sid => new CrtLinkRecord(stream), + CrtMlFrtContinueRecord.sid => new CrtMlFrtContinueRecord(stream), + CrtMlFrtRecord.sid => new CrtMlFrtRecord(stream), + DataFormatRecord.sid => new DataFormatRecord(stream), + DataLabExtContentsRecord.sid => new DataLabExtContentsRecord(stream), + DataLabExtRecord.sid => new DataLabExtRecord(stream), + DatRecord.sid => new DatRecord(stream), + DefaultTextRecord.sid => new DefaultTextRecord(stream), + DropBarRecord.sid => new DropBarRecord(stream), + EndBlockRecord.sid => new EndBlockRecord(stream), + EndRecord.sid => new EndRecord(stream), + LinkedDataRecord.sid => new LinkedDataRecord(stream), + Fbi2Record.sid => new Fbi2Record(stream), + FbiRecord.sid => new FbiRecord(stream), + FontIndexRecord.sid => new FontIndexRecord(stream), + FrameRecord.sid => new FrameRecord(stream), + FrtFontListRecord.sid => new FrtFontListRecord(stream), + GelFrameRecord.sid => new GelFrameRecord(stream), + IFmtRecordRecord.sid => new IFmtRecordRecord(stream), + LegendExceptionRecord.sid => new LegendExceptionRecord(stream), + LegendRecord.sid => new LegendRecord(stream), + LineFormatRecord.sid => new LineFormatRecord(stream), + MarkerFormatRecord.sid => new MarkerFormatRecord(stream), + ObjectLinkRecord.sid => new ObjectLinkRecord(stream), + PicFRecord.sid => new PicFRecord(stream), + PieFormatRecord.sid => new PieFormatRecord(stream), + PieRecord.sid => new PieRecord(stream), + PlotAreaRecord.sid => new PlotAreaRecord(stream), + PlotGrowthRecord.sid => new PlotGrowthRecord(stream), + PosRecord.sid => new PosRecord(stream), + RadarAreaRecord.sid => new RadarAreaRecord(stream), + RadarRecord.sid => new RadarRecord(stream), + RichTextStreamRecord.sid => new RichTextStreamRecord(stream), + ScatterRecord.sid => new ScatterRecord(stream), + SerAuxErrBarRecord.sid => new SerAuxErrBarRecord(stream), + SerAuxTrendRecord.sid => new SerAuxTrendRecord(stream), + SerFmtRecord.sid => new SerFmtRecord(stream), + SeriesIndexRecord.sid => new SeriesIndexRecord(stream), + SeriesListRecord.sid => new SeriesListRecord(stream), + SerParentRecord.sid => new SerParentRecord(stream), + SerToCrtRecord.sid => new SerToCrtRecord(stream), + ShapePropsStreamRecord.sid => new ShapePropsStreamRecord(stream), + ShtPropsRecord.sid => new ShtPropsRecord(stream), + StartBlockRecord.sid => new StartBlockRecord(stream), + SurfRecord.sid => new SurfRecord(stream), + TextPropsStreamRecord.sid => new TextPropsStreamRecord(stream), + TextRecord.sid => new TextRecord(stream), + TickRecord.sid => new TickRecord(stream), + UnitsRecord.sid => new UnitsRecord(stream), + YMultRecord.sid => new YMultRecord(stream), + DataItemRecord.sid => new DataItemRecord(stream), + ExtendedPivotTableViewFieldsRecord.sid => new ExtendedPivotTableViewFieldsRecord(stream), + PageItemRecord.sid => new PageItemRecord(stream), + StreamIDRecord.sid => new StreamIDRecord(stream), + ViewDefinitionRecord.sid => new ViewDefinitionRecord(stream), + ViewFieldsRecord.sid => new ViewFieldsRecord(stream), + ViewSourceRecord.sid => new ViewSourceRecord(stream), + AutoFilterRecord.sid => new AutoFilterRecord(stream), + FilterModeRecord.sid => new FilterModeRecord(stream), + Excel9FileRecord.sid => new Excel9FileRecord(stream), + _ => new UnknownRecord(stream) + }; } - //private static Hashtable recordsMap; /** * cache of the recordsToMap(); */ - private static Dictionary _recordCreatorsById = null;//RecordsToMap(recordClasses); + //private static Dictionary _recordCreatorsById = null;//RecordsToMap(recordClasses); private static short[] _allKnownRecordSIDs; /** @@ -422,15 +778,7 @@ static RecordFactory() */ public static Type GetRecordClass(int sid) { - I_RecordCreator rc = null; - if (_recordCreatorsById.ContainsKey((short)sid)) - rc = _recordCreatorsById[(short)sid]; - - if (rc == null) - { - return null; - } - return rc.GetRecordClass(); + return _recordTypes.TryGetValue((short)sid, out var type) ? type : null; } /** * Changes the default capacity (10000) to handle larger files @@ -468,15 +816,6 @@ public static List CreateRecords(Stream in1) return records; } - [Obsolete] - private static void AddAll(List destList, Record[] srcRecs) - { - for (int i = 0; i < srcRecs.Length; i++) - { - destList.Add(srcRecs[i]); - } - } - public static Record[] CreateRecord(RecordInputStream in1) { @@ -516,15 +855,7 @@ public static BlankRecord[] ConvertBlankRecords(MulBlankRecord mbk) public static Record CreateSingleRecord(RecordInputStream in1) { - if (_recordCreatorsById.ContainsKey(in1.Sid)) - { - I_RecordCreator constructor = _recordCreatorsById[in1.Sid]; - return constructor.Create(in1); - } - else - { - return new UnknownRecord(in1); - } + return CreateBySid(in1.Sid, in1); } /// /// RK record is a slightly smaller alternative to NumberRecord @@ -567,109 +898,11 @@ public static short[] GetAllKnownRecordSIDs() { if (_allKnownRecordSIDs == null) { - short[] results = new short[_recordCreatorsById.Count]; - int i = 0; - - foreach (KeyValuePair kv in _recordCreatorsById) - { - results[i++] = kv.Key; - } - Array.Sort(results); - _allKnownRecordSIDs = results; + _allKnownRecordSIDs = _recordTypes.Keys.ToArray(); + Array.Sort(_allKnownRecordSIDs); } return (short[])_allKnownRecordSIDs.Clone(); } - - private static Dictionary RecordsToMap(Type[] records) - { - Dictionary result = new Dictionary(); - Hashtable uniqueRecClasses = new Hashtable(records.Length * 3 / 2); - - for (int i = 0; i < records.Length; i++) - { - - Type recClass = records[i]; - if (!typeof(Record).IsAssignableFrom(recClass)) - { - throw new Exception("Invalid record sub-class (" + recClass.Name + ")"); - } - if (recClass.IsAbstract) - { - throw new Exception("Invalid record class (" + recClass.Name + ") - must not be abstract"); - } - if (uniqueRecClasses.Contains(recClass)) - { - throw new Exception("duplicate record class (" + recClass.Name + ")"); - } - uniqueRecClasses.Add(recClass, recClass); - - short sid = 0; - try - { - sid = (short)recClass.GetField("sid").GetValue(null); - } - catch (Exception ArgumentException) - { - throw new RecordFormatException( - "Unable to determine record types", ArgumentException); - } - if (result.ContainsKey(sid)) - { - Type prevClass = result[sid].GetRecordClass(); - throw new RuntimeException("duplicate record sid 0x" + sid.ToString("X", CultureInfo.CurrentCulture) - + " for classes (" + recClass.Name + ") and (" + prevClass.Name + ")"); - } - result[sid] = GetRecordCreator(recClass); - } - return result; - } - [Obsolete] - private static void CheckZeros(Stream in1, int avail) - { - int count = 0; - while (true) - { - int b = (int)in1.ReadByte(); - if (b < 0) - { - break; - } - if (b != 0) - { - Console.Error.WriteLine(HexDump.ByteToHex(b)); - } - count++; - } - if (avail != count) - { - Console.Error.WriteLine("avail!=count (" + avail + "!=" + count + ")."); - } - } - - private static I_RecordCreator GetRecordCreator(Type recClass) - { - try - { - ConstructorInfo constructor; - constructor = recClass.GetConstructor(CONSTRUCTOR_ARGS); - if (constructor != null) - return new ReflectionConstructorRecordCreator(constructor); - } - catch - { - // fall through and look for other construction methods - } - try - { - MethodInfo m = recClass.GetMethod("Create", CONSTRUCTOR_ARGS); - return new ReflectionMethodRecordCreator(m); - } - catch - { - throw new RuntimeException("Failed to find constructor or create method for (" + recClass.Name + ")."); - } - } - } }