FileImporter.cs 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Drawing;
  4. using System.Linq;
  5. using System.Text;
  6. using System.Text.RegularExpressions;
  7. using System.Threading.Tasks;
  8. namespace SketchAssistant
  9. {
  10. public class FileImporter
  11. {
  12. /// <summary>
  13. /// pointer to the running instance of main program
  14. /// </summary>
  15. Form1 program;
  16. public FileImporter(Form1 newProgram)
  17. {
  18. program = newProgram;
  19. }
  20. /// <summary>
  21. /// parses a drawing consisting of line objects, given as a file in the application specific .isad format
  22. /// </summary>
  23. /// <param name="fileName">the path of the input file</param>
  24. /// <returns>the width and height of the left canvas and the parsed picture as a list of lines</returns>
  25. public (int, int, List<Line>) ParseISADInputFile(String fileName)
  26. {
  27. return ParseISADInput(System.IO.File.ReadAllLines(fileName));
  28. }
  29. /// <summary>
  30. /// parses a drawing consisting of line objects, given as the content of a .isad file, seperated into lines
  31. /// </summary>
  32. /// <param name="allLines">an array holding all lines of the input file</param>
  33. /// <returns>the width and height of the left canvas and the parsed picture as a list of lines</returns>
  34. private (int, int, List<Line>) ParseISADInput(String[] allLines)
  35. {
  36. if (allLines.Length == 0)
  37. {
  38. throw new FileImporterException("file is empty", "", -1);
  39. }
  40. if (!"drawing".Equals(allLines[0]))
  41. {
  42. throw new FileImporterException("file is not an interactive sketch assistant drawing", ".isad files have to start with the 'drawing' token", 1);
  43. }
  44. if (!"enddrawing".Equals(allLines[allLines.Length - 1]))
  45. {
  46. throw new FileImporterException("unterminated drawing definition", ".isad files have to end with the 'enddrawing' token", allLines.Length);
  47. }
  48. (int, int) dimensions = ParseISADHeader(allLines);
  49. List<Line> picture = ParseISADBody(allLines, dimensions.Item1, dimensions.Item2);
  50. return (dimensions.Item1, dimensions.Item2, picture);
  51. }
  52. /// <summary>
  53. /// parses the first two lines of an input file in .isad format
  54. /// </summary>
  55. /// <param name="allLines">the input file as an array of lines</param>
  56. /// <returns>the width and height of the left canvas</returns>
  57. private (int, int) ParseISADHeader(String[] allLines)
  58. {
  59. int width;
  60. int height;
  61. if (!(allLines.Length > 1) || !Regex.Match(allLines[1], @"^\d+x?\d+$", RegexOptions.None).Success)
  62. {
  63. throw new FileImporterException("invalid or missing canvas size definition", "format: [width]x[heigth]", 2);
  64. }
  65. String[] size = allLines[1].Split('x');
  66. width = Convert.ToInt32(size[0]);
  67. height = Convert.ToInt32(size[1]);
  68. return (width, height);
  69. }
  70. /// <summary>
  71. /// parses all line entries of an input file in .isad format
  72. /// </summary>
  73. /// <param name="allLines">the input file as an array of lines</param>
  74. /// <returns>the parsed picture as a list of lines</returns>
  75. private List<Line> ParseISADBody(String[] allLines, int width, int height)
  76. {
  77. String lineStartString = "line";
  78. String lineEndString = "endline";
  79. List<Line> drawing = new List<Line>();
  80. //number of the line currently being parsed, enumeration starting at 0, body starts at the third line, therefore lin number 2
  81. int i = 2;
  82. //parse 'line' token and complete line definition
  83. int lineStartPointer = i;
  84. //holds the line number of the next expected beginning of a line definition, or of the enddrawing token
  85. while (lineStartString.Equals(allLines[i]))
  86. {
  87. //start parsing next line
  88. i++;
  89. List<Point> newLine = new List<Point>();
  90. while (!lineEndString.Equals(allLines[i]))
  91. {
  92. if (i == allLines.Length)
  93. {
  94. throw new FileImporterException("unterminated line definition", null, (i + 1));
  95. }
  96. //parse single point definition
  97. if (!Regex.Match(allLines[i], @"^\d+;\d+$", RegexOptions.None).Success)
  98. {
  99. throw new FileImporterException("invalid Point definition: wrong format", "format: [xCoordinate];[yCoordinate]", (i + 1) );
  100. }
  101. String[] coordinates = allLines[i].Split(';');
  102. //no errors possible, convertability to int already checked above
  103. int xCoordinate = Convert.ToInt32(coordinates[0]);
  104. int yCoordinate = Convert.ToInt32(coordinates[1]);
  105. if (xCoordinate < 0 || yCoordinate < 0 || xCoordinate > width - 1 || yCoordinate > height - 1)
  106. {
  107. throw new FileImporterException("invalid Point definition: point out of bounds", null, (i + 1) );
  108. }
  109. newLine.Add(new Point(xCoordinate, yCoordinate));
  110. //start parsing next line
  111. i++;
  112. }
  113. //"parse" 'endline' token, syntax already checked at the beginning, and start parsing next line
  114. i++;
  115. //add line to drawing
  116. drawing.Add(new Line(newLine));
  117. //update lineStartPointer to the presumable start of the next line
  118. lineStartPointer = i;
  119. }
  120. //check if end of body is reached after there are no more line definitions
  121. if(i != allLines.Length - 1)
  122. {
  123. throw new FileImporterException("missing or invalid line definition token", "line definitions start with the 'line' token", (i + 1));
  124. }
  125. //return parsed picture
  126. return drawing;
  127. }
  128. /// <summary>
  129. /// connection point for testing use only: calls ParseISADInput(String[] allLines) and directly passes the given argument (effectively bypassing the File Input functionality)
  130. /// </summary>
  131. /// <param name="allLines">an array holding all lines of the input file</param>
  132. /// <returns>the width and height of the left canvas and the parsed picture as a list of lines</returns>
  133. public (int, int, List<Line>) ParseISADInputForTesting(String[] allLines)
  134. {
  135. return ParseISADInput(allLines);
  136. }
  137. }
  138. }