Merge branch 'devel'
[aoi.git] / src / utils.cxx
blobb6d3d735e853ac5f07d821b0ff4b58088f03f9b9
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());
51 void gzip_decompress_file( const char *infilename, const char *outfilename )
53 gzFile infile = gzopen(infilename, "rb");
54 FILE *outfile = fopen(outfilename, "wb");
56 if (!infile)
57 throw std::runtime_error("Can't open file");
58 if (!outfile)
59 throw std::runtime_error("Can't write file");
61 char buffer[128];
62 int num_read = 0;
63 while ((num_read = gzread(infile, buffer, sizeof(buffer))) > 0)
64 fwrite(buffer, 1, num_read, outfile);
66 int ret = gzclose(infile);
67 fclose(outfile);
69 check_zlib_error( ret );
73 std::pair<string,vector<TextTag>> parse_markup ( const char *s )
75 size_t i = 0;
76 int raw_pos = 0;
77 int len = 0;
78 int n = 0;
79 char name[MAX_TAGNAME_LENGTH];
80 vector<TextTag> tags;
81 std::stringstream raw;
83 size_t slen = strlen(s);
85 while ( i < slen && s[i] != '\0' ){
86 // tag starts
87 if ( s[i] == '<' ){
88 // << (i.e. escaped < )
89 if ( s[i+1] == '<' ){
90 i++;
91 continue;
93 // </tag>
94 if ( s[i+1] == '/' )
95 tags.push_back( { name, raw_pos-len, len, n++ } );
97 size_t j = 0;
98 while ( s[i++] != '>' ){
99 name[j++] = s[i];
101 // <tag/>
102 if ( s[i-2] == '/' ) {
103 name[j-2] = '\0';
104 tags.push_back( { name, raw_pos, 0, n++ } );
106 name[j-1] = '\0';
107 len = 0;
108 if ( i < slen && s[i+1] != '<' )
109 continue;
110 } // closing '>' reached
111 raw_pos++;
112 len++;
113 raw << s[i++];
114 } // while ( s[i] != '/0' )
115 return { raw.str(), tags };
119 vector<string> split_string ( const string &s, const char *delimiters )
121 vector<string> v;
122 char tmp[strlen(s.c_str())+1];
123 strcpy( tmp, s.c_str() );
124 char *ss = strtok( tmp, delimiters ); // strtok destroys tmp
125 while ( ss != nullptr ){
126 v.push_back( string(ss) );
127 ss = strtok( nullptr, delimiters );
129 return v;
133 vector<int> split_string_int ( const string &s, const char *delimiters )
135 vector<int> v;
136 char tmp[strlen(s.c_str())+1];
137 strcpy( tmp, s.c_str() );
138 char *ss = strtok( tmp, delimiters ); // strtok destroys tmp
139 while ( ss != nullptr ){
140 v.push_back( atoi(ss) );
141 ss = strtok( nullptr, delimiters );
143 return v;
147 vector<string> str_to_chars ( const char *s )
149 vector<string> v;
150 while ( *s != '\0' ){
151 int len = fl_utf8len(*s);
152 std::stringstream ss;
153 if (len!=-1){
154 for ( int i=0; i<len; i++ ) ss << *s++;
155 v.push_back(ss.str());
158 return v;
162 vector<vector<string>> separate_groups ( vector<string> &v )
164 std::sort( v.begin(), v.end() );
165 vector<vector<string>> groups;
166 vector<string> group;
167 for ( size_t i=0; i < v.size(); ++i ){
168 // similar names
169 if ( i > 0 ){
170 const char *prev = v[i-1].c_str();
171 const char *curr = v[i].c_str();
172 size_t pos = find_first_digit( curr );
173 if ( !strncmp( prev, curr, pos ) )
174 group.push_back( v[i] );
176 else{
177 if ( !group.empty() )
178 groups.push_back( group );
179 group = { v[i] };
182 // last element
183 groups.push_back( group );
184 return groups;
186 } // namespace utils