Neuron®
The Neuron® is the basis for the creation of open and secure federated networks for smart societies.
Loading...
Searching...
No Matches
CSV.cs
1using System;
2using System.Collections.Generic;
3using System.Text;
7
8namespace Waher.Content
9{
15 public delegate string ToString(IElement Element);
16
20 public static class CSV
21 {
22 #region Encoding/Decoding
23
29 public static string[][] Parse(string Csv)
30 {
31 int Pos = 0;
32 int Len = Csv.Length;
33 string[][] Result = Parse(Csv, ref Pos, Len);
34 char ch;
35
36 while (Pos < Len && ((ch = Csv[Pos]) <= ' ' || ch == 160))
37 Pos++;
38
39 if (Pos < Len)
40 throw new Exception("Unexpected content at end of string.");
41
42 return Result;
43 }
44
45 private static string[][] Parse(string Csv, ref int Pos, int Len)
46 {
47 List<string[]> Records = new List<string[]>();
48 List<string> Fields = new List<string>();
49 StringBuilder sb = new StringBuilder();
50 int State = 0;
51 int i = 0;
52 char ch;
53 bool sbEmpty = true;
54
55 while (Pos < Len)
56 {
57 ch = Csv[Pos++];
58 switch (State)
59 {
60 case 0:
61 if (ch == '"')
62 State += 2;
63 else if (ch == ',')
64 Fields.Add(string.Empty);
65 else if (ch == '\r' || ch == '\n')
66 {
67 if (Fields.Count > 0)
68 {
69 Records.Add(Fields.ToArray());
70 Fields.Clear();
71 }
72 }
73 else
74 {
75 sb.Append(ch);
76 sbEmpty = false;
77 State++;
78 }
79 break;
80
81 case 1: // Undelimited string
82 if (ch == ',')
83 {
84 Fields.Add(sb.ToString());
85 sb.Clear();
86 sbEmpty = true;
87 State = 0;
88 }
89 else if (ch == '\r' || ch == '\n')
90 {
91 Fields.Add(sb.ToString());
92 sb.Clear();
93 sbEmpty = true;
94 State = 0;
95
96 Records.Add(Fields.ToArray());
97 Fields.Clear();
98 }
99 else
100 {
101 sb.Append(ch);
102 sbEmpty = false;
103 }
104 break;
105
106 case 2: // String.
107 if (ch == '\\')
108 State++;
109 else if (ch == '"')
110 State--;
111 else
112 {
113 sb.Append(ch);
114 sbEmpty = false;
115 }
116 break;
117
118 case 3: // String, escaped character.
119 switch (ch)
120 {
121 case 'a':
122 sb.Append('\a');
123 break;
124
125 case 'b':
126 sb.Append('\b');
127 break;
128
129 case 'f':
130 sb.Append('\f');
131 break;
132
133 case 'n':
134 sb.Append('\n');
135 break;
136
137 case 'r':
138 sb.Append('\r');
139 break;
140
141 case 't':
142 sb.Append('\t');
143 break;
144
145 case 'v':
146 sb.Append('\v');
147 break;
148
149 case 'x':
150 i = 0;
151 State += 4;
152 break;
153
154 case 'u':
155 i = 0;
156 State += 2;
157 break;
158
159 default:
160 sb.Append(ch);
161 break;
162 }
163
164 sbEmpty = false;
165 State--;
166 break;
167
168 case 4: // hex digit 1(4)
169 i = JSON.HexDigit(ch);
170 State++;
171 break;
172
173 case 5: // hex digit 2(4)
174 i <<= 4;
175 i |= JSON.HexDigit(ch);
176 State++;
177 break;
178
179 case 6: // hex digit 3(4)
180 i <<= 4;
181 i |= JSON.HexDigit(ch);
182 State++;
183 break;
184
185 case 7: // hex digit 4(4)
186 i <<= 4;
187 i |= JSON.HexDigit(ch);
188 sb.Append((char)i);
189 sbEmpty = false;
190 State -= 5;
191 break;
192 }
193 }
194
195 if (!sbEmpty)
196 Fields.Add(sb.ToString());
197
198 if (Fields.Count > 0)
199 Records.Add(Fields.ToArray());
200
201 return Records.ToArray();
202 }
203
209 public static string Encode(string[][] Records)
210 {
211 StringBuilder sb = new StringBuilder();
212 bool First;
213
214 foreach (string[] Record in Records)
215 {
216 First = true;
217
218 foreach (string Field in Record)
219 {
220 bool Comma = false;
221 bool Control = false;
222 bool Quote = false;
223
224 if (First)
225 First = false;
226 else
227 sb.Append(',');
228
229 if (Field is null)
230 continue;
231
232 foreach (char ch in Field)
233 {
234 if (ch == ',')
235 Comma = true;
236 else if (ch == '"')
237 Quote = true;
238 else if (ch < ' ')
239 Control = true;
240 }
241
242 if (Comma || Quote || Control)
243 {
244 string Escaped = Field;
245
246 if (Quote)
247 Escaped = Escaped.Replace("\"", "\\\"");
248
249 if (Control)
250 {
251 Escaped = Escaped.
252 Replace("\a", "\\a").
253 Replace("\b", "\\b").
254 Replace("\f", "\\f").
255 Replace("\n", "\\n").
256 Replace("\r", "\\r").
257 Replace("\t", "\\t").
258 Replace("\v", "\\v");
259 }
260
261 sb.Append('"');
262 sb.Append(Escaped);
263 sb.Append('"');
264 }
265 else
266 sb.Append(Field);
267 }
268
269 sb.AppendLine();
270 }
271
272 return sb.ToString();
273 }
274
280 public static string Encode(IMatrix Matrix)
281 {
282 return Encode(Matrix, (E) =>
283 {
284 if (E.AssociatedObjectValue is string s)
285 return s;
286 else if (E.AssociatedObjectValue is double d)
287 return CommonTypes.Encode(d);
288 else
289 return E.AssociatedObjectValue?.ToString();
290 });
291 }
292
299 public static string Encode(IMatrix Matrix, ToString ElementToString)
300 {
301 if (ElementToString is null)
302 throw new ArgumentNullException(nameof(ElementToString));
303
304 List<string[]> Records = new List<string[]>();
305 List<string> Fields = new List<string>();
306
307 if (Matrix is ObjectMatrix M)
308 {
309 if (!(M.ColumnNames is null))
310 Records.Add(M.ColumnNames);
311 }
312
313 int Row, NrRows = Matrix.Rows;
314 int Column, NrColumns = Matrix.Columns;
315
316 for (Row = 0; Row < NrRows; Row++)
317 {
318 for (Column = 0; Column < NrColumns; Column++)
319 Fields.Add(ElementToString(Matrix.GetElement(Column, Row)));
320
321 Records.Add(Fields.ToArray());
322 Fields.Clear();
323 }
324
325 return Encode(Records.ToArray());
326 }
327
328 #endregion
329 }
330}
Helps with common CSV-related tasks. (CSV=Comma Separated Values)
Definition: CSV.cs:21
static string[][] Parse(string Csv)
Parses a CSV string.
Definition: CSV.cs:29
static string Encode(string[][] Records)
Encodes records as a Comma-separated values string.
Definition: CSV.cs:209
static string Encode(IMatrix Matrix, ToString ElementToString)
Encodes a matrix as a Comma-separated values string.
Definition: CSV.cs:299
static string Encode(IMatrix Matrix)
Encodes a matrix as a Comma-separated values string.
Definition: CSV.cs:280
Helps with parsing of commong data types.
Definition: CommonTypes.cs:13
static string Encode(bool x)
Encodes a Boolean for use in XML and other formats.
Definition: CommonTypes.cs:594
Base class for all types of elements.
Definition: Element.cs:13
Extract the fields of a type or an object.
Definition: Fields.cs:17
Basic interface for all types of elements.
Definition: IElement.cs:20
Basic interface for matrices.
Definition: IMatrix.cs:9
IElement GetElement(int Column, int Row)
Gets an element of the matrix.
delegate string ToString(IElement Element)
Delegate for callback methods that convert an element value to a string.