Exemple #1
0
        /* Function: SaveBinaryFile
         * Saves the passed information in <BuildState.nd>.
         */
        public static void SaveBinaryFile(Path filename, HTMLBuildState buildState)
        {
            using (BinaryFile binaryFile = new BinaryFile())
            {
                binaryFile.OpenForWriting(filename);

                // [Byte: Need to Build Frame Page (0 or 1)]
                // [Byte: Need to Build Main Style Files (0 or 1)]
                // [Byte: Need to Build Menu (0 or 1)]
                // [Byte: Need to Build Search Prefix Index (0 or 1)]

                binaryFile.WriteByte((byte)(buildState.needToBuildFramePage ? 1 : 0));
                binaryFile.WriteByte((byte)(buildState.needToBuildMainStyleFiles ? 1 : 0));
                binaryFile.WriteByte((byte)(buildState.needToBuildMenu ? 1 : 0));
                binaryFile.WriteByte((byte)(buildState.needToBuildSearchPrefixIndex ? 1 : 0));

                // [NumberSet: Source File IDs to Rebuild]
                // [NumberSet: Class IDs to Rebuild]
                // [NumberSet: Style File IDs to Rebuild]
                // [NumberSet: Source File IDs with Content]
                // [NumberSet: Class IDs with Content]
                // [StringSet: Search Prefixes to Rebuild]
                // [StringSet: Folders to Check for Deletion]

                binaryFile.WriteNumberSet(buildState.sourceFilesToRebuild);
                binaryFile.WriteNumberSet(buildState.classFilesToRebuild);
                binaryFile.WriteNumberSet(buildState.styleFilesToRebuild);
                binaryFile.WriteNumberSet(buildState.sourceFilesWithContent);
                binaryFile.WriteNumberSet(buildState.classFilesWithContent);
                binaryFile.WriteStringSet(buildState.searchPrefixesToRebuild);
                binaryFile.WriteStringSet(buildState.foldersToCheckForDeletion);

                // [String: Menu Data File Type] [NumberSet: Menu Data File Numbers]
                // [String: Menu Data File Type] [NumberSet: Menu Data File Numbers]
                // ...
                // [String: null]

                foreach (var menuDataFilePair in buildState.usedMenuDataFiles)
                {
                    binaryFile.WriteString(menuDataFilePair.Key);
                    binaryFile.WriteNumberSet(menuDataFilePair.Value);
                }

                binaryFile.WriteString(null);
            }
        }
Exemple #2
0
        /* Function: Save
         * Saves the current state into <Files.nd>.  Throws an exception if unsuccessful.  All <Files> in the structure should have
         * their last modification time set to tick count zero before calling this function.
         */
        public void Save(Path filename, IDObjects.Manager <File> files)
        {
            BinaryFile binaryFile = new BinaryFile();

            binaryFile.OpenForWriting(filename);

            try
            {
                foreach (File file in files)
                {
                    // [Int32: ID]
                    // [String: Path]
                    // [Byte: Type]
                    // [Int64: Last Modification in Ticks or 0]
                    // (if image)
                    //    [UInt32: Width in Pixels or 0 if unknown]
                    //    [UInt32: Height in Pixels or 0 if unknown]

                    binaryFile.WriteInt32(file.ID);
                    binaryFile.WriteString(file.FileName);
                    binaryFile.WriteByte((byte)file.Type);
                    binaryFile.WriteInt64(file.LastModified.Ticks);

                    if (file.Type == FileType.Image)
                    {
                        ImageFile imageFile = (ImageFile)file;

                        if (imageFile.DimensionsKnown)
                        {
                            binaryFile.WriteUInt32(imageFile.Width);
                            binaryFile.WriteUInt32(imageFile.Height);
                        }
                        else
                        {
                            binaryFile.WriteUInt32(0);
                            binaryFile.WriteUInt32(0);
                        }
                    }
                }

                // [Int32: 0]
                binaryFile.WriteInt32(0);
            }
            finally
            { binaryFile.Close(); }
        }
