xaizek / hstr (License: Apachev2) (since 2018-12-07)
Bash and Zsh shell history suggest box - easily view, navigate, search and manage your command history.
Commit ba5ba43352f2e543b8f6f480777e89896d5afcea

TABs > SPACEs
Author: Martin Dvorak
Author date (UTC): 2014-10-29 19:26
Committer name: Martin Dvorak
Committer date (UTC): 2014-10-29 19:26
Parent(s): d28d9fb18bcaa84cfad5e87a3e591f5becf75a64
Signing key:
Tree: 2b5ec28b365f39506e193a709f038df77bb76daf
File Lines added Lines deleted
src/hashset.c 42 42
src/hstr_curses.c 9 9
src/hstr_favorites.c 144 144
src/hstr_history.c 132 132
src/hstr_regexp.c 35 35
src/hstr_utils.c 69 69
src/include/hstr_favorites.h 4 4
src/include/hstr_history.h 4 4
src/include/hstr_regexp.h 2 2
src/include/radixsort.h 18 18
src/radixsort.c 179 179
tests/src/test_args.c 19 19
tests/src/test_curses_keyb.c 39 39
tests/src/test_escape_chars.c 7 7
tests/src/test_favorites.c 5 5
tests/src/test_getopt.c 71 71
tests/src/test_hashset.c 24 24
tests/src/test_keyb.c 10 10
tests/src/test_ranking.c 31 31
tests/src/test_regexp.c 30 30
tests/src/test_utf8.c 82 82
File src/hashset.c changed (mode: 100644) (index b73f8fd..6e06ee0)
... ... void *hashset_get(const HashSet * hs, const char *key)
46 46
47 47 int hashset_contains(const HashSet * hs, const char *key) int hashset_contains(const HashSet * hs, const char *key)
48 48 { {
49 return (hashset_get(hs, key) != NULL);
49 return (hashset_get(hs, key) != NULL);
50 50 } }
51 51
52 52 int hashset_put(HashSet *hs, const char *key, void *value) int hashset_put(HashSet *hs, const char *key, void *value)
 
... ... int hashset_put(HashSet *hs, const char *key, void *value)
74 74
75 75 int hashset_add(HashSet * hs, const char *key) int hashset_add(HashSet * hs, const char *key)
76 76 { {
77 return hashset_put(hs, key, "nil");
77 return hashset_put(hs, key, "nil");
78 78 } }
79 79
80 80 int hashset_size(const HashSet *hs) int hashset_size(const HashSet *hs)
 
