Represents all data from an INI file
Inheritance: ICloneable
		/// <summary>
		/// 
		/// </summary>
		/// <param name="bindings"></param>
		/// <param name="path"></param>
		public static void LoadFromStream	( IEnumerable<GameModule.ModuleBinding> bindings, Stream stream )
		{
			try {
		
				var iniData = new IniData();
				var parser = new StreamIniDataParser();

				parser.Parser.Configuration.CommentString	=	"# ";

				using ( var sw = new StreamReader(stream) ) {
					iniData	= parser.ReadData( sw );
				}
			

				//	read data :
				foreach ( var section in iniData.Sections ) {

					var bind	=	bindings
								.Where( b => b.NiceName == section.SectionName )
								.SingleOrDefault();

					if (bind==null) {
						Log.Warning("Module {0} does not exist. Section ignored.", section.SectionName );
					}

					bind.Module.SetConfiguration( section.Keys );
				}

			} catch (IniParser.Exceptions.ParsingException e) {
				Log.Warning("INI parser error: {0}", e.Message);
			}
		}
        /// <summary>
        ///     Writes the ini data to a stream.
        /// </summary>
        /// <param name="writer">A write stream where the ini data will be stored</param>
        /// <param name="iniData">An <see cref="IniData"/> instance.</param>
        /// <exception cref="ArgumentNullException">
        ///     Thrown if <paramref name="writer"/> is <c>null</c>.
        /// </exception>
        public void WriteData(StreamWriter writer, IniData iniData)
        {
            if (iniData == null)
                throw new ArgumentNullException("iniData");
            if (writer == null)
                throw new ArgumentNullException("writer");

            writer.Write(iniData.ToString());
        }
Example #3
0
		/// <summary>
		/// 
		/// </summary>
		/// <param name="options"></param>
		public BuildContext ( BuildOptions options, IniData iniData )
		{
			this.Options	=	options;

			Log.Message("Source directories:");

				contentPaths	=	new List<string>();
				contentPaths.Add( options.FullInputDirectory );
				contentPaths.AddRange( GetAllKeysFromSection( iniData, "ContentDirectories" ).Select( p => ResolveDirectory( p )).Where( p1 => p1!=null ) );

				foreach ( var dir in contentPaths ) {
					Log.Message("  {0}", dir );
				}

			Log.Message("");


			Log.Message("Binary directories:");
				binaryPaths	=	new List<string>();
				binaryPaths.AddRange( GetAllKeysFromSection( iniData, "BinaryDirectories" ).Select( p => ResolveDirectory( p )).Where( p1 => p1!=null ) );

				foreach ( var dir in binaryPaths ) {
					Log.Message("  {0}", dir );
				}
			Log.Message("");


			
			Log.Message("Target directory:");
			Log.Message("  {0}", options.FullOutputDirectory );
			Log.Message("");

			
			Log.Message("Temp directory:");
			Log.Message("  {0}", options.FullTempDirectory );

			Log.Message("");
			 
		}
		public static void SaveToStream ( IEnumerable<GameModule.ModuleBinding> bindings, Stream stream )
		{
			try {
		
				//	prepare ini data :			
				IniData iniData = new IniData();
				iniData.Configuration.CommentString	=	"# ";

				foreach ( var bind in bindings ) {

					var sectionName		=	bind.NiceName;
					var config			=	bind.Module.GetConfiguration();

					iniData.Sections.AddSection( sectionName );

					var sectionData	=	iniData.Sections.GetSectionData( sectionName );

					foreach ( var key in config ) { 
						if (sectionData.Keys.ContainsKey(key.KeyName)) {
							sectionData.Keys.RemoveKey(key.KeyName);
						}
						sectionData.Keys.AddKey( key );
					}
				}


				//	write file :
				var parser = new StreamIniDataParser();

				using ( var sw = new StreamWriter(stream) ) {
					parser.WriteData( sw, iniData );
				}

			} catch (IniParser.Exceptions.ParsingException e) {
				Log.Warning("INI parser error: {0}", e.Message);
			}
		}
