Reactos
at master 262 lines 7.5 kB view raw
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 29using namespace std; 30 31string hhp_section::get_name() 32{ 33 return name; 34} 35 36void hhp_section::set_name(string name) 37{ 38 this->name = name; 39} 40 41hhp_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 49void hhp_pair::set_value(string value) 50{ 51 this->value = value; 52 value_has_been_set = true; 53} 54 55string 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 68string hhp_pair::get_key() 69{ 70 return key; 71} 72 73void 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 86void 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 94hhp_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 119hhp_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 142hhp_files_section::hhp_files_section() 143{ 144 set_name("FILES"); 145} 146 147void hhp_files_section::process_line(string line) 148{ 149 filenames.push_back(line); 150} 151 152hhp_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 165hhp_reader::~hhp_reader() 166{ 167 delete options; 168 delete files; 169} 170 171void 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 179void 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 216void 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 224string hhp_reader::get_title_string() 225{ 226 return options->title->get_value(); 227} 228 229string hhp_reader::get_contents_file_string() 230{ 231 return options->contents_file->get_value(); 232} 233 234string hhp_reader::get_index_file_string() 235{ 236 return options->index_file->get_value(); 237} 238 239string hhp_reader::get_default_topic_string() 240{ 241 return options->default_topic->get_value(); 242} 243 244unsigned int hhp_reader::get_language_code() 245{ 246 return strtoul(options->language->get_value().c_str(), NULL, 0); 247} 248 249string hhp_reader::get_compiled_file_string() 250{ 251 return options->compiled_file->get_value(); 252} 253 254set<string>::iterator hhp_reader::get_file_pathes_iterator_begin() 255{ 256 return unique_file_pathes.begin(); 257} 258 259set<string>::iterator hhp_reader::get_file_pathes_iterator_end() 260{ 261 return unique_file_pathes.end(); 262}