... ... void hashset_stat(const HashSet *hs)
95 95
96 96 char** hashset_keys(const HashSet *hs) char** hashset_keys(const HashSet *hs)
97 97 { {
98 if(hs->currentSize) {
99 char **result=malloc(sizeof(char*) * hs->currentSize);
100 int i=0, j=0;
101 struct HashSetNode *p;
102 for(i=0; i<HASH_MAP_SIZE; i++) {
103 p=hs->lists[i];
104 while(p && p->next) {
105 result[j++]=hstr_strdup(p->key);
106 p=p->next;
107 }
108 if(p) {
109 result[j++]=hstr_strdup(p->key);
110 }
111 }
112 return result;
113 } else {
114 return NULL;
115 }
98 if(hs->currentSize) {
99 char **result=malloc(sizeof(char*) * hs->currentSize);
100 int i=0, j=0;
101 struct HashSetNode *p;
102 for(i=0; i<HASH_MAP_SIZE; i++) {
103 p=hs->lists[i];
104 while(p && p->next) {
105 result[j++]=hstr_strdup(p->key);
106 p=p->next;
107 }
108 if(p) {
109 result[j++]=hstr_strdup(p->key);
110 }
111 }
112 return result;
113 } else {
114 return NULL;
115 }
116 116 } }
117 117
118 118 void hashset_destroy(HashSet *hs, const bool freeValues) void hashset_destroy(HashSet *hs, const bool freeValues)
119 119 { {
120 // only hashset keys (and possibly values) are freed - caller must free hashset itself
121 if(hs && hs->currentSize) {
122 int i=0;
123 struct HashSetNode *p, *pp;
124 for(i=0; i<HASH_MAP_SIZE; i++) {
125 p=hs->lists[i];
126 while(p && p->next) {
127 if(p->key) {
128 free(p->key);
129 if(freeValues && p->value) free(p->value);
130 }
131 pp=p;
132 p=p->next;
133 free(pp);
134 }
135 if(p && p->key) {
136 free(p->key);
137 if(freeValues && p->value) free(p->value);
138 free(p);
139 }
140 }
141 }
120 // only hashset keys (and possibly values) are freed - caller must free hashset itself
121 if(hs && hs->currentSize) {
122 int i=0;
123 struct HashSetNode *p, *pp;
124 for(i=0; i<HASH_MAP_SIZE; i++) {
125 p=hs->lists[i];
126 while(p && p->next) {
127 if(p->key) {
128 free(p->key);
129 if(freeValues && p->value) free(p->value);
130 }
131 pp=p;
132 p=p->next;
133 free(pp);
134 }
135 if(p && p->key) {
136 free(p->key);
137 if(freeValues && p->value) free(p->value);
138 free(p);
139 }
140 }
141 }
142 142 } }
File src/hstr_curses.c changed (mode: 100644) (index 4840406..55908d3)
... ... static bool terminalHasColors=FALSE;
14 14
15 15 void hstr_curses_start() void hstr_curses_start()
16 16 { {
17 initscr();
18 keypad(stdscr, TRUE);
19 noecho();
20 terminalHasColors=has_colors();
21 if(terminalHasColors) {
22 start_color();
23 use_default_colors();
24 }
17 initscr();
18 keypad(stdscr, TRUE);
19 noecho();
20 terminalHasColors=has_colors();
21 if(terminalHasColors) {
22 start_color();
23 use_default_colors();
24 }
25 25 } }
26 26
27 27 bool terminal_has_colors() { bool terminal_has_colors() {
28 return terminalHasColors;
28 return terminalHasColors;
29 29 } }
30 30
31 31 void hstr_curses_stop() { void hstr_curses_stop() {
File src/hstr_favorites.c changed (mode: 100644) (index 77055c7..be966cf)
18 18
19 19 void favorites_init(FavoriteItems *favorites) void favorites_init(FavoriteItems *favorites)
20 20 { {
21 favorites->items=NULL;
22 favorites->count=0;
23 favorites->loaded=false;
24 favorites->set=malloc(sizeof(HashSet));
21 favorites->items=NULL;
22 favorites->count=0;
23 favorites->loaded=false;
24 favorites->set=malloc(sizeof(HashSet));
25 25 } }
26 26
27 27 void favorites_show(FavoriteItems *favorites) void favorites_show(FavoriteItems *favorites)
28 28 { {
29 printf("\n\nFavorites (%d):", favorites->count);
30 if(favorites->count) {
31 int i;
32 for(i=0;i<favorites->count;i++) {
33 printf("\n%s",favorites->items[i]);
34 }
35 }
36 printf("\n");
29 printf("\n\nFavorites (%d):", favorites->count);
30 if(favorites->count) {
31 int i;
32 for(i=0;i<favorites->count;i++) {
33 printf("\n%s",favorites->items[i]);
34 }
35 }
36 printf("\n");
37 37 } }
38 38
39 39 char* favorites_get_filename() char* favorites_get_filename()
40 40 { {
41 char *home = getenv(ENV_VAR_HOME);
42 char *fileName = (char*) malloc(strlen(home) + 1 + strlen(FILE_HH_RC) + 1);
43 strcpy(fileName, home);
44 strcat(fileName, "/");
45 strcat(fileName, FILE_HH_RC);
46 return fileName;
41 char *home = getenv(ENV_VAR_HOME);
42 char *fileName = (char*) malloc(strlen(home) + 1 + strlen(FILE_HH_RC) + 1);
43 strcpy(fileName, home);
44 strcat(fileName, "/");
45 strcat(fileName, FILE_HH_RC);
46 return fileName;
47 47 } }
48 48
49 49 void favorites_get(FavoriteItems *favorites) void favorites_get(FavoriteItems *favorites)
50 50 { {
51 if(!favorites->loaded) {
52 char* fileName = favorites_get_filename();
53 char *file_contents=NULL;
54 if(access(fileName, F_OK) != -1) {
55 long input_file_size;
56
57 FILE *input_file = fopen(fileName, "rb");
58 fseek(input_file, 0, SEEK_END);
59 input_file_size = ftell(input_file);
60 rewind(input_file);
61 file_contents = malloc((input_file_size + 1) * (sizeof(char)));
62 if(fread(file_contents, sizeof(char), input_file_size, input_file)==-1) {
63 exit(EXIT_FAILURE);
64 }
65 fclose(input_file);
66 file_contents[input_file_size] = 0;
67
68 if(file_contents && strlen(file_contents)) {
69 favorites->count = 0;
70 char *p=strchr(file_contents,'\n');
71 while (p!=NULL) {
72 favorites->count++;
73 p=strchr(p+1,'\n');
74 }
75
76 favorites->items = malloc(sizeof(char*) * favorites->count);
77 favorites->count=0;
78 char *pb=file_contents, *pe, *s;
79 pe=strchr(file_contents, '\n');
80 HashSet set;
81 hashset_init(&set);
82 while(pe!=NULL) {
83 *pe=0;
84 if(!hashset_contains(&set,pb)) {
85 s=hstr_strdup(pb);
86 favorites->items[favorites->count++]=s;
87 hashset_add(&set,s);
88 }
89 pb=pe+1;
90 pe=strchr(pb, '\n');
91 }
92 free(file_contents);
93 }
94 } else {
95 // favorites file not found > favorites don't exist yet
96 favorites->loaded=true;
97 return;
98 }
99 free(fileName);
100 }
51 if(!favorites->loaded) {
52 char* fileName = favorites_get_filename();
53 char *file_contents=NULL;
54 if(access(fileName, F_OK) != -1) {
55 long input_file_size;
56
57 FILE *input_file = fopen(fileName, "rb");
58 fseek(input_file, 0, SEEK_END);
59 input_file_size = ftell(input_file);
60 rewind(input_file);
61 file_contents = malloc((input_file_size + 1) * (sizeof(char)));
62 if(fread(file_contents, sizeof(char), input_file_size, input_file)==-1) {
63 exit(EXIT_FAILURE);
64 }
65 fclose(input_file);
66 file_contents[input_file_size] = 0;
67
68 if(file_contents && strlen(file_contents)) {
69 favorites->count = 0;
70 char *p=strchr(file_contents,'\n');
71 while (p!=NULL) {
72 favorites->count++;
73 p=strchr(p+1,'\n');
74 }
75
76 favorites->items = malloc(sizeof(char*) * favorites->count);
77 favorites->count=0;
78 char *pb=file_contents, *pe, *s;
79 pe=strchr(file_contents, '\n');
80 HashSet set;
81 hashset_init(&set);
82 while(pe!=NULL) {
83 *pe=0;
84 if(!hashset_contains(&set,pb)) {
85 s=hstr_strdup(pb);
86 favorites->items[favorites->count++]=s;
87 hashset_add(&set,s);
88 }
89 pb=pe+1;
90 pe=strchr(pb, '\n');
91 }
92 free(file_contents);
93 }
94 } else {
95 // favorites file not found > favorites don't exist yet
96 favorites->loaded=true;
97 return;
98 }
99 free(fileName);
100 }
101 101 } }
102 102
103 103 void favorites_save(FavoriteItems *favorites) void favorites_save(FavoriteItems *favorites)
104 104 { {
105 char *fileName=favorites_get_filename();
106
107 if(favorites->count) {
108 FILE *output_file = fopen(fileName, "wb");
109 rewind(output_file);
110 int i;
111 for(i=0; i<favorites->count; i++) {
112 if(fwrite(favorites->items[i], sizeof(char), strlen(favorites->items[i]), output_file)==-1) {
113 exit(EXIT_FAILURE);
114 }
115 if(fwrite("\n", sizeof(char), strlen("\n"), output_file)==-1) {
116 exit(EXIT_FAILURE);
117 }
118 }
119 fclose(output_file);
120 } else {
121 if(access(fileName, F_OK) != -1) {
122 FILE *output_file = fopen(fileName, "wb");
123 fclose(output_file);
124 }
125 }
126 free(fileName);
105 char *fileName=favorites_get_filename();
106
107 if(favorites->count) {
108 FILE *output_file = fopen(fileName, "wb");
109 rewind(output_file);
110 int i;
111 for(i=0; i<favorites->count; i++) {
112 if(fwrite(favorites->items[i], sizeof(char), strlen(favorites->items[i]), output_file)==-1) {
113 exit(EXIT_FAILURE);
114 }
115 if(fwrite("\n", sizeof(char), strlen("\n"), output_file)==-1) {
116 exit(EXIT_FAILURE);
117 }
118 }
119 fclose(output_file);
120 } else {
121 if(access(fileName, F_OK) != -1) {
122 FILE *output_file = fopen(fileName, "wb");
123 fclose(output_file);
124 }
125 }
126 free(fileName);
127 127 } }
128 128
129 129 void favorites_add(FavoriteItems *favorites, char *newFavorite) void favorites_add(FavoriteItems *favorites, char *newFavorite)
130 130 { {
131 if(favorites->count) {
132 favorites->items=realloc(favorites->items, sizeof(char *) * ++favorites->count);
133 favorites->items[favorites->count-1]=hstr_strdup(newFavorite);
134 favorites_choose(favorites, newFavorite);
135 } else {
136 favorites->items=malloc(sizeof(char*));
137 favorites->items[0]=hstr_strdup(newFavorite);
138 favorites->count=1;
139 }
140
141 favorites_save(favorites);
131 if(favorites->count) {
132 favorites->items=realloc(favorites->items, sizeof(char *) * ++favorites->count);
133 favorites->items[favorites->count-1]=hstr_strdup(newFavorite);
134 favorites_choose(favorites, newFavorite);
135 } else {
136 favorites->items=malloc(sizeof(char*));
137 favorites->items[0]=hstr_strdup(newFavorite);
138 favorites->count=1;
139 }
140
141 favorites_save(favorites);
142 142 } }
143 143
144 144 void favorites_choose(FavoriteItems *favorites, char *choice) void favorites_choose(FavoriteItems *favorites, char *choice)
145 145 { {
146 if(favorites->count && choice) {
147 int r;
148 char *b=NULL, *next;
149 for(r=0; r<favorites->count; r++) {
150 if(!strcmp(favorites->items[r],choice)) {
151 favorites->items[0]=favorites->items[r];
152 if(b) {
153 favorites->items[r]=b;
154 }
155 favorites_save(favorites);
156 return;
157 }
158 next=favorites->items[r];
159 favorites->items[r]=b;
160 b=next;
161 }
162 }
146 if(favorites->count && choice) {
147 int r;
148 char *b=NULL, *next;
149 for(r=0; r<favorites->count; r++) {
150 if(!strcmp(favorites->items[r],choice)) {
151 favorites->items[0]=favorites->items[r];
152 if(b) {
153 favorites->items[r]=b;
154 }
155 favorites_save(favorites);
156 return;
157 }
158 next=favorites->items[r];
159 favorites->items[r]=b;
160 b=next;
161 }
162 }
163 163 } }
164 164
165 165 bool favorites_remove(FavoriteItems *favorites, char *almostDead) bool favorites_remove(FavoriteItems *favorites, char *almostDead)
166 166 { {
167 if(favorites->count) {
168 int r, w, count;
169 count=favorites->count;
170 for(r=0, w=0; r<count; r++) {
171 if(!strcmp(favorites->items[r], almostDead)) {
172 favorites->count--;
173 } else {
174 if(w<r) {
175 favorites->items[w]=favorites->items[r];
176 }
177 w++;
178 }
179 }
180 favorites_save(favorites);
181 return true;
182 } else {
183 return false;
184 }
167 if(favorites->count) {
168 int r, w, count;
169 count=favorites->count;
170 for(r=0, w=0; r<count; r++) {
171 if(!strcmp(favorites->items[r], almostDead)) {
172 favorites->count--;
173 } else {
174 if(w<r) {
175 favorites->items[w]=favorites->items[r];
176 }
177 w++;
178 }
179 }
180 favorites_save(favorites);
181 return true;
182 } else {
183 return false;
184 }
185 185 } }
186 186
187 187 void favorites_destroy(FavoriteItems *favorites) void favorites_destroy(FavoriteItems *favorites)
188 188 { {
189 if(favorites) {
190 int i;
191 for(i=0; i<favorites->count; i++) {
192 free(favorites->items[i]);
193 }
194 hashset_destroy(favorites->set, false);
195 free(favorites);
196 }
189 if(favorites) {
190 int i;
191 for(i=0; i<favorites->count; i++) {
192 free(favorites->items[i]);
193 }
194 hashset_destroy(favorites->set, false);
195 free(favorites);
196 }
197 197 } }
File src/hstr_history.c changed (mode: 100644) (index 35655db..722625f)
16 16 #include <assert.h> #include <assert.h>
17 17
18 18 typedef struct { typedef struct {
19 char *item;
20 unsigned rank;
19 char *item;
20 unsigned rank;
21 21 } RankedHistoryItem; } RankedHistoryItem;
22 22
23 23 static HistoryItems *prioritizedHistory; static HistoryItems *prioritizedHistory;
24 24 static bool dirty; static bool dirty;
25 25
26 26 static const char *commandBlacklist[] = { static const char *commandBlacklist[] = {
27 "ls", "pwd", "cd", "cd ..", "hh", "mc",
28 "ls ", "pwd ", "cd ", "cd .. ", "hh ", "mc "
27 "ls", "pwd", "cd", "cd ..", "hh", "mc",
28 "ls ", "pwd ", "cd ", "cd .. ", "hh ", "mc "
29 29 }; };
30 30
31 31 #ifdef DEBUG_RADIX #ifdef DEBUG_RADIX
 
... ... static const char *commandBlacklist[] = {
35 35 #endif #endif
36 36
37 37 unsigned history_ranking_function(unsigned rank, int newOccurenceOrder, size_t length) { unsigned history_ranking_function(unsigned rank, int newOccurenceOrder, size_t length) {
38 long metrics=rank+(log(newOccurenceOrder)*10.0)+length;
39 // alternative metrics:
40 // rank+newOccurenceOrder/10+length
41 assert(metrics<UINT_MAX);
42 return metrics;
38 long metrics=rank+(log(newOccurenceOrder)*10.0)+length;
39 // alternative metrics:
40 // rank+newOccurenceOrder/10+length
41 assert(metrics<UINT_MAX);
42 return metrics;
43 43 } }
44 44
45 45 char *get_history_file_name() char *get_history_file_name()
46 46 { {
47 char *historyFile=getenv(ENV_VAR_HISTFILE);
48 if(!historyFile || strlen(historyFile)==0) {
49 char *home = getenv(ENV_VAR_HOME);
50 historyFile = malloc(strlen(home) + 1 + strlen(FILE_DEFAULT_HISTORY) + 1);
51 strcat(strcat(strcpy(historyFile, home), "/"), FILE_DEFAULT_HISTORY);
52 }
53 return historyFile;
47 char *historyFile=getenv(ENV_VAR_HISTFILE);
48 if(!historyFile || strlen(historyFile)==0) {
49 char *home = getenv(ENV_VAR_HOME);
50 historyFile = malloc(strlen(home) + 1 + strlen(FILE_DEFAULT_HISTORY) + 1);
51 strcat(strcat(strcpy(historyFile, home), "/"), FILE_DEFAULT_HISTORY);
52 }
53 return historyFile;
54 54 } }
55 55
56 56 void dump_prioritized_history(HistoryItems *ph) void dump_prioritized_history(HistoryItems *ph)
57 57 { {
58 printf("\n\nPrioritized history:");
59 int i;
60 for(i=0; i<ph->count; i++) {
61 if(ph->items[i]!=NULL) {
62 printf("\n%s",ph->items[i]); fflush(stdout);
63 } else {
64 printf("\n %d NULL",i); fflush(stdout);
65 }
66 }
67 printf("\n"); fflush(stdout);
58 printf("\n\nPrioritized history:");
59 int i;
60 for(i=0; i<ph->count; i++) {
61 if(ph->items[i]!=NULL) {
62 printf("\n%s",ph->items[i]); fflush(stdout);
63 } else {
64 printf("\n %d NULL",i); fflush(stdout);
65 }
66 }
67 printf("\n"); fflush(stdout);
68 68 } }
69 69
70 70 HistoryItems *get_prioritized_history() HistoryItems *get_prioritized_history()
71 71 { {
72 using_history();
73
74 char *historyFile = get_history_file_name();
75 if(read_history(historyFile)!=0) {
76 fprintf(stderr, "\nUnable to read history file from '%s'!\n",historyFile);
77 exit(EXIT_FAILURE);
78 }
79 HISTORY_STATE *historyState=history_get_history_state();
80
81 if(historyState->length > 0) {
82 HashSet rankmap;
83 hashset_init(&rankmap);
84
85 HashSet blacklist;
86 int i;
87 hashset_init(&blacklist);
88 int length=sizeof(commandBlacklist)/sizeof(commandBlacklist[0]);
89 for(i=0; i<length; i++) {
90 hashset_add(&blacklist, commandBlacklist[i]);
91 }
92
93 RadixSorter rs;
94 unsigned radixMaxKeyEstimate=historyState->size*1000;
95 radixsort_init(&rs, (radixMaxKeyEstimate<100000?100000:radixMaxKeyEstimate));
96 rs.optFloorAndInsertBigKeys=true;
97
98 RankedHistoryItem *r;
99 RadixItem *radixItem;
72 using_history();
73
74 char *historyFile = get_history_file_name();
75 if(read_history(historyFile)!=0) {
76 fprintf(stderr, "\nUnable to read history file from '%s'!\n",historyFile);
77 exit(EXIT_FAILURE);
78 }
79 HISTORY_STATE *historyState=history_get_history_state();
80
81 if(historyState->length > 0) {
82 HashSet rankmap;
83 hashset_init(&rankmap);
84
85 HashSet blacklist;
86 int i;
87 hashset_init(&blacklist);
88 int length=sizeof(commandBlacklist)/sizeof(commandBlacklist[0]);
89 for(i=0; i<length; i++) {
90 hashset_add(&blacklist, commandBlacklist[i]);
91 }
92
93 RadixSorter rs;
94 unsigned radixMaxKeyEstimate=historyState->size*1000;
95 radixsort_init(&rs, (radixMaxKeyEstimate<100000?100000:radixMaxKeyEstimate));
96 rs.optFloorAndInsertBigKeys=true;
97
98 RankedHistoryItem *r;
99 RadixItem *radixItem;
100 100 HIST_ENTRY **historyList=history_list(); HIST_ENTRY **historyList=history_list();
101 101 char **rawHistory=malloc(sizeof(char*) * historyState->length); char **rawHistory=malloc(sizeof(char*) * historyState->length);
102 102 int rawOffset=historyState->length-1; int rawOffset=historyState->length-1;
103 char *line;
104 for(i=0; i<historyState->length; i++, rawOffset--) {
105 line=historyList[i]->line;
106 rawHistory[rawOffset]=line;
107 if(hashset_contains(&blacklist, line)) {
108 continue;
109 }
110 if((r=hashset_get(&rankmap, line))==NULL) {
111 r=malloc(sizeof(RankedHistoryItem));
112 r->rank=history_ranking_function(0, i, strlen(line));
113 r->item=historyList[i]->line;
114
115 hashset_put(&rankmap, line, r);
116
117 radixItem=malloc(sizeof(RadixItem));
118 radixItem->key=r->rank;
119 radixItem->data=r;
120 radixItem->next=NULL;
121 radixsort_add(&rs, radixItem);
122 } else {
123 radixItem=radix_cut(&rs, r->rank, r);
124
125 assert(radixItem);
126
127 if(radixItem) {
128 r->rank=history_ranking_function(r->rank, i, strlen(line));
129 radixItem->key=r->rank;
130 radixsort_add(&rs, radixItem);
131 }
132 }
133 }
134
135 DEBUG_RADIXSORT();
136
137 RadixItem **prioritizedRadix=radixsort_dump(&rs);
138 prioritizedHistory=malloc(sizeof(HistoryItems));
139 prioritizedHistory->count=rs.size;
140 prioritizedHistory->rawCount=historyState->length;
141 prioritizedHistory->items=malloc(rs.size * sizeof(char*));
142 prioritizedHistory->raw=rawHistory;
143 for(i=0; i<rs.size; i++) {
144 if(prioritizedRadix[i]->data) {
145 prioritizedHistory->items[i]=((RankedHistoryItem *)(prioritizedRadix[i]->data))->item;
146 }
147 free(prioritizedRadix[i]->data);
148 free(prioritizedRadix[i]);
149 }
150
151 radixsort_destroy(&rs);
152 // TODO rankmap (?) and blacklist (?) to be destroyed
153
154 return prioritizedHistory;
155 } else {
156 return NULL;
157 }
103 char *line;
104 for(i=0; i<historyState->length; i++, rawOffset--) {
105 line=historyList[i]->line;
106 rawHistory[rawOffset]=line;
107 if(hashset_contains(&blacklist, line)) {
108 continue;
109 }
110 if((r=hashset_get(&rankmap, line))==NULL) {
111 r=malloc(sizeof(RankedHistoryItem));
112 r->rank=history_ranking_function(0, i, strlen(line));
113 r->item=historyList[i]->line;
114
115 hashset_put(&rankmap, line, r);
116
117 radixItem=malloc(sizeof(RadixItem));
118 radixItem->key=r->rank;
119 radixItem->data=r;
120 radixItem->next=NULL;
121 radixsort_add(&rs, radixItem);
122 } else {
123 radixItem=radix_cut(&rs, r->rank, r);
124
125 assert(radixItem);
126
127 if(radixItem) {
128 r->rank=history_ranking_function(r->rank, i, strlen(line));
129 radixItem->key=r->rank;
130 radixsort_add(&rs, radixItem);
131 }
132 }
133 }
134
135 DEBUG_RADIXSORT();
136
137 RadixItem **prioritizedRadix=radixsort_dump(&rs);
138 prioritizedHistory=malloc(sizeof(HistoryItems));
139 prioritizedHistory->count=rs.size;
140 prioritizedHistory->rawCount=historyState->length;
141 prioritizedHistory->items=malloc(rs.size * sizeof(char*));
142 prioritizedHistory->raw=rawHistory;
143 for(i=0; i<rs.size; i++) {
144 if(prioritizedRadix[i]->data) {
145 prioritizedHistory->items[i]=((RankedHistoryItem *)(prioritizedRadix[i]->data))->item;
146 }
147 free(prioritizedRadix[i]->data);
148 free(prioritizedRadix[i]);
149 }
150
151 radixsort_destroy(&rs);
152 // TODO rankmap (?) and blacklist (?) to be destroyed
153
154 return prioritizedHistory;
155 } else {
156 return NULL;
157 }
158 158 } }
159 159
160 160 void free_prioritized_history() void free_prioritized_history()
161 161 { {
162 free(prioritizedHistory->items);
163 free(prioritizedHistory);
162 free(prioritizedHistory->items);
163 free(prioritizedHistory);
164 164 } }
165 165
166 166 void history_mgmt_open() void history_mgmt_open()
167 167 { {
168 dirty=false;
168 dirty=false;
169 169 } }
170 170
171 171 void history_clear_dirty() void history_clear_dirty()
172 172 { {
173 dirty=false;
173 dirty=false;
174 174 } }
175 175
176 176 int history_mgmt_remove(char *cmd) int history_mgmt_remove(char *cmd)
177 177 { {
178 int offset=history_search_pos(cmd, 0, 0), occurences=0;
179 char *l;
180 HISTORY_STATE *historyState=history_get_history_state();
181 while(offset>=0) {
182 l=historyState->entries[offset]->line;
183 if(offset<historyState->length && !strcmp(cmd, l)) {
184 occurences++;
185 free_history_entry(remove_history(offset));
186 }
187 offset=history_search_pos(cmd, 0, ++offset);
188 }
189 if(occurences) {
190 write_history(get_history_file_name());
191 dirty=true;
192 }
193 return occurences;
178 int offset=history_search_pos(cmd, 0, 0), occurences=0;
179 char *l;
180 HISTORY_STATE *historyState=history_get_history_state();
181 while(offset>=0) {
182 l=historyState->entries[offset]->line;
183 if(offset<historyState->length && !strcmp(cmd, l)) {
184 occurences++;
185 free_history_entry(remove_history(offset));
186 }
187 offset=history_search_pos(cmd, 0, ++offset);
188 }
189 if(occurences) {
190 write_history(get_history_file_name());
191 dirty=true;
192 }
193 return occurences;
194 194 } }
195 195
196 196 void history_mgmt_flush() void history_mgmt_flush()
197 197 { {
198 if(dirty) {
199 fill_terminal_input("history -r\n", false);
200 }
198 if(dirty) {
199 fill_terminal_input("history -r\n", false);
200 }
201 201 } }
File src/hstr_regexp.c changed (mode: 100644) (index 06e9029..dc6c59d)
15 15
16 16 void hstr_regexp_init(HstrRegexp *hstrRegexp) void hstr_regexp_init(HstrRegexp *hstrRegexp)
17 17 { {
18 hashset_init(&hstrRegexp->cache);
18 hashset_init(&hstrRegexp->cache);
19 19 } }
20 20
21 21 bool hstr_regexp_match( bool hstr_regexp_match(
22 HstrRegexp *hstrRegexp,
23 const char *regexp,
24 const char *text,
25 regmatch_t *match,
26 char *errorMessage,
27 const size_t errorMessageSize)
22 HstrRegexp *hstrRegexp,
23 const char *regexp,
24 const char *text,
25 regmatch_t *match,
26 char *errorMessage,
27 const size_t errorMessageSize)
28 28 { {
29 regex_t* compiled;
30 if(hashset_contains(&hstrRegexp->cache,regexp)) {
31 compiled=hashset_get(&hstrRegexp->cache, regexp);
32 } else {
33 compiled=malloc(sizeof(regex_t));
34 int compilationFlags=(hstrRegexp->caseSensitive?0:REG_ICASE);
35 int compilationStatus=regcomp(compiled, regexp, compilationFlags);
36 if(!compilationStatus) {
37 hashset_put(&hstrRegexp->cache, hstr_strdup(regexp), compiled);
38 } else {
39 regerror(compilationStatus, compiled, errorMessage, errorMessageSize);
40 free(compiled);
41 return false;
42 }
43 }
29 regex_t* compiled;
30 if(hashset_contains(&hstrRegexp->cache,regexp)) {
31 compiled=hashset_get(&hstrRegexp->cache, regexp);
32 } else {
33 compiled=malloc(sizeof(regex_t));
34 int compilationFlags=(hstrRegexp->caseSensitive?0:REG_ICASE);
35 int compilationStatus=regcomp(compiled, regexp, compilationFlags);
36 if(!compilationStatus) {
37 hashset_put(&hstrRegexp->cache, hstr_strdup(regexp), compiled);
38 } else {
39 regerror(compilationStatus, compiled, errorMessage, errorMessageSize);
40 free(compiled);
41 return false;
42 }
43 }
44 44
45 int matches=REGEXP_MATCH_BUFFER_SIZE;
46 regmatch_t matchPtr[REGEXP_MATCH_BUFFER_SIZE];
47 int matchingFlags=0;
48 int matchingStatus=regexec(compiled, text, matches, matchPtr, matchingFlags);
49 if(!matchingStatus) {
50 if(matchPtr[0].rm_so != -1) {
51 match->rm_so=matchPtr[0].rm_so;
52 match->rm_eo=matchPtr[0].rm_eo;
53 return true;
54 }
55 }
56 return false;
45 int matches=REGEXP_MATCH_BUFFER_SIZE;
46 regmatch_t matchPtr[REGEXP_MATCH_BUFFER_SIZE];
47 int matchingFlags=0;
48 int matchingStatus=regexec(compiled, text, matches, matchPtr, matchingFlags);
49 if(!matchingStatus) {
50 if(matchPtr[0].rm_so != -1) {
51 match->rm_so=matchPtr[0].rm_so;
52 match->rm_eo=matchPtr[0].rm_eo;
53 return true;
54 }
55 }
56 return false;
57 57 } }
58 58
59 59 void hstr_regexp_destroy(HstrRegexp *hstrRegexp) void hstr_regexp_destroy(HstrRegexp *hstrRegexp)
60 60 { {
61 hashset_destroy(&hstrRegexp->cache, true);
61 hashset_destroy(&hstrRegexp->cache, true);
62 62 } }
File src/hstr_utils.c changed (mode: 100644) (index 720663b..57b7621)
... ... char *hstr_strdup(const char * s)
25 25 // wide char aware strlen() // wide char aware strlen()
26 26 int hstr_strlen(const char *s) int hstr_strlen(const char *s)
27 27 { {
28 if(s) {
29 int result=0;
30 bool isHighBitSet=false;
31 int i=0;
32 while(s[i]) {
33 if(1<<7 & s[i]) {
34 if(isHighBitSet) {
35 isHighBitSet=false;
36 result++;
37 } else {
38 isHighBitSet=true;
39 }
40 } else {
41 result++;
42 }
43 i++;
44 }
45 return result;
46 } else {
47 return 0;
48 }
28 if(s) {
29 int result=0;
30 bool isHighBitSet=false;
31 int i=0;
32 while(s[i]) {
33 if(1<<7 & s[i]) {
34 if(isHighBitSet) {
35 isHighBitSet=false;
36 result++;
37 } else {
38 isHighBitSet=true;
39 }
40 } else {
41 result++;
42 }
43 i++;
44 }
45 return result;
46 } else {
47 return 0;
48 }
49 49 } }
50 50
51 51 void hstr_chop(char *s) void hstr_chop(char *s)
52 52 { {
53 if(s) {
54 int i=strlen(s);
55 if(i) {
56 if(1<<7 & s[i-1]) {
57 s[i-2]=0;
58 } else {
59 s[i-1]=0;
60 }
61 }
62 }
53 if(s) {
54 int i=strlen(s);
55 if(i) {
56 if(1<<7 & s[i-1]) {
57 s[i-2]=0;
58 } else {
59 s[i-1]=0;
60 }
61 }
62 }
63 63 } }
64 64
65 65 void tiocsti() void tiocsti()
66 66 { {
67 char buf[] = DEFAULT_COMMAND;
68 int i;
69 for (i = 0; i < sizeof buf - 1; i++) {
70 ioctl(0, TIOCSTI, &buf[i]);
71 }
67 char buf[] = DEFAULT_COMMAND;
68 int i;
69 for (i = 0; i < sizeof buf - 1; i++) {
70 ioctl(0, TIOCSTI, &buf[i]);
71 }
72 72 } }
73 73
74 74 void fill_terminal_input(char *cmd, bool padding) void fill_terminal_input(char *cmd, bool padding)
75 75 { {
76 if(cmd && strlen(cmd)>0) {
77 size_t size = strlen(cmd);
78 unsigned i;
79 char *c;
80 for (i = 0; i < size; i++) {
81 // terminal I/O control, simulate terminal input
82 c=(cmd+i);
83 ioctl(0, TIOCSTI, c);
84 }
85 // echo, but don't flush to terminal
86 if(padding) printf("\n");
87 }
76 if(cmd && strlen(cmd)>0) {
77 size_t size = strlen(cmd);
78 unsigned i;
79 char *c;
80 for (i = 0; i < size; i++) {
81 // terminal I/O control, simulate terminal input
82 c=(cmd+i);
83 ioctl(0, TIOCSTI, c);
84 }
85 // echo, but don't flush to terminal
86 if(padding) printf("\n");
87 }
88 88 } }
89 89
90 90 void reverse_char_pointer_array(char **array, unsigned length) void reverse_char_pointer_array(char **array, unsigned length)
91 91 { {
92 char *temp;
93 unsigned i;
92 char *temp;
93 unsigned i;
94 94 for (i=0; i<length/2; i++) { for (i=0; i<length/2; i++) {
95 95 temp = array[i]; temp = array[i];
96 96 array[i] = array[length-i-1]; array[i] = array[length-i-1];
 
... ... void reverse_char_pointer_array(char **array, unsigned length)
101 101 void get_hostname(int bufferSize, char *buffer) void get_hostname(int bufferSize, char *buffer)
102 102 { {
103 103 char *b=buffer; char *b=buffer;
104 if(access(PROC_HOSTNAME, F_OK) != -1) {
105 FILE *file = fopen(PROC_HOSTNAME, "r");
106 b=fgets(buffer, bufferSize, file);
107 fclose(file);
108 if(b) {
109 b[strlen(b)-1]=0;
110 return;
111 }
112 }
104 if(access(PROC_HOSTNAME, F_OK) != -1) {
105 FILE *file = fopen(PROC_HOSTNAME, "r");
106 b=fgets(buffer, bufferSize, file);
107 fclose(file);
108 if(b) {
109 b[strlen(b)-1]=0;
110 return;
111 }
112 }
113 113 strcpy(buffer,"localhost"); strcpy(buffer,"localhost");
114 114 } }
115 115
116 116 void toggle_case(char *str, bool lowercase) { void toggle_case(char *str, bool lowercase) {
117 if(str && strlen(str)>0) {
118 int i;
119 for(i = 0; str[i]; i++){
120 if(lowercase) {
121 str[i] = tolower(str[i]);
122 } else {
123 str[i] = toupper(str[i]);
124 }
125 }
126 }
117 if(str && strlen(str)>0) {
118 int i;
119 for(i = 0; str[i]; i++){
120 if(lowercase) {
121 str[i] = tolower(str[i]);
122 } else {
123 str[i] = toupper(str[i]);
124 }
125 }
126 }
127 127 } }
File src/include/hstr_favorites.h changed (mode: 100644) (index 0ff47ba..f3573a9)
20 20 #define FILE_HH_RC ".hh_favorites" #define FILE_HH_RC ".hh_favorites"
21 21
22 22 typedef struct { typedef struct {
23 char **items;
24 unsigned count;
25 bool loaded;
26 HashSet *set;
23 char **items;
24 unsigned count;
25 bool loaded;
26 HashSet *set;
27 27 } FavoriteItems; } FavoriteItems;
28 28
29 29 void favorites_init(FavoriteItems *favorites); void favorites_init(FavoriteItems *favorites);
File src/include/hstr_history.h changed (mode: 100644) (index 82ddebc..73d2916)
28 28 #define FILE_DEFAULT_HISTORY ".bash_history" #define FILE_DEFAULT_HISTORY ".bash_history"
29 29
30 30 typedef struct { typedef struct {
31 char **items;
32 unsigned count;
33 char **raw;
34 unsigned rawCount;
31 char **items;
32 unsigned count;
33 char **raw;
34 unsigned rawCount;
35 35 } HistoryItems; } HistoryItems;
36 36
37 37 HistoryItems *get_prioritized_history(); HistoryItems *get_prioritized_history();
File src/include/hstr_regexp.h changed (mode: 100644) (index a1fcacd..70e1a89)
17 17 #include "hashset.h" #include "hashset.h"
18 18
19 19 typedef struct { typedef struct {
20 bool caseSensitive;
21 HashSet cache;
20 bool caseSensitive;
21 HashSet cache;
22 22 } HstrRegexp; } HstrRegexp;
23 23
24 24 void hstr_regexp_init(HstrRegexp *hstrRegexp); void hstr_regexp_init(HstrRegexp *hstrRegexp);
File src/include/radixsort.h changed (mode: 100644) (index fa5d864..cbb5cfc)
24 24 #define RADIX_DEBUG_LEVEL_DEBUG 2 #define RADIX_DEBUG_LEVEL_DEBUG 2
25 25
26 26 typedef struct radixitem { typedef struct radixitem {
27 unsigned key;
28 void *data;
29 struct radixitem *next;
27 unsigned key;
28 void *data;
29 struct radixitem *next;
30 30 } RadixItem; } RadixItem;
31 31
32 32 typedef struct radixslot { typedef struct radixslot {
33 unsigned min;
34 unsigned max;
35 unsigned size;
33 unsigned min;
34 unsigned max;
35 unsigned size;
36 36 } RadixSlot; } RadixSlot;
37 37
38 38 typedef struct { typedef struct {
39 unsigned size;
40 unsigned maxKey;
41 unsigned keyLimit;
42 RadixItem ***topDigits;
43
44 bool optFloorAndInsertBigKeys;
45 bool optIgnoreBigKeys;
46
47 RadixSlot **_slotDescriptors;
48 unsigned _slotsCount;
49 unsigned _topIndexLimit;
50 unsigned _debug;
39 unsigned size;
40 unsigned maxKey;
41 unsigned keyLimit;
42 RadixItem ***topDigits;
43
44 bool optFloorAndInsertBigKeys;
45 bool optIgnoreBigKeys;
46
47 RadixSlot **_slotDescriptors;
48 unsigned _slotsCount;
49 unsigned _topIndexLimit;
50 unsigned _debug;
51 51 } RadixSorter; } RadixSorter;
52 52
53 53 void radixsort_init(RadixSorter *rs, unsigned keyLimit); void radixsort_init(RadixSorter *rs, unsigned keyLimit);
File src/radixsort.c changed (mode: 100644) (index 6c4cbc5..6ab0d4e)
14 14
15 15 void radixsort_init(RadixSorter *rs, unsigned keyLimit) void radixsort_init(RadixSorter *rs, unsigned keyLimit)
16 16 { {
17 rs->optFloorAndInsertBigKeys=false;
18 rs->optIgnoreBigKeys=false;
19
20 rs->_topIndexLimit=GET_TOP_INDEX(keyLimit);
21 rs->size=0;
22 rs->topDigits=malloc(rs->_topIndexLimit * sizeof(RadixItem ***));
23 memset(rs->topDigits, 0, rs->_topIndexLimit * sizeof(RadixItem ***));
24 rs->maxKey=0;
25 rs->keyLimit=keyLimit;
26
27 rs->_slotDescriptors=malloc(rs->_topIndexLimit * sizeof(RadixSlot **));
28 rs->_slotsCount=0;
17 rs->optFloorAndInsertBigKeys=false;
18 rs->optIgnoreBigKeys=false;
19
20 rs->_topIndexLimit=GET_TOP_INDEX(keyLimit);
21 rs->size=0;
22 rs->topDigits=malloc(rs->_topIndexLimit * sizeof(RadixItem ***));
23 memset(rs->topDigits, 0, rs->_topIndexLimit * sizeof(RadixItem ***));
24 rs->maxKey=0;
25 rs->keyLimit=keyLimit;
26
27 rs->_slotDescriptors=malloc(rs->_topIndexLimit * sizeof(RadixSlot **));
28 rs->_slotsCount=0;
29 29 } }
30 30
31 31 void radixsort_set_debug_level(RadixSorter *rs, unsigned debugLevel) void radixsort_set_debug_level(RadixSorter *rs, unsigned debugLevel)
32 32 { {
33 rs->_debug=debugLevel;
33 rs->_debug=debugLevel;
34 34 } }
35 35
36 36 RadixItem **radixsort_get_slot(RadixSorter *rs, unsigned topIndex) RadixItem **radixsort_get_slot(RadixSorter *rs, unsigned topIndex)
37 37 { {
38 RadixItem **slot=malloc(RADIX_SLOT_SIZE * sizeof(RadixItem *));
39 memset(slot, 0, RADIX_SLOT_SIZE * sizeof(RadixItem *));
38 RadixItem **slot=malloc(RADIX_SLOT_SIZE * sizeof(RadixItem *));
39 memset(slot, 0, RADIX_SLOT_SIZE * sizeof(RadixItem *));
40 40
41 RadixSlot *descriptor=malloc(sizeof(RadixSlot));
42 descriptor->min=rs->keyLimit;
43 descriptor->max=0;
44 descriptor->size=0;
41 RadixSlot *descriptor=malloc(sizeof(RadixSlot));
42 descriptor->min=rs->keyLimit;
43 descriptor->max=0;
44 descriptor->size=0;
45 45
46 rs->_slotDescriptors[topIndex]=descriptor;
47 rs->_slotsCount++;
48 return slot;
46 rs->_slotDescriptors[topIndex]=descriptor;
47 rs->_slotsCount++;
48 return slot;
49 49 } }
50 50
51 51 void radixsort_add(RadixSorter *rs, RadixItem *item) void radixsort_add(RadixSorter *rs, RadixItem *item)
52 52 { {
53 if(item->key > rs->keyLimit) {
54 if(rs->_debug > RADIX_DEBUG_LEVEL_NONE) {
55 fprintf(stderr, "WARNING: Radix sort overflow - inserted key is bigger than limit (%u): %u\n", rs->keyLimit, item->key);
56 }
57 if(rs->optFloorAndInsertBigKeys) {
58 item->key = rs->keyLimit-1;
59 } else {
60 if(rs->optIgnoreBigKeys) {
61 return;
62 } else {
63 exit(0);
64 }
65 }
66 }
67
68 unsigned topIndex = GET_TOP_INDEX(item->key);
69 unsigned lowIndex = GET_LOW_INDEX(item->key);
70
71 if(!rs->topDigits[topIndex]) {
72 rs->topDigits[topIndex]=radixsort_get_slot(rs, topIndex);
73 }
74
75 RadixItem *chain=rs->topDigits[topIndex][lowIndex];
76 rs->topDigits[topIndex][lowIndex]=item;
77 if(chain==NULL) {
78 item->next=NULL;
79 } else {
80 item->next=chain;
81 }
82
83 rs->size++;
84 rs->maxKey=MAX(rs->maxKey,item->key);
85 rs->_slotDescriptors[topIndex]->min=MIN(rs->_slotDescriptors[topIndex]->min,item->key);
86 rs->_slotDescriptors[topIndex]->max=MAX(rs->_slotDescriptors[topIndex]->max,item->key);
87 rs->_slotDescriptors[topIndex]->size++;
53 if(item->key > rs->keyLimit) {
54 if(rs->_debug > RADIX_DEBUG_LEVEL_NONE) {
55 fprintf(stderr, "WARNING: Radix sort overflow - inserted key is bigger than limit (%u): %u\n", rs->keyLimit, item->key);
56 }
57 if(rs->optFloorAndInsertBigKeys) {
58 item->key = rs->keyLimit-1;
59 } else {
60 if(rs->optIgnoreBigKeys) {
61 return;
62 } else {
63 exit(0);
64 }
65 }
66 }
67
68 unsigned topIndex = GET_TOP_INDEX(item->key);
69 unsigned lowIndex = GET_LOW_INDEX(item->key);
70
71 if(!rs->topDigits[topIndex]) {
72 rs->topDigits[topIndex]=radixsort_get_slot(rs, topIndex);
73 }
74
75 RadixItem *chain=rs->topDigits[topIndex][lowIndex];
76 rs->topDigits[topIndex][lowIndex]=item;
77 if(chain==NULL) {
78 item->next=NULL;
79 } else {
80 item->next=chain;
81 }
82
83 rs->size++;
84 rs->maxKey=MAX(rs->maxKey,item->key);
85 rs->_slotDescriptors[topIndex]->min=MIN(rs->_slotDescriptors[topIndex]->min,item->key);
86 rs->_slotDescriptors[topIndex]->max=MAX(rs->_slotDescriptors[topIndex]->max,item->key);
87 rs->_slotDescriptors[topIndex]->size++;
88 88 } }
89 89
90 90 void radix_dec_slot_descriptor_size(RadixSorter *rs, RadixSlot *descriptor, unsigned key, unsigned topIndex) void radix_dec_slot_descriptor_size(RadixSorter *rs, RadixSlot *descriptor, unsigned key, unsigned topIndex)
91 91 { {
92 descriptor->size--;
93 if(!descriptor->size) {
94 descriptor->min=rs->keyLimit;
95 descriptor->max=0;
96 } else {
97 if(descriptor->size==1) {
98 if(rs->topDigits[topIndex][GET_LOW_INDEX(descriptor->max)]) {
99 descriptor->min=descriptor->max;
100 } else {
101 if(rs->topDigits[topIndex][GET_LOW_INDEX(descriptor->min)]) {
102 descriptor->max=descriptor->min;
103 }
104 }
105 }
106 }
92 descriptor->size--;
93 if(!descriptor->size) {
94 descriptor->min=rs->keyLimit;
95 descriptor->max=0;
96 } else {
97 if(descriptor->size==1) {
98 if(rs->topDigits[topIndex][GET_LOW_INDEX(descriptor->max)]) {
99 descriptor->min=descriptor->max;
100 } else {
101 if(rs->topDigits[topIndex][GET_LOW_INDEX(descriptor->min)]) {
102 descriptor->max=descriptor->min;
103 }
104 }
105 }
106 }
107 107 } }
108 108
109 109 RadixItem *radix_cut(RadixSorter *rs, unsigned key, void *data) RadixItem *radix_cut(RadixSorter *rs, unsigned key, void *data)
110 110 { {
111 // TODO optimization: fix min/max on cut of a value
112 if(key <= rs->maxKey) {
113 unsigned topIndex = GET_TOP_INDEX(key);
114 unsigned lowIndex = GET_LOW_INDEX(key);
115
116 if(rs->topDigits[topIndex]) {
117 RadixItem *ri=rs->topDigits[topIndex][lowIndex];
118 RadixItem *lastRi=NULL;
119 while(ri->data!=data) {
120 if(ri->next) {
121 lastRi=ri;
122 ri=ri->next;
123 } else {
124 break;
125 }
126 }
127 if(ri->data==data) {
128 if(lastRi) {
129 lastRi->next=ri->next;
130 } else {
131 rs->topDigits[topIndex][lowIndex]=ri->next;
132 }
133 ri->next=NULL;
134 rs->size--;
135 radix_dec_slot_descriptor_size(rs, rs->_slotDescriptors[topIndex], key, topIndex);
136 return ri;
137 }
138 }
139 }
140 return NULL;
111 // TODO optimization: fix min/max on cut of a value
112 if(key <= rs->maxKey) {
113 unsigned topIndex = GET_TOP_INDEX(key);
114 unsigned lowIndex = GET_LOW_INDEX(key);
115
116 if(rs->topDigits[topIndex]) {
117 RadixItem *ri=rs->topDigits[topIndex][lowIndex];
118 RadixItem *lastRi=NULL;
119 while(ri->data!=data) {
120 if(ri->next) {
121 lastRi=ri;
122 ri=ri->next;
123 } else {
124 break;
125 }
126 }
127 if(ri->data==data) {
128 if(lastRi) {
129 lastRi->next=ri->next;
130 } else {
131 rs->topDigits[topIndex][lowIndex]=ri->next;
132 }
133 ri->next=NULL;
134 rs->size--;
135 radix_dec_slot_descriptor_size(rs, rs->_slotDescriptors[topIndex], key, topIndex);
136 return ri;
137 }
138 }
139 }
140 return NULL;
141 141 } }
142 142
143 143 RadixItem **radixsort_dump(RadixSorter *rs) RadixItem **radixsort_dump(RadixSorter *rs)
144 144 { {
145 if(rs->size>0) {
146 RadixItem **result=malloc(rs->size * sizeof(RadixItem *));
147 int t = GET_TOP_INDEX(rs->maxKey);
148 int slotMin, slotSize, slotCount, l;
149 unsigned items=0;
150 do {
151 if(rs->topDigits[t]) {
152 if(rs->_slotDescriptors[t]->size>0) {
153 l=GET_LOW_INDEX(rs->_slotDescriptors[t]->max);
154 slotMin=GET_LOW_INDEX(rs->_slotDescriptors[t]->min);
155 slotSize=rs->_slotDescriptors[t]->size;
156 slotCount=0;
157 do {
158 if(rs->topDigits[t][l]) {
159 result[items++]=rs->topDigits[t][l];
160 slotCount++;
161 RadixItem *ri=rs->topDigits[t][l]->next;
162 while(ri) {
163 result[items++]=ri;
164 slotCount++;
165 ri=ri->next;
166 }
167 }
168 } while(--l>=slotMin && slotCount<slotSize);
169 }
170 }
171 } while(--t>=0);
172 return result;
173 }
174 return NULL;
145 if(rs->size>0) {
146 RadixItem **result=malloc(rs->size * sizeof(RadixItem *));
147 int t = GET_TOP_INDEX(rs->maxKey);
148 int slotMin, slotSize, slotCount, l;
149 unsigned items=0;
150 do {
151 if(rs->topDigits[t]) {
152 if(rs->_slotDescriptors[t]->size>0) {
153 l=GET_LOW_INDEX(rs->_slotDescriptors[t]->max);
154 slotMin=GET_LOW_INDEX(rs->_slotDescriptors[t]->min);
155 slotSize=rs->_slotDescriptors[t]->size;
156 slotCount=0;
157 do {
158 if(rs->topDigits[t][l]) {
159 result[items++]=rs->topDigits[t][l];
160 slotCount++;
161 RadixItem *ri=rs->topDigits[t][l]->next;
162 while(ri) {
163 result[items++]=ri;
164 slotCount++;
165 ri=ri->next;
166 }
167 }
168 } while(--l>=slotMin && slotCount<slotSize);
169 }
170 }
171 } while(--t>=0);
172 return result;
173 }
174 return NULL;
175 175 } }
176 176
177 177 void radixsort_stat(RadixSorter *rs, bool listing) void radixsort_stat(RadixSorter *rs, bool listing)
178 178 { {
179 printf("\n Radixsort (size/max/limit/slot count): %u %u %u %u", rs->size, rs->maxKey, rs->keyLimit, rs->_slotsCount);
180 unsigned memory=rs->_topIndexLimit * sizeof(RadixItem ***);
181 memory+=memory;
182 memory+=rs->_slotsCount*(RADIX_SLOT_SIZE * sizeof(RadixItem *));
183 printf("\n Memory: %u\n", memory);
184 if(listing && rs->size>0) {
185 int t = GET_TOP_INDEX(rs->maxKey);
186 int slotMin, slotSize, slotCount, l;
187 unsigned items=0;
188 do {
189 if(rs->topDigits[t]) {
190 printf("\n Slot %u (size/min/max): %u %u %u",t, rs->_slotDescriptors[t]->size, rs->_slotDescriptors[t]->min, rs->_slotDescriptors[t]->max);
191 if(rs->_slotDescriptors[t]->size>0) {
192 l=GET_LOW_INDEX(rs->_slotDescriptors[t]->max);
193 slotMin=GET_LOW_INDEX(rs->_slotDescriptors[t]->min);
194 slotSize=rs->_slotDescriptors[t]->size;
195 slotCount=0;
196 do {
197 if(rs->topDigits[t][l]) {
198 printf("\n > %d #%u",l, ++items);
199 ++slotCount;
200 RadixItem *ri=rs->topDigits[t][l]->next;
201 while(ri) {
202 printf(" #%u",++items);
203 ++slotCount;
204 ri=ri->next;
205 }
206 }
207 } while(--l>=slotMin && slotCount<slotSize);
208 printf("\n STOP @ %d",l);
209 } else {
210 printf(" > SKIPPED");
211 }
212 }
213 } while(--t>=0);
214 }
215 fflush(stdout);
179 printf("\n Radixsort (size/max/limit/slot count): %u %u %u %u", rs->size, rs->maxKey, rs->keyLimit, rs->_slotsCount);
180 unsigned memory=rs->_topIndexLimit * sizeof(RadixItem ***);
181 memory+=memory;
182 memory+=rs->_slotsCount*(RADIX_SLOT_SIZE * sizeof(RadixItem *));
183 printf("\n Memory: %u\n", memory);
184 if(listing && rs->size>0) {
185 int t = GET_TOP_INDEX(rs->maxKey);
186 int slotMin, slotSize, slotCount, l;
187 unsigned items=0;
188 do {
189 if(rs->topDigits[t]) {
190 printf("\n Slot %u (size/min/max): %u %u %u",t, rs->_slotDescriptors[t]->size, rs->_slotDescriptors[t]->min, rs->_slotDescriptors[t]->max);
191 if(rs->_slotDescriptors[t]->size>0) {
192 l=GET_LOW_INDEX(rs->_slotDescriptors[t]->max);
193 slotMin=GET_LOW_INDEX(rs->_slotDescriptors[t]->min);
194 slotSize=rs->_slotDescriptors[t]->size;
195 slotCount=0;
196 do {
197 if(rs->topDigits[t][l]) {
198 printf("\n > %d #%u",l, ++items);
199 ++slotCount;
200 RadixItem *ri=rs->topDigits[t][l]->next;
201 while(ri) {
202 printf(" #%u",++items);
203 ++slotCount;
204 ri=ri->next;
205 }
206 }
207 } while(--l>=slotMin && slotCount<slotSize);
208 printf("\n STOP @ %d",l);
209 } else {
210 printf(" > SKIPPED");
211 }
212 }
213 } while(--t>=0);
214 }
215 fflush(stdout);
216 216 } }
217 217
218 218 void radixsort_destroy(RadixSorter *rs) void radixsort_destroy(RadixSorter *rs)
219 219 { {
220 // radix items: DONE (passed on dump() by reference)
221 // rs: DONE (created and destroyed by caller)
222 // slots:
223 int topIndex = GET_TOP_INDEX(rs->maxKey);
224 do {
225 if(rs->topDigits[topIndex]) {
226 free(rs->topDigits[topIndex]);
227 free(rs->_slotDescriptors[topIndex]);
228 }
229 } while(--topIndex>=0);
220 // radix items: DONE (passed on dump() by reference)
221 // rs: DONE (created and destroyed by caller)
222 // slots:
223 int topIndex = GET_TOP_INDEX(rs->maxKey);
224 do {
225 if(rs->topDigits[topIndex]) {
226 free(rs->topDigits[topIndex]);
227 free(rs->_slotDescriptors[topIndex]);
228 }
229 } while(--topIndex>=0);
230 230 } }
File tests/src/test_args.c changed (mode: 100644) (index 6989620..eb422d6)
14 14
15 15 int main(int argc, char *argv[]) int main(int argc, char *argv[])
16 16 { {
17 printf("%d",strchr("a\nb",10));
17 printf("%d",strchr("a\nb",10));
18 18
19 if(argc>0) {
20 int i;
21 char line[LINELNG];
22 line[0]=0;
23 for(i=0; i<argc; i++) {
24 if((strlen(line)+strlen(argv[i])*2)>LINELNG) break;
25 printf("%d %s\n", i, argv[i]);
26 if(strstr(argv[i], " ")) {
27 strcat(line, "\"");
28 }
29 strcat(line, argv[i]);
30 if(strstr(argv[i], " ")) {
31 strcat(line, "\"");
32 }
33 strcat(line, " ");
34 }
19 if(argc>0) {
20 int i;
21 char line[LINELNG];
22 line[0]=0;
23 for(i=0; i<argc; i++) {
24 if((strlen(line)+strlen(argv[i])*2)>LINELNG) break;
25 printf("%d %s\n", i, argv[i]);
26 if(strstr(argv[i], " ")) {
27 strcat(line, "\"");
28 }
29 strcat(line, argv[i]);
30 if(strstr(argv[i], " ")) {
31 strcat(line, "\"");
32 }
33 strcat(line, " ");
34 }
35 35
36 printf("#%s#", line);
37 }
36 printf("#%s#", line);
37 }
38 38 } }
File tests/src/test_curses_keyb.c changed (mode: 100644) (index 39d126a..ca81aab)
12 12
13 13 int main(int argc, char *argv[]) int main(int argc, char *argv[])
14 14 { {
15 initscr();
16 noecho();
17 keypad(stdscr, TRUE);
18
19 int c;
20 while(TRUE) {
21 c = getch();
22
23 mvprintw(1, 0, "Key number: '%3d' / Char: '%c'", c, c);
24
25 switch(c) {
26 // ctrl-r, ctrl-h, ctrl-i
27 case KEY_BACKSPACE:
28 case KEY_LEFT:
29 case KEY_RIGHT:
30 case KEY_UP:
31 case KEY_DOWN:
32 mvprintw(5, 0, "CATCHED! %3d",c);
33 break;
34
35 case KEY_STAB:
36 case KEY_BTAB:
37 case KEY_CTAB:
38 mvprintw(5, 0, "TAB! %3d",c);
39 break;
40
41 case KEY_RESIZE:
42 mvprintw(5, 0, "RESIZE! %3d",c);
43 break;
44
45 case KEY_ENTER:
46 endwin();
47 exit(0);
48 default:
49 break;
50 }
51 }
52
53 endwin();
15 initscr();
16 noecho();
17 keypad(stdscr, TRUE);
18
19 int c;
20 while(TRUE) {
21 c = getch();
22
23 mvprintw(1, 0, "Key number: '%3d' / Char: '%c'", c, c);
24
25 switch(c) {
26 // ctrl-r, ctrl-h, ctrl-i
27 case KEY_BACKSPACE:
28 case KEY_LEFT:
29 case KEY_RIGHT:
30 case KEY_UP:
31 case KEY_DOWN:
32 mvprintw(5, 0, "CATCHED! %3d",c);
33 break;
34
35 case KEY_STAB:
36 case KEY_BTAB:
37 case KEY_CTAB:
38 mvprintw(5, 0, "TAB! %3d",c);
39 break;
40
41 case KEY_RESIZE:
42 mvprintw(5, 0, "RESIZE! %3d",c);
43 break;
44
45 case KEY_ENTER:
46 endwin();
47 exit(0);
48 default:
49 break;
50 }
51 }
52
53 endwin();
54 54 } }
File tests/src/test_escape_chars.c changed (mode: 100644) (index e8bdee5..4508348)
8 8 */ */
9 9
10 10 void generate_bash_history_with_special_chars() { void generate_bash_history_with_special_chars() {
11 /*
12 // crash
13 %s
11 /*
12 // crash
13 %s
14 14
15 // substituation > should not happen:
16 date -d yesterday +%A
15 // substituation > should not happen:
16 date -d yesterday +%A
17 17 date -d yesterday +0X1.4C41E000008P-895 date -d yesterday +0X1.4C41E000008P-895
18 18
19 19 // crash // crash
20 20 mocp -Q "<%state> '%file'\n" mocp -Q "<%state> '%file'\n"
21 */
21 */
22 22 } }
23 23
24 24 void main() { void main() {
25 generate_bash_history_with_special_chars();
25 generate_bash_history_with_special_chars();
26 26 } }
27 27
File tests/src/test_favorites.c changed (mode: 100644) (index 5665703..e67433a)
11 11
12 12 int main(int argc, char *argv[]) int main(int argc, char *argv[])
13 13 { {
14 FavoriteItems favoriteItems;
14 FavoriteItems favoriteItems;
15 15
16 favorites_init(&favoriteItems);
17 favorites_get(&favoriteItems);
18 favorites_remove(&favoriteItems, "c");
16 favorites_init(&favoriteItems);
17 favorites_get(&favoriteItems);
18 favorites_remove(&favoriteItems, "c");
19 19
20 favorites_choose(&favoriteItems, "ccc");
20 favorites_choose(&favoriteItems, "ccc");
21 21 } }
File tests/src/test_getopt.c changed (mode: 100644) (index 4b4a32e..c421017)
13 13
14 14 int main(int argc, char **argv) int main(int argc, char **argv)
15 15 { {
16 int c;
17 int digit_optind = 0;
18
19 while (1) {
20 int this_option_optind = optind ? optind : 1;
21 int option_index = 0;
22 static struct option long_options[] = {
23 {"add", required_argument, 0, 0 },
24 {"append", no_argument, 0, 0 },
25 {"delete", required_argument, 0, 0 },
26 {"verbose", no_argument, 0, 0 },
27 {"create", required_argument, 0, 'c'},
28 {"file", required_argument, 0, 0 },
29 {0, 0, 0, 0 }
30 };
31
32 c = getopt_long(argc, argv, "abc:d:012", long_options, &option_index);
33 if (c == -1)
34 break;
35
36
37 switch (c) {
38 case 0:
39 printf("option %s", long_options[option_index].name);
40 if (optarg)
41 printf(" with arg %s", optarg);
42 printf("\n");
43 break;
44
45 case '0':
46 case '1':
47 case '2':
48 if (digit_optind != 0 && digit_optind != this_option_optind)
49 printf("digits occur in two different argv-elements.\n");
50 digit_optind = this_option_optind;
51 printf("option %c\n", c);
52 break;
53
54 case 'a':
55 printf("option a\n");
56 break;
57
58 case 'b':
59 printf("option b\n");
60 break;
61
62 case 'c':
63 printf("option c with value '%s'\n", optarg);
64 break;
65
66 case 'd':
67 printf("option d with value '%s'\n", optarg);
68 break;
69
70 case '?':
71
72 break;
73
74 default:
75 printf("?? getopt returned character code 0%o ??\n", c);
76 }
77 }
78
79 if (optind < argc) {
80 printf("non-option ARGV-elements: ");
81 while (optind < argc)
82 printf("%s ", argv[optind++]);
83 printf("\n");
84 }
85
86 exit(EXIT_SUCCESS);
16 int c;
17 int digit_optind = 0;
18
19 while (1) {
20 int this_option_optind = optind ? optind : 1;
21 int option_index = 0;
22 static struct option long_options[] = {
23 {"add", required_argument, 0, 0 },
24 {"append", no_argument, 0, 0 },
25 {"delete", required_argument, 0, 0 },
26 {"verbose", no_argument, 0, 0 },
27 {"create", required_argument, 0, 'c'},
28 {"file", required_argument, 0, 0 },
29 {0, 0, 0, 0 }
30 };
31
32 c = getopt_long(argc, argv, "abc:d:012", long_options, &option_index);
33 if (c == -1)
34 break;
35
36
37 switch (c) {
38 case 0:
39 printf("option %s", long_options[option_index].name);
40 if (optarg)
41 printf(" with arg %s", optarg);
42 printf("\n");
43 break;
44
45 case '0':
46 case '1':
47 case '2':
48 if (digit_optind != 0 && digit_optind != this_option_optind)
49 printf("digits occur in two different argv-elements.\n");
50 digit_optind = this_option_optind;
51 printf("option %c\n", c);
52 break;
53
54 case 'a':
55 printf("option a\n");
56 break;
57
58 case 'b':
59 printf("option b\n");
60 break;
61
62 case 'c':
63 printf("option c with value '%s'\n", optarg);
64 break;
65
66 case 'd':
67 printf("option d with value '%s'\n", optarg);
68 break;
69
70 case '?':
71
72 break;
73
74 default:
75 printf("?? getopt returned character code 0%o ??\n", c);
76 }
77 }
78
79 if (optind < argc) {
80 printf("non-option ARGV-elements: ");
81 while (optind < argc)
82 printf("%s ", argv[optind++]);
83 printf("\n");
84 }
85
86 exit(EXIT_SUCCESS);
87 87 } }
File tests/src/test_hashset.c changed (mode: 100644) (index ec42edd..7291acc)
11 11 #include "../../src/include/hstr_utils.h" #include "../../src/include/hstr_utils.h"
12 12
13 13 void testBlacklist() { void testBlacklist() {
14 const char* commandBlacklist[] = { "a","b","c","d","e" };
15 HashSet blacklist;
16 int i;
17 hashset_init(&blacklist);
18 for (i = 0; i < 5; i++) {
19 hashset_add(&blacklist, commandBlacklist[i]);
20 }
21 for (i = 0; i < 5; i++) {
22 printf("match %d\n", hashset_contains(&blacklist, hstr_strdup(commandBlacklist[i])));
23 }
14 const char* commandBlacklist[] = { "a","b","c","d","e" };
15 HashSet blacklist;
16 int i;
17 hashset_init(&blacklist);
18 for (i = 0; i < 5; i++) {
19 hashset_add(&blacklist, commandBlacklist[i]);
20 }
21 for (i = 0; i < 5; i++) {
22 printf("match %d\n", hashset_contains(&blacklist, hstr_strdup(commandBlacklist[i])));
23 }
24 24 } }
25 25
26 26 void testGetKeys() { void testGetKeys() {
27 const char* commandBlacklist[] = { "a","b","c","d","e" };
28 HashSet blacklist;
29 int i;
30 hashset_init(&blacklist);
31 for (i = 0; i < 5; i++) {
32 hashset_add(&blacklist, commandBlacklist[i]);
33 }
27 const char* commandBlacklist[] = { "a","b","c","d","e" };
28 HashSet blacklist;
29 int i;
30 hashset_init(&blacklist);
31 for (i = 0; i < 5; i++) {
32 hashset_add(&blacklist, commandBlacklist[i]);
33 }
34 34
35 char **keys=hashset_keys(&blacklist);
36 if(keys) {
37 for(i=0; i<hashset_size(&blacklist); i++) {
38 printf("\nKey: %s", keys[i]);
39 }
40 }
35 char **keys=hashset_keys(&blacklist);
36 if(keys) {
37 for(i=0; i<hashset_size(&blacklist); i++) {
38 printf("\nKey: %s", keys[i]);
39 }
40 }
41 41 } }
42 42
43 43 int main(int argc, char *argv[]) int main(int argc, char *argv[])
44 44 { {
45 testGetKeys();
45 testGetKeys();
46 46 } }
File tests/src/test_keyb.c changed (mode: 100644) (index 1e309cd..0a6c24d)
16 16
17 17 void echo_printable_characters() void echo_printable_characters()
18 18 { {
19 int c;
20 for(c=0; c<255; c++) {
21 printf("Key number: '%3d' / Char: '%c' Meta: \n", c, c, c&meta_character_bit);
22 }
19 int c;
20 for(c=0; c<255; c++) {
21 printf("Key number: '%3d' / Char: '%c' Meta: \n", c, c, c&meta_character_bit);
22 }
23 23 } }
24 24
25 25 void echo_keyb_characters() void echo_keyb_characters()
26 26 { {
27 int c;
28 while(1) {
29 c = getc(stdin);
30 printf("Key number: '%3d' / Char: '%c' Meta: %d Ctrl: %d Ctrl mask: %d\n", c, c, META_CHAR(c), CTRL_CHAR(c), c&control_character_mask);
31 }
27 int c;
28 while(1) {
29 c = getc(stdin);
30 printf("Key number: '%3d' / Char: '%c' Meta: %d Ctrl: %d Ctrl mask: %d\n", c, c, META_CHAR(c), CTRL_CHAR(c), c&control_character_mask);
31 }
32 32 } }
33 33
34 34 int main(int argc, char *argv[]) int main(int argc, char *argv[])
35 35 { {
36 echo_keyb_characters();
36 echo_keyb_characters();
37 37 } }
File tests/src/test_ranking.c changed (mode: 100644) (index 7c5090d..ab1bca7)
11 11 #include <math.h> #include <math.h>
12 12
13 13 void testLog() { void testLog() {
14 const int HISTORY_SIZE=2000;
15 int i;
16 for(i=0; i<HISTORY_SIZE; i++) {
17 printf("\n%d # l: %f # l10: %f # l2: %f", i, log(i), log10(i), log2(i));
18 }
14 const int HISTORY_SIZE=2000;
15 int i;
16 for(i=0; i<HISTORY_SIZE; i++) {
17 printf("\n%d # l: %f # l10: %f # l2: %f", i, log(i), log10(i), log2(i));
18 }
19 19 } }
20 20
21 21 #define MAX_CHARACTER_CODE 10000 #define MAX_CHARACTER_CODE 10000
 
... ... static char line[MAX_CHARACTER_CODE];
23 23
24 24 void testGenerateHugeHistoryFileWithDifferentLines() void testGenerateHugeHistoryFileWithDifferentLines()
25 25 { {
26 FILE *file = fopen(".bash_history_huge","a");
27 fseek(file,0, SEEK_END);
26 FILE *file = fopen(".bash_history_huge","a");
27 fseek(file,0, SEEK_END);
28 28
29 line[0]=0;
30 int i;
31 for(i=0; i<MAX_CHARACTER_CODE; i++) {
32 sprintf(line,"%s%c",line,i);
33 fprintf(file,"%s\n",line);
34 }
35 fclose(file);
29 line[0]=0;
30 int i;
31 for(i=0; i<MAX_CHARACTER_CODE; i++) {
32 sprintf(line,"%s%c",line,i);
33 fprintf(file,"%s\n",line);
34 }
35 fclose(file);
36 36 } }
37 37
38 38
39 39 void testGenerateHugeHistoryFileWithSameLines() void testGenerateHugeHistoryFileWithSameLines()
40 40 { {
41 FILE *file = fopen(".bash_history_same","a");
42 fseek(file,0, SEEK_END);
41 FILE *file = fopen(".bash_history_same","a");
42 fseek(file,0, SEEK_END);
43 43
44 int i;
45 for(i=0; i<100000; i++) {
46 fprintf(file,"find . | while read X; do echo $X; cat $X | grep -i ctrl; done | less\n",line);
47 fprintf(file,
48 "git commit -a -m \"Code review and stabilization.\" && git push origin master#"
49 "git commit -a -m \"Code review and stabilization.\" && git push origin master#"
50 "git commit -a -m \"Code review and stabilization.\" && git push origin master#"
51 "git commit -a -m \"Code review and stabilization.\" && git push origin master#"
52 "git commit -a -m \"Code review and stabilization.\" && git push origin master#"
53 "git commit -a -m \"Code review and stabilization.\" && git push origin master#"
54 "git commit -a -m \"Code review and stabilization.\" && git push origin master\n",
55 line);
56 }
57 fclose(file);
44 int i;
45 for(i=0; i<100000; i++) {
46 fprintf(file,"find . | while read X; do echo $X; cat $X | grep -i ctrl; done | less\n",line);
47 fprintf(file,
48 "git commit -a -m \"Code review and stabilization.\" && git push origin master#"
49 "git commit -a -m \"Code review and stabilization.\" && git push origin master#"
50 "git commit -a -m \"Code review and stabilization.\" && git push origin master#"
51 "git commit -a -m \"Code review and stabilization.\" && git push origin master#"
52 "git commit -a -m \"Code review and stabilization.\" && git push origin master#"
53 "git commit -a -m \"Code review and stabilization.\" && git push origin master#"
54 "git commit -a -m \"Code review and stabilization.\" && git push origin master\n",
55 line);
56 }
57 fclose(file);
58 58 } }
59 59
60 60
61 61 int main(int argc, char *argv[]) int main(int argc, char *argv[])
62 62 { {
63 testGenerateHugeHistoryFileWithSameLines();
63 testGenerateHugeHistoryFileWithSameLines();
64 64 } }
65 65
File tests/src/test_regexp.c changed (mode: 100644) (index 06982df..85d4300)
14 14 #define REGEXP_MATCH_BUFFER_SIZE 10 #define REGEXP_MATCH_BUFFER_SIZE 10
15 15
16 16 void main() { void main() {
17 bool caseSensitive=false;
18
19 char *regexp="^b";
20 char *text="This is a command that I want to match: go.sh there";
21
22 regex_t compiled;
23 int compilationFlags=(caseSensitive?0:REG_ICASE);
24 printf("Regular expressions matching:\n '%s'\n '%s'",text,regexp);
25 int compilationStatus=regcomp(&compiled, regexp, compilationFlags);
26 printf("\nCompilation: %d",compilationStatus);
27
28 int matches=REGEXP_MATCH_BUFFER_SIZE;
29 regmatch_t matchPtr[REGEXP_MATCH_BUFFER_SIZE];
30 int matchingFlags=0;
31 int matchingStatus=regexec(&compiled, text, matches, matchPtr, matchingFlags);
32 printf("\nMatching (status/matches): %s %d",(!matchingStatus?"match":"no-match"),matches);
33
34 if(!matchingStatus) {
35 int i;
36 for(i=0; i<REGEXP_MATCH_BUFFER_SIZE; i++) {
37 printf("\n %d %d",matchPtr[i].rm_so, matchPtr[i].rm_eo);
38 if(matchPtr[i].rm_so != -1) {
39 printf("\n* %d %d",matchPtr[i].rm_so,matchPtr[i].rm_eo);
40 }
41 }
42 } else {
43 regerror(matchingStatus);
44 }
45
46 printf("\n");
17 bool caseSensitive=false;
18
19 char *regexp="^b";
20 char *text="This is a command that I want to match: go.sh there";
21
22 regex_t compiled;
23 int compilationFlags=(caseSensitive?0:REG_ICASE);
24 printf("Regular expressions matching:\n '%s'\n '%s'",text,regexp);
25 int compilationStatus=regcomp(&compiled, regexp, compilationFlags);
26 printf("\nCompilation: %d",compilationStatus);
27
28 int matches=REGEXP_MATCH_BUFFER_SIZE;
29 regmatch_t matchPtr[REGEXP_MATCH_BUFFER_SIZE];
30 int matchingFlags=0;
31 int matchingStatus=regexec(&compiled, text, matches, matchPtr, matchingFlags);
32 printf("\nMatching (status/matches): %s %d",(!matchingStatus?"match":"no-match"),matches);
33
34 if(!matchingStatus) {
35 int i;
36 for(i=0; i<REGEXP_MATCH_BUFFER_SIZE; i++) {
37 printf("\n %d %d",matchPtr[i].rm_so, matchPtr[i].rm_eo);
38 if(matchPtr[i].rm_so != -1) {
39 printf("\n* %d %d",matchPtr[i].rm_so,matchPtr[i].rm_eo);
40 }
41 }
42 } else {
43 regerror(matchingStatus);
44 }
45
46 printf("\n");
47 47 } }
File tests/src/test_utf8.c changed (mode: 100644) (index 98ba726..b619a1c)
... ... void console_echo_czech()
45 45 } }
46 46
47 47 void loop_string() { void loop_string() {
48 // char *s="a";
49 char *s="Ča";
50 // char *s="Čeština";
51 int i;
52 for(i=0; i<10; i++) {
53 printf("\n%d",s[i]);
54 show_bits(s[i]);
55 if(!s[i]) break;
56 }
48 // char *s="a";
49 char *s="Ča";
50 // char *s="Čeština";
51 int i;
52 for(i=0; i<10; i++) {
53 printf("\n%d",s[i]);
54 show_bits(s[i]);
55 if(!s[i]) break;
56 }
57 57 } }
58 58
59 59 void get_string_length() { void get_string_length() {
60 char *s="Čeština";
61 wchar_t *w=L"Čeština";
62
63 printf("%s (7): strlen(): %zd, mbstowcs(): %zd, wcslen(): %zd",
64 s,
65 strlen(s),
66 mbstowcs(NULL,s,0),
67 wcslen(w)); // OK
60 char *s="Čeština";
61 wchar_t *w=L"Čeština";
62
63 printf("%s (7): strlen(): %zd, mbstowcs(): %zd, wcslen(): %zd",
64 s,
65 strlen(s),
66 mbstowcs(NULL,s,0),
67 wcslen(w)); // OK
68 68 } }
69 69
70 70 void console_static_wide_czech() void console_static_wide_czech()
 
... ... void console_static_wide_czech()
74 74 wchar_t *w=L"Čeština."; // wide wchar_t *w=L"Čeština."; // wide
75 75 char multibyte[100]; // multi-byte char multibyte[100]; // multi-byte
76 76 if(iswprint(*w)) { if(iswprint(*w)) {
77 printf("\nString to be printed is UTF8 wide!");
78 int offset=wctomb(multibyte, w);
79 printf("\nStatic (wide) printf: %s", multibyte);
77 printf("\nString to be printed is UTF8 wide!");
78 int offset=wctomb(multibyte, w);
79 printf("\nStatic (wide) printf: %s", multibyte);
80 80 } else { } else {
81 printf("\nString to be printed is NOT UTF8 wide!");
82 wprintf(L"\nStatic wprintf: %ls", w);
81 printf("\nString to be printed is NOT UTF8 wide!");
82 wprintf(L"\nStatic wprintf: %ls", w);
83 83 } }
84 84 } }
85 85
 
... ... void curses_wide_czech()
112 112 } }
113 113
114 114 void print_char_bits(int y, int x, char c) { void print_char_bits(int y, int x, char c) {
115 int i;
115 int i;
116 116 static int intSizeInBits = sizeof(char) * 8; static int intSizeInBits = sizeof(char) * 8;
117 117 static char symbol[2] = {'0','1'}; static char symbol[2] = {'0','1'};
118 118 char * binary = (char *)malloc(intSizeInBits + 1); char * binary = (char *)malloc(intSizeInBits + 1);
 
... ... void print_char_bits(int y, int x, char c) {
126 126 } }
127 127
128 128 void getch_with_counter_curses() { void getch_with_counter_curses() {
129 // TODO implement getch with counter; getch result analysis (trip); append analysis; ...
130
131 initscr();
132 keypad(stdscr, TRUE);
133 noecho();
134 start_color();
135 use_default_colors();
136
137 char pattern[512];
138 int c;
139
140 pattern[0]=0;
141 while (1) {
142 c = wgetch(stdscr);
143 strcat(pattern, (char*)(&c));
144 mvprintw(2, 0, "Pattern '%s'", pattern);
145 mvprintw(3, 0, "Char '%d'", c);
146
147 mvprintw(6, 0, "strlen() '%d'", strlen(pattern));
148 mvprintw(7, 0, "mbstowcs() '%d'", mbstowcs(NULL,pattern,0));
149
150 int i;
151 int intSizeInBits = sizeof(int) * 8;
152 char symbol[2] = {'0','1'};
153 char * binary = (char *)malloc(intSizeInBits + 1);
154 memset(binary, 0, intSizeInBits + 1);
155 for (i=0; i< intSizeInBits; i++) {
156 binary[intSizeInBits-i-1] = symbol[(c>>i) & 0x01];
157 }
158 mvprintw(10, 0, "bits: %s", binary);
159 free(binary);
160
161 mvprintw(11, 0, "high bit: %d %d ", 1<<7, 1<<7 & c);
162
163 char cc=pattern[0];
164 i=0;
165 int myStrlen=0;
166 char isHighBitSet=0;
167 while(cc) {
168 print_char_bits(12, 9*i-8, pattern[i++]);
169 cc=pattern[i];
170
171 if(1<<7 & pattern[i]) {
172 if(isHighBitSet) {
173 isHighBitSet=0;
174 myStrlen++;
175 } else {
176 isHighBitSet=1;
177 }
178 } else {
179 myStrlen++;
180 }
181 }
182
183 mvprintw(14, 0, "mystrlen(): %d ", myStrlen);
184 }
129 // TODO implement getch with counter; getch result analysis (trip); append analysis; ...
130
131 initscr();
132 keypad(stdscr, TRUE);
133 noecho();
134 start_color();
135 use_default_colors();
136
137 char pattern[512];
138 int c;
139
140 pattern[0]=0;
141 while (1) {
142 c = wgetch(stdscr);
143 strcat(pattern, (char*)(&c));
144 mvprintw(2, 0, "Pattern '%s'", pattern);
145 mvprintw(3, 0, "Char '%d'", c);
146
147 mvprintw(6, 0, "strlen() '%d'", strlen(pattern));
148 mvprintw(7, 0, "mbstowcs() '%d'", mbstowcs(NULL,pattern,0));
149
150 int i;
151 int intSizeInBits = sizeof(int) * 8;
152 char symbol[2] = {'0','1'};
153 char * binary = (char *)malloc(intSizeInBits + 1);
154 memset(binary, 0, intSizeInBits + 1);
155 for (i=0; i< intSizeInBits; i++) {
156 binary[intSizeInBits-i-1] = symbol[(c>>i) & 0x01];
157 }
158 mvprintw(10, 0, "bits: %s", binary);
159 free(binary);
160
161 mvprintw(11, 0, "high bit: %d %d ", 1<<7, 1<<7 & c);
162
163 char cc=pattern[0];
164 i=0;
165 int myStrlen=0;
166 char isHighBitSet=0;
167 while(cc) {
168 print_char_bits(12, 9*i-8, pattern[i++]);
169 cc=pattern[i];
170
171 if(1<<7 & pattern[i]) {
172 if(isHighBitSet) {
173 isHighBitSet=0;
174 myStrlen++;
175 } else {
176 isHighBitSet=1;
177 }
178 } else {
179 myStrlen++;
180 }
181 }
182
183 mvprintw(14, 0, "mystrlen(): %d ", myStrlen);
184 }
185 185
186 186 clear(); clear();
187 187 refresh(); refresh();
 
... ... void getch_with_counter_curses() {
190 190 } }
191 191
192 192 void done() { void done() {
193 printf("\n\n");
193 printf("\n\n");
194 194 } }
195 195
196 196 int main(int argc, char *argv[]) int main(int argc, char *argv[])
 
... ... int main(int argc, char *argv[])
203 203 //get_string_length(); //get_string_length();
204 204 //loop_string(); //loop_string();
205 205
206 getch_with_counter_curses();
207 done();
206 getch_with_counter_curses();
207 done();
208 208 } }
Hints

Before first commit, do not forget to setup your git environment:
git config --global user.name "your_name_here"
git config --global user.email "your@email_here"

Clone this repository using HTTP(S):
git clone https://code.reversed.top/user/xaizek/hstr

Clone this repository using ssh (do not forget to upload a key first):
git clone ssh://rocketgit@code.reversed.top/user/xaizek/hstr

You are allowed to anonymously push to this repository.
This means that your pushed commits will automatically be transformed into a pull request:
... clone the repository ...
... make some changes and some commits ...
git push origin master