/// <summary> /// Process a job XML file. /// </summary> /// <param name="xml">An open stream to the XML data.</param> /// <param name="commitStore">If not null, this will hold all store commits made /// by this job.</param> /// <param name="writeLog">Ignored in release builds. This will accumulate a /// log of write operations into the output SWF file(s).</param> /// <param name="abcWriteLog">A log of write events to ABC data within the /// output SWF files.</param> /// <param name="abcInterceptor">Ignored in release builds. This will be called /// when an ABC file is loaded as an opportunity to dump the data to file /// for inspection.</param> /// <param name="readLogHandler">Ignored in release builds. Whenever /// the Swiffotron reads a SWF file, this is called so that it can dump read /// operations to a log.</param> public void Process( Stream xml, Dictionary<string, byte[]> commitStore = null, StringBuilder writeLog = null, StringBuilder abcWriteLog = null, IABCLoadInterceptor abcInterceptor = null, ISwiffotronReadLogHandler readLogHandler = null) { #if DEBUG this.abcInterceptor = abcInterceptor; this.readLogHandler = readLogHandler; #endif this.commitStore = commitStore; Xml.LoadSwiffotronXML(xml); string jobID = Xml.SelectString("swf:swiffotron/@id"); this.Context = new SwiffotronContext(jobID); this.Xml.SetContext(this.Context); this.swfProc = new SWFProcessor(this.Context); this.processingList = new List<XPathNavigator>(); this.dependencyMap = new List<DependencyList>(); this.processedSWFs = new Dictionary<string, SWF>(); this.localCache = new Dictionary<string, object>(); /* Take local copies of all referenced cache objects to guard against * them being ejected before we access them, since we work out what we * need to do based on what's in the cache before we do it. */ foreach (XPathNavigator keyNode in Xml.Select(@"//@cachekey")) { string key = keyNode.ToString(); object data = this.caches.Get(this.Context, key); if (data != null) { this.localCache.Add(key, data); } } /* Select all the swf tags that have some sort of output: */ foreach (XPathNavigator outputTag in Xml.Select(@"//swf:swfout|//swf:pngout|//swf:vidout|//swf:svgout|//swf:htmlout")) { XmlAttributeCollection attribs = ((XmlElement)outputTag.UnderlyingObject).Attributes; /* ISSUE 28: Check the runifnotchanged thing. */ string dest = outputTag.GetAttribute(XMLHelper.AttrStore, string.Empty); outputTag.MoveToParent(); /* Select SWF tag */ if (!this.IsInDependenciesMap(outputTag)) { /* Add them with no dependencies. We'll work out dependencies in the * next step. */ this.dependencyMap.Add(new DependencyList(outputTag, null)); } } int pos = 0; while (pos < this.dependencyMap.Count) { this.AddDependencies(this.dependencyMap[pos]); pos++; } /* Now that we have a list of things and their dependencies, we * need to copy those nodes into the processingList in the correct * order. */ while (this.dependencyMap.Count > 0) { List<DependencyList> newMap = new List<DependencyList>(); foreach (DependencyList dep in this.dependencyMap) { if (dep.Count == 0) { this.processingList.Add(dep.Node); foreach (DependencyList filterDep in this.dependencyMap) { filterDep.RemoveDependency(dep.Node); } } else { /* Things still to be done. */ newMap.Add(dep); } } if (newMap.Count == this.dependencyMap.Count) { /* No progress was made, so: */ throw new SwiffotronException( SwiffotronError.BadInputXML, this.Context, @"A circular dependency was detected."); } this.dependencyMap = newMap; } /* And so, after all that, we can begin: */ this.GenerateSWFs(writeLog, abcWriteLog); }
/// <summary> /// Initializes a new instance of a SWF parser. /// </summary> /// <param name="swfIn">A stream with SWF data to read from.</param> /// <param name="binaryDump">Only has an effect in debug builds.</param> /// <param name="abcInterceptor">Only has an effect in debug builds.</param> /// <param name="dbugConstFilter">Only has an effect in debug builds.</param> public SWFReader( Stream swfIn, SWFReaderOptions options, StringBuilder binaryDump, IABCLoadInterceptor abcInterceptor) { this.options = options; this.sdtr = new SWFDataTypeReader(swfIn); this.characterUnmarshaller = new Dictionary<int, ICharacter>(); this.LateClassResolutions = new Dictionary<string, Timeline>(); this.doAbcCount = 0; #if DEBUG this.binaryDump = binaryDump; this.binaryDumpNest = 0; this.abcInterceptor = abcInterceptor; #endif }