1 /*
2  * This file is part of StarDict.
3  *
4  * StarDict is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 3 of the License, or
7  * (at your option) any later version.
8  *
9  * StarDict is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with StarDict.  If not, see <http://www.gnu.org/licenses/>.
16  */
17 
18 #ifdef HAVE_CONFIG_H
19 #  include "config.h"
20 #endif
21 
22 #include <algorithm>
23 #include <errno.h>
24 #include <cstring>
25 #include "lib_common_dict.h"
26 
clear(void)27 void article_data_t::clear(void)
28 {
29 	key.clear();
30 	synonyms.clear();
31 	definitions.clear();
32 }
33 
34 /* Return value:
35  * EXIT_FAILURE - key already exists
36  * EXIT_SUCCESS - key added
37  * */
add_key(const std::string & new_key)38 int article_data_t::add_key(const std::string& new_key)
39 {
40 	if(new_key.empty())
41 		return EXIT_FAILURE;
42 	if(key == new_key)
43 		return EXIT_FAILURE;
44 	if(std::find(synonyms.begin(), synonyms.end(), new_key) != synonyms.end())
45 		return EXIT_FAILURE;
46 	if(key.empty()) {
47 		key = new_key;
48 		return EXIT_SUCCESS;
49 	}
50 	synonyms.push_back(new_key);
51 	return EXIT_SUCCESS;
52 }
53 
54 /* Return value:
55  * EXIT_FAILURE - key or synonym already exists
56  * EXIT_SUCCESS - synonym added
57  * */
add_synonym(const std::string & new_synonym)58 int article_data_t::add_synonym(const std::string& new_synonym)
59 {
60 	if(new_synonym.empty())
61 		return EXIT_FAILURE;
62 	if(key == new_synonym)
63 		return EXIT_FAILURE;
64 	if(std::find(synonyms.begin(), synonyms.end(), new_synonym) != synonyms.end())
65 		return EXIT_FAILURE;
66 	synonyms.push_back(new_synonym);
67 	return EXIT_SUCCESS;
68 }
69 
70 /* Return value:
71  * EXIT_FAILURE or EXIT_SUCCESS */
add_definition(const article_def_t & def)72 int article_data_t::add_definition(const article_def_t& def)
73 {
74 	definitions.push_back(def);
75 	return EXIT_SUCCESS;
76 }
77 
common_dict_t(void)78 common_dict_t::common_dict_t(void)
79 :
80 	lot_of_memory(false)
81 {
82 
83 }
84 
85 /* clean articles
86  * prepare a new file to write data */
reset(void)87 int common_dict_t::reset(void)
88 {
89 	articles.clear();
90 	// First close the previous temporary file, otherwise we'll cannot remove it.
91 	contents_file.reset(NULL);
92 	contents_file_name.clear();
93 	data_store.clear();
94 	if(!lot_of_memory) {
95 		contents_file_name = contents_file_creator.create_temp_file();
96 		if(contents_file_name.empty())
97 			return EXIT_FAILURE;
98 		// open file for reading and writing
99 		contents_file.reset(g_fopen(contents_file_name.c_str(), "wb+"));
100 		if(!contents_file) {
101 			g_critical(create_temp_file_err, contents_file_name.c_str());
102 			return EXIT_FAILURE;
103 		}
104 	}
105 	dict_info.clear();
106 	return EXIT_SUCCESS;
107 }
108 
109 /* write data to contents file.
110  * set offset to the beginning of the record in the file */
write_data(const char * data,size_t size,size_t & offset)111 int common_dict_t::write_data(const char* data, size_t size, size_t& offset)
112 {
113 	if(!data || size == 0) {
114 		g_critical(incorrect_arg_err);
115 		return EXIT_FAILURE;
116 	}
117 	if(lot_of_memory) {
118 		offset = data_store.size();
119 		data_store.resize(data_store.size()+size);
120 		memcpy(&data_store[offset], data, size);
121 	} else {
122 		if(fseek(get_impl(contents_file), 0, SEEK_END)) {
123 			std::string error(g_strerror(errno));
124 			g_critical(read_file_err, contents_file_name.c_str(), error.c_str());
125 			return EXIT_FAILURE;
126 		}
127 		offset = ftell(get_impl(contents_file));
128 		if(1 != fwrite(data, size, 1, get_impl(contents_file))) {
129 			g_critical(write_file_err, contents_file_name.c_str());
130 			return EXIT_FAILURE;
131 		}
132 	}
133 	return EXIT_SUCCESS;
134 }
135 
136 /* read data from contents file
137  * offset - offset of the first byte in the file,
138  * size - size of the data in bytes
139  * data - where to save data, must point to a buffer of enough size */
read_data(char * data,size_t size,size_t offset)140 int common_dict_t::read_data(char* data, size_t size, size_t offset)
141 {
142 	if(!data || size == 0) {
143 		g_critical(incorrect_arg_err);
144 		return EXIT_FAILURE;
145 	}
146 	if(lot_of_memory) {
147 		if(offset+size > data_store.size())
148 			return EXIT_FAILURE;
149 		memcpy(data, &data_store[offset], size);
150 	} else {
151 		if(fseek(get_impl(contents_file), offset, SEEK_SET)) {
152 			std::string error(g_strerror(errno));
153 			g_critical(read_file_err, contents_file_name.c_str(), error.c_str());
154 			return EXIT_FAILURE;
155 		}
156 		if(1 != fread(data, size, 1, get_impl(contents_file))) {
157 			std::string error(g_strerror(errno));
158 			g_critical(read_file_err, contents_file_name.c_str(), error.c_str());
159 			return EXIT_FAILURE;
160 		}
161 	}
162 	return EXIT_SUCCESS;
163 }
164 
add_article(const article_data_t & article)165 int common_dict_t::add_article(const article_data_t& article)
166 {
167 	articles.push_back(article);
168 	return EXIT_SUCCESS;
169 }
170