melisa 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (88) hide show
  1. data/README.md +11 -0
  2. data/ext/marisa/bindings/marisa-swig.cxx +253 -0
  3. data/ext/marisa/bindings/marisa-swig.h +183 -0
  4. data/ext/marisa/bindings/perl/marisa-swig.cxx +253 -0
  5. data/ext/marisa/bindings/perl/marisa-swig.h +183 -0
  6. data/ext/marisa/bindings/perl/marisa-swig_wrap.cxx +5160 -0
  7. data/ext/marisa/bindings/python/marisa-swig.cxx +253 -0
  8. data/ext/marisa/bindings/python/marisa-swig.h +183 -0
  9. data/ext/marisa/bindings/python/marisa-swig_wrap.cxx +6090 -0
  10. data/ext/marisa/bindings/ruby/extconf.rb +5 -0
  11. data/ext/marisa/bindings/ruby/marisa-swig.cxx +253 -0
  12. data/ext/marisa/bindings/ruby/marisa-swig.h +183 -0
  13. data/ext/marisa/bindings/ruby/marisa-swig_wrap.cxx +4708 -0
  14. data/ext/marisa/lib/marisa.h +14 -0
  15. data/ext/marisa/lib/marisa/agent.cc +51 -0
  16. data/ext/marisa/lib/marisa/agent.h +73 -0
  17. data/ext/marisa/lib/marisa/base.h +193 -0
  18. data/ext/marisa/lib/marisa/exception.h +82 -0
  19. data/ext/marisa/lib/marisa/grimoire/algorithm.h +26 -0
  20. data/ext/marisa/lib/marisa/grimoire/algorithm/sort.h +196 -0
  21. data/ext/marisa/lib/marisa/grimoire/intrin.h +115 -0
  22. data/ext/marisa/lib/marisa/grimoire/io.h +18 -0
  23. data/ext/marisa/lib/marisa/grimoire/io/mapper.cc +163 -0
  24. data/ext/marisa/lib/marisa/grimoire/io/mapper.h +67 -0
  25. data/ext/marisa/lib/marisa/grimoire/io/reader.cc +147 -0
  26. data/ext/marisa/lib/marisa/grimoire/io/reader.h +66 -0
  27. data/ext/marisa/lib/marisa/grimoire/io/writer.cc +148 -0
  28. data/ext/marisa/lib/marisa/grimoire/io/writer.h +65 -0
  29. data/ext/marisa/lib/marisa/grimoire/trie.h +16 -0
  30. data/ext/marisa/lib/marisa/grimoire/trie/cache.h +81 -0
  31. data/ext/marisa/lib/marisa/grimoire/trie/config.h +155 -0
  32. data/ext/marisa/lib/marisa/grimoire/trie/entry.h +82 -0
  33. data/ext/marisa/lib/marisa/grimoire/trie/header.h +61 -0
  34. data/ext/marisa/lib/marisa/grimoire/trie/history.h +65 -0
  35. data/ext/marisa/lib/marisa/grimoire/trie/key.h +228 -0
  36. data/ext/marisa/lib/marisa/grimoire/trie/louds-trie.cc +876 -0
  37. data/ext/marisa/lib/marisa/grimoire/trie/louds-trie.h +134 -0
  38. data/ext/marisa/lib/marisa/grimoire/trie/range.h +115 -0
  39. data/ext/marisa/lib/marisa/grimoire/trie/state.h +117 -0
  40. data/ext/marisa/lib/marisa/grimoire/trie/tail.cc +218 -0
  41. data/ext/marisa/lib/marisa/grimoire/trie/tail.h +72 -0
  42. data/ext/marisa/lib/marisa/grimoire/vector.h +18 -0
  43. data/ext/marisa/lib/marisa/grimoire/vector/bit-vector.cc +826 -0
  44. data/ext/marisa/lib/marisa/grimoire/vector/bit-vector.h +179 -0
  45. data/ext/marisa/lib/marisa/grimoire/vector/flat-vector.h +205 -0
  46. data/ext/marisa/lib/marisa/grimoire/vector/pop-count.h +110 -0
  47. data/ext/marisa/lib/marisa/grimoire/vector/rank-index.h +82 -0
  48. data/ext/marisa/lib/marisa/grimoire/vector/vector.h +256 -0
  49. data/ext/marisa/lib/marisa/iostream.h +18 -0
  50. data/ext/marisa/lib/marisa/key.h +85 -0
  51. data/ext/marisa/lib/marisa/keyset.cc +181 -0
  52. data/ext/marisa/lib/marisa/keyset.h +80 -0
  53. data/ext/marisa/lib/marisa/query.h +71 -0
  54. data/ext/marisa/lib/marisa/scoped-array.h +48 -0
  55. data/ext/marisa/lib/marisa/scoped-ptr.h +52 -0
  56. data/ext/marisa/lib/marisa/stdio.h +15 -0
  57. data/ext/marisa/lib/marisa/trie.cc +249 -0
  58. data/ext/marisa/lib/marisa/trie.h +64 -0
  59. data/ext/marisa/tests/base-test.cc +309 -0
  60. data/ext/marisa/tests/io-test.cc +252 -0
  61. data/ext/marisa/tests/marisa-assert.h +26 -0
  62. data/ext/marisa/tests/marisa-test.cc +388 -0
  63. data/ext/marisa/tests/trie-test.cc +507 -0
  64. data/ext/marisa/tests/vector-test.cc +466 -0
  65. data/ext/marisa/tools/cmdopt.cc +298 -0
  66. data/ext/marisa/tools/cmdopt.h +58 -0
  67. data/ext/marisa/tools/marisa-benchmark.cc +418 -0
  68. data/ext/marisa/tools/marisa-build.cc +206 -0
  69. data/ext/marisa/tools/marisa-common-prefix-search.cc +143 -0
  70. data/ext/marisa/tools/marisa-dump.cc +151 -0
  71. data/ext/marisa/tools/marisa-lookup.cc +110 -0
  72. data/ext/marisa/tools/marisa-predictive-search.cc +143 -0
  73. data/ext/marisa/tools/marisa-reverse-lookup.cc +110 -0
  74. data/lib/melisa.rb +7 -0
  75. data/lib/melisa/base_config_flags.rb +76 -0
  76. data/lib/melisa/bytes_trie.rb +55 -0
  77. data/lib/melisa/int_trie.rb +14 -0
  78. data/lib/melisa/search.rb +55 -0
  79. data/lib/melisa/trie.rb +96 -0
  80. data/lib/melisa/version.rb +3 -0
  81. data/melisa.gemspec +36 -0
  82. data/spec/base_config_flags_spec.rb +73 -0
  83. data/spec/bytes_trie_spec.rb +16 -0
  84. data/spec/int_trie_spec.rb +16 -0
  85. data/spec/search_spec.rb +29 -0
  86. data/spec/spec_helper.rb +1 -0
  87. data/spec/trie_spec.rb +30 -0
  88. metadata +207 -0
