trace_visualization 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (37) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +2 -1
  3. data/Rakefile +11 -1
  4. data/lib/trace_visualization/assert.rb +5 -0
  5. data/lib/trace_visualization/data/lexeme.rb +59 -0
  6. data/lib/trace_visualization/lexeme_overlap_filter.rb +64 -0
  7. data/lib/trace_visualization/mapping.rb +219 -56
  8. data/lib/trace_visualization/preprocessor/Makefile +43 -0
  9. data/lib/trace_visualization/preprocessor/hashmap.c +93 -0
  10. data/lib/trace_visualization/preprocessor/hashmap.h +27 -0
  11. data/lib/trace_visualization/preprocessor/hashmap_test.cpp +90 -0
  12. data/lib/trace_visualization/preprocessor/lexeme.h +11 -0
  13. data/lib/trace_visualization/preprocessor/lexeme_table.c +50 -0
  14. data/lib/trace_visualization/preprocessor/lexeme_table.h +13 -0
  15. data/lib/trace_visualization/preprocessor/lexeme_table_cpp.h +61 -0
  16. data/lib/trace_visualization/preprocessor/parser_functions.c +42 -0
  17. data/lib/trace_visualization/preprocessor/parser_test.cpp +71 -0
  18. data/lib/trace_visualization/preprocessor/preprocessor.l +18 -0
  19. data/lib/trace_visualization/preprocessor/test_main.cpp +39 -0
  20. data/lib/trace_visualization/profile.rb +38 -0
  21. data/lib/trace_visualization/reorder.rb +22 -11
  22. data/lib/trace_visualization/repetitions_psy.rb +1 -1
  23. data/lib/trace_visualization/suffix_array.rb +4 -0
  24. data/lib/trace_visualization/utils.rb +38 -0
  25. data/lib/trace_visualization/version.rb +1 -1
  26. data/lib/trace_visualization/visualization/console_color_print.rb +4 -2
  27. data/lib/trace_visualization.rb +68 -4
  28. data/spec/bwt_spec.rb +29 -7
  29. data/spec/lexeme_overlap_filter_spec.rb +59 -0
  30. data/spec/longest_common_prefix_spec.rb +3 -3
  31. data/spec/mapping_spec.rb +80 -34
  32. data/spec/reorder_spec.rb +25 -7
  33. data/spec/repetitions_psy_spec.rb +5 -5
  34. data/spec/suffix_array_spec.rb +30 -8
  35. data/spec/utils_spec.rb +30 -0
  36. metadata +22 -3
  37. data/LICENSE.txt +0 -22
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: f106c8e07d09c745ae16a15ed0e3b96b932e2424
4
- data.tar.gz: 1c0d4dcd86297c71fe3028c0db5db7a959cd7e38
3
+ metadata.gz: a5779b63579f93699f091c22ada7121df9469fc7
4
+ data.tar.gz: 336cfdc696d598e2247d09b089ec2b426df18e58
5
5
  SHA512:
6
- metadata.gz: 4e15434bcc8cfb6a9546d039ecd5d5b5e2030d5b315eadeec2a8e39e27c832f3362c540bb7e1c9b9d3e9df48400bc9021560cc96353389de45d64041d2bdfc29
7
- data.tar.gz: c322d0e30da40e0dec6d987d3dddef2ba95aa7497a2e3cbaa252197b07bdc7a6721a074888d18d9822579a582cb97cc662b4bdb2fbd6015af9c273ad223ca3e2
6
+ metadata.gz: 583564ac99432f9a0b05e1a51550497ae2f18d30fad51a7443fd8f9e6930567a66cac481a48c9cd594483a35eccdb4eff852a644bc8ce896fe7bffa14c3562fa
7
+ data.tar.gz: 721cf7cdf88fe2ac0380f4eb9517ffda3e6846cba7d317e6c5f1cdfac453c288b40b2b7d674de2039a0a2e88aab0a2b33b89dcde0d379a3b0c674b59fb5bb688
data/Gemfile CHANGED
@@ -1,6 +1,7 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
- ruby "2.0.0"
3
+ ruby '2.0.0'
4
4
 
5
5
  # Specify your gem's dependencies in trace_visualization.gemspec
6
6
  gemspec