Exemple #3
0
        /* Function: SaveBinaryFile
         * Saves the passed information in <SearchIndex.nd>.
         */
        public static void SaveBinaryFile(Path filename, StringTable <IDObjects.NumberSet> prefixTopicIDs)
        {
            using (BinaryFile binaryFile = new BinaryFile())
            {
                binaryFile.OpenForWriting(filename);

                // [String: Prefix]
                // [NumberSet: Prefix Topic IDs]
                // ...
                // [String: null]

                foreach (var prefixPair in prefixTopicIDs)
                {
                    binaryFile.WriteString(prefixPair.Key);
                    binaryFile.WriteNumberSet(prefixPair.Value);
                }

                binaryFile.WriteString(null);
            }
        }
Exemple #4
0
        // Group: Saving Functions
        // __________________________________________________________________________


        /* Function: Save
         * Saves the current computed languages into <Languages.nd>.  Throws an exception if unsuccessful.
         */
        public void Save(Path filename, Config config)
        {
            BinaryFile file = new BinaryFile();

            file.OpenForWriting(filename);

            try
            {
                // [String: Language Name]
                // [[Language Attributes]]
                // ...
                // [String: null]

                foreach (var language in config.Languages)
                {
                    file.WriteString(language.Name);

                    // [Int32: ID]
                    // [Byte: Type]
                    // [String: Simple Identifier]
                    // [Byte: Enum Values]
                    // [Byte: Case Sensitive (1 or 0)]
                    // [String: Member Operator Symbol]
                    // [String: Line Extender Symbol]

                    file.WriteInt32(language.ID);
                    file.WriteByte((byte)language.Type);
                    file.WriteString(language.SimpleIdentifier);
                    file.WriteByte((byte)language.EnumValue);
                    file.WriteByte((byte)(language.CaseSensitive ? 1 : 0));
                    file.WriteString(language.MemberOperator);
                    file.WriteString(language.LineExtender);

                    // [String: Line Comment Symbol] [] ... [String: null]
                    // [String: Opening Block Comment Symbol] [String: Closing Block Comment Symbo] [] [] ... [String: null]
                    // [String: Javadoc First Line Comment Symbol] [String: Javadoc Following Lines Comment Symbol [] ... [String: null]
                    // [String: Javadoc Opening Block Comment Symbol] [String: Javadoc Closing Block Comment Symbol] [] [] ... [String: null]
                    // [String: XML Line Comment Symbol] [] ... [String: null]

                    WriteSymbolList(file, language.LineCommentSymbols);
                    WriteBlockCommentSymbolsList(file, language.BlockCommentSymbols);
                    WriteLineCommentSymbolsList(file, language.JavadocLineCommentSymbols);
                    WriteBlockCommentSymbolsList(file, language.JavadocBlockCommentSymbols);
                    WriteSymbolList(file, language.XMLLineCommentSymbols);

                    // Prototype Enders:
                    // [Int32: Comment Type ID]
                    // [Byte: Include Line Breaks (0 or 1)]
                    // [String: Prototype Ender Symbol] [] ... [String: null]
                    // ...
                    // [Int32: 0]

                    if (language.HasPrototypeEnders)
                    {
                        foreach (var prototypeEnders in language.PrototypeEnders)
                        {
                            file.WriteInt32(prototypeEnders.CommentTypeID);
                            file.WriteByte((byte)(prototypeEnders.IncludeLineBreaks ? 1 : 0));
                            WriteSymbolList(file, prototypeEnders.Symbols);
                        }
                    }

                    file.WriteInt32(0);
                }

                file.WriteString(null);


                // [String: Alias] [Int32: Language ID] [] [] ... [String: Null]

                foreach (KeyValuePair <string, int> aliasKVP in config.Aliases)
                {
                    file.WriteString(aliasKVP.Key);
                    file.WriteInt32(aliasKVP.Value);
                }

                file.WriteString(null);


                // [String: File Extension] [Int32: Language ID] [] [] ... [String: Null]

                foreach (KeyValuePair <string, int> fileExtensionKVP in config.FileExtensions)
                {
                    file.WriteString(fileExtensionKVP.Key);
                    file.WriteInt32(fileExtensionKVP.Value);
                }

                file.WriteString(null);


                // [String: Shebang String] [Int32: Language ID] [] [] ... [String: Null]

                foreach (KeyValuePair <string, int> shebangStringKVP in config.ShebangStrings)
                {
                    file.WriteString(shebangStringKVP.Key);
                    file.WriteInt32(shebangStringKVP.Value);
                }

                file.WriteString(null);
            }

            finally
            {
                file.Close();
            }
        }
        /* Function: Save
         * Saves the passed information in <BuildState.nd>.
         */
        public void Save(Path filename, BuildState buildState, UnprocessedChanges unprocessedChanges)
        {
            // We're assuming no other code is accessing these variables at the point at which we'd be saving them so we don't
            // need to call Lock() and Unlock().

            using (BinaryFile binaryFile = new BinaryFile())
            {
                binaryFile.OpenForWriting(filename);

                // [Byte: Need to Build Frame Page (0 or 1)]
                // [Byte: Need to Build Main Style Files (0 or 1)]
                // [Byte: Need to Build Menu (0 or 1)]
                // [Byte: Need to Build Main Search Files (0 or 1)]

                binaryFile.WriteByte((byte)(unprocessedChanges.framePage ? 1 : 0));
                binaryFile.WriteByte((byte)(unprocessedChanges.mainStyleFiles ? 1 : 0));
                binaryFile.WriteByte((byte)(unprocessedChanges.menu ? 1 : 0));
                binaryFile.WriteByte((byte)(unprocessedChanges.mainSearchFiles ? 1 : 0));

                // [NumberSet: Source File IDs to Rebuild]
                // [NumberSet: Class IDs to Rebuild]
                // [NumberSet: Image File IDs to Rebuild]
                // [NumberSet: Style File IDs to Rebuild]
                // [NumberSet: Source File IDs with Content]
                // [NumberSet: Class IDs with Content]
                // [NumberSet: Used Image File IDs]
                // [NumberSet: Unchanged Image File Use Check IDs]

                binaryFile.WriteNumberSet(unprocessedChanges.sourceFiles);
                binaryFile.WriteNumberSet(unprocessedChanges.classes);
                binaryFile.WriteNumberSet(unprocessedChanges.imageFiles);
                binaryFile.WriteNumberSet(unprocessedChanges.styleFiles);
                binaryFile.WriteNumberSet(buildState.sourceFilesWithContent);
                binaryFile.WriteNumberSet(buildState.classesWithContent);
                binaryFile.WriteNumberSet(buildState.usedImageFiles);
                binaryFile.WriteNumberSet(unprocessedChanges.unchangedImageFileUseChecks);

                // [StringSet: Search Prefixes to Rebuild]
                // [StringSet: Folders to Check for Deletion]

                binaryFile.WriteStringSet(unprocessedChanges.searchPrefixes);
                binaryFile.WriteStringSet(unprocessedChanges.possiblyEmptyFolders);

                // [String: Menu Data File Type] [NumberSet: Menu Data File Numbers]
                // [String: Menu Data File Type] [NumberSet: Menu Data File Numbers]
                // ...
                // [String: null]

                foreach (var menuDataFilePair in buildState.usedMenuDataFiles)
                {
                    switch (menuDataFilePair.Key)
                    {
                    case Hierarchy.File:
                        binaryFile.WriteString("files");
                        break;

                    case Hierarchy.Class:
                        binaryFile.WriteString("classes");
                        break;

                    case Hierarchy.Database:
                        binaryFile.WriteString("database");
                        break;

                    default:
                        throw new NotImplementedException();
                    }

                    binaryFile.WriteNumberSet(menuDataFilePair.Value);
                }

                binaryFile.WriteString(null);
            }
        }
