xref: /reactos/sdk/tools/hhpcomp/hhp_reader.cpp (revision 8a978a17)
1 
2 // This file is part of hhpcomp, a free HTML Help Project (*.hhp) compiler.
3 // Copyright (C) 2015  Benedikt Freisen
4 //
5 // This library is free software; you can redistribute it and/or
6 // modify it under the terms of the GNU Lesser General Public
7 // License as published by the Free Software Foundation; either
8 // version 2.1 of the License, or (at your option) any later version.
9 //
10 // This library is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13 // Lesser General Public License for more details.
14 //
15 // You should have received a copy of the GNU Lesser General Public
16 // License along with this library; if not, write to the Free Software
17 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
18 
19 
20 #include <iostream>
21 #include <fstream>
22 #include <stdexcept>
23 
24 #include <stdlib.h>
25 
26 #include "hhp_reader.h"
27 #include "utils.h"
28 
29 using namespace std;
30 
31 string hhp_section::get_name()
32 {
33     return name;
34 }
35 
36 void hhp_section::set_name(string name)
37 {
38     this->name = name;
39 }
40 
41 hhp_pair::hhp_pair(string key, bool has_default_value, string default_value)
42 {
43     this->key = key;
44     this->has_default_value = has_default_value;
45     this->default_value = default_value;
46     value_has_been_set = false;
47 }
48 
49 void hhp_pair::set_value(string value)
50 {
51     this->value = value;
52     value_has_been_set = true;
53 }
54 
55 string hhp_pair::get_value()
56 {
57     if (value_has_been_set)
58         return value;
59     else
60     {
61         if (has_default_value)
62             return default_value;
63         else
64             throw domain_error("pair '" + key + "' does not have a default value");
65     }
66 }
67 
68 string hhp_pair::get_key()
69 {
70     return key;
71 }
72 
73 void hhp_key_value_section::process_line(string line)
74 {
75     int pos_equals_sign = line.find_first_of('=');
76     if (pos_equals_sign == string::npos)
77         throw runtime_error("key-value pair does not contain an equals sign");
78     string key = to_upper(line.substr(0, pos_equals_sign));
79     string value = line.substr(pos_equals_sign + 1);
80     if (key.length() == 0)
81         throw runtime_error("key has length zero");
82 
83     entries.find(key)->second->set_value(value);
84 }
85 
86 void hhp_key_value_section::add_entry(hhp_pair* entry)
87 {
88     string upper_case_key = to_upper(entry->get_key());
89     if (entries.count(upper_case_key) != 0)
90         throw logic_error("trying to redundantly add key '" + upper_case_key + "'");
91     entries.insert(pair<string, hhp_pair*>(upper_case_key, entry));
92 }
93 
94 hhp_options_section::hhp_options_section()
95 {
96     set_name("OPTIONS");
97 
98     add_entry(binary_TOC    = new hhp_pair("Binary TOC", true, "No"));
99     add_entry(binary_index  = new hhp_pair("Binary Index", true, "Yes"));
100     add_entry(compiled_file = new hhp_pair("Compiled File", false));
101     add_entry(contents_file = new hhp_pair("Contents File", true, ""));
102     add_entry(index_file    = new hhp_pair("Index File", true, ""));
103     add_entry(autoindex     = new hhp_pair("AutoIndex", true, "No"));
104     add_entry(defaultwindow = new hhp_pair("DefaultWindow", true, ""));//?
105     add_entry(default_topic = new hhp_pair("Default Topic", true, "Index.htm"));//?
106     add_entry(defaultfont   = new hhp_pair("DefaultFont", true, ""));
107     add_entry(language      = new hhp_pair("Language", true, "0x409 English (US)"));//?
108     add_entry(title         = new hhp_pair("Title", true, ""));//?
109     add_entry(createchifile = new hhp_pair("CreateCHIFile", true, "No"));
110     add_entry(compatibility = new hhp_pair("Compatibility", true, "1.1"));
111     add_entry(errorlogfile  = new hhp_pair("ErrorLogFile", true, "Compiler.log"));//?
112     add_entry(full_text_search = new hhp_pair("Full-text search", true, "Yes"));//?
113     add_entry(display_compile_progress = new hhp_pair("Display compile progress", true, "Yes"));//?
114     add_entry(display_compile_note = new hhp_pair("Display compile note", true, "Yes"));//?
115     add_entry(flat          = new hhp_pair("Flat", true, "No"));
116     add_entry(full_text_search_stop_list_file = new hhp_pair("Full text search stop list file", true, ""));
117 }
118 
119 hhp_options_section::~hhp_options_section()
120 {
121     delete binary_TOC;
122     delete binary_index;
123     delete compiled_file;
124     delete contents_file;
125     delete index_file;
126     delete autoindex;
127     delete defaultwindow;
128     delete default_topic;
129     delete defaultfont;
130     delete language;
131     delete title;
132     delete createchifile;
133     delete compatibility;
134     delete errorlogfile;
135     delete full_text_search;
136     delete display_compile_progress;
137     delete display_compile_note;
138     delete flat;
139     delete full_text_search_stop_list_file;
140 }
141 
142 hhp_files_section::hhp_files_section()
143 {
144     set_name("FILES");
145 }
146 
147 void hhp_files_section::process_line(string line)
148 {
149     filenames.push_back(line);
150 }
151 
152 hhp_reader::hhp_reader(string filename)
153 {
154     this->filename = filename;
155 
156     options = new hhp_options_section();
157     add_section(options);
158     files = new hhp_files_section();
159     add_section(files);
160 
161     read();
162     compute_unique_file_pathes_set();
163 }
164 
165 hhp_reader::~hhp_reader()
166 {
167     delete options;
168     delete files;
169 }
170 
171 void hhp_reader::add_section(hhp_section* section)
172 {
173     string upper_case_name = to_upper(section->get_name());
174     if (sections.count(upper_case_name) != 0)
175         throw logic_error("trying to redundantly add section '" + upper_case_name + "'");
176     sections.insert(pair<string, hhp_section*>(upper_case_name, section));
177 }
178 
179 void hhp_reader::read()
180 {
181     ifstream hhp_file;
182     hhp_file.open(filename.c_str());
183 
184     string line;
185     int line_number = 0;
186     hhp_section* section = NULL;
187     while (hhp_file.good())
188     {
189         getline(hhp_file, line);
190         line_number++;
191         if (line[line.length() - 1] == '\015')  // delete CR character if present
192             line = line.substr(0, line.length() - 1);
193         if (line[0] == '[' && line[line.length() - 1] == ']')
194         {
195             string name = to_upper(line.substr(1, line.length() - 2));
196             if (sections.count(name))
197             {
198                 section = sections.find(name)->second;
199                 clog << section->get_name() << endl;
200             }
201             else
202             {
203                 clog << "unknown section: " << name << endl;
204             }
205         }
206         else if (line[0] != ';' && !line.empty())
207         {
208             if (section)
209                 section->process_line(line);
210         }
211     }
212 
213     hhp_file.close();
214 }
215 
216 void hhp_reader::compute_unique_file_pathes_set()
217 {
218     for (list<string>::iterator it = files->filenames.begin(); it != files->filenames.end(); ++it)
219     {
220         unique_file_pathes.insert(replace_backslashes(real_path(it->c_str())));
221     }
222 }
223 
224 string hhp_reader::get_title_string()
225 {
226     return options->title->get_value();
227 }
228 
229 string hhp_reader::get_contents_file_string()
230 {
231     return options->contents_file->get_value();
232 }
233 
234 string hhp_reader::get_index_file_string()
235 {
236     return options->index_file->get_value();
237 }
238 
239 string hhp_reader::get_default_topic_string()
240 {
241     return options->default_topic->get_value();
242 }
243 
244 unsigned int hhp_reader::get_language_code()
245 {
246     return strtoul(options->language->get_value().c_str(), NULL, 0);
247 }
248 
249 string hhp_reader::get_compiled_file_string()
250 {
251     return options->compiled_file->get_value();
252 }
253 
254 set<string>::iterator hhp_reader::get_file_pathes_iterator_begin()
255 {
256     return unique_file_pathes.begin();
257 }
258 
259 set<string>::iterator hhp_reader::get_file_pathes_iterator_end()
260 {
261     return unique_file_pathes.end();
262 }
263