7
+
data/Rakefile CHANGED
@@ -1 +1,11 @@
1
- require "bundler/gem_tasks"
1
+ require 'bundler/gem_tasks'
2
+
3
+ desc 'Compile preprocessor'
4
+ task :install do
5
+ system('cd lib/trace_visualization/preprocessor; make install; make clean')
6
+ end
7
+
8
+ desc 'Spec all functionality of gem'
9
+ task :spec_all do
10
+ system('rspec spec/*')
11
+ end
@@ -0,0 +1,5 @@
1
+ module TraceVisualization
2
+ def self.assert_instance_of(object, expected_class)
3
+ raise "Illegal parameter type: expected #{expected_class}, actual #{object.class}. Object: #{object}" if not object.instance_of? expected_class
4
+ end
5
+ end
@@ -0,0 +1,59 @@
1
+ module TraceVisualization
2
+ module Data
3
+ class Lexeme
4
+ attr_accessor :name
5
+ attr_accessor :value
6
+ attr_accessor :int_value
7
+
8
+ # Length of preprocessed string (see LEXEME_REGEXP)
9
+ attr_accessor :lexeme_length
10
+
11
+ attr_accessor :ord
12
+
13
+ def initialize(name, value, int_value = -1)
14
+ @name, @value, @int_value = name, value, int_value
15
+ end
16
+
17
+ def length
18
+ @value.length
19
+ end
20
+
21
+ def <=>(anOther)
22
+ @ord <=> anOther.ord
23
+ end
24
+
25
+ def <(other)
26
+ @ord < other.ord
27
+ end
28
+
29
+ def to_int
30
+ @ord
31
+ end
32
+
33
+ def to_i
34
+ to_int
35
+ end
36
+
37
+ def to_str
38
+ @value
39
+ end
40
+
41
+ def to_s
42
+ to_str
43
+ end
44
+
45
+ def method_missing(name, *args, &blk)
46
+ raise "Missing method #{name}"
47
+ end
48
+ end
49
+
50
+ class LexemePos
51
+ attr_accessor :lexeme
52
+ attr_accessor :pos
53
+
54
+ def initialize(lexeme, pos)
55
+ @lexeme, @pos = lexeme, pos
56
+ end
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,64 @@
1
+ module TraceVisualization
2
+ module LexemeOverlapFilter
3
+
4
+ def self.process(lexeme_poss)
5
+ lexeme_poss.sort! { |a, b| a.pos <=> b.pos }
6
+ left_bound = lexeme_poss.inject(0) do |left_bound, lexeme_pos|
7
+ [lexeme_pos.pos + lexeme_pos.lexeme.length, left_bound].max
8
+ end
9
+
10
+ idx, current, result = 0, [], []
11
+
12
+ for pos in 0 .. left_bound
13
+
14
+ i = 0
15
+ while i < current.size
16
+ lexeme_pos = current[i]
17
+
18
+ if lexeme_pos.pos + lexeme_pos.lexeme.length == pos
19
+ fl_delete_lexeme = false
20
+
21
+ if current.size == 1
22
+ result << lexeme_pos
23
+ fl_delete_lexeme = true
24
+ else
25
+ if is_longest_lexeme(current, lexeme_pos)
26
+ result << lexeme_pos
27
+ current = []
28
+ else
29
+ fl_delete_lexeme = true
30
+ end
31
+ end
32
+
33
+ if fl_delete_lexeme
34
+ current.delete_at(i)
35
+ i -= 1
36
+ end
37
+ end
38
+
39
+ i += 1
40
+ end
41
+
42
+ while idx < lexeme_poss.size && lexeme_poss[idx].pos == pos
43
+ current << lexeme_poss[idx]
44
+ idx += 1
45
+ end
46
+ end
47
+
48
+ result
49
+ end
50
+
51
+ def self.is_longest_lexeme(lexeme_poss, lexeme_pos)
52
+ result = true
53
+
54
+ lexeme_poss.each do |other_lexeme_pos|
55
+ if lexeme_pos != other_lexeme_pos && lexeme_pos.lexeme.length < other_lexeme_pos.lexeme.length
56
+ result = false
57
+ break
58
+ end
59
+ end
60
+
61
+ result
62
+ end
63
+ end
64
+ end
@@ -1,72 +1,241 @@
1
- module TraceVisualization
2
- module Mapping
3
- require 'time'
4
- require 'ipaddr'
1
+ require 'time'
2
+ require 'ipaddr'
3
+
4
+ require 'trace_visualization/reorder'
5
+ require 'trace_visualization/lexeme_overlap_filter'
6
+ require 'trace_visualization/data/lexeme'
5
7
 