Exemple #6
0
        /* Function: Save
         * Saves the passed information in <Config.nd>.
         */
        public void Save(Path filename, Config.ProjectInfo projectInfo, List <Style> styles, List <FileSourceInfo> fileSourceInfoList)
        {
            using (BinaryFile binaryFile = new BinaryFile())
            {
                binaryFile.OpenForWriting(filename);

                // [String: Project Title or null]
                // [String: Project Subtitle or null]
                // [String: Project Copyright or null]
                // [String: Project Timestamp Code or null]

                binaryFile.WriteString(projectInfo.Title);
                binaryFile.WriteString(projectInfo.Subtitle);
                binaryFile.WriteString(projectInfo.Copyright);
                binaryFile.WriteString(projectInfo.TimestampCode);


                // [String: Style Path]
                //    (properties)
                // [String: Style Path]
                // ...
                // [String: null]

                foreach (var style in styles)
                {
                    if (style is Styles.CSSOnly)
                    {
                        binaryFile.WriteString((style as Styles.CSSOnly).CSSFile);
                    }
                    else if (style is Styles.Advanced)
                    {
                        binaryFile.WriteString((style as Styles.Advanced).ConfigFile);
                    }
                    else
                    {
                        throw new NotImplementedException();
                    }


                    // [String: Inherit] ... [String: null]

                    if (style.Inherits != null)
                    {
                        foreach (var inheritStatement in style.Inherits)
                        {
                            binaryFile.WriteString(inheritStatement.Name);
                        }
                    }

                    binaryFile.WriteString(null);


                    // [String: OnLoad] [Byte: Page Type] ... [String: null]

                    if (style.OnLoad != null)
                    {
                        foreach (var onLoadStatement in style.OnLoad)
                        {
                            binaryFile.WriteString(onLoadStatement.Statement);
                            binaryFile.WriteByte((byte)onLoadStatement.Type);
                        }
                    }

                    binaryFile.WriteString(null);


                    // [String: Link] [Byte: Page Type] ... [String: null]

                    if (style.Links != null)
                    {
                        foreach (var linkStatement in style.Links)
                        {
                            binaryFile.WriteString(linkStatement.File);
                            binaryFile.WriteByte((byte)linkStatement.Type);
                        }
                    }

                    binaryFile.WriteString(null);


                    // [String: Home Page or null]

                    binaryFile.WriteString(style.HomePage);
                }

                // End of style paths
                binaryFile.WriteString(null);


                // [Int32: Source FileSource Number] [String: Source FileSource UniqueIDString]
                // [Int32: Source FileSource Number] [String: Source FileSource UniqueIDString]
                // ...
                // [Int32: 0]

                foreach (FileSourceInfo fileSourceInfo in fileSourceInfoList)
                {
                    if (fileSourceInfo.Type == Files.InputType.Source)
                    {
                        binaryFile.WriteInt32(fileSourceInfo.Number);
                        binaryFile.WriteString(fileSourceInfo.UniqueIDString);
                    }
                }

                binaryFile.WriteInt32(0);

                // [Int32: Image FileSource Number] [String: Image FileSource UniqueIDString]
                // [Int32: Image FileSource Number] [String: Image FileSource UniqueIDString]
                // ...
                // [Int32: 0]

                foreach (FileSourceInfo fileSourceInfo in fileSourceInfoList)
                {
                    if (fileSourceInfo.Type == Files.InputType.Image)
                    {
                        binaryFile.WriteInt32(fileSourceInfo.Number);
                        binaryFile.WriteString(fileSourceInfo.UniqueIDString);
                    }
                }

                binaryFile.WriteInt32(0);
            }
        }