Example #5
0
        /// <summary>
        ///     Processes one line and parses the data found in that line
        ///     (section or key/value pair who may or may not have comments)
        /// </summary>
        /// <param name="currentLine">The string with the line to process</param>
        protected virtual void ProcessLine(string currentLine, IniData currentIniData)
        {
            currentLine = currentLine.Trim();

            // Extract comments from current line and store them in a tmp field
            if (LineContainsAComment(currentLine))
            {
                currentLine = ExtractComment(currentLine);
            }

            // By default comments must span a complete line (i.e. the comment character
            // must be located at the beginning of a line, so it seems that the following
            // check is not needed.
            // But, if the comment parsing behaviour is changed in a derived class e.g. to
            // to allow parsing comment characters in the middle of a line, the implementor
            // will be forced to rewrite this complete method.
            // That was actually the behaviour for parsing comments
            // in earlier versions of the library, so checking if the current line is empty
            // (meaning the complete line was a comment) is future-proof.

            // If the entire line was a comment now should be empty,
            // so no further processing is needed.
            if (currentLine == String.Empty)
                return;

            //Process sections
            if (LineMatchesASection(currentLine))
            {
                ProcessSection(currentLine, currentIniData);
                return;
            }

            //Process keys
            if (LineMatchesAKeyValuePair(currentLine))
            {
                ProcessKeyValuePair(currentLine, currentIniData);
                return;
            }

			if (Configuration.AllowKeysWithoutValues) {
				if (LineMatchesAKeyOnly(currentLine))
				{
					ProcessKeyOnly(currentLine, currentIniData);
					return;
				}
			}

            if (Configuration.SkipInvalidLines)
                return;

            throw new ParsingException(
                "Unknown file format. Couldn't parse the line: '" + currentLine + "'.");
        }
Example #6
0
		/// <summary>
		/// 
		/// </summary>
		/// <param name="iniData"></param>
		/// <param name="sectionName"></param>
		/// <returns></returns>
		string[] GetAllKeysFromSection ( IniData iniData, string sectionName )
		{
			if (!iniData.Sections.ContainsSection(sectionName)) {
				return new string[0];
			}

			return iniData.Sections[ sectionName ]
					.Select( key => key.KeyName )
					.ToArray();
		}
Example #7
0
 /// <summary>
 /// Copies an instance of the <see cref="Fusion.Core.IniParser.Model.IniDataCaseInsensitive"/> class
 /// </summary>
 /// <param name="ori">Original </param>
 public IniDataCaseInsensitive(IniData ori)
     : this(new SectionDataCollection(ori.Sections, StringComparer.OrdinalIgnoreCase))
 {
     Global        = (KeyDataCollection)ori.Global.Clone();
     Configuration = ori.Configuration.Clone();
 }
Example #8
0
		/// <summary>
		/// 
		/// </summary>
		/// <param name="sourceFolder"></param>
		/// <returns></returns>
		List<AssetSource> GatherAssetFiles ( string[] ignorePatterns, IniData iniData, BuildContext context, ref BuildResult result )
		{
			var assetSources = new List<AssetSource>();

			//	key contain key path
			//	value containt full path
			var files	=	new List<LocalFile>();

			//	gather files from all directories 
			//	and then distinct them by key path.
			foreach ( var contentDir in context.ContentDirectories ) {

				var localFiles	=	Directory.EnumerateFiles( contentDir, "*", SearchOption.AllDirectories )
								.Where( f1 => Path.GetFileName(f1).ToLowerInvariant() != ".content" );
							
				files.AddRange( localFiles.Select( fullpath => new LocalFile( contentDir, fullpath ) ) );
			}

			files			=	files.DistinctBy( file => file.KeyPath ).ToList();
			result.Total	=	files.Count;


			//	ignore files by ignore pattern
			//	and count ignored files :
			result.Ignored = files.RemoveAll( file => {
				foreach ( var pattern in ignorePatterns ) {
					if (Wildcard.Match( file.KeyPath, pattern )) {
						return true;
					}
				}
				return false;
			});



			foreach ( var section in iniData.Sections ) {

				//	'Ingore' is a special section.
				if (section.SectionName=="Ignore") { continue; }
				if (section.SectionName=="ContentDirectories") { continue; }
				if (section.SectionName=="BinaryDirectories") { continue; }
				if (section.SectionName=="Download") { continue; }

				//	get processor :
				if (!processors.ContainsKey(section.SectionName)) {
					Log.Warning("Asset processor '{0}' not found. Files will be skipped.", section.SectionName );
					Log.Message("");
					continue;
				}
				
				var procBind = processors[section.SectionName];

				//	get mask and arguments :
				var maskArgs = section.Keys
					.Reverse()
					.Select( key => new {
						Mask = key.KeyName.Split(' ', '\t').FirstOrDefault(), 
						Args = CommandLineParser.SplitCommandLine( key.KeyName ).Skip(1).ToArray()
					 })
					.ToList();
					

				foreach ( var file in files ) {

					if (file.Handled) {
						continue;
					}

					foreach ( var maskArg in maskArgs ) {
						if ( Wildcard.Match( file.KeyPath, maskArg.Mask, true ) ) {
							file.Handled = true;
							assetSources.Add( new AssetSource( file.KeyPath, file.BaseDir, procBind.Type, maskArg.Args, context ) ); 
							break;
						}
					}
				}

				//	count unhandled files :
				result.Skipped = files.Count( f => !f.Handled );
			}


			return assetSources;
		}
