added utils::separate_groups() and utils::find_first_digit(); utils.cxx: added copyright
[aoi.git] / src / utils.cxx
blob5f86d3f301a18024b39ddb079690630f27aeb74c
1 /*
2 Copyright 2013 Karel Matas
4 This program 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.
9 This program 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.
14 You should have received a copy of the GNU General Public License
15 along with this program. If not, see <http://www.gnu.org/licenses/>.
17 #include "utils.hxx"
18 #include <cstring>
19 #include <sstream>
20 #include <cstdio>
21 #include <FL/fl_utf8.h>
22 #include <stdexcept>
23 #include "logger.hxx"
25 namespace utils {
27 void check_zlib_error ( int err )
29 std::string msg;
30 switch (err){
31 case Z_STREAM_ERROR:
32 msg = "File is not valid.";
33 break;
34 case Z_ERRNO:
35 msg = "File operation error.";
36 break;
37 case Z_MEM_ERROR:
38 msg = "Out of memory.";
39 break;
40 case Z_BUF_ERROR:
41 msg = "LAst read ended in the middle of gzip stream.";
42 case Z_OK:
43 return;
44 default:
45 msg = "This should not happen (gzclose() returned" + std::to_string(err) + ")";
47 throw std::runtime_error(msg.c_str());
50 void gzip_decompress_file( const char *infilename, const char *outfilename )
52 gzFile infile = gzopen(infilename, "rb");
53 FILE *outfile = fopen(outfilename, "wb");
55 if (!infile)
56 throw std::runtime_error("Can't open file");
57 if (!outfile)
58 throw std::runtime_error("Can't write file");
60 char buffer[128];
61 int num_read = 0;
62 while ((num_read = gzread(infile, buffer, sizeof(buffer))) > 0)
63 fwrite(buffer, 1, num_read, outfile);
65 int ret = gzclose(infile);
66 fclose(outfile);
68 check_zlib_error( ret );
72 std::pair<string,vector<TextTag>> parse_markup ( const char *s )
74 size_t i = 0;
75 int raw_pos = 0;
76 int len = 0;
77 int n = 0;
78 char name[MAX_TAGNAME_LENGTH];
79 vector<TextTag> tags;
80 std::stringstream raw;
82 size_t slen = strlen(s);
84 while ( i < slen && s[i] != '\0' ){
85 // tag starts
86 if ( s[i] == '<' ){
87 // << (i.e. escaped < )
88 if ( s[i+1] == '<' ){
89 i++;
90 continue;
92 // </tag>
93 if ( s[i+1] == '/' )
94 tags.push_back( { name, raw_pos-len, len, n++ } );
96 size_t j = 0;
97 while ( s[i++] != '>' ){
98 name[j++] = s[i];
100 // <tag/>
101 if ( s[i-2] == '/' ) {
102 name[j-2] = '\0';
103 tags.push_back( { name, raw_pos, 0, n++ } );
105 name[j-1] = '\0';
106 len = 0;
107 if ( i < slen && s[i+1] != '<' )
108 continue;
109 } // closing '>' reached
110 raw_pos++;
111 len++;
112 raw << s[i++];
113 } // while ( s[i] != '/0' )
114 return { raw.str(), tags };
117 vector<string> split_string ( const string &s, const char *delimiters )
119 vector<string> v;
120 char tmp[strlen(s.c_str())+1];
121 strcpy( tmp, s.c_str() );
122 char *ss = strtok( tmp, delimiters ); // strtok destroys tmp
123 while ( ss != nullptr ){
124 v.push_back( string(ss) );
125 ss = strtok( nullptr, delimiters );
127 return v;
130 vector<int> split_string_int ( const string &s, const char *delimiters )
132 vector<int> v;
133 char tmp[strlen(s.c_str())+1];
134 strcpy( tmp, s.c_str() );
135 char *ss = strtok( tmp, delimiters ); // strtok destroys tmp
136 while ( ss != nullptr ){
137 v.push_back( atoi(ss) );
138 ss = strtok( nullptr, delimiters );
140 return v;
143 // XXX: chybi osetreni chyb
144 vector<string> str_to_chars ( const char *s )
146 vector<string> v;
147 while ( *s != '\0' ){
148 int len = fl_utf8len(*s);
149 std::stringstream ss;
150 if (len!=-1){
151 for ( int i=0; i<len; i++ ) ss << *s++;
152 v.push_back(ss.str());
155 return v;
158 vector<vector<string>> separate_groups ( vector<string> &v )
160 std::sort( v.begin(), v.end() );
161 vector<vector<string>> groups;
162 vector<string> group;
163 for ( int i=0; i < v.size(); ++i ){
164 // similar names
165 if ( i > 0 ){
166 const char *prev = v[i-1].c_str();
167 const char *curr = v[i].c_str();
168 size_t pos = find_first_digit( curr );
169 if ( !strncmp( prev, curr, pos ) )
170 group.push_back( v[i] );
172 else{
173 if ( !group.empty() )
174 groups.push_back( group );
175 group = { v[i] };
178 // last element
179 groups.push_back( group );
180 return groups;
182 } // namespace utils