File: WorkflowSymbol.cs

package info (click to toggle)
mono 6.8.0.105%2Bdfsg-3.3
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 1,284,512 kB
  • sloc: cs: 11,172,132; xml: 2,850,069; ansic: 671,653; cpp: 122,091; perl: 59,366; javascript: 30,841; asm: 22,168; makefile: 20,093; sh: 15,020; python: 4,827; pascal: 925; sql: 859; sed: 16; php: 1
file content (217 lines) | stat: -rw-r--r-- 8,047 bytes parent folder | download | duplicates (7)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
//----------------------------------------------------------------
// Copyright (c) Microsoft Corporation.  All rights reserved.
//----------------------------------------------------------------
namespace System.Activities.Debugger.Symbol
{
    using System;
    using System.IO;
    using System.IO.Compression;
    using System.Runtime;
    using System.Runtime.Serialization;
    using System.Text;
    using System.Globalization;
    using System.Collections.Generic;
    using System.Security.Cryptography;

    // Represent debug symbol of a workflow tree (similar to pdb file).
    // It contains the absolute path of the xaml file and the location of each activity in the workflow tree.
    // This is used to instrument the workflow without having access to the original xaml file.
    public class WorkflowSymbol
    {
        public string FileName { get; set; }
        public ICollection<ActivitySymbol> Symbols { get; set; }

        private byte[] checksum;
        public byte[] GetChecksum()
        {
            if (this.checksum == null)
            {
                return null;
            }
            return (byte[]) this.checksum.Clone();
        }
        
        [Flags]
        internal enum EncodingFormat : byte
        {
            String = 0x76,    // Format as well as cookie. String format is hidden from public.
            Binary = 0x77,
            Checksum = 0x80            
        }

        internal const EncodingFormat DefaultEncodingFormat = EncodingFormat.Binary;

        public WorkflowSymbol()
        {
        }

        // These constructors are private and used by Decode() method.

        // Binary deserializer.
        WorkflowSymbol(BinaryReader reader, byte[] checksum)
        {
            this.FileName = reader.ReadString();
            int numSymbols = SymbolHelper.ReadEncodedInt32(reader);
            this.Symbols = new List<ActivitySymbol>(numSymbols);
            for (int i = 0; i < numSymbols; ++i)
            {
                this.Symbols.Add(new ActivitySymbol(reader));
            }
            this.checksum = checksum;
        }

        // Decode from Base64 string.
        public static WorkflowSymbol Decode(string symbolString)
        {
            byte[] data = Convert.FromBase64String(symbolString);
            using (BinaryReader reader = new BinaryReader(new MemoryStream(data)))
            {
                byte[] checksum = null;
                EncodingFormat format = (EncodingFormat)reader.ReadByte();
                int payloadBytesCount = data.Length - sizeof(EncodingFormat);
                if (0 != (format & EncodingFormat.Checksum))
                {
                    int bytesCount = SymbolHelper.ReadEncodedInt32(reader);
                    checksum = reader.ReadBytes(bytesCount);
                    payloadBytesCount -= SymbolHelper.GetEncodedSize(bytesCount);
                    format &= (~EncodingFormat.Checksum);
                }
                switch (format)
                {
                    case EncodingFormat.Binary:
                        return ParseBinary(reader.ReadBytes(payloadBytesCount), checksum); // Compute the 
                    case EncodingFormat.String:
                        return ParseStringRepresentation(reader.ReadString(), checksum);
                }
            }
            throw FxTrace.Exception.AsError(new SerializationException());
        }

        // Serialization

        // Encode to Base64 string
        public string Encode()
        {
            return Encode(WorkflowSymbol.DefaultEncodingFormat); // default format
        }

        internal string Encode(EncodingFormat encodingFormat)
        {
            using (MemoryStream ms = new MemoryStream())
            {
                using (BinaryWriter writer = new BinaryWriter(ms))
                {
                    if (this.checksum != null)
                    {
                        writer.Write((byte)(encodingFormat | EncodingFormat.Checksum));
                        SymbolHelper.WriteEncodedInt32(writer, this.checksum.Length);
                        writer.Write(this.checksum);
                    }
                    else
                    {
                        writer.Write((byte)encodingFormat);
                    }
                    switch (encodingFormat)
                    {
                        case EncodingFormat.Binary:
                            this.Write(writer);
                            break;
                        case EncodingFormat.String:
                            writer.Write(this.ToString());
                            break;
                        default:
                            throw FxTrace.Exception.AsError(new SerializationException());
                    }
                    // Need to copy to a buffer to trim excess capacity.
                    byte[] buffer = new byte[ms.Length];
                    Array.Copy(ms.GetBuffer(), buffer, ms.Length);
                    return Convert.ToBase64String(buffer);
                }
            } 
        }

        // Binary deserializer
        static WorkflowSymbol ParseBinary(byte[] bytes, byte[] checksum)
        {
            using (BinaryReader reader = new BinaryReader(new MemoryStream(bytes)))
            {
                return new WorkflowSymbol(reader, checksum);
            }
        }

        // Binary serializer
        void Write(BinaryWriter writer)
        {
            writer.Write(this.FileName ?? string.Empty);
            if (this.Symbols != null)
            {
                SymbolHelper.WriteEncodedInt32(writer, this.Symbols.Count);
                foreach (ActivitySymbol actSym in this.Symbols)
                {
                    actSym.Write(writer);
                }
            }
            else
            {
                SymbolHelper.WriteEncodedInt32(writer, 0);
            }
        }

        // String encoding serialization.

        // This is used for String encoding format.
        public override string ToString()
        {
            StringBuilder builder = new StringBuilder();
            builder.AppendFormat("{0}", this.FileName ?? string.Empty);
            if (this.Symbols != null)
            {
                foreach (ActivitySymbol symbol in Symbols)
                {
                    builder.AppendFormat(";{0}", symbol.ToString());
                }
            }
            return builder.ToString();
        }

        // Deserialization of string encoding format.
        static WorkflowSymbol ParseStringRepresentation(string symbolString, byte[] checksum)
        {
            string[] s = symbolString.Split(';');
            int numSymbols = s.Length - 1;
            ActivitySymbol[] symbols = new ActivitySymbol[numSymbols];
            for (int i = 0; i < numSymbols; ++i)
            {
                string[] symbolSegments = s[i + 1].Split(',');
                Fx.Assert(symbolSegments.Length == 5, "Invalid activity symbol");
                symbols[i] = new ActivitySymbol
                {
                    QualifiedId = QualifiedId.Parse(symbolSegments[0]).AsByteArray(),
                    StartLine = int.Parse(symbolSegments[1], CultureInfo.InvariantCulture),
                    StartColumn = int.Parse(symbolSegments[2], CultureInfo.InvariantCulture),
                    EndLine = int.Parse(symbolSegments[3], CultureInfo.InvariantCulture),
                    EndColumn = int.Parse(symbolSegments[4], CultureInfo.InvariantCulture)
                };
            }

            return new WorkflowSymbol
            {
                FileName = s[0],
                Symbols = symbols,
                checksum = checksum
            };

        }

        public bool CalculateChecksum()
        {
            this.checksum = null;
            if (!string.IsNullOrEmpty(this.FileName))
            {
                this.checksum = SymbolHelper.CalculateChecksum(this.FileName);
            }
            return (this.checksum != null);
        }

    }
}