@@ -0,0 +1,115 @@
1
+ #ifndef MARISA_GRIMOIRE_INTRIN_H_
2
+ #define MARISA_GRIMOIRE_INTRIN_H_
3
+
4
+ #include "marisa/base.h"
5
+
6
+ #if defined(__x86_64__) || defined(_M_X64)
7
+ #define MARISA_X64
8
+ #elif defined(__i386__) || defined(_M_IX86)
9
+ #define MARISA_X86
10
+ #else // defined(__i386__) || defined(_M_IX86)
11
+ #ifdef MARISA_USE_POPCNT
12
+ #undef MARISA_USE_POPCNT
13
+ #endif // MARISA_USE_POPCNT
14
+ #ifdef MARISA_USE_SSE4A
15
+ #undef MARISA_USE_SSE4A
16
+ #endif // MARISA_USE_SSE4A
17
+ #ifdef MARISA_USE_SSE4
18
+ #undef MARISA_USE_SSE4
19
+ #endif // MARISA_USE_SSE4
20
+ #ifdef MARISA_USE_SSE4_2
21
+ #undef MARISA_USE_SSE4_2
22
+ #endif // MARISA_USE_SSE4_2
23
+ #ifdef MARISA_USE_SSE4_1
24
+ #undef MARISA_USE_SSE4_1
25
+ #endif // MARISA_USE_SSE4_1
26
+ #ifdef MARISA_USE_SSSE3
27
+ #undef MARISA_USE_SSSE3
28
+ #endif // MARISA_USE_SSSE3
29
+ #ifdef MARISA_USE_SSE3
30
+ #undef MARISA_USE_SSE3
31
+ #endif // MARISA_USE_SSE3
32
+ #ifdef MARISA_USE_SSE2
33
+ #undef MARISA_USE_SSE2
34
+ #endif // MARISA_USE_SSE2
35
+ #endif // defined(__i386__) || defined(_M_IX86)
36
+
37
+ #ifdef MARISA_USE_POPCNT
38
+ #ifndef MARISA_USE_SSE3
39
+ #define MARISA_USE_SSE3
40
+ #endif // MARISA_USE_SSE3
41
+ #ifdef _MSC_VER
42
+ #include <intrin.h>
43
+ #else // _MSC_VER
44
+ #include <popcntintrin.h>
45
+ #endif // _MSC_VER
46
+ #endif // MARISA_USE_POPCNT
47
+
48
+ #ifdef MARISA_USE_SSE4A
49
+ #ifndef MARISA_USE_SSE3
50
+ #define MARISA_USE_SSE3
51
+ #endif // MARISA_USE_SSE3
52
+ #ifndef MARISA_USE_POPCNT
53
+ #define MARISA_USE_POPCNT
54
+ #endif // MARISA_USE_POPCNT
55
+ #endif // MARISA_USE_SSE4A
56
+
57
+ #ifdef MARISA_USE_SSE4
58
+ #ifndef MARISA_USE_SSE4_2
59
+ #define MARISA_USE_SSE4_2
60
+ #endif // MARISA_USE_SSE4_2
61
+ #endif // MARISA_USE_SSE4
62
+
63
+ #ifdef MARISA_USE_SSE4_2
64
+ #ifndef MARISA_USE_SSE4_1
65
+ #define MARISA_USE_SSE4_1
66
+ #endif // MARISA_USE_SSE4_1
67
+ #ifndef MARISA_USE_POPCNT
68
+ #define MARISA_USE_POPCNT
69
+ #endif // MARISA_USE_POPCNT
70
+ #endif // MARISA_USE_SSE4_2
71
+
72
+ #ifdef MARISA_USE_SSE4_1
73
+ #ifndef MARISA_USE_SSSE3
74
+ #define MARISA_USE_SSSE3
75
+ #endif // MARISA_USE_SSSE3
76
+ #endif // MARISA_USE_SSE4_1
77
+
78
+ #ifdef MARISA_USE_SSSE3
79
+ #ifndef MARISA_USE_SSE3
80
+ #define MARISA_USE_SSE3
81
+ #endif // MARISA_USE_SSE3
82
+ #ifdef MARISA_X64
83
+ #define MARISA_X64_SSSE3
84
+ #else // MARISA_X64
85
+ #define MARISA_X86_SSSE3
86
+ #endif // MAIRSA_X64
87
+ #include <tmmintrin.h>
88
+ #endif // MARISA_USE_SSSE3
89
+
90
+ #ifdef MARISA_USE_SSE3
91
+ #ifndef MARISA_USE_SSE2
92
+ #define MARISA_USE_SSE2
93
+ #endif // MARISA_USE_SSE2
94
+ #endif // MARISA_USE_SSE3
95
+
96
+ #ifdef MARISA_USE_SSE2
97
+ #ifdef MARISA_X64
98
+ #define MARISA_X64_SSE2
99
+ #else // MARISA_X64
100
+ #define MARISA_X86_SSE2
101
+ #endif // MAIRSA_X64
102
+ #include <emmintrin.h>
103
+ #endif // MARISA_USE_SSE2
104
+
105
+ #ifdef _MSC_VER
106
+ #if MARISA_WORD_SIZE == 64
107
+ #include <intrin.h>
108
+ #pragma intrinsic(_BitScanForward64)
109
+ #else // MARISA_WORD_SIZE == 64
110
+ #include <intrin.h>
111
+ #pragma intrinsic(_BitScanForward)
112
+ #endif // MARISA_WORD_SIZE == 64
113
+ #endif // _MSC_VER
114
+
115
+ #endif // MARISA_GRIMOIRE_INTRIN_H_
@@ -0,0 +1,18 @@
1
+ #ifndef MARISA_GRIMOIRE_IO_H_
2
+ #define MARISA_GRIMOIRE_IO_H_
3
+
4
+ #include "marisa/grimoire/io/mapper.h"
5
+ #include "marisa/grimoire/io/reader.h"
6
+ #include "marisa/grimoire/io/writer.h"
7
+
8
+ namespace marisa {
9
+ namespace grimoire {
10
+
11
+ using io::Mapper;
12
+ using io::Reader;
13
+ using io::Writer;
14
+
15
+ } // namespace grimoire
16
+ } // namespace marisa
17
+
18
+ #endif // MARISA_GRIMOIRE_IO_H_
@@ -0,0 +1,163 @@
1
+ #if (defined _WIN32) || (defined _WIN64)
2
+ #include <sys/types.h>
3
+ #include <sys/stat.h>
4
+ #include <windows.h>
5
+ #else // (defined _WIN32) || (defined _WIN64)
6
+ #include <sys/mman.h>
7
+ #include <sys/stat.h>
8
+ #include <sys/types.h>
9
+ #include <fcntl.h>
10
+ #include <unistd.h>
11
+ #endif // (defined _WIN32) || (defined _WIN64)
12
+
13
+ #include "marisa/grimoire/io/mapper.h"
14
+
15
+ namespace marisa {
16
+ namespace grimoire {
17
+ namespace io {
18
+
19
+ #if (defined _WIN32) || (defined _WIN64)
20
+ Mapper::Mapper()
21
+ : ptr_(NULL), origin_(NULL), avail_(0), size_(0),
22
+ file_(NULL), map_(NULL) {}
23
+ #else // (defined _WIN32) || (defined _WIN64)
24
+ Mapper::Mapper()
25
+ : ptr_(NULL), origin_(MAP_FAILED), avail_(0), size_(0), fd_(-1) {}
26
+ #endif // (defined _WIN32) || (defined _WIN64)
27
+
28
+ #if (defined _WIN32) || (defined _WIN64)
29
+ Mapper::~Mapper() {
30
+ if (origin_ != NULL) {
31
+ ::UnmapViewOfFile(origin_);
32
+ }
33
+
34
+ if (map_ != NULL) {
35
+ ::CloseHandle(map_);
36
+ }
37
+
38
+ if (file_ != NULL) {
39
+ ::CloseHandle(file_);
40
+ }
41
+ }
42
+ #else // (defined _WIN32) || (defined _WIN64)
43
+ Mapper::~Mapper() {
44
+ if (origin_ != MAP_FAILED) {
45
+ ::munmap(origin_, size_);
46
+ }
47
+
48
+ if (fd_ != -1) {
49
+ ::close(fd_);
50
+ }
51
+ }
52
+ #endif // (defined _WIN32) || (defined _WIN64)
53
+
54
+ void Mapper::open(const char *filename) {
55
+ MARISA_THROW_IF(filename == NULL, MARISA_NULL_ERROR);
56
+
57
+ Mapper temp;
58
+ temp.open_(filename);
59
+ swap(temp);
60
+ }
61
+
62
+ void Mapper::open(const void *ptr, std::size_t size) {
63
+ MARISA_THROW_IF((ptr == NULL) && (size != 0), MARISA_NULL_ERROR);
64
+
65
+ Mapper temp;
66
+ temp.open_(ptr, size);
67
+ swap(temp);
68
+ }
69
+
70
+ void Mapper::seek(std::size_t size) {
71
+ MARISA_THROW_IF(!is_open(), MARISA_STATE_ERROR);
72
+ MARISA_THROW_IF(size > avail_, MARISA_IO_ERROR);
73
+
74
+ map_data(size);
75
+ }
76
+
77
+ bool Mapper::is_open() const {
78
+ return ptr_ != NULL;
79
+ }
80
+
81
+ void Mapper::clear() {
82
+ Mapper().swap(*this);
83
+ }
84
+
85
+ void Mapper::swap(Mapper &rhs) {
86
+ marisa::swap(ptr_, rhs.ptr_);
87
+ marisa::swap(avail_, rhs.avail_);
88
+ marisa::swap(origin_, rhs.origin_);
89
+ marisa::swap(size_, rhs.size_);
90
+ #if (defined _WIN32) || (defined _WIN64)
91
+ marisa::swap(file_, rhs.file_);
92
+ marisa::swap(map_, rhs.map_);
93
+ #else // (defined _WIN32) || (defined _WIN64)
94
+ marisa::swap(fd_, rhs.fd_);
95
+ #endif // (defined _WIN32) || (defined _WIN64)
96
+ }
97
+
98
+ const void *Mapper::map_data(std::size_t size) {
99
+ MARISA_THROW_IF(!is_open(), MARISA_STATE_ERROR);
100
+ MARISA_THROW_IF(size > avail_, MARISA_IO_ERROR);
101
+
102
+ const char * const data = static_cast<const char *>(ptr_);
103
+ ptr_ = data + size;
104
+ avail_ -= size;
105
+ return data;
106
+ }
107
+
108
+ #if (defined _WIN32) || (defined _WIN64)
109
+ #ifdef __MSVCRT_VERSION__
110
+ #if __MSVCRT_VERSION__ >= 0x0601
111
+ #define MARISA_HAS_STAT64
112
+ #endif // __MSVCRT_VERSION__ >= 0x0601
113
+ #endif // __MSVCRT_VERSION__
114
+ void Mapper::open_(const char *filename) {
115
+ #ifdef MARISA_HAS_STAT64
116
+ struct __stat64 st;
117
+ MARISA_THROW_IF(::_stat64(filename, &st) != 0, MARISA_IO_ERROR);
118
+ #else // MARISA_HAS_STAT64
119
+ struct _stat st;
120
+ MARISA_THROW_IF(::_stat(filename, &st) != 0, MARISA_IO_ERROR);
121
+ #endif // MARISA_HAS_STAT64
122
+ MARISA_THROW_IF((UInt64)st.st_size > MARISA_SIZE_MAX, MARISA_SIZE_ERROR);
123
+ size_ = (std::size_t)st.st_size;
124
+
125
+ file_ = ::CreateFileA(filename, GENERIC_READ, FILE_SHARE_READ,
126
+ NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
127
+ MARISA_THROW_IF(file_ == INVALID_HANDLE_VALUE, MARISA_IO_ERROR);
128
+
129
+ map_ = ::CreateFileMapping(file_, NULL, PAGE_READONLY, 0, 0, NULL);
130
+ MARISA_THROW_IF(map_ == NULL, MARISA_IO_ERROR);
131
+
132
+ origin_ = ::MapViewOfFile(map_, FILE_MAP_READ, 0, 0, 0);
133
+ MARISA_THROW_IF(origin_ == NULL, MARISA_IO_ERROR);
134
+
135
+ ptr_ = static_cast<const char *>(origin_);
136
+ avail_ = size_;
137
+ }
138
+ #else // (defined _WIN32) || (defined _WIN64)
139
+ void Mapper::open_(const char *filename) {
140
+ struct stat st;
141
+ MARISA_THROW_IF(::stat(filename, &st) != 0, MARISA_IO_ERROR);
142
+ MARISA_THROW_IF((UInt64)st.st_size > MARISA_SIZE_MAX, MARISA_SIZE_ERROR);
143
+ size_ = (std::size_t)st.st_size;
144
+
145
+ fd_ = ::open(filename, O_RDONLY);
146
+ MARISA_THROW_IF(fd_ == -1, MARISA_IO_ERROR);
147
+
148
+ origin_ = ::mmap(NULL, size_, PROT_READ, MAP_SHARED, fd_, 0);
149
+ MARISA_THROW_IF(origin_ == MAP_FAILED, MARISA_IO_ERROR);
150
+
151
+ ptr_ = static_cast<const char *>(origin_);
152
+ avail_ = size_;
153
+ }
154
+ #endif // (defined _WIN32) || (defined _WIN64)
155
+
156
+ void Mapper::open_(const void *ptr, std::size_t size) {
157
+ ptr_ = ptr;
158
+ avail_ = size;
159
+ }
160
+
161
+ } // namespace io
162
+ } // namespace grimoire
163
+ } // namespace marisa
@@ -0,0 +1,67 @@
1
+ #ifndef MARISA_GRIMOIRE_IO_MAPPER_H_
2
+ #define MARISA_GRIMOIRE_IO_MAPPER_H_
3
+
4
+ #include <cstdio>
5
+
6
+ #include "marisa/base.h"
7
+
8
+ namespace marisa {
9
+ namespace grimoire {
10
+ namespace io {
11
+
12
+ class Mapper {
13
+ public:
14
+ Mapper();
15
+ ~Mapper();
16
+
17
+ void open(const char *filename);
18
+ void open(const void *ptr, std::size_t size);
19
+
20
+ template <typename T>
21
+ void map(T *obj) {
22
+ MARISA_THROW_IF(obj == NULL, MARISA_NULL_ERROR);
23
+ *obj = *static_cast<const T *>(map_data(sizeof(T)));
24
+ }
25
+
26
+ template <typename T>
27
+ void map(const T **objs, std::size_t num_objs) {
28
+ MARISA_THROW_IF((objs == NULL) && (num_objs != 0), MARISA_NULL_ERROR);
29
+ MARISA_THROW_IF(num_objs > (MARISA_SIZE_MAX / sizeof(T)),
30
+ MARISA_SIZE_ERROR);
31
+ *objs = static_cast<const T *>(map_data(sizeof(T) * num_objs));
32
+ }
33
+
34
+ void seek(std::size_t size);
35
+
36
+ bool is_open() const;
37
+
38
+ void clear();
39
+ void swap(Mapper &rhs);
40
+
41
+ private:
42
+ const void *ptr_;
43
+ void *origin_;
44
+ std::size_t avail_;
45
+ std::size_t size_;
46
+ #if (defined _WIN32) || (defined _WIN64)
47
+ void *file_;
48
+ void *map_;
49
+ #else // (defined _WIN32) || (defined _WIN64)
50
+ int fd_;
51
+ #endif // (defined _WIN32) || (defined _WIN64)
52
+
53
+ void open_(const char *filename);
54
+ void open_(const void *ptr, std::size_t size);
55
+
56
+ const void *map_data(std::size_t size);
57
+
58
+ // Disallows copy and assignment.
59
+ Mapper(const Mapper &);
60
+ Mapper &operator=(const Mapper &);
61
+ };
62
+
63
+ } // namespace io
64
+ } // namespace grimoire
65
+ } // namespace marisa
66
+
67
+ #endif // MARISA_GRIMOIRE_IO_MAPPER_H_
@@ -0,0 +1,147 @@
1
+ #include <stdio.h>
2
+
3
+ #ifdef _WIN32
4
+ #include <io.h>
5
+ #else // _WIN32
6
+ #include <unistd.h>
7
+ #endif // _WIN32
8
+
9
+ #include <limits>
10
+
11
+ #include "marisa/grimoire/io/reader.h"
12
+
13
+ namespace marisa {
14
+ namespace grimoire {
15
+ namespace io {
16
+
17
+ Reader::Reader()
18
+ : file_(NULL), fd_(-1), stream_(NULL), needs_fclose_(false) {}
19
+
20
+ Reader::~Reader() {
21
+ if (needs_fclose_) {
22
+ ::fclose(file_);
23
+ }
24
+ }
25
+
26
+ void Reader::open(const char *filename) {
27
+ MARISA_THROW_IF(filename == NULL, MARISA_NULL_ERROR);
28
+
29
+ Reader temp;
30
+ temp.open_(filename);
31
+ swap(temp);
32
+ }
33
+
34
+ void Reader::open(std::FILE *file) {
35
+ MARISA_THROW_IF(file == NULL, MARISA_NULL_ERROR);
36
+
37
+ Reader temp;
38
+ temp.open_(file);
39
+ swap(temp);
40
+ }
41
+
42
+ void Reader::open(int fd) {
43
+ MARISA_THROW_IF(fd == -1, MARISA_CODE_ERROR);
44
+
45
+ Reader temp;
46
+ temp.open_(fd);
47
+ swap(temp);
48
+ }
49
+
50
+ void Reader::open(std::istream &stream) {
51
+ Reader temp;
52
+ temp.open_(stream);
53
+ swap(temp);
54
+ }
55
+
56
+ void Reader::clear() {
57
+ Reader().swap(*this);
58
+ }
59
+
60
+ void Reader::swap(Reader &rhs) {
61
+ marisa::swap(file_, rhs.file_);
62
+ marisa::swap(fd_, rhs.fd_);
63
+ marisa::swap(stream_, rhs.stream_);
64
+ marisa::swap(needs_fclose_, rhs.needs_fclose_);
65
+ }
66
+
67
+ void Reader::seek(std::size_t size) {
68
+ MARISA_THROW_IF(!is_open(), MARISA_STATE_ERROR);
69
+ if (size == 0) {
70
+ return;
71
+ } else if (size <= 16) {
72
+ char buf[16];
73
+ read_data(buf, size);
74
+ } else {
75
+ char buf[1024];
76
+ while (size != 0) {
77
+ const std::size_t count = (size < sizeof(buf)) ? size : sizeof(buf);
78
+ read_data(buf, count);
79
+ size -= count;
80
+ }
81
+ }
82
+ }
83
+
84
+ bool Reader::is_open() const {
85
+ return (file_ != NULL) || (fd_ != -1) || (stream_ != NULL);
86
+ }
87
+
88
+ void Reader::open_(const char *filename) {
89
+ std::FILE *file = NULL;
90
+ #ifdef _MSC_VER
91
+ MARISA_THROW_IF(::fopen_s(&file, filename, "rb") != 0, MARISA_IO_ERROR);
92
+ #else // _MSC_VER
93
+ file = ::fopen(filename, "rb");
94
+ MARISA_THROW_IF(file == NULL, MARISA_IO_ERROR);
95
+ #endif // _MSC_VER
96
+ file_ = file;
97
+ needs_fclose_ = true;
98
+ }
99
+
100
+ void Reader::open_(std::FILE *file) {
101
+ file_ = file;
102
+ }
103
+
104
+ void Reader::open_(int fd) {
105
+ fd_ = fd;
106
+ }
107
+
108
+ void Reader::open_(std::istream &stream) {
109
+ stream_ = &stream;
110
+ }
111
+
112
+ void Reader::read_data(void *buf, std::size_t size) {
113
+ MARISA_THROW_IF(!is_open(), MARISA_STATE_ERROR);
114
+ if (size == 0) {
115
+ return;
116
+ } else if (fd_ != -1) {
117
+ while (size != 0) {
118
+ #ifdef _WIN32
119
+ static const std::size_t CHUNK_SIZE =
120
+ std::numeric_limits<int>::max();
121
+ const unsigned int count = (size < CHUNK_SIZE) ? size : CHUNK_SIZE;
122
+ const int size_read = ::_read(fd_, buf, count);
123
+ #else // _WIN32
124
+ static const std::size_t CHUNK_SIZE =
125
+ std::numeric_limits< ::ssize_t>::max();
126
+ const ::size_t count = (size < CHUNK_SIZE) ? size : CHUNK_SIZE;
127
+ const ::ssize_t size_read = ::read(fd_, buf, count);
128
+ #endif // _WIN32
129
+ MARISA_THROW_IF(size_read <= 0, MARISA_IO_ERROR);
130
+ buf = static_cast<char *>(buf) + size_read;
131
+ size -= size_read;
132
+ }
133
+ } else if (file_ != NULL) {
134
+ MARISA_THROW_IF(::fread(buf, 1, size, file_) != size, MARISA_IO_ERROR);
135
+ } else if (stream_ != NULL) {
136
+ try {
137
+ MARISA_THROW_IF(!stream_->read(static_cast<char *>(buf), size),
138
+ MARISA_IO_ERROR);
139
+ } catch (const std::ios_base::failure &) {
140
+ MARISA_THROW(MARISA_IO_ERROR, "std::ios_base::failure");
141
+ }
142
+ }
143
+ }
144
+
145
+ } // namespace io
146
+ } // namespace grimoire
147
+ } // namespace marisa