source: EcnlProtoTool/trunk/webapp/webmrbc/Ecnl/ValueRange.cs@ 270

Last change on this file since 270 was 270, checked in by coas-nagasima, 7 years ago

mruby版ECNLプロトタイピング・ツールを追加

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
  • Property svn:mime-type set to text/x-csharp
File size: 20.4 KB
Line 
1/*
2 * TOPPERS ECHONET Lite Communication Middleware
3 *
4 * Copyright (C) 2015 Cores Co., Ltd. Japan
5 *
6 * 上記著作権者は,以下の(1)~(4)の条件を満たす場合に限り,本ソフトウェ
7 * ア(本ソフトウェアを改変したものを含む.以下同じ)を使用・複製・改
8 * 変・再配布(以下,利用と呼ぶ)することを無償で許諾する.
9 * (1) 本ソフトウェアをソースコードの形で利用する場合には,上記の著作
10 * 権表示,この利用条件および下記の無保証規定が,そのままの形でソー
11 * スコード中に含まれていること.
12 * (2) 本ソフトウェアを,ライブラリ形式など,他のソフトウェア開発に使
13 * 用できる形で再配布する場合には,再配布に伴うドキュメント(利用
14 * 者マニュアルなど)に,上記の著作権表示,この利用条件および下記
15 * の無保証規定を掲載すること.
16 * (3) 本ソフトウェアを,機器に組み込むなど,他のソフトウェア開発に使
17 * 用できない形で再配布する場合には,次のいずれかの条件を満たすこ
18 * と.
19 * (a) 再配布に伴うドキュメント(利用者マニュアルなど)に,上記の著
20 * 作権表示,この利用条件および下記の無保証規定を掲載すること.
21 * (b) 再配布の形態を,別に定める方法によって,TOPPERSプロジェクトに
22 * 報告すること.
23 * (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
24 * 害からも,上記著作権者およびTOPPERSプロジェクトを免責すること.
25 * また,本ソフトウェアのユーザまたはエンドユーザからのいかなる理
26 * 由に基づく請求からも,上記著作権者およびTOPPERSプロジェクトを
27 * 免責すること.
28 *
29 * 本ソフトウェアは,無保証で提供されているものである.上記著作権者お
30 * よびTOPPERSプロジェクトは,本ソフトウェアに関して,特定の使用目的
31 * に対する適合性も含めて,いかなる保証も行わない.また,本ソフトウェ
32 * アの利用により直接的または間接的に生じたいかなる損害に関しても,そ
33 * の責任を負わない.
34 *
35 * @(#) $Id: ValueRange.cs 270 2017-02-09 04:03:47Z coas-nagasima $
36 */
37
38using System;
39using System.Linq;
40using System.Collections.Generic;
41using Bridge;
42using Bridge.Text.RegularExpressions;
43
44namespace WebMrbc
45{
46 enum TokenType
47 {
48 Separetor,
49 HexValue,
50 Numeric,
51 String,
52 End,
53 };
54
55 class TokenInfo
56 {
57 public string Token;
58 public TokenType Type;
59 public static string Separetor = @"[=,:\(\)\[\]~]";
60 public static string HexValue = "^0x[0-9A-Fa-f]+";
61 public static string Numeric = @"^[\-\+]?[\.]?[0-9]+[0-9,\.]*";
62
63 public TokenInfo(string token, TokenType type)
64 {
65 Token = token;
66 Type = type;
67 }
68
69 public override string ToString()
70 {
71 return Token;
72 }
73
74 public int ToInt32()
75 {
76 switch (Type) {
77 case TokenType.HexValue:
78 return Script.ParseInt(Token.Substring(2)/*0xの削除*/, 16);
79 case TokenType.Numeric:
80 return Script.ParseInt(Token);
81 default:
82 return 0;
83 }
84 }
85
86 public long ToInt64(string typeName)
87 {
88 string temp;
89
90 switch (Type) {
91 case TokenType.HexValue:
92 temp = Token.Substring(2)/*0xの削除*/;
93 return Script.ParseInt(temp, 16);
94 case TokenType.Numeric:
95 return Script.ParseInt(Token);
96 default:
97 return 0;
98 }
99 }
100 }
101
102 enum State
103 {
104 Value,
105 EqualOrRange,
106 Description,
107 UnitOrCommaOrEnd,
108 RengeMax,
109 StartParenthesis,
110 RangeDescription,
111 MinDescription,
112 RangeSeparetor,
113 MaxDescription,
114 EndParenthesis,
115 CommaOrEnd,
116 BitFieldLSB,
117 BitRange,
118 BitFieldMSB,
119 BitFieldDescription,
120 BitRangeEnd,
121 Colon,
122 }
123
124 public abstract class Value
125 {
126 public abstract string Disp { get; }
127 public abstract string GetInitialValue();
128 }
129
130 public class Option : Value
131 {
132 private long _Val;
133 private string _Disp;
134
135 public Option(long val, string disp)
136 {
137 _Val = val;
138 _Disp = disp;
139 }
140
141 public long Val { get { return _Val; } }
142 public override string Disp { get { return _Disp; } }
143
144 public override string GetInitialValue()
145 {
146 return _Val.ToString(16).ToUpper();
147 }
148 }
149
150 public class Range : Value
151 {
152 private long _Min;
153 private long _Max;
154 private string _Disp;
155 private string _MinDisp;
156 private string _MaxDisp;
157 private string _Unit;
158 private long _InitialValue;
159
160 public Range(long min, long max, string disp)
161 {
162 _Min = min;
163 _Max = max;
164 _Disp = disp;
165 _MinDisp = "";
166 _MaxDisp = "";
167 _Unit = "";
168 _InitialValue = min;
169 }
170
171 public Range(long min, long max, string disp, string minDisp, string maxDisp, string unit)
172 {
173 _Min = min;
174 _Max = max;
175 _Disp = disp;
176 _MinDisp = minDisp;
177 _MaxDisp = maxDisp;
178 _Unit = unit;
179 _InitialValue = min;
180 }
181
182 public long Min { get { return _Min; } }
183 public long Max { get { return _Max; } }
184 public override string Disp { get { return _Disp; } }
185 public string MinDisp { get { return _MinDisp; } }
186 public string MaxDisp { get { return _MaxDisp; } }
187 public string Unit { get { return _Unit; } }
188 public long InitialValue {
189 get { return _InitialValue; }
190 set { _InitialValue = value; }
191 }
192
193 public override string GetInitialValue()
194 {
195 return _InitialValue.ToString(16).ToUpper();
196 }
197
198 public string GetDisp(long value)
199 {
200 return _Disp + value.ToString() + _Unit;
201 }
202 }
203
204 public class InRangeValue : Value
205 {
206 private Range _Range;
207 private long _Value;
208
209 public InRangeValue(Range range, long value)
210 {
211 _Range = range;
212 _Value = value;
213 }
214
215 public Range Range { get { return _Range; } }
216 public long Value { get { return _Value; } }
217 public override string Disp { get { return _Range.GetDisp(_Value); } }
218
219 public override string GetInitialValue()
220 {
221 return _Value.ToString(16).ToUpper();
222 }
223 }
224
225 public class BitField : Value
226 {
227 private int _Least;
228 private int _Most;
229 private string _Disp;
230 private Option[] _Values = new Option[0];
231 private Range[] _Ranges = new Range[0];
232 private Value _InitailValue;
233
234 public BitField(int least, int most, string disp)
235 {
236 _Least = least;
237 _Most = most;
238 _Disp = disp;
239 }
240
241 public int Least { get { return _Least; } }
242 public int Most { get { return _Most; } }
243 public override string Disp { get { return _Disp; } }
244 public Option[] Values { get { return _Values; } }
245 public Range[] Ranges { get { return _Ranges; } }
246 public Value InitailValue { get { return _InitailValue; } }
247
248 public override string GetInitialValue()
249 {
250 if (_InitailValue == null)
251 return "";
252 return _InitailValue.GetInitialValue();
253 }
254
255 internal void AddValue(Option option)
256 {
257 if (_InitailValue == null)
258 _InitailValue = option;
259 _Values.Push(option);
260 }
261
262 internal void AddRange(Range range)
263 {
264 if (_InitailValue == null)
265 _InitailValue = range;
266 _Ranges.Push(range);
267 }
268
269 internal bool IsInRange(long val64)
270 {
271 foreach (var val in _Values) {
272 if (val.Val != val64)
273 continue;
274
275 return true;
276 }
277
278 foreach (var rng in _Ranges) {
279 if ((rng.Min > val64) || (rng.Max < val64))
280 continue;
281
282 return true;
283 }
284
285 return false;
286 }
287
288 internal Value GetInRangeValue(long val64)
289 {
290 foreach (var val in _Values) {
291 if (val.Val != val64)
292 continue;
293
294 return val;
295 }
296
297 foreach (var rng in _Ranges) {
298 if ((rng.Min > val64) || (rng.Max < val64))
299 continue;
300
301 return new InRangeValue(rng, val64);
302 }
303
304 return null;
305 }
306 }
307
308 public class BitFiledsValue : Value
309 {
310 private BitField[] _BitFields;
311 private Value[] _BitFieldValues;
312 private long _Value;
313
314 public BitFiledsValue(BitField[] bitFlds, Value[] bitFldVals, long value)
315 {
316 _BitFields = bitFlds;
317 _BitFieldValues = bitFldVals;
318 _Value = value;
319 }
320
321 public override string Disp {
322 get { return ""; }
323 }
324
325 public override string GetInitialValue()
326 {
327 return _Value.ToString(16).ToUpper();
328 }
329 }
330
331 class ValueSet
332 {
333 public Option[] values;
334 public Range[] ranges;
335 public BitField bitField;
336 public Value initialValue;
337
338 public ValueSet(Option[] values, Range[] ranges, BitField bitField, Value initialValue)
339 {
340 this.values = values;
341 this.ranges = ranges;
342 this.bitField = bitField;
343 this.initialValue = initialValue;
344 }
345 }
346
347 public class ValueRange
348 {
349 private Option[] _Values = new Option[0];
350 private Range[] _Ranges = new Range[0];
351 private BitField[] _BitFields = new BitField[0];
352 private ValueRange[] _MemberFields = new ValueRange[0];
353 private Value _InitailValue;
354 static Dictionary<string, ValueSet> _ParsedText = new Dictionary<string, ValueSet>();
355
356 public Option[] Values { get { return _Values; } }
357 public Range[] Ranges { get { return _Ranges; } }
358 public BitField[] BitFields { get { return _BitFields; } }
359 public ValueRange[] MemberFields { get { return _MemberFields; } }
360
361 public string InitailValue {
362 get {
363 if (_InitailValue == null)
364 return "";
365 return _InitailValue.GetInitialValue();
366 }
367 set {
368 int val64 = Script.ParseInt(value);
369 foreach (var val in _Values) {
370 if (val.Val != val64)
371 continue;
372
373 _InitailValue = val;
374 return;
375 }
376
377 foreach (var rng in _Ranges) {
378 if ((rng.Min > val64) || (rng.Max < val64))
379 continue;
380
381 _InitailValue = new InRangeValue(rng, val64);
382 return;
383 }
384
385 if (_BitFields.Length > 0) {
386 bool ok = true;
387 var bitFlds = new Value[0];
388 foreach (var bit in _BitFields) {
389 if (!bit.IsInRange(val64)) {
390 ok = false;
391 break;
392 }
393
394 bitFlds.Push(bit.GetInRangeValue(val64));
395 }
396
397 if (ok) {
398 _InitailValue = new BitFiledsValue(_BitFields, bitFlds, val64);
399 return;
400 }
401 }
402 }
403 }
404
405 private static bool ParseValueRange(string input, string type, Option[] values, Range[] ranges,
406 out BitField bitFeild, out Value initialValue)
407 {
408 bitFeild = null;
409 initialValue = null;
410
411 var tokens = new TokenInfo[0];
412 int pos = 0;
413 while (pos < input.Length) {
414 Regex ms;
415 string[] m;
416 if ((m = (ms = new Regex(TokenInfo.HexValue)).Exec(input.Substring(pos))) != null) {
417 tokens.Push(new TokenInfo(m[0], TokenType.HexValue));
418 pos += m[0].Length;
419 }
420 else if ((m = (ms = new Regex(TokenInfo.Numeric)).Exec(input.Substring(pos))) != null) {
421 tokens.Push(new TokenInfo(m[0], TokenType.Numeric));
422 pos += m[0].Length;
423 }
424 else {
425 if ((m = (ms = new Regex(TokenInfo.Separetor)).Exec(input.Substring(pos))) == null) {
426 tokens.Push(new TokenInfo(input.Substring(pos), TokenType.String));
427 break;
428 }
429 int index = pos + Script.Write<int>("m.index");
430 if (index == pos) {
431 tokens.Push(new TokenInfo(m[0], TokenType.Separetor));
432 pos += m.Length;
433 }
434 else {
435 tokens.Push(new TokenInfo(input.Substring(pos, index - pos), TokenType.String));
436 tokens.Push(new TokenInfo(m[0], TokenType.Separetor));
437 pos = index + 1;
438 }
439 }
440 }
441 tokens.Push(new TokenInfo("", TokenType.End));
442
443 bool OK = false;
444 var sentence = new TokenInfo[0];
445 State state = State.Value;
446 foreach (TokenInfo token in tokens) {
447 switch (state) {
448 case State.Value:
449 if ((token.Type == TokenType.HexValue)
450 || (token.Type == TokenType.Numeric)) {
451 sentence.Push(token);
452 state = State.EqualOrRange;
453 continue;
454 }
455 else if ((token.Type == TokenType.Separetor)
456 && (token.Token == "[")) {
457 if (bitFeild != null)
458 break;
459 state = State.BitFieldLSB;
460 continue;
461 }
462 break;
463 case State.EqualOrRange:
464 if (token.Type == TokenType.Separetor) {
465 switch (token.Token) {
466 case "=":
467 state = State.Description;
468 continue;
469 case "~":
470 state = State.RengeMax;
471 continue;
472 }
473 }
474 else if (token.Type == TokenType.End) {
475 Option option = new Option(sentence[0].ToInt64(type), "固定");
476 if (bitFeild != null)
477 bitFeild.AddValue(option);
478 else {
479 if (initialValue == null)
480 initialValue = option;
481 values.Push(option);
482 }
483 sentence.Splice(0, sentence.Length);
484 state = State.CommaOrEnd;
485 continue;
486 }
487 break;
488 case State.Description:
489 if (token.Type == TokenType.String) {
490 Option option = new Option(sentence[0].ToInt64(type), token.Token);
491 if (bitFeild != null)
492 bitFeild.AddValue(option);
493 else {
494 if (initialValue == null)
495 initialValue = option;
496 values.Push(option);
497 }
498 sentence.Splice(0, sentence.Length);
499 state = State.CommaOrEnd;
500 continue;
501 }
502 else if (token.Type == TokenType.Numeric) {
503 sentence.Push(token);
504 state = State.UnitOrCommaOrEnd;
505 continue;
506 }
507 break;
508 case State.UnitOrCommaOrEnd:
509 if (token.Type == TokenType.String) {
510 Option option = new Option(sentence[0].ToInt64(type), sentence[1].Token + token.Token);
511 if (bitFeild != null)
512 bitFeild.AddValue(option);
513 else {
514 if (initialValue == null)
515 initialValue = option;
516 values.Push(option);
517 }
518 sentence.Splice(0, sentence.Length);
519 state = State.CommaOrEnd;
520 continue;
521 }
522 else if ((token.Type == TokenType.Separetor)
523 && (token.Token == ",")) {
524 Option option = new Option(sentence[0].ToInt64(type), sentence[1].Token);
525 if (bitFeild != null)
526 bitFeild.AddValue(option);
527 else {
528 if (initialValue == null)
529 initialValue = option;
530 values.Push(option);
531 }
532 sentence.Splice(0, sentence.Length);
533 state = State.Value;
534 continue;
535 }
536 else if (token.Type == TokenType.End) {
537 Option option = new Option(sentence[0].ToInt64(type), sentence[1].Token);
538 if (bitFeild != null)
539 bitFeild.AddValue(option);
540 else {
541 if (initialValue == null)
542 initialValue = option;
543 values.Push(option);
544 }
545 sentence.Splice(0, sentence.Length);
546 OK = true;
547 }
548 break;
549 case State.RengeMax:
550 if ((token.Type == TokenType.HexValue)
551 || (token.Type == TokenType.Numeric)) {
552 sentence.Push(token);
553 state = State.StartParenthesis;
554 continue;
555 }
556 else if ((token.Type == TokenType.Separetor)
557 && (token.Token == "=")) {
558 string max = "0x";
559 for (int i = sentence[0].Token.Length - 2; i > 0; i--) {
560 max += "F";
561 }
562 sentence.Push(new TokenInfo(max, TokenType.HexValue));
563 state = State.RangeDescription;
564 continue;
565 }
566 break;
567 case State.StartParenthesis:
568 if (token.Type == TokenType.Separetor) {
569 switch (token.Token) {
570 case "=":
571 if (sentence.Length == 2) {
572 state = State.RangeDescription;
573 continue;
574 }
575 break;
576 case "(":
577 sentence.Push(new TokenInfo("", TokenType.String));
578 state = State.MinDescription;
579 continue;
580 case ",":
581 Range range = new Range(sentence[0].ToInt64(type), sentence[1].ToInt64(type), (sentence.Length > 2) ? sentence[2].Token : "");
582 if (bitFeild != null) {
583 bitFeild.AddRange(range);
584 }
585 else {
586 if (initialValue == null)
587 initialValue = range;
588 ranges.Push(range);
589 }
590 sentence.Splice(0, sentence.Length);
591 state = State.Value;
592 continue;
593 }
594 }
595 else if (token.Type == TokenType.End) {
596 Range range = new Range(sentence[0].ToInt64(type), sentence[1].ToInt64(type), (sentence.Length > 2) ? sentence[2].Token : "");
597 if (bitFeild != null) {
598 bitFeild.AddRange(range);
599 }
600 else {
601 if (initialValue == null)
602 initialValue = range;
603 ranges.Push(range);
604 }
605 sentence.Splice(0, sentence.Length);
606 OK = true;
607 }
608 break;
609 case State.RangeDescription:
610 if (token.Type == TokenType.String) {
611 sentence.Push(token);
612 state = State.StartParenthesis;
613 continue;
614 }
615 break;
616 case State.MinDescription:
617 if ((token.Type == TokenType.Numeric)
618 || (token.Type == TokenType.String)) {
619 sentence.Push(token);
620 state = State.RangeSeparetor;
621 continue;
622 }
623 break;
624 case State.RangeSeparetor:
625 if ((token.Type == TokenType.Separetor)
626 && (token.Token == "~")) {
627 state = State.MaxDescription;
628 continue;
629 }
630 break;
631 case State.MaxDescription:
632 if ((token.Type == TokenType.Numeric)
633 || (token.Type == TokenType.String)) {
634 sentence.Push(token);
635 state = State.EndParenthesis;
636 continue;
637 }
638 break;
639 case State.EndParenthesis:
640 if ((token.Type == TokenType.Separetor)
641 && (token.Token == ")")) {
642 Range range = new Range(
643 sentence[0].ToInt64(type),
644 sentence[1].ToInt64(type),
645 sentence[2].Token,
646 sentence[3].Token,
647 sentence[4].Token,
648 (sentence.Length > 5) ? sentence[5].Token : "");
649 if (bitFeild != null) {
650 bitFeild.AddRange(range);
651 }
652 else {
653 if (initialValue == null)
654 initialValue = range;
655 ranges.Push(range);
656 }
657 sentence.Splice(0, sentence.Length);
658 state = State.CommaOrEnd;
659 continue;
660 }
661 else if (token.Type == TokenType.String) {
662 sentence.Push(token);
663 state = State.EndParenthesis;
664 continue;
665 }
666 break;
667 case State.BitFieldLSB:
668 if (token.Type == TokenType.Numeric) {
669 sentence.Push(token);
670 state = State.BitRange;
671 continue;
672 }
673 break;
674 case State.BitRange:
675 if (token.Type == TokenType.Separetor) {
676 switch (token.Token) {
677 case "~":
678 state = State.BitFieldMSB;
679 continue;
680 case "]":
681 sentence.Push(sentence[0]);
682 state = State.BitFieldDescription;
683 continue;
684 }
685 }
686 break;
687 case State.BitFieldMSB:
688 if (token.Type == TokenType.Numeric) {
689 sentence.Push(token);
690 state = State.BitRangeEnd;
691 continue;
692 }
693 break;
694 case State.BitRangeEnd:
695 if ((token.Type == TokenType.Separetor)
696 && (token.Token == "]")) {
697 state = State.BitFieldDescription;
698 continue;
699 }
700 break;
701 case State.BitFieldDescription:
702 if (token.Type == TokenType.String) {
703 sentence.Push(token);
704 state = State.Colon;
705 continue;
706 }
707 break;
708 case State.Colon:
709 if ((token.Type == TokenType.Separetor)
710 && (token.Token == ":")) {
711 bitFeild = new BitField(sentence[0].ToInt32(), sentence[1].ToInt32(), sentence[2].Token);
712 if (initialValue == null)
713 initialValue = bitFeild;
714 sentence.Splice(0, sentence.Length);
715 state = State.Value;
716 continue;
717 }
718 else if (token.Type == TokenType.End) {
719 bitFeild = new BitField(sentence[0].ToInt32(), sentence[1].ToInt32(), sentence[2].Token);
720 if (initialValue == null)
721 initialValue = bitFeild;
722 sentence.Splice(0, sentence.Length);
723 OK = true;
724 break;
725 }
726 break;
727 case State.CommaOrEnd:
728 if (token.Type == TokenType.End) {
729 OK = true;
730 }
731 else if ((token.Type == TokenType.Separetor)
732 && (token.Token == ",")) {
733 state = State.Value;
734 continue;
735 }
736 break;
737 }
738 break;
739 }
740
741 return OK;
742 }
743
744 public static ValueRange Parse(string valrng, JsonFieldInfo emti)
745 {
746 ValueRange valueRange = new ValueRange();
747
748 if (emti.primitive) {
749 string[] lines = valrng.Split(new Regex("\r\n"));
750 foreach (string line in lines) {
751 if (new Regex("^<(.+)>$").Test(line))
752 continue;
753
754 Option[] values;
755 Range[] ranges;
756 BitField bitField;
757 Value initialValue;
758
759 ValueSet pair;
760 if (_ParsedText.TryGetValue(line, out pair)) {
761 values = pair.values;
762 ranges = pair.ranges;
763 bitField = pair.bitField;
764 initialValue = pair.initialValue;
765 }
766 else {
767 values = new Option[0];
768 ranges = new Range[0];
769
770 ParseValueRange(line, emti.type, values, ranges, out bitField, out initialValue);
771
772 _ParsedText.Add(line, new ValueSet(values, ranges, bitField, initialValue));
773 }
774
775 valueRange._Values = (Option[])valueRange._Values.Concat(values);
776 valueRange._Ranges = (Range[])valueRange._Ranges.Concat(ranges);
777 if (bitField != null)
778 valueRange._BitFields.Push(bitField);
779 if (valueRange._InitailValue == null)
780 valueRange._InitailValue = initialValue;
781 }
782 }
783 else {
784 foreach (JsonFieldInfo efi in emti.fields) {
785 ValueRange member = Parse(efi.valueDescription, efi);
786 valueRange._MemberFields.Push(member);
787 }
788 }
789
790 return valueRange;
791 }
792 }
793}
Note: See TracBrowser for help on using the repository browser.