Exemple #1
0
        /// <summary>
        /// Serializes the project and writes it to the specified file.
        /// </summary>
        /// <param name="proj">Project to serialize.</param>
        /// <param name="pathName">Output path name.</param>
        /// <param name="errorMessage">Human-readable error string, or an empty string if all
        ///   went well.</param>
        /// <returns>True on success.</returns>
        public static bool SerializeToFile(DisasmProject proj, string pathName,
                                           out string errorMessage)
        {
            try {
                string serializedData = SerializableProjectFile1.SerializeProject(proj);
                if (ADD_CRLF)
                {
                    // Add some line breaks.  This looks awful, but it makes text diffs
                    // much more useful.
                    serializedData = TextUtil.NonQuoteReplace(serializedData, "{", "{\r\n");
                    serializedData = TextUtil.NonQuoteReplace(serializedData, "},", "},\r\n");
                }

                // Check to see if the project file is read-only.  We want to fail early
                // so we don't leave our .TMP file sitting around -- the File.Delete() call
                // will fail if the destination is read-only.
                if (File.Exists(pathName) &&
                    (File.GetAttributes(pathName) & FileAttributes.ReadOnly) != 0)
                {
                    throw new IOException(string.Format(Properties.Resources.ERR_FILE_READ_ONLY,
                                                        pathName));
                }

                // The BOM is not required or recommended for UTF-8 files, but anecdotal
                // evidence suggests that it's sometimes useful.  Shouldn't cause any harm
                // to have it in the project file.  The explicit Encoding.UTF8 argument
                // causes it to appear -- WriteAllText normally doesn't.
                //
                // Write to a temp file, then rename over original after write has succeeded.
                string tmpPath = pathName + ".TMP";
                File.WriteAllText(tmpPath, serializedData, Encoding.UTF8);
                if (File.Exists(pathName))
                {
                    File.Delete(pathName);
                }
                File.Move(tmpPath, pathName);
                errorMessage = string.Empty;
                return(true);
            } catch (Exception ex) {
                errorMessage = ex.Message;
                return(false);
            }
        }
Exemple #2
0
        /// <summary>
        /// Reads the specified file and deserializes it into the project.
        /// </summary>
        /// <param name="pathName">Input path name.</param>
        /// <param name="proj">Project to deserialize into.</param>
        /// <param name="report">File load report, which may contain errors or warnings.</param>
        /// <returns>True on success.</returns>
        public static bool DeserializeFromFile(string pathName, DisasmProject proj,
                                               out FileLoadReport report)
        {
            Debug.WriteLine("Deserializing '" + pathName + "'");
            report = new FileLoadReport(pathName);
            string serializedData;

            try {
                serializedData = File.ReadAllText(pathName);
            } catch (Exception ex) {
                report.Add(FileLoadItem.Type.Error, Properties.Resources.ERR_PROJECT_LOAD_FAIL +
                           ": " + ex.Message);
                return(false);
            }

            if (serializedData.StartsWith(SerializableProjectFile1.MAGIC))
            {
                // File is a match for SerializableProjectFile1.  Strip header and deserialize.
                serializedData = serializedData.Substring(SerializableProjectFile1.MAGIC.Length);
                try {
                    bool ok = SerializableProjectFile1.DeserializeProject(serializedData,
                                                                          proj, report);
                    if (ok)
                    {
                        proj.UpdateCpuDef();
                    }
                    return(ok);
                } catch (Exception ex) {
                    // Ideally this won't happen -- errors should be caught explicitly.  This
                    // is a catch-all to keep us from crashing on expectedly bad input.
                    report.Add(FileLoadItem.Type.Error,
                               Properties.Resources.ERR_PROJECT_FILE_CORRUPT + ": " + ex);
                    return(false);
                }
            }
            else
            {
                report.Add(FileLoadItem.Type.Error, Properties.Resources.ERR_NOT_PROJECT_FILE);
                return(false);
            }
        }