6
- require 'trace_visualization/reorder'
8
+ module TraceVisualization
9
+ class Mapping
7
10
 
8
- PATTERNS = {
11
+ attr_accessor :tokens
12
+
13
+ LEXEME_REGEXP = /\{LEXEME;(?<name>[a-zA-Z0-9]+);(?<source>[^;]+);(?<value>[0-9]+)\}/
9
14
 
10
- "id" => [
11
- /(?<value>\[\d{3,}\])/
15
+ DEFAULT_TOKENS = {
16
+ :ID => [
17
+ /(?<lexeme>\[\d{3,}\])/,
18
+ lambda { |source| source[1 ... -1].to_i }
12
19
  ],
13
-
14
- "ip" => [
15
- /(?<value>(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?))/
20
+
21
+ :IP => [
22
+ /(?<lexeme>(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?))/,
23
+ lambda { |source| IPAddr.new(source).to_i }
16
24
  ],
25
+
26
+ :TIME => [
27
+ /(?<lexeme>\[\d{2} [a-zA-Z]{3} \d{4} \d{2}\:\d{2}\:\d{2}\])/,
28
+ lambda { |source| Time.parse(source[1 ... -1]).to_i }
29
+ ]
30
+ }
31
+
32
+ def initialize
33
+ # hash map: lexeme-object by lexeme-string
34
+ @lexeme_table = {}
35
+
36
+ @tokens = {}
37
+ @mapped_str = []
38
+ end
17
39
 
18
- "time" => [
19
- /(?<value>\[\d{2} [a-zA-Z]{3} \d{4} \d{2}\:\d{2}\:\d{2}\])/
20
- ]
40
+ def self.init(&block)
41
+ mapping = Mapping.new
42
+ mapping.instance_eval(&block)
43
+ mapping
44
+ end
21
45
 
22
- }
46
+ # new
47
+ def token(name, pattern, converter_func)
48
+ @tokens[name] = [pattern, converter_func]
49
+ end
23
50
 
24
- class Item
25
- include Comparable
26
-
27
- attr_reader :value # integer value for comparison
28
- attr_reader :src # source value
29
- attr_reader :type # source type
51
+ def default_tokens
52
+ @tokens.merge!(DEFAULT_TOKENS)
53
+ end
54
+
55
+ # new
56
+ def process(&block)
57
+ instance_eval(&block)
58
+ @max_value = TraceVisualization::Reorder.process(@mapped_str)
59
+ end
30
60
 
31
- attr_accessor :ord # re-order value
32
-
33
- def initialize(src, type)
34
- @src = src
35
- @type = type
36
-
37
- case type
38
- when "id"
39
- @value = @src[1 ... -1].to_i
40
- when "ip"
41
- @value = IPAddr.new(src).to_i
42
- when "time"
43
- @value = Time.parse(@src[1 ... -1]).to_i
44
- when "char"
45
- @value = src.getbyte(0)
61
+ # Load data from source file. File is read line by line
62
+ def from_file(path)
63
+ raise ArgumentError, 'Argument must be a string' unless path.instance_of? String
64
+ raise ArgumentError, 'File path is not defined' unless path.empty?
65
+ raise RuntimeError, 'File doesn\'t exists' unless File.exists?(path)
66
+
67
+ fd = open(path)
68
+ process_line(line) while line = fd.gets
69
+ fd.close
70
+ end
71
+
72
+ # Load data from preprocessed file. File is read line by line
73
+ def from_preprocessed_file(path)
74
+ raise ArgumentError, 'Argument must be a string' unless path.instance_of? String
75
+ raise ArgumentError, 'File path is not defined' unless path.empty?
76
+ raise RuntimeError, 'File doesn\'t exists' unless File.exists?(path)
77
+
78
+ fd = open(path)
79
+ process_preprocessed_line line while line = fd.gets
80
+ fd.close
81
+ end
82
+
83
+ # new
84
+ def from_string(str)
85
+ raise ArgumentError, 'Argument must be a string' unless str.instance_of? String
86
+ raise ArgumentError, 'String is not defined' if str.empty?
87
+
88
+ @str = str
89
+
90
+ str.split("\n").each do |line|
91
+ process_line(line)
92
+ end
93
+ end
94
+
95
+ def from_preprocessed_string(str)
96
+ raise ArgumentError, 'Argument must be a string' if not str.instance_of? String
97
+ raise ArgumentError, 'String is not defined' if str.empty?
98
+
99
+ str.split("\n").each do |line|
100
+ process_preprocessed_line(line)
101
+ end
102
+ end
103
+
104
+ def process_preprocessed_line(line)
105
+ lexeme_positions = []
106
+ pos = 0
107
+ while (m = LEXEME_REGEXP.match(line, pos))
108
+ pos = m.begin(0)
109
+
110
+ lexeme = install_lexeme_m(m)
111
+ lexeme_positions << TraceVisualization::Data::LexemePos.new(lexeme, pos)
112
+
113
+ pos += lexeme.lexeme_length
114
+ end
115
+
116
+ pos, idx = 0, 0
117
+ while pos < line.length
118
+ lexeme = nil
119
+ if idx < lexeme_positions.size && lexeme_positions[idx].pos == pos
120
+ lexeme = lexeme_positions[idx].lexeme
121
+ idx += 1
46
122
  else
47
- raise Exception.new("unknown type")
123
+ lexeme = install_lexeme('CHAR', line[pos], line[pos].ord, 1)
48
124
  end
125
+ pos += lexeme.lexeme_length
126
+ @mapped_str << lexeme
49
127
  end
50
-
51
- def length
52
- @src.length
128
+
129
+ @mapped_str << install_lexeme('CHAR', "\n", "\n".ord, 1)
130
+ end
131
+
132
+ # new
133
+ def process_line(line)
134
+ lexeme_poss = []
135
+
136
+ @tokens.each do |name, value|
137
+ pattern, converter_func = value
138
+ pos = 0
139
+ while (m = pattern.match(line, pos))
140
+ lexeme_string, pos = m[:lexeme], m.begin(0)
141
+
142
+ lexeme = install_lexeme(name, lexeme_string, converter_func.call(lexeme_string), lexeme_string.length)
143
+ lexeme_poss << TraceVisualization::Data::LexemePos.new(lexeme, pos)
144
+
145
+ pos += lexeme_string.length
146
+ end
53
147
  end
54
-
55
- def <=>(anOther)
56
- @ord <=> anOther.ord
148
+
149
+ lexeme_poss = TraceVisualization::LexemeOverlapFilter.process(lexeme_poss)
150
+
151
+ pos, idx = 0, 0
152
+ while pos < line.length
153
+ lexeme = nil
154
+ if idx < lexeme_poss.size && lexeme_poss[idx].pos == pos
155
+ lexeme = lexeme_poss[idx].lexeme
156
+ idx += 1
157
+ else
158
+ lexeme = install_lexeme('CHAR', line[pos], line[pos].ord, 1)
159
+ end
160
+ pos += lexeme.length
161
+ @mapped_str << lexeme
57
162
  end
58
163
 
59
- def to_str
60
- @src
164
+ @mapped_str << install_lexeme('CHAR', "\n", "\n".ord, 1)
165
+ end
166
+
167
+ def install_lexeme(name, lexeme_string, int_value, lexeme_length)
168
+ lexeme = @lexeme_table[lexeme_string]
169
+
170
+ if lexeme == nil
171
+ lexeme = TraceVisualization::Data::Lexeme.new(name, lexeme_string, int_value)
172
+ lexeme.lexeme_length = lexeme_length
173
+ @lexeme_table[lexeme_string] = lexeme
174
+ end
175
+
176
+ lexeme
177
+ end
178
+
179
+ def install_lexeme_m(m)
180
+ lexeme = @lexeme_table[m[:source]]
181
+
182
+ if lexeme == nil
183
+ lexeme = TraceVisualization::Data::Lexeme.new(m[:name], m[:source], m[:value].to_i)
184
+ lexeme.lexeme_length = m.to_s.length
185
+ @lexeme_table[m[:source]] = lexeme
61
186
  end
187
+
188
+ lexeme
189
+ end
190
+
191
+ def [](index)
192
+ @mapped_str[index]
193
+ end
194
+
195
+ def length
196
+ @mapped_str.length
197
+ end
198
+
199
+ def size
200
+ length
201
+ end
202
+
203
+ def <<(object)
204
+ @mapped_str << Item.new(object, "unknown")
205
+ end
206
+
207
+ def pop
208
+ @mapped_str.pop
209
+ end
210
+
211
+ def max
212
+ @max_value
213
+ end
214
+
215
+ def find_all
216
+ @mapped_str.find_all { |item| yield(item) }
62
217
  end
63
218
 
64
- def self.parse(str)
219
+ def restore(pos = 0, length = @mapped_str.length)
220
+ @mapped_str[pos ... pos + length].inject("") { |res, c| res += c.value }
221
+ end
222
+
223
+ def to_ary
224
+ @mapped_str.collect { |lexeme| lexeme.value }
225
+ end
226
+
227
+ def method_missing(name, *args, &blk)
228
+ raise "Missing method #{name}"
229
+ end
230
+
231
+ private
232
+
233
+ def parse(str)
65
234
  map = {}
66
235
  ppos = []
67
236
  itemByPos = {}
68
237
 
69
- PATTERNS.each do |type, patterns|
238
+ DEFAULT_TOKENS.each do |type, patterns|
70
239
  patterns.each do |pattern|
71
240
  match(str, type, pattern, map, ppos, itemByPos)
72
241
  end
@@ -81,20 +250,19 @@ module TraceVisualization
81
250
  if i == ppos[j]
82
251
  item = itemByPos[ppos[j]]
83
252
  result << item
84
- i += item.length
85
- j += 1
253
+ i, j = i + item.length, j + 1
86
254
  else
87
255
  result << Item.new(str[i], "char")
88
256
  i += 1
89
257
  end
90
258
  end
91
259
 
92
- TraceVisualization::Reorder.process(result)
260
+ @max_value = TraceVisualization::Reorder.process(result)
93
261
 
94
262
  result
95
263
  end
96
264
 
97
- def self.match(str, type, pattern, map, ppos, itemByPos)
265
+ def match(str, type, pattern, map, ppos, itemByPos)
98
266
  pos = 0
99
267
 
100
268
  limit = 1000
@@ -111,10 +279,5 @@ module TraceVisualization
111
279
  end
112
280
 
113
281
  end
114
-
115
- def self.restore(array)
116
- array.inject("") { |res, c| res += c.to_str }
117
- end
118
-
119
282
  end
120
283
  end
@@ -0,0 +1,43 @@
1
+ LEX = flex
2
+ CC = gcc
3
+ CPP = g++
4
+
5
+ LDFLAGS =-lfl
6
+
7
+ CPPUNIT_BIN_CFG = cppunit-config
8
+ CPPUNIT_CFLAGS = `$(CPPUNIT_BIN_CFG) --cflags`
9
+ CPPUNIT_LIBS = `$(CPPUNIT_BIN_CFG) --libs`
10
+
11
+ CFLAGS =-O0 -Wall -g
12
+ CPPFLAGS =-O0 -Wall $(CPPUNIT_CFLAGS) -g
13
+ # CPPFLAGS =-O0 -Wall -std=c++11 $(CPPUNIT_CFLAGS)
14
+
15
+ .cpp.o :
16
+ $(CPP) $(CPPFLAGS) -o $@ -c $<
17
+
18
+ .c.o :
19
+ $(CC) $(CFLAGS) -o $@ -c $<
20
+
21
+ %.cppo : %.c
22
+ $(CPP) $(CPPFLAGS) -o $@ -c $<
23
+
24
+ preprocessor: preprocessor.o parser_functions.o
25
+ $(CC) -o $@ $(LDFLAGS) $^
26
+
27
+ preprocessor.c: preprocessor.l
28
+ $(LEX) -o $@ $^
29
+
30
+ unit_tests: test_main.o hashmap.cppo hashmap_test.o \
31
+ parser_functions.cppo parser_test.o \
32
+ lexeme_table.cppo
33
+ $(CPP) -o $@ $(CPPUNIT_LIBS) $^
34
+
35
+ unit_tests_run: unit_tests
36
+ ./unit_tests
37
+
38
+ install: preprocessor
39
+ cp preprocessor ../../../bin/
40
+ make clean
41
+
42
+ clean:
43
+ rm -f *.o *.cppo preprocessor.c unit_tests preprocessor
@@ -0,0 +1,93 @@
1
+ #include "hashmap.h"
2
+ #include <stdio.h>
3
+
4
+ hashmap_t* hashmap_new() {
5
+ hashmap_t* hashmap = (hashmap_t*)malloc(sizeof(hashmap_t));
6
+
7
+ hashmap->size = 0;
8
+ hashmap->table = (hashmap_element**)calloc(HASHMAP_SIZE, sizeof(hashmap_element*));
9
+
10
+ return hashmap;
11
+ }
12
+
13
+ void* hashmap_get(hashmap_t* map, long key) {
14
+ hashmap_element* ptr;
15
+ int idx = (int)(key % HASHMAP_SIZE);
16
+
17
+ for (ptr = map->table[idx]; ptr != NULL; ptr = ptr->next) {
18
+ if (ptr->key == key) {
19
+ return ptr->value;
20
+ }
21
+ }
22
+
23
+ return NULL;
24
+ }
25
+
26
+ int hashmap_put(hashmap_t* map, long key, void* value) {
27
+ int result = 1;
28
+
29
+ if (hashmap_get(map, key) == NULL) {
30
+ hashmap_element* ptr;
31
+ hashmap_element* element = (hashmap_element*) malloc(sizeof(hashmap_element));
32
+
33
+ element->key = key;
34
+ element->value = value;
35
+ element->next = NULL;
36
+
37
+ int idx = (int)(key % HASHMAP_SIZE);
38
+ ptr = map->table[idx];
39
+
40
+ if (ptr) {
41
+ while (ptr->next) ptr = ptr->next;
42
+ ptr->next = element;
43
+ } else {
44
+ map->table[idx] = element;
45
+ }
46
+
47
+ map->size += 1;
48
+
49
+ result = 0;
50
+ }
51
+
52
+ return result;
53
+ }
54
+
55
+ void** hashmap_values(hashmap_t* map) {
56
+ int i = 0;
57
+ int j = 0;
58
+ hashmap_element* ptr;
59
+ void** values = (void**)malloc(map->size * sizeof(void*));
60
+
61
+ for (; i < HASHMAP_SIZE; i += 1) {
62
+ ptr = map->table[i];
63
+
64
+ while (ptr) {
65
+ values[j] = ptr->value;
66
+ ptr = ptr->next;
67
+ j += 1;
68
+ }
69
+ }
70
+
71
+ return values;
72
+ }
73
+
74
+ void hashmap_values_free(void** values) {
75
+ free(values);
76
+ }
77
+
78
+ void hashmap_free(hashmap_t* map) {
79
+ hashmap_element* ptr;
80
+ hashmap_element* tmp;
81
+ int i;
82
+ for (i = 0; i < HASHMAP_SIZE; i++) {
83
+ for (ptr = map->table[i]; ptr != NULL; ) {
84
+ tmp = ptr;
85
+ ptr = (hashmap_element*)ptr->next;
86
+
87
+ free(tmp);
88
+ }
89
+ }
90
+ free(map);
91
+ }
92
+
93
+
@@ -0,0 +1,27 @@
1
+ #ifndef __HASHMAP_H__
2
+ #define __HASHMAP_H__
3
+
4
+ #include <stdlib.h>
5
+
6
+ #define HASHMAP_SIZE (256)
7
+
8
+ // typedef struct hashmap_element hashmap_element;
9
+ struct hashmap_element {
10
+ long key;
11
+ void* value;
12
+ hashmap_element * next;
13
+ };
14
+
15
+ struct hashmap_t {
16
+ hashmap_element** table;
17
+ int size;
18
+ };
19
+
20
+ extern hashmap_t* hashmap_new();
21
+ extern int hashmap_put(hashmap_t* map, long key, void* value);
22
+ extern void* hashmap_get(hashmap_t* map, long key);
23
+ extern void** hashmap_values(hashmap_t* map);
24
+ extern void hashmap_values_free(void** values);
25
+ extern void hashmap_free(hashmap_t* map);
26
+
27
+ #endif