Example #9
0
        /// <summary>
        ///     Writes INI data to a text file.
        /// </summary>
        /// <param name="filePath">
        ///     Path to the file.
        /// </param>
        /// <param name="parsedData">
        ///     IniData to be saved as an INI file.
        /// </param>
        /// <param name="fileEncoding">
        ///     Specifies the encoding used to create the file.
        /// </param>
        public void WriteFile(string filePath, IniData parsedData, Encoding fileEncoding = null)
        {
            // The default value can't be assigned as a default parameter value because it is not
            // a constant expression.
			if (fileEncoding == null)
				fileEncoding = Encoding.ASCII;

            if (string.IsNullOrEmpty(filePath))
                throw new ArgumentException("Bad filename.");

            if (parsedData == null)
                throw new ArgumentNullException("parsedData");

            using (FileStream fs = File.Open(filePath, FileMode.Create, FileAccess.Write))
            {
                using (StreamWriter sr = new StreamWriter(fs, fileEncoding))
                {
                    WriteData(sr, parsedData);
                }
            }
        }
Example #10
0
 public IniData(IniData ori) : this((SectionDataCollection)ori.Sections)
 {
     Global        = (KeyDataCollection)ori.Global.Clone();
     Configuration = ori.Configuration.Clone();
 }
Example #11
0
 public IniData(IniData ori): this((SectionDataCollection) ori.Sections)
 {
     Global = (KeyDataCollection) ori.Global.Clone();
     Configuration = ori.Configuration.Clone();
 }
Example #12
0
        /// <summary>
        ///     Merges the other iniData into this one by overwriting existing values.
        ///     Comments get appended.
        /// </summary>
        /// <param name="toMergeIniData">
        ///     IniData instance to merge into this. 
        ///     If it is null this operation does nothing.
        /// </param>
        public void Merge(IniData toMergeIniData)
        {

            if (toMergeIniData == null) return;

            Global.Merge(toMergeIniData.Global);

            Sections.Merge(toMergeIniData.Sections);

        }
 /// <summary>
 /// Copies an instance of the <see cref="Fusion.Core.IniParser.Model.IniDataCaseInsensitive"/> class
 /// </summary>
 /// <param name="ori">Original </param>
 public IniDataCaseInsensitive(IniData ori)
     : this(new SectionDataCollection(ori.Sections, StringComparer.OrdinalIgnoreCase))
 {
     Global = (KeyDataCollection) ori.Global.Clone();
     Configuration = ori.Configuration.Clone();
 }
Example #14
0
 /// <summary>
 /// Creates a string from the INI data.
 /// </summary>
 /// <param name="iniData">An <see cref="IniData"/> instance.</param>
 /// <returns>
 /// A formatted string with the contents of the
 /// <see cref="IniData"/> instance object.
 /// </returns>
 public string WriteString(IniData iniData)
 {
     return iniData.ToString();
 }
Example #15
0
        /// <summary>
        ///     Proccess a string which contains an ini section.
        /// </summary>
        /// <param name="line">
        ///     The string to be processed
        /// </param>
        protected virtual void ProcessSection(string line, IniData currentIniData)
        {
            // Get section name with delimiters from line...
            string sectionName = Configuration.SectionRegex.Match(line).Value.Trim();

            // ... and remove section's delimiters to get just the name
            sectionName = sectionName.Substring(1, sectionName.Length - 2).Trim();

            // Check that the section's name is not empty
            if (sectionName == string.Empty)
            {
                throw new ParsingException("Section name is empty");
            }

            // Temporally save section name.
            _currentSectionNameTemp = sectionName;

            //Checks if the section already exists
            if (currentIniData.Sections.ContainsSection(sectionName))
            {
                if (Configuration.AllowDuplicateSections)
                {
                    return;
                }

                throw new ParsingException(string.Format("Duplicate section with name '{0}' on line '{1}'", sectionName, line));
            }


            // If the section does not exists, add it to the ini data
            currentIniData.Sections.AddSection(sectionName);

            // Save comments read until now and assign them to this section
            currentIniData.Sections.GetSectionData(sectionName).LeadingComments = _currentCommentListTemp;
            _currentCommentListTemp.Clear();

        }
Example #16
0
		/// <summary>
		/// 
		/// </summary>
		/// <param name="sourceFolder"></param>
		/// <param name="targetFolder"></param>
		/// <param name="force"></param>
		public BuildResult Build ( BuildOptions options, IniData iniData )
		{
			BuildResult result	=	new BuildResult();
	
			context				=	new BuildContext( options, iniData );
			var ignorePatterns	=	new string[0];

			if ( iniData.Sections.ContainsSection("Ignore") ) {
				ignorePatterns	=	iniData.Sections["Ignore"]
									.Select( element => element.KeyName )
									.Select( key => ContentUtils.BackslashesToSlashes( key ) )
									.ToArray();
			}


			if ( iniData.Sections.ContainsSection("Download") ) {
				Download( context, iniData.Sections["Download"], result );
			}


			//
			//	gather files on source folder ignoring 
			//	files that match ignore pattern :
			//
			Log.Message("Gathering files...");
			var assetSources =	GatherAssetFiles( ignorePatterns, iniData, context, ref result );
			Log.Message("");


			//
			//	Check hash collisions :
			//
			var collisions	=	assetSources
								.GroupBy( file0 => file0.TargetName )
								.Where( fileGroup1 => fileGroup1.Count() > 1 )
								.Distinct()
								.ToArray();

			if (collisions.Any()) {
				Log.Error("Hash collisions detected:");
				int collisionCount = 0;
				foreach ( var collision in collisions ) {
					Log.Error("  [{0}] {1}", collisionCount++, collision.Key);
					foreach ( var collisionEntry in collision ) {
						Log.Error( "    {0}",  collisionEntry.FullSourcePath );
					}
				}
				throw new BuildException("Hash collisions detected");
			}


			//
			//	remove stale built content :
			//
			Log.Message("Cleaning stale content up...");
			CleanStaleContent( options.FullOutputDirectory, assetSources );			
			Log.Message("");


			//
			//	Build everything :
			//
			foreach ( var assetSource in assetSources ) {
				
				var proc = assetSource.CreateProcessor();
				BuildAsset( proc, assetSource.BuildArguments, assetSource, ref result );

			}

			return result;
		}
Example #17
0
        /// <summary>
        ///     Processes a string containing an ini key/value pair.
        /// </summary>
        /// <param name="line">
        ///     The string to be processed
        /// </param>
        protected virtual void ProcessKeyOnly(string line, IniData currentIniData)
        {
            // get key and value data
            string key = line;
            string value = "";

            // Check if we haven't read any section yet
            if (string.IsNullOrEmpty(_currentSectionNameTemp))
            {
                if (!Configuration.AllowKeysWithoutSection)
                {
                    throw new ParsingException("key value pairs must be enclosed in a section");
                }

                AddKeyToKeyValueCollection(key, value, currentIniData.Global, "global");
            }
            else
            {
                var currentSection = currentIniData.Sections.GetSectionData(_currentSectionNameTemp);

                AddKeyToKeyValueCollection(key, value, currentSection.Keys, _currentSectionNameTemp);
            }
        }
Example #18
0
 public void SaveFile(string filePath, IniData parsedData)
 {
     WriteFile(filePath, parsedData, Encoding.ASCII);
 }