Exemple #3
0
        /// <summary>
        /// Serializes a DisasmProject into an augmented JSON string.
        /// </summary>
        /// <param name="proj">Project to serialize.</param>
        /// <returns>Augmented JSON string.</returns>
        public static string SerializeProject(DisasmProject proj)
        {
            StringBuilder sb = new StringBuilder();

            sb.Append(MAGIC);   // augment with version string, which will be stripped
            sb.Append("\r\n");  // will be ignored by deserializer; might get converted to \n

            SerializableProjectFile1 spf = new SerializableProjectFile1();

            spf._ContentVersion = ProjectFile.CONTENT_VERSION;

            Debug.Assert(proj.FileDataLength == proj.FileData.Length);
            spf.FileDataLength = proj.FileDataLength;
            spf.FileDataCrc32  = (int)proj.FileDataCrc32;

            // Convert AddressMap to serializable form.
            spf.AddressMap = new List <SerAddressMap>();
            foreach (AddressMap.AddressMapEntry ent in proj.AddrMap)
            {
                spf.AddressMap.Add(new SerAddressMap(ent));
            }

            // Reduce TypeHints to a collection of ranges.  Output the type enum as a string
            // so we're not tied to a specific value.
            spf.TypeHints = new List <SerTypeHintRange>();
            TypedRangeSet trs = new TypedRangeSet();

            for (int i = 0; i < proj.TypeHints.Length; i++)
            {
                trs.Add(i, (int)proj.TypeHints[i]);
            }
            IEnumerator <TypedRangeSet.TypedRange> iter = trs.RangeListIterator;

            while (iter.MoveNext())
            {
                if (iter.Current.Type == (int)CodeAnalysis.TypeHint.NoHint)
                {
                    continue;
                }
                spf.TypeHints.Add(new SerTypeHintRange(iter.Current.Low, iter.Current.High,
                                                       ((CodeAnalysis.TypeHint)iter.Current.Type).ToString()));
            }

            // Convert StatusFlagOverrides to serializable form.  Just write the state out
            // as an integer... not expecting it to change.  If it does, we can convert.
            spf.StatusFlagOverrides = new Dictionary <string, int>();
            for (int i = 0; i < proj.StatusFlagOverrides.Length; i++)
            {
                if (proj.StatusFlagOverrides[i] == Asm65.StatusFlags.DefaultValue)
                {
                    continue;
                }
                spf.StatusFlagOverrides.Add(i.ToString(), proj.StatusFlagOverrides[i].AsInt);
            }

            // Convert Comments to serializable form.
            spf.Comments = new Dictionary <string, string>();
            for (int i = 0; i < proj.Comments.Length; i++)
            {
                if (string.IsNullOrEmpty(proj.Comments[i]))
                {
                    continue;
                }
                spf.Comments.Add(i.ToString(), proj.Comments[i]);
            }

            // Convert multi-line comments to serializable form.
            spf.LongComments = new Dictionary <string, SerMultiLineComment>();
            foreach (KeyValuePair <int, MultiLineComment> kvp in proj.LongComments)
            {
                spf.LongComments.Add(kvp.Key.ToString(), new SerMultiLineComment(kvp.Value));
            }

            // Convert multi-line notes to serializable form.
            spf.Notes = new Dictionary <string, SerMultiLineComment>();
            foreach (KeyValuePair <int, MultiLineComment> kvp in proj.Notes)
            {
                spf.Notes.Add(kvp.Key.ToString(), new SerMultiLineComment(kvp.Value));
            }

            // Convert user-defined labels to serializable form.
            spf.UserLabels = new Dictionary <string, SerSymbol>();
            foreach (KeyValuePair <int, Symbol> kvp in proj.UserLabels)
            {
                spf.UserLabels.Add(kvp.Key.ToString(), new SerSymbol(kvp.Value));
            }

            // Convert operand and data item format descriptors to serializable form.
            spf.OperandFormats = new Dictionary <string, SerFormatDescriptor>();
            foreach (KeyValuePair <int, FormatDescriptor> kvp in proj.OperandFormats)
            {
                spf.OperandFormats.Add(kvp.Key.ToString(), new SerFormatDescriptor(kvp.Value));
            }

            spf.ProjectProps = new SerProjectProperties(proj.ProjectProps);

            JavaScriptSerializer ser = new JavaScriptSerializer();
            string cereal            = ser.Serialize(spf);

            sb.Append(cereal);

            // Stick a linefeed at the end.  Makes git happier.
            sb.Append("\r\n");

            return(sb.ToString());
        }