SectorZone: add attribute arc_boundary
[xcsoar.git] / src / Task / TaskFileIGC.cpp
blobc896bf5a05fa1a09d257fd7f5a09bba97da24d79
1 /*
2 Copyright_License {
4 XCSoar Glide Computer - http://www.xcsoar.org/
5 Copyright (C) 2000-2013 The XCSoar Project
6 A detailed list of copyright holders can be found in the file "AUTHORS".
8 This program is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public License
10 as published by the Free Software Foundation; either version 2
11 of the License, or (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24 #include "Task/TaskFileIGC.hpp"
25 #include "IGC/IGCParser.hpp"
26 #include "IGC/IGCDeclaration.hpp"
27 #include "IO/FileLineReader.hpp"
28 #include "Engine/Task/Factory/AbstractTaskFactory.hpp"
29 #include "Engine/Task/Ordered/OrderedTask.hpp"
30 #include "Engine/Task/Ordered/Points/StartPoint.hpp"
31 #include "Engine/Task/Ordered/Points/FinishPoint.hpp"
32 #include "Engine/Task/Ordered/Points/IntermediatePoint.hpp"
33 #include "Language/Language.hpp"
34 #include "Waypoint/Waypoint.hpp"
36 #include <list>
37 #include <assert.h>
39 static bool
40 ReadIGCDeclaration(const TCHAR *path, IGCDeclarationHeader &header,
41 std::list<IGCDeclarationTurnpoint> &turnpoints)
43 // Create FileReader for reading the task
44 FileLineReaderA reader(path);
45 if (reader.error())
46 return false;
48 // Read IGC file
49 char *line;
50 bool header_found = false;
51 while ((line = reader.ReadLine()) != NULL) {
52 // Skip lines which are not declaration records
53 if (*line != _T('C'))
54 continue;
56 if (!header_found) {
57 if (!IGCParseDeclarationHeader(line, header))
58 return false;
60 header_found = true;
61 continue;
64 IGCDeclarationTurnpoint tp;
65 if (IGCParseDeclarationTurnpoint(line, tp))
66 turnpoints.emplace_back(tp);
69 return header_found;
72 OrderedTask*
73 TaskFileIGC::GetTask(const TaskBehaviour &task_behaviour,
74 const Waypoints *waypoints, unsigned index) const
76 assert(index == 0);
78 IGCDeclarationHeader header;
79 std::list<IGCDeclarationTurnpoint> turnpoints;
81 if (!ReadIGCDeclaration(path, header, turnpoints))
82 return NULL;
84 // Number of turnpoints including start and finish
85 unsigned num_turnpoints = header.num_turnpoints + 2;
87 if (num_turnpoints + 2 == turnpoints.size()) {
88 // Remove takeoff and landing points from the turnpoints list
89 turnpoints.pop_front();
90 turnpoints.pop_back();
91 } else if (num_turnpoints != turnpoints.size())
92 // Declared number of turnpoints is not matching parsed number of turnpoints
93 return NULL;
95 // Create a blank task
96 OrderedTask *task = new OrderedTask(task_behaviour);
97 AbstractTaskFactory &fact = task->GetFactory();
99 unsigned i = 0;
100 for (const auto &it : turnpoints) {
101 StaticString<256> waypoint_name;
102 if (!it.name.empty()) {
103 waypoint_name.clear();
104 waypoint_name.UnsafeAppendASCII(it.name);
105 } else if (i == 0)
106 waypoint_name = _T("Start");
107 else if (i == num_turnpoints - 1)
108 waypoint_name = _T("Finish");
109 else
110 waypoint_name.Format(_T("%s #%u"), _T("Turnpoint"), i);
112 Waypoint wp(it.location);
113 wp.name = waypoint_name.c_str();
115 /* we don't know the elevation, so we just set it to zero; this is
116 not correct, but better than leaving it uninitialised */
117 wp.elevation = fixed(0);
119 OrderedTaskPoint *tp;
121 if (i == 0)
122 tp = fact.CreateStart(wp);
123 else if (i == num_turnpoints - 1)
124 tp = fact.CreateFinish(wp);
125 else
126 tp = fact.CreateIntermediate(wp);
128 if (tp != NULL) {
129 fact.Append(*tp);
130 delete tp;
133 ++i;
136 return task;
139 unsigned
140 TaskFileIGC::Count()
142 // Open the IGC file
143 FileLineReaderA reader(path);
144 if (reader.error())
145 return 0;
147 IGCDeclarationHeader header;
149 // Search for declaration
150 char *line;
151 while ((line = reader.ReadLine()) != NULL) {
152 if (*line != 'C')
153 continue;
155 if (!IGCParseDeclarationHeader(line, header) ||
156 header.num_turnpoints == 0)
157 return 0;
159 if (!header.task_name.empty() &&
160 !StringIsEqual(header.task_name, "Task")) {
161 // Remember the task name
162 StaticString<256> task_name;
163 task_name.clear();
164 task_name.UnsafeAppendASCII(header.task_name.c_str());
165 namesuffixes.append(_tcsdup(task_name.c_str()));
168 return 1;
171 return 0;