Exemple #7
0
        // Group: Saving Functions
        // __________________________________________________________________________


        /* Function: Save
         * Saves the current computed languages into <Languages.nd>.  Throws an exception if unsuccessful.
         */
        public void Save(Path filename, IDObjects.Manager <Language> languages,
                         StringTable <Language> aliases, StringTable <Language> extensions,
                         SortedStringTable <Language> shebangStrings, StringSet ignoredExtensions)
        {
            BinaryFile file = new BinaryFile();

            file.OpenForWriting(filename);

            try
            {
                // [String: Language Name]
                // [Int32: ID]
                // [Byte: Type]
                // [String: Simple Identifier]
                // [Byte: Enum Values]
                // [Byte: Case Sensitive (1 or 0)]
                // [String: Member Operator Symbol]
                // [String: Line Extender Symbol]
                // [String: Line Comment Symbol] [] ... [String: null]
                // [String: Opening Block Comment Symbol] [String: Closing Block Comment Symbo] [] [] ... [String: null]
                // [String: Opening Javadoc Line Comment Symbol] [String: Remainder Javadoc Line Comment Symbol [] ... [String: null]
                // [String: Opening Javadoc Block Comment Symbol] [String: Closing Javadoc Block Comment Symbol] [] [] ... [String: null]
                // [String: XML Line Comment Symbol] [] ... [String: null]

                // [Int32: Comment Type ID]
                // [Byte: Include Line Breaks (0 or 1)]
                // [String: Prototype Ender Symbol] [] ... [String: null]
                // ...
                // [Int32: 0]

                // ...
                // [String: null]

                foreach (Language language in languages)
                {
                    file.WriteString(language.Name);
                    file.WriteInt32(language.ID);
                    file.WriteByte((byte)language.Type);
                    file.WriteString(language.SimpleIdentifier);
                    file.WriteByte((byte)language.EnumValue);
                    file.WriteByte((byte)(language.CaseSensitive ? 1 : 0));
                    file.WriteString(language.MemberOperator);
                    file.WriteString(language.LineExtender);

                    WriteStringArray(file, language.LineCommentStrings);
                    WriteStringArray(file, language.BlockCommentStringPairs);
                    WriteStringArray(file, language.JavadocLineCommentStringPairs);
                    WriteStringArray(file, language.JavadocBlockCommentStringPairs);
                    WriteStringArray(file, language.XMLLineCommentStrings);

                    int[] commentTypes = language.GetCommentTypesWithPrototypeEnders();
                    if (commentTypes != null)
                    {
                        foreach (int commentType in commentTypes)
                        {
                            PrototypeEnders prototypeEnders = language.GetPrototypeEnders(commentType);

                            file.WriteInt32(commentType);
                            file.WriteByte((byte)(prototypeEnders.IncludeLineBreaks ? 1 : 0));
                            WriteStringArray(file, prototypeEnders.Symbols);
                        }
                    }
                    file.WriteInt32(0);
                }

                file.WriteString(null);


                // [String: Alias] [Int32: Language ID] [] [] ... [String: Null]

                foreach (KeyValuePair <string, Language> pair in aliases)
                {
                    file.WriteString(pair.Key);
                    file.WriteInt32(pair.Value.ID);
                }

                file.WriteString(null);


                // [String: Extension] [Int32: Language ID] [] [] ... [String: Null]

                foreach (KeyValuePair <string, Language> pair in extensions)
                {
                    file.WriteString(pair.Key);
                    file.WriteInt32(pair.Value.ID);
                }

                file.WriteString(null);


                // [String: Shebang String] [Int32: Language ID] [] [] ... [String: Null]

                foreach (KeyValuePair <string, Language> pair in shebangStrings)
                {
                    file.WriteString(pair.Key);
                    file.WriteInt32(pair.Value.ID);
                }

                file.WriteString(null);


                // [String: Ignored Extension] [] ... [String: Null]

                foreach (string ignoredExtension in ignoredExtensions)
                {
                    file.WriteString(ignoredExtension);
                }

                file.WriteString(null);
            }

            finally
            {
                file.Close();
            }
        }
        /* Function: Save
         * Saves the passed <Config> into <Comments.nd>.  Throws an exception if unsuccessful.
         */
        public void Save(Path filename, Config config)
        {
            BinaryFile file = new BinaryFile();

            file.OpenForWriting(filename);

            try
            {
                // [String: Tag Name]
                // [Int32: ID]
                // ...
                // [String: null]

                foreach (var tag in config.Tags)
                {
                    file.WriteString(tag.Name);
                    file.WriteInt32(tag.ID);
                }

                file.WriteString(null);


                // [String: Comment Type Name]
                // [Int32: ID]
                // [String: Display Name]
                // [String: Plural Display Name]
                // [String: Simple Identifier]
                // [Byte: Scope]
                // [Byte: Flags]
                // ...
                // [String: null]

                foreach (var commentType in config.CommentTypes)
                {
                    file.WriteString(commentType.Name);
                    file.WriteInt32(commentType.ID);
                    file.WriteString(commentType.DisplayName);
                    file.WriteString(commentType.PluralDisplayName);
                    file.WriteString(commentType.SimpleIdentifier);
                    file.WriteByte((byte)commentType.Scope);
                    file.WriteByte((byte)commentType.Flags);
                }

                file.WriteString(null);


                // [String: Keyword]
                // [Byte: Plural (0 or 1)]
                // [Int32: Comment Type ID]
                // [Int32: Language ID or 0 if agnostic]
                // ...
                // [String: null]

                foreach (var keywordDefinition in config.KeywordDefinitions)
                {
                    file.WriteString(keywordDefinition.Keyword);
                    file.WriteByte((byte)(keywordDefinition.Plural ? 1 : 0));
                    file.WriteInt32(keywordDefinition.CommentTypeID);
                    file.WriteInt32((keywordDefinition.IsLanguageSpecific ? keywordDefinition.LanguageID : 0));
                }

                file.WriteString(null);
            }

            finally
            {
                file.Close();
            }
        }
Exemple #9
0
        /* Function: Save
         * Saves the passed information in <Config.nd>.
         */
        public void Save(Path filename, List <Style> styles, List <FileSourceInfo> fileSourceInfoList)
        {
            using (BinaryFile binaryFile = new BinaryFile())
            {
                binaryFile.OpenForWriting(filename);

                // [String: Style Path]
                // [String: Style Path]
                // ...
                // [String: null]

                foreach (var style in styles)
                {
                    if (style is Styles.CSSOnly)
                    {
                        binaryFile.WriteString((style as Styles.CSSOnly).CSSFile);
                    }
                    else if (style is Styles.Advanced)
                    {
                        binaryFile.WriteString((style as Styles.Advanced).ConfigFile);
                    }
                    else
                    {
                        throw new NotImplementedException();
                    }
                }

                binaryFile.WriteString(null);

                // [Int32: Source FileSource Number] [String: Source FileSource UniqueIDString]
                // [Int32: Source FileSource Number] [String: Source FileSource UniqueIDString]
                // ...
                // [Int32: 0]

                foreach (FileSourceInfo fileSourceInfo in fileSourceInfoList)
                {
                    if (fileSourceInfo.Type == Files.InputType.Source)
                    {
                        binaryFile.WriteInt32(fileSourceInfo.Number);
                        binaryFile.WriteString(fileSourceInfo.UniqueIDString);
                    }
                }

                binaryFile.WriteInt32(0);

                // [Int32: Image FileSource Number] [String: Image FileSource UniqueIDString]
                // [Int32: Image FileSource Number] [String: Image FileSource UniqueIDString]
                // ...
                // [Int32: 0]

                foreach (FileSourceInfo fileSourceInfo in fileSourceInfoList)
                {
                    if (fileSourceInfo.Type == Files.InputType.Image)
                    {
                        binaryFile.WriteInt32(fileSourceInfo.Number);
                        binaryFile.WriteString(fileSourceInfo.UniqueIDString);
                    }
                }

                binaryFile.WriteInt32(0);
            }
        }
Exemple #10
0
        // Group: Saving Functions
        // __________________________________________________________________________


        /* Function: Save
         * Saves the passed <ProjectConfig> into <Project.nd>.  Throws an exception if unsuccessful.
         */
        public void Save(Path filename, ProjectConfig projectConfig)
        {
            var output = new BinaryFile();

            output.OpenForWriting(filename);

            try
            {
                // [Int32: Tab Width]
                // [Byte: Documented Only (0 or 1)]
                // [Byte: Auto Group (0 or 1)]
                // [Byte: Shrink Files (0 or 1)]

                output.WriteInt32(projectConfig.TabWidth);
                output.WriteByte((byte)((bool)projectConfig.DocumentedOnly == false ? 0 : 1));
                output.WriteByte((byte)((bool)projectConfig.AutoGroup == false ? 0 : 1));
                output.WriteByte((byte)((bool)projectConfig.ShrinkFiles == false ? 0 : 1));

                // [String: Identifier]
                // [[Properties]]
                // ...
                // [String: null]

                foreach (var target in projectConfig.InputTargets)
                {
                    if (target is Targets.SourceFolder)
                    {
                        SaveSourceFolder((Targets.SourceFolder)target, output);
                    }
                    else if (target is Targets.ImageFolder)
                    {
                        SaveImageFolder((Targets.ImageFolder)target, output);
                    }
                    else
                    {
                        throw new NotImplementedException();
                    }
                }

                // We don't save filter targets

                foreach (var target in projectConfig.OutputTargets)
                {
                    if (target is Targets.HTMLOutputFolder)
                    {
                        SaveHTMLOutputFolder((Targets.HTMLOutputFolder)target, output);
                    }
                    else
                    {
                        throw new NotImplementedException();
                    }
                }

                output.WriteString(null);
            }

            finally
            {
                output.Close();
            }
        }
Exemple #11
0
        /* Function: Save
         * Saves the current computed comment types into <Comments.nd>.  Throws an exception if unsuccessful.
         */
        public void Save(Path filename, IDObjects.Manager <CommentType> commentTypes, IDObjects.Manager <Tag> tags,
                         StringTable <CommentType> singularKeywords, StringTable <CommentType> pluralKeywords,
                         StringSet ignoredKeywords)
        {
            BinaryFile file = new BinaryFile();

            file.OpenForWriting(filename);

            try
            {
                // [String: Tag Name]
                // [Int32: ID]
                // ...
                // [String: null]

                foreach (Tag tag in tags)
                {
                    file.WriteString(tag.Name);
                    file.WriteInt32(tag.ID);
                }

                file.WriteString(null);


                // [String: Comment Type Name]
                // [Int32: ID]
                // [String: Display Name]
                // [String: Plural Display Name]
                // [String: Simple Identifier]
                // [Byte: Index]
                // [Int32: Index With ID]?
                // [Byte: Scope]
                // [Byte: Break Lists]
                // [UInt16: Flags]
                // ...
                // [String: null]

                foreach (CommentType commentType in commentTypes)
                {
                    file.WriteString(commentType.Name);
                    file.WriteInt32(commentType.ID);
                    file.WriteString(commentType.DisplayName);
                    file.WriteString(commentType.PluralDisplayName);
                    file.WriteString(commentType.SimpleIdentifier);
                    file.WriteByte((byte)commentType.Index);

                    if (commentType.Index == CommentType.IndexValue.IndexWith)
                    {
                        file.WriteInt32(commentType.IndexWith);
                    }

                    file.WriteByte((byte)commentType.Scope);
                    file.WriteByte((byte)(commentType.BreakLists ? 1 : 0));
                    file.WriteUInt16((ushort)commentType.Flags.AllConfigurationProperties);
                }

                file.WriteString(null);


                // [String: Singular Keyword]
                // [Int32: Comment Type ID]
                // ...
                // [String: null]

                foreach (KeyValuePair <string, CommentType> pair in singularKeywords)
                {
                    file.WriteString(pair.Key);
                    file.WriteInt32(pair.Value.ID);
                }

                file.WriteString(null);


                // [String: Plural Keyword]
                // [Int32: Comment Type ID]
                // ...
                // [String: null]

                foreach (KeyValuePair <string, CommentType> pair in pluralKeywords)
                {
                    file.WriteString(pair.Key);
                    file.WriteInt32(pair.Value.ID);
                }

                file.WriteString(null);


                // [String: Ignored Keyword]
                // ...
                // [String: null]

                foreach (string keyword in ignoredKeywords)
                {
                    file.WriteString(keyword);
                }

                file.WriteString(null);
            }

            finally
            {
                file.Close();
            }
        }