sdsykes-ferret 0.11.6.19

Sign up to get free protection for your applications and to get access to all the features.
Files changed (195) hide show
  1. data/CHANGELOG +24 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README +102 -0
  4. data/Rakefile +338 -0
  5. data/TODO +17 -0
  6. data/TUTORIAL +231 -0
  7. data/bin/ferret-browser +79 -0
  8. data/ext/analysis.c +1555 -0
  9. data/ext/analysis.h +219 -0
  10. data/ext/api.c +69 -0
  11. data/ext/api.h +27 -0
  12. data/ext/array.c +123 -0
  13. data/ext/array.h +53 -0
  14. data/ext/bitvector.c +540 -0
  15. data/ext/bitvector.h +272 -0
  16. data/ext/compound_io.c +383 -0
  17. data/ext/config.h +42 -0
  18. data/ext/document.c +156 -0
  19. data/ext/document.h +53 -0
  20. data/ext/except.c +120 -0
  21. data/ext/except.h +168 -0
  22. data/ext/extconf.rb +14 -0
  23. data/ext/ferret.c +402 -0
  24. data/ext/ferret.h +91 -0
  25. data/ext/filter.c +156 -0
  26. data/ext/fs_store.c +483 -0
  27. data/ext/global.c +418 -0
  28. data/ext/global.h +117 -0
  29. data/ext/hash.c +567 -0
  30. data/ext/hash.h +473 -0
  31. data/ext/hashset.c +170 -0
  32. data/ext/hashset.h +187 -0
  33. data/ext/header.h +58 -0
  34. data/ext/helper.c +62 -0
  35. data/ext/helper.h +13 -0
  36. data/ext/inc/lang.h +48 -0
  37. data/ext/inc/threading.h +31 -0
  38. data/ext/index.c +6425 -0
  39. data/ext/index.h +961 -0
  40. data/ext/lang.h +66 -0
  41. data/ext/libstemmer.c +92 -0
  42. data/ext/libstemmer.h +79 -0
  43. data/ext/mempool.c +87 -0
  44. data/ext/mempool.h +35 -0
  45. data/ext/modules.h +162 -0
  46. data/ext/multimapper.c +310 -0
  47. data/ext/multimapper.h +51 -0
  48. data/ext/posh.c +1006 -0
  49. data/ext/posh.h +1007 -0
  50. data/ext/priorityqueue.c +151 -0
  51. data/ext/priorityqueue.h +143 -0
  52. data/ext/q_boolean.c +1608 -0
  53. data/ext/q_const_score.c +161 -0
  54. data/ext/q_filtered_query.c +209 -0
  55. data/ext/q_fuzzy.c +268 -0
  56. data/ext/q_match_all.c +148 -0
  57. data/ext/q_multi_term.c +677 -0
  58. data/ext/q_parser.c +2825 -0
  59. data/ext/q_phrase.c +1126 -0
  60. data/ext/q_prefix.c +100 -0
  61. data/ext/q_range.c +350 -0
  62. data/ext/q_span.c +2402 -0
  63. data/ext/q_term.c +337 -0
  64. data/ext/q_wildcard.c +171 -0
  65. data/ext/r_analysis.c +2575 -0
  66. data/ext/r_index.c +3472 -0
  67. data/ext/r_qparser.c +585 -0
  68. data/ext/r_search.c +4105 -0
  69. data/ext/r_store.c +513 -0
  70. data/ext/r_utils.c +963 -0
  71. data/ext/ram_store.c +471 -0
  72. data/ext/search.c +1741 -0
  73. data/ext/search.h +885 -0
  74. data/ext/similarity.c +150 -0
  75. data/ext/similarity.h +82 -0
  76. data/ext/sort.c +983 -0
  77. data/ext/stem_ISO_8859_1_danish.c +338 -0
  78. data/ext/stem_ISO_8859_1_danish.h +16 -0
  79. data/ext/stem_ISO_8859_1_dutch.c +635 -0
  80. data/ext/stem_ISO_8859_1_dutch.h +16 -0
  81. data/ext/stem_ISO_8859_1_english.c +1156 -0
  82. data/ext/stem_ISO_8859_1_english.h +16 -0
  83. data/ext/stem_ISO_8859_1_finnish.c +792 -0
  84. data/ext/stem_ISO_8859_1_finnish.h +16 -0
  85. data/ext/stem_ISO_8859_1_french.c +1276 -0
  86. data/ext/stem_ISO_8859_1_french.h +16 -0
  87. data/ext/stem_ISO_8859_1_german.c +512 -0
  88. data/ext/stem_ISO_8859_1_german.h +16 -0
  89. data/ext/stem_ISO_8859_1_italian.c +1091 -0
  90. data/ext/stem_ISO_8859_1_italian.h +16 -0
  91. data/ext/stem_ISO_8859_1_norwegian.c +296 -0
  92. data/ext/stem_ISO_8859_1_norwegian.h +16 -0
  93. data/ext/stem_ISO_8859_1_porter.c +776 -0
  94. data/ext/stem_ISO_8859_1_porter.h +16 -0
  95. data/ext/stem_ISO_8859_1_portuguese.c +1035 -0
  96. data/ext/stem_ISO_8859_1_portuguese.h +16 -0
  97. data/ext/stem_ISO_8859_1_spanish.c +1119 -0
  98. data/ext/stem_ISO_8859_1_spanish.h +16 -0
  99. data/ext/stem_ISO_8859_1_swedish.c +307 -0
  100. data/ext/stem_ISO_8859_1_swedish.h +16 -0
  101. data/ext/stem_KOI8_R_russian.c +701 -0
  102. data/ext/stem_KOI8_R_russian.h +16 -0
  103. data/ext/stem_UTF_8_danish.c +344 -0
  104. data/ext/stem_UTF_8_danish.h +16 -0
  105. data/ext/stem_UTF_8_dutch.c +653 -0
  106. data/ext/stem_UTF_8_dutch.h +16 -0
  107. data/ext/stem_UTF_8_english.c +1176 -0
  108. data/ext/stem_UTF_8_english.h +16 -0
  109. data/ext/stem_UTF_8_finnish.c +808 -0
  110. data/ext/stem_UTF_8_finnish.h +16 -0
  111. data/ext/stem_UTF_8_french.c +1296 -0
  112. data/ext/stem_UTF_8_french.h +16 -0
  113. data/ext/stem_UTF_8_german.c +526 -0
  114. data/ext/stem_UTF_8_german.h +16 -0
  115. data/ext/stem_UTF_8_italian.c +1113 -0
  116. data/ext/stem_UTF_8_italian.h +16 -0
  117. data/ext/stem_UTF_8_norwegian.c +302 -0
  118. data/ext/stem_UTF_8_norwegian.h +16 -0
  119. data/ext/stem_UTF_8_porter.c +794 -0
  120. data/ext/stem_UTF_8_porter.h +16 -0
  121. data/ext/stem_UTF_8_portuguese.c +1055 -0
  122. data/ext/stem_UTF_8_portuguese.h +16 -0
  123. data/ext/stem_UTF_8_russian.c +709 -0
  124. data/ext/stem_UTF_8_russian.h +16 -0
  125. data/ext/stem_UTF_8_spanish.c +1137 -0
  126. data/ext/stem_UTF_8_spanish.h +16 -0
  127. data/ext/stem_UTF_8_swedish.c +313 -0
  128. data/ext/stem_UTF_8_swedish.h +16 -0
  129. data/ext/stopwords.c +401 -0
  130. data/ext/store.c +692 -0
  131. data/ext/store.h +777 -0
  132. data/ext/term_vectors.c +352 -0
  133. data/ext/threading.h +31 -0
  134. data/ext/utilities.c +446 -0
  135. data/ext/win32.h +54 -0
  136. data/lib/ferret.rb +29 -0
  137. data/lib/ferret/browser.rb +246 -0
  138. data/lib/ferret/browser/s/global.js +192 -0
  139. data/lib/ferret/browser/s/style.css +148 -0
  140. data/lib/ferret/browser/views/document/list.rhtml +49 -0
  141. data/lib/ferret/browser/views/document/show.rhtml +27 -0
  142. data/lib/ferret/browser/views/error/index.rhtml +7 -0
  143. data/lib/ferret/browser/views/help/index.rhtml +8 -0
  144. data/lib/ferret/browser/views/home/index.rhtml +29 -0
  145. data/lib/ferret/browser/views/layout.rhtml +22 -0
  146. data/lib/ferret/browser/views/term-vector/index.rhtml +4 -0
  147. data/lib/ferret/browser/views/term/index.rhtml +199 -0
  148. data/lib/ferret/browser/views/term/termdocs.rhtml +1 -0
  149. data/lib/ferret/browser/webrick.rb +14 -0
  150. data/lib/ferret/document.rb +130 -0
  151. data/lib/ferret/field_infos.rb +44 -0
  152. data/lib/ferret/index.rb +786 -0
  153. data/lib/ferret/number_tools.rb +157 -0
  154. data/lib/ferret_version.rb +3 -0
  155. data/setup.rb +1555 -0
  156. data/test/test_all.rb +5 -0
  157. data/test/test_helper.rb +24 -0
  158. data/test/threading/number_to_spoken.rb +132 -0
  159. data/test/threading/thread_safety_index_test.rb +79 -0
  160. data/test/threading/thread_safety_read_write_test.rb +76 -0
  161. data/test/threading/thread_safety_test.rb +133 -0
  162. data/test/unit/analysis/tc_analyzer.rb +548 -0
  163. data/test/unit/analysis/tc_token_stream.rb +646 -0
  164. data/test/unit/index/tc_index.rb +762 -0
  165. data/test/unit/index/tc_index_reader.rb +699 -0
  166. data/test/unit/index/tc_index_writer.rb +437 -0
  167. data/test/unit/index/th_doc.rb +315 -0
  168. data/test/unit/largefile/tc_largefile.rb +46 -0
  169. data/test/unit/query_parser/tc_query_parser.rb +238 -0
  170. data/test/unit/search/tc_filter.rb +135 -0
  171. data/test/unit/search/tc_fuzzy_query.rb +147 -0
  172. data/test/unit/search/tc_index_searcher.rb +61 -0
  173. data/test/unit/search/tc_multi_searcher.rb +128 -0
  174. data/test/unit/search/tc_multiple_search_requests.rb +58 -0
  175. data/test/unit/search/tc_search_and_sort.rb +179 -0
  176. data/test/unit/search/tc_sort.rb +49 -0
  177. data/test/unit/search/tc_sort_field.rb +27 -0
  178. data/test/unit/search/tc_spans.rb +190 -0
  179. data/test/unit/search/tm_searcher.rb +384 -0
  180. data/test/unit/store/tc_fs_store.rb +77 -0
  181. data/test/unit/store/tc_ram_store.rb +35 -0
  182. data/test/unit/store/tm_store.rb +34 -0
  183. data/test/unit/store/tm_store_lock.rb +68 -0
  184. data/test/unit/tc_document.rb +81 -0
  185. data/test/unit/ts_analysis.rb +2 -0
  186. data/test/unit/ts_index.rb +2 -0
  187. data/test/unit/ts_largefile.rb +4 -0
  188. data/test/unit/ts_query_parser.rb +2 -0
  189. data/test/unit/ts_search.rb +2 -0
  190. data/test/unit/ts_store.rb +2 -0
  191. data/test/unit/ts_utils.rb +2 -0
  192. data/test/unit/utils/tc_bit_vector.rb +295 -0
  193. data/test/unit/utils/tc_number_tools.rb +117 -0
  194. data/test/unit/utils/tc_priority_queue.rb +106 -0
  195. metadata +285 -0
@@ -0,0 +1,310 @@
1
+ #include "multimapper.h"
2
+ #include "array.h"
3
+ #include "bitvector.h"
4
+ #include <string.h>
5
+
6
+ #define St(state) ((State *)(state))
7
+ #define UCtoI(val) ((int)(unsigned char)(val))
8
+
9
+ static void state_destroy(State *state)
10
+ {
11
+ state->destroy_i(state);
12
+ }
13
+
14
+ typedef struct LetterState
15
+ {
16
+ State super;
17
+ int c;
18
+ int val;
19
+ char *mapping;
20
+ } LetterState;
21
+ #define LSt(state) ((LetterState *)(state))
22
+
23
+
24
+ static int lstate_next(LetterState *self, int c, int *states)
25
+ {
26
+ if (c == self->c) {
27
+ states[0] = self->val;
28
+ return 1;
29
+ }
30
+ else {
31
+ return 0;
32
+ }
33
+ }
34
+
35
+ static int lstate_is_match(LetterState *self, char **mapping)
36
+ {
37
+ if (self->val < 0) {
38
+ *mapping = self->mapping;
39
+ return self->val;
40
+ }
41
+ else {
42
+ return 0;
43
+ }
44
+ }
45
+
46
+ static LetterState *lstate_new(int c, int val)
47
+ {
48
+ LetterState *self = ALLOC(LetterState);
49
+ self->c = c;
50
+ self->val = val;
51
+ self->mapping = NULL;
52
+ St(self)->next = (int (*)(State *, int, int *))&lstate_next;
53
+ St(self)->destroy_i = (void (*)(State *))&free;
54
+ St(self)->is_match = (int (*)(State *, char **))&lstate_is_match;
55
+ return self;
56
+ }
57
+
58
+ typedef struct NonDeterministicState
59
+ {
60
+ State super;
61
+ int *states[256];
62
+ int size[256];
63
+ int capa[256];
64
+ } NonDeterministicState;
65
+
66
+ static int ndstate_next(NonDeterministicState *self, int c, int *states)
67
+ {
68
+ int size = self->size[c];
69
+ memcpy(states, self->states[c], size * sizeof(int));
70
+ return size;
71
+ }
72
+
73
+ static void ndstate_add(NonDeterministicState *self, int c, int state)
74
+ {
75
+ if (self->capa[c] <= self->size[c]) {
76
+ if (self->capa[c] == 0) {
77
+ self->capa[c] = 4;
78
+ }
79
+ else {
80
+ self->capa[c] <<= 1;
81
+ }
82
+ REALLOC_N(self->states[c], int, self->capa[c]);
83
+ }
84
+ self->states[c][self->size[c]++] = state;
85
+ }
86
+
87
+ static void ndstate_destroy_i(NonDeterministicState *self)
88
+ {
89
+ int i;
90
+ for (i = 0; i < 256; i++) {
91
+ free(self->states[i]);
92
+ }
93
+ free(self);
94
+ }
95
+
96
+ static int ndstate_is_match(State *self, char **mapping)
97
+ {
98
+ (void)self; (void)mapping;
99
+ return 0;
100
+ }
101
+
102
+ static NonDeterministicState *ndstate_new()
103
+ {
104
+ NonDeterministicState *self = ALLOC_AND_ZERO(NonDeterministicState);
105
+ St(self)->next = (int (*)(State *, int, int *))&ndstate_next;
106
+ St(self)->destroy_i = (void (*)(State *))&ndstate_destroy_i;
107
+ St(self)->is_match = &ndstate_is_match;
108
+ return self;
109
+ }
110
+
111
+ MultiMapper *mulmap_new()
112
+ {
113
+ MultiMapper *self = ALLOC_AND_ZERO(MultiMapper);
114
+ self->capa = 128;
115
+ self->mappings = ALLOC_N(Mapping *, 128);
116
+ self->d_capa = 128;
117
+ self->dstates = ALLOC_N(DeterministicState *, 128);
118
+ self->dstates_map = NULL;
119
+ self->nstates = NULL;
120
+ self->ref_cnt = 1;
121
+ return self;
122
+ }
123
+
124
+ static INLINE void mulmap_free_dstates(MultiMapper *self)
125
+ {
126
+ if (self->d_size > 0) {
127
+ int i;
128
+ for (i = self->d_size - 1; i >= 0; i--) {
129
+ free(self->dstates[i]);
130
+ }
131
+ self->d_size = 0;
132
+ }
133
+ }
134
+
135
+ void mulmap_add_mapping(MultiMapper *self, const char *pattern, const char *rep)
136
+ {
137
+ if (pattern == NULL || pattern[0] == '\0') {
138
+ RAISE(ARG_ERROR, "Tried to add empty pattern to multi_mapper");
139
+ }
140
+ else {
141
+ Mapping *mapping = ALLOC(Mapping);
142
+ if (self->size >= self->capa) {
143
+ self->capa <<= 1;
144
+ REALLOC_N(self->mappings, Mapping *, self->capa);
145
+ }
146
+ mapping->pattern = estrdup(pattern);
147
+ mapping->replacement = estrdup(rep);
148
+ self->mappings[self->size++] = mapping;
149
+ mulmap_free_dstates(self);
150
+ }
151
+ }
152
+
153
+
154
+ static INLINE void mulmap_bv_set_states(BitVector *bv, int *states, int cnt)
155
+ {
156
+ int i;
157
+ for (i = cnt - 1; i >= 0; i--) {
158
+ bv_set(bv, states[i]);
159
+ }
160
+ }
161
+
162
+ static DeterministicState *mulmap_process_state(MultiMapper *self, BitVector *bv)
163
+ {
164
+ DeterministicState *current_state = h_get(self->dstates_map, bv);
165
+ if (current_state == NULL) {
166
+ int bit, i;
167
+ int match_len = 0, max_match_len = 0;
168
+ State *start = self->nstates[0];
169
+ DeterministicState *start_ds;
170
+ current_state = ALLOC_AND_ZERO(DeterministicState);
171
+ h_set(self->dstates_map, bv, current_state);
172
+ if (self->d_size >= self->d_capa) {
173
+ self->d_capa <<= 1;
174
+ REALLOC_N(self->dstates, DeterministicState *, self->d_capa);
175
+ }
176
+ self->dstates[self->d_size++] = current_state;
177
+ start_ds = self->dstates[0];
178
+ for (i = 0; i <= 256; i++) {
179
+ current_state->next[i] = start_ds;
180
+ }
181
+ while ((bit = bv_scan_next(bv)) >= 0) {
182
+ char *mapping;
183
+ State *st = self->nstates[bit];
184
+ if ((match_len = -st->is_match(st, &mapping)) > max_match_len) {
185
+ current_state->longest_match = max_match_len = match_len;
186
+ current_state->mapping = mapping;
187
+ current_state->mapping_len = strlen(mapping);
188
+ }
189
+ }
190
+ for (i = self->a_size - 1; i >= 0; i--) {
191
+ unsigned char c = self->alphabet[i];
192
+ BitVector *nxt_bv = bv_new_capa(self->nsize);
193
+ mulmap_bv_set_states(nxt_bv, self->next_states,
194
+ start->next(start, (int)c, self->next_states));
195
+ bv_scan_reset(bv);
196
+ while ((bit = bv_scan_next(bv)) >= 0) {
197
+ State *state = self->nstates[bit];
198
+ mulmap_bv_set_states(nxt_bv, self->next_states,
199
+ state->next(state, (int)c, self->next_states));
200
+ }
201
+ current_state->next[(int)c] = mulmap_process_state(self, nxt_bv);
202
+ }
203
+ }
204
+ else {
205
+ bv_destroy(bv);
206
+ }
207
+ return current_state;
208
+ }
209
+
210
+ void mulmap_compile(MultiMapper *self)
211
+ {
212
+ NonDeterministicState *start = ndstate_new();
213
+ int i, j;
214
+ int size = 1;
215
+ int capa = 128;
216
+ LetterState *ls;
217
+ State **nstates = ALLOC_N(State *, capa);
218
+ Mapping **mappings = self->mappings;
219
+ unsigned char alphabet[256];
220
+ nstates[0] = (State *)start;
221
+ memset(alphabet, 0, 256);
222
+
223
+ for (i = self->size - 1; i >= 0; i--) {
224
+ const char *pattern = mappings[i]->pattern;
225
+ const int plen = (int)strlen(pattern);
226
+ ndstate_add(start, UCtoI(pattern[0]), size);
227
+ if (size + plen + 1 >= capa) {
228
+ capa <<= 2;
229
+ REALLOC_N(nstates, State *, capa);
230
+ }
231
+ for (j = 0; j < plen; j++) {
232
+ alphabet[UCtoI(pattern[j])] = 1;
233
+ size += 1;
234
+ nstates[size-1] = (State *)lstate_new(UCtoI(pattern[j+1]), size);
235
+ }
236
+ ls = LSt(nstates[size-1]);
237
+ ls->mapping = mappings[i]->replacement;
238
+ ls->val = -plen;
239
+ ls->c = -1;
240
+ }
241
+ for (i = j = 0; i < 256; i++) {
242
+ if (alphabet[i]) self->alphabet[j++] = i;
243
+ }
244
+ self->a_size = j;
245
+ mulmap_free_dstates(self);
246
+ self->nstates = nstates;
247
+ self->nsize = size;
248
+ self->next_states = ALLOC_N(int, size);
249
+ self->dstates_map = h_new((hash_ft)&bv_hash, (eq_ft)&bv_eq,
250
+ (free_ft)&bv_destroy, (free_ft)NULL);
251
+ mulmap_process_state(self, bv_new_capa(0));
252
+ h_destroy(self->dstates_map);
253
+ for (i = size - 1; i >= 0; i--) {
254
+ state_destroy(nstates[i]);
255
+ }
256
+ free(self->next_states);
257
+ free(nstates);
258
+ }
259
+
260
+ int mulmap_map_len(MultiMapper *self, char *to, char *from, int capa)
261
+ {
262
+ DeterministicState *start = self->dstates[0];
263
+ DeterministicState *state = start;
264
+ char *s = from, *d = to, *end = to + capa - 1;
265
+ if (self->d_size == 0) {
266
+ RAISE(STATE_ERROR, "You forgot to compile your MultiMapper");
267
+ }
268
+ while (*s && d < end) {
269
+ state = state->next[UCtoI(*s)];
270
+ if (state->mapping) {
271
+ int len = state->mapping_len;
272
+ d -= (state->longest_match - 1);
273
+ if ((d + len) > end) {
274
+ len = end - d;
275
+ }
276
+ memcpy(d, state->mapping, len);
277
+ d += len;
278
+ state = start;
279
+ }
280
+ else {
281
+ *(d++) = *s;
282
+ }
283
+ s++;
284
+ }
285
+ *d = '\0';
286
+ return d - to;
287
+ }
288
+
289
+ char *mulmap_map(MultiMapper *self, char *to, char *from, int capa)
290
+ {
291
+ mulmap_map_len(self, to, from, capa);
292
+ return to;
293
+ }
294
+
295
+ void mulmap_destroy(MultiMapper *self)
296
+ {
297
+ if (--(self->ref_cnt) <= 0) {
298
+ int i;
299
+ mulmap_free_dstates(self);
300
+ for (i = self->size - 1; i >= 0; i--) {
301
+ Mapping *mapping = self->mappings[i];
302
+ free(mapping->pattern);
303
+ free(mapping->replacement);
304
+ free(mapping);
305
+ }
306
+ free(self->mappings);
307
+ free(self->dstates);
308
+ free(self);
309
+ }
310
+ }
@@ -0,0 +1,51 @@
1
+ #ifndef FRT_MAPPER_H
2
+ #define FRT_MAPPER_H
3
+
4
+ #include "hash.h"
5
+
6
+ typedef struct State
7
+ {
8
+ int (*next)(struct State *self, int c, int *states);
9
+ void (*destroy_i)(struct State *self);
10
+ int (*is_match)(struct State *self, char **mapping);
11
+ } State;
12
+
13
+ typedef struct DeterministicState
14
+ {
15
+ struct DeterministicState *next[256];
16
+ int longest_match;
17
+ char *mapping;
18
+ int mapping_len;
19
+ } DeterministicState;
20
+
21
+ typedef struct Mapping
22
+ {
23
+ char *pattern;
24
+ char *replacement;
25
+ } Mapping;
26
+
27
+ typedef struct MultiMapper
28
+ {
29
+ Mapping **mappings;
30
+ int size;
31
+ int capa;
32
+ DeterministicState **dstates;
33
+ int d_size;
34
+ int d_capa;
35
+ unsigned char alphabet[256];
36
+ int a_size;
37
+ HashTable *dstates_map;
38
+ State **nstates;
39
+ int nsize;
40
+ int *next_states;
41
+ int ref_cnt;
42
+ } MultiMapper;
43
+
44
+ extern MultiMapper *mulmap_new();
45
+ extern void mulmap_add_mapping(MultiMapper *self, const char *p, const char *r);
46
+ extern void mulmap_compile(MultiMapper *self);
47
+ extern char *mulmap_map(MultiMapper *self, char *to, char *from, int capa);
48
+ extern int mulmap_map_len(MultiMapper *self, char *to, char *from, int capa);
49
+ extern void mulmap_destroy(MultiMapper *self);
50
+
51
+ #endif
@@ -0,0 +1,1006 @@
1
+ /*
2
+ LICENSE:
3
+
4
+ Copyright (c) 2004, Brian Hook
5
+ All rights reserved.
6
+
7
+ Redistribution and use in source and binary forms, with or without
8
+ modification, are permitted provided that the following conditions are
9
+ met:
10
+
11
+ * Redistributions of source code must retain the above copyright
12
+ notice, this list of conditions and the following disclaimer.
13
+
14
+ * Redistributions in binary form must reproduce the above
15
+ copyright notice, this list of conditions and the following
16
+ disclaimer in the documentation and/or other materials provided
17
+ with the distribution.
18
+
19
+ * The names of this package'ss contributors contributors may not
20
+ be used to endorse or promote products derived from this
21
+ software without specific prior written permission.
22
+
23
+
24
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
25
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
26
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
27
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
28
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
29
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
30
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
31
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
32
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
33
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
34
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35
+ */
36
+ /**
37
+ @file posh.c
38
+ @author Brian Hook
39
+ @date 2002
40
+ @brief Portable Open Source Harness primary source file
41
+ */
42
+ #include "posh.h"
43
+
44
+ #if !defined FORCE_DOXYGEN
45
+
46
+ #if !defined POSH_NO_FLOAT
47
+ # define POSH_FLOAT_STRING "enabled"
48
+ #else
49
+ # define POSH_FLOAT_STRING "disabled"
50
+ #endif
51
+
52
+ #if defined POSH_64BIT_INTEGER
53
+ # define POSH_64BIT_INTEGER_STRING "yes"
54
+ #else
55
+ # define POSH_64BIT_INTEGER_STRING "no"
56
+ #endif
57
+
58
+ #if defined POSH_64BIT_POINTER
59
+ # define POSH_POINTER_STRING "64-bits"
60
+ #else
61
+ # define POSH_POINTER_STRING "32-bits"
62
+ #endif
63
+
64
+ #if defined POSH_LITTLE_ENDIAN
65
+ # define IS_BIG_ENDIAN 0
66
+
67
+ # define NATIVE16 POSH_LittleU16
68
+ # define NATIVE32 POSH_LittleU32
69
+ # define NATIVE64 POSH_LittleU64
70
+ # define FOREIGN16 POSH_BigU16
71
+ # define FOREIGN32 POSH_BigU32
72
+ # define FOREIGN64 POSH_BigU64
73
+ #else
74
+ # define IS_BIG_ENDIAN 1
75
+
76
+ # define NATIVE16 POSH_BigU16
77
+ # define NATIVE32 POSH_BigU32
78
+ # define NATIVE64 POSH_BigU64
79
+ # define FOREIGN16 POSH_LittleU16
80
+ # define FOREIGN32 POSH_LittleU32
81
+ # define FOREIGN64 POSH_LittleU64
82
+ #endif /* POSH_LITTLE_ENDIAN */
83
+
84
+ static
85
+ int
86
+ s_testBigEndian( void )
87
+ {
88
+ union
89
+ {
90
+ posh_byte_t c[ 4 ];
91
+ posh_u32_t i;
92
+ } u;
93
+
94
+ u.i= 1;
95
+
96
+ if ( u.c[ 0 ] == 1 )
97
+ {
98
+ return 0;
99
+ }
100
+ return 1;
101
+ }
102
+
103
+ static
104
+ const char *
105
+ s_testSerialization( void )
106
+ {
107
+ posh_byte_t serbuf[ 8 ];
108
+ posh_u16_t tmp16;
109
+ posh_u32_t tmp32;
110
+
111
+ /* 16-bit serialization */
112
+ POSH_WriteU16ToLittle( serbuf, 0xABCD );
113
+ if ( ( tmp16 = POSH_ReadU16FromLittle( serbuf ) ) != 0xABCD )
114
+ {
115
+ return "*ERROR: failed little-endian 16-bit serialization test";
116
+ }
117
+
118
+ POSH_WriteU16ToBig( serbuf, 0xABCD );
119
+ if ( ( tmp16 = POSH_ReadU16FromBig( serbuf ) ) != 0xABCD )
120
+ {
121
+ return "*ERROR: failed big-endian 16-bit serialization test";
122
+ }
123
+
124
+ /* 32-bit serialization */
125
+ POSH_WriteU32ToLittle( serbuf, 0xABCD1234L );
126
+ if ( ( tmp32 = POSH_ReadU32FromLittle( serbuf ) ) != 0xABCD1234 )
127
+ {
128
+ return "*ERROR: failed little-endian 32-bit serialization test";
129
+ }
130
+
131
+ POSH_WriteU32ToBig( serbuf, 0xABCD1234L );
132
+ if ( ( tmp32 = POSH_ReadU32FromBig( serbuf ) ) != 0xABCD1234 )
133
+ {
134
+ return "*ERROR: failed big-endian 32-bit serialization test";
135
+ }
136
+
137
+ #if defined POSH_64BIT_INTEGER
138
+ {
139
+ #define REF64 POSH_U64(0xFEDCBA9876543210)
140
+
141
+ posh_u64_t tmp64;
142
+
143
+ POSH_WriteU64ToLittle( serbuf, REF64 );
144
+
145
+ if ( ( tmp64 = POSH_ReadU64FromLittle( serbuf ) ) != REF64 )
146
+ {
147
+ return "*ERROR: failed little-endian 64-bit serialization test";
148
+ }
149
+
150
+ POSH_WriteU64ToBig( serbuf, REF64 );
151
+
152
+ if ( ( tmp64 = POSH_ReadU64FromBig( serbuf ) ) != REF64 )
153
+ {
154
+ return "*ERROR: failed big-endian 64-bit serialization test";
155
+ }
156
+ }
157
+ #endif
158
+
159
+ return 0;
160
+ }
161
+
162
+ #if !defined POSH_NO_FLOAT
163
+ static
164
+ const char *
165
+ s_testFloatingPoint( void )
166
+ {
167
+ float fRef = 10.0f/30.0f;
168
+ double dRef = 10.0/30.0;
169
+ posh_byte_t dbuf[ 8 ];
170
+ float fTmp;
171
+ double dTmp;
172
+
173
+ fTmp = POSH_FloatFromLittleBits( POSH_LittleFloatBits( fRef ) );
174
+
175
+ if ( fTmp != fRef )
176
+ {
177
+ return "*ERROR: POSH little endian floating point conversion failed. Please report this to poshlib@poshlib.org!\n";
178
+ }
179
+
180
+ fTmp = POSH_FloatFromBigBits( POSH_BigFloatBits( fRef ) );
181
+ if ( fTmp != fRef )
182
+ {
183
+ return "*ERROR: POSH big endian floating point conversion failed. Please report this to poshlib@poshlib.org!\n";
184
+ }
185
+
186
+ POSH_DoubleBits( dRef, dbuf );
187
+
188
+ dTmp = POSH_DoubleFromBits( dbuf );
189
+
190
+ if ( dTmp != dRef )
191
+ {
192
+ return "*ERROR: POSH double precision floating point serialization failed. Please report this to poshlib@poshlib.org!\n";
193
+ }
194
+
195
+ return 0;
196
+ }
197
+ #endif /* !defined POSH_NO_FLOAT */
198
+
199
+ static
200
+ const char *
201
+ s_testEndianess( void )
202
+ {
203
+ /* check endianess */
204
+ if ( s_testBigEndian() != IS_BIG_ENDIAN )
205
+ {
206
+ return "*ERROR: POSH compile time endianess does not match run-time endianess verification. Please report this to poshlib@poshlib.org!\n";
207
+ }
208
+
209
+ /* make sure our endian swap routines work */
210
+ if ( ( NATIVE32( 0x11223344L ) != 0x11223344L ) ||
211
+ ( FOREIGN32( 0x11223344L ) != 0x44332211L ) ||
212
+ ( NATIVE16( 0x1234 ) != 0x1234 ) ||
213
+ ( FOREIGN16( 0x1234 ) != 0x3412 ) )
214
+ {
215
+ return "*ERROR: POSH endianess macro selection failed. Please report this to poshlib@poshlib.org!\n";
216
+ }
217
+
218
+ /* test serialization routines */
219
+
220
+ return 0;
221
+ }
222
+ #endif /* !defined FORCE_DOXYGEN */
223
+
224
+ /**
225
+ Returns a string describing this platform's basic attributes.
226
+
227
+ POSH_GetArchString() reports on an architecture's statically determined
228
+ attributes. In addition, it will perform run-time verification checks
229
+ to make sure the various platform specific functions work. If an error
230
+ occurs, please contact me at poshlib@poshlib.org so we can try to resolve
231
+ what the specific failure case is.
232
+ @returns a string describing this platform on success, or a string in the
233
+ form "*ERROR: [text]" on failure. You can simply check to see if
234
+ the first character returned is '*' to verify an error condition.
235
+ */
236
+ const char *
237
+ POSH_GetArchString( void )
238
+ {
239
+ const char *err;
240
+ const char *s = "OS:.............."POSH_OS_STRING"\n"
241
+ "CPU:............."POSH_CPU_STRING"\n"
242
+ "endian:.........."POSH_ENDIAN_STRING"\n"
243
+ "ptr size:........"POSH_POINTER_STRING"\n"
244
+ "64-bit ints......"POSH_64BIT_INTEGER_STRING"\n"
245
+ "floating point..."POSH_FLOAT_STRING"\n"
246
+ "compiler........."POSH_COMPILER_STRING"\n";
247
+
248
+ /* test endianess */
249
+ err = s_testEndianess();
250
+
251
+ if ( err != 0 )
252
+ {
253
+ return err;
254
+ }
255
+
256
+ /* test serialization */
257
+ err = s_testSerialization();
258
+
259
+ if ( err != 0 )
260
+ {
261
+ return err;
262
+ }
263
+
264
+ #if !defined POSH_NO_FLOAT
265
+ /* check that our floating point support is correct */
266
+ err = s_testFloatingPoint();
267
+
268
+ if ( err != 0 )
269
+ {
270
+ return err;
271
+ }
272
+
273
+ #endif
274
+
275
+ return s;
276
+ }
277
+
278
+ /* ---------------------------------------------------------------------------*/
279
+ /* BYTE SWAPPING SUPPORT */
280
+ /* ---------------------------------------------------------------------------*/
281
+ /**
282
+ * Byte swaps a 16-bit unsigned value
283
+ *
284
+ @ingroup ByteSwapFunctions
285
+ @param v [in] unsigned 16-bit input value to swap
286
+ @returns a byte swapped version of v
287
+ */
288
+ posh_u16_t
289
+ POSH_SwapU16( posh_u16_t v )
290
+ {
291
+ posh_u16_t swapped;
292
+
293
+ swapped = v << 8;
294
+ swapped |= v >> 8;
295
+
296
+ return swapped;
297
+ }
298
+
299
+ /**
300
+ * Byte swaps a 16-bit signed value
301
+ *
302
+ @ingroup ByteSwapFunctions
303
+ @param v [in] signed 16-bit input value to swap
304
+ @returns a byte swapped version of v
305
+ @remarks This just calls back to the unsigned version, since byte swapping
306
+ is independent of sign. However, we still provide this function to
307
+ avoid signed/unsigned mismatch compiler warnings.
308
+ */
309
+ posh_i16_t
310
+ POSH_SwapI16( posh_i16_t v )
311
+ {
312
+ return ( posh_i16_t ) POSH_SwapU16( v );
313
+ }
314
+
315
+ /**
316
+ * Byte swaps a 32-bit unsigned value
317
+ *
318
+ @ingroup ByteSwapFunctions
319
+ @param v [in] unsigned 32-bit input value to swap
320
+ @returns a byte swapped version of v
321
+ */
322
+ posh_u32_t
323
+ POSH_SwapU32( posh_u32_t v )
324
+ {
325
+ posh_u32_t swapped;
326
+
327
+ swapped = ( v & 0xFF ) << 24;
328
+ swapped |= ( v & 0xFF00 ) << 8;
329
+ swapped |= ( v >> 8 ) & 0xFF00;
330
+ swapped |= ( v >> 24 );
331
+
332
+ return swapped;
333
+ }
334
+
335
+ /**
336
+ * Byte swaps a 32-bit signed value
337
+ *
338
+ @ingroup ByteSwapFunctions
339
+ @param v [in] signed 32-bit input value to swap
340
+ @returns a byte swapped version of v
341
+ @remarks This just calls back to the unsigned version, since byte swapping
342
+ is independent of sign. However, we still provide this function to
343
+ avoid signed/unsigned mismatch compiler warnings.
344
+ */
345
+ posh_i32_t
346
+ POSH_SwapI32( posh_i32_t v )
347
+ {
348
+ return ( posh_i32_t ) POSH_SwapU32( ( posh_u32_t ) v );
349
+ }
350
+
351
+ #if defined POSH_64BIT_INTEGER
352
+ /**
353
+ * Byte swaps a 64-bit unsigned value
354
+
355
+ @param v [in] a 64-bit input value to swap
356
+ @ingroup SixtyFourBit
357
+ @returns a byte swapped version of v
358
+ */
359
+ posh_u64_t
360
+ POSH_SwapU64( posh_u64_t v )
361
+ {
362
+ posh_byte_t tmp;
363
+ union {
364
+ posh_byte_t bytes[ 8 ];
365
+ posh_u64_t u64;
366
+ } u;
367
+
368
+ u.u64 = v;
369
+
370
+ tmp = u.bytes[ 0 ]; u.bytes[ 0 ] = u.bytes[ 7 ]; u.bytes[ 7 ] = tmp;
371
+ tmp = u.bytes[ 1 ]; u.bytes[ 1 ] = u.bytes[ 6 ]; u.bytes[ 6 ] = tmp;
372
+ tmp = u.bytes[ 2 ]; u.bytes[ 2 ] = u.bytes[ 5 ]; u.bytes[ 5 ] = tmp;
373
+ tmp = u.bytes[ 3 ]; u.bytes[ 3 ] = u.bytes[ 4 ]; u.bytes[ 4 ] = tmp;
374
+
375
+ return u.u64;
376
+ }
377
+
378
+ /**
379
+ * Byte swaps a 64-bit signed value
380
+
381
+ @param v [in] a 64-bit input value to swap
382
+ @ingroup SixtyFourBit
383
+ @returns a byte swapped version of v
384
+ */
385
+ posh_i64_t
386
+ POSH_SwapI64( posh_i64_t v )
387
+ {
388
+ return ( posh_i64_t ) POSH_SwapU64( ( posh_u64_t ) v );
389
+ }
390
+
391
+ #endif /* defined POSH_64BIT_INTEGER */
392
+
393
+ /* ---------------------------------------------------------------------------*/
394
+ /* IN-MEMORY SERIALIZATION */
395
+ /* ---------------------------------------------------------------------------*/
396
+
397
+ /**
398
+ * Writes an unsigned 16-bit value to a little endian buffer
399
+
400
+ @ingroup MemoryBuffer
401
+ @param dst [out] pointer to the destination buffer, may not be NULL. Alignment doesn't matter.
402
+ @param value [in] host-endian unsigned 16-bit value
403
+ @returns a pointer to the location two bytes after dst
404
+ @remarks does no validation of the inputs
405
+ */
406
+ posh_u16_t *
407
+ POSH_WriteU16ToLittle( void *dst, posh_u16_t value )
408
+ {
409
+ posh_u16_t *p16 = ( posh_u16_t * ) dst;
410
+ posh_byte_t *p = ( posh_byte_t * ) dst;
411
+
412
+ p[ 0 ] = value & 0xFF;
413
+ p[ 1 ] = ( value & 0xFF00) >> 8;
414
+
415
+ return p16 + 1;
416
+ }
417
+
418
+ /**
419
+ * Writes a signed 16-bit value to a little endian buffer
420
+
421
+ @ingroup MemoryBuffer
422
+ @param dst [out] pointer to the destination buffer, may not be NULL
423
+ @param value [in] host-endian signed 16-bit value
424
+ @returns a pointer to the location two bytes after dst
425
+ @remarks does no validation of the inputs. This simply calls
426
+ POSH_WriteU16ToLittle() with appropriate casting.
427
+ */
428
+ posh_i16_t *
429
+ POSH_WriteI16ToLittle( void *dst, posh_i16_t value )
430
+ {
431
+ return ( posh_i16_t * ) POSH_WriteU16ToLittle( dst, ( posh_u16_t ) value );
432
+ }
433
+
434
+ /**
435
+ * Writes an unsigned 32-bit value to a little endian buffer
436
+
437
+ @ingroup MemoryBuffer
438
+ @param dst [out] pointer to the destination buffer, may not be NULL
439
+ @param value [in] host-endian signed 32-bit value
440
+ @returns a pointer to the location four bytes after dst
441
+ @remarks does no validation of the inputs.
442
+ */
443
+ posh_u32_t *
444
+ POSH_WriteU32ToLittle( void *dst, posh_u32_t value )
445
+ {
446
+ posh_u32_t *p32 = ( posh_u32_t * ) dst;
447
+ posh_byte_t *p = ( posh_byte_t * ) dst;
448
+
449
+ p[ 0 ] = ( value & 0xFF );
450
+ p[ 1 ] = ( value & 0xFF00 ) >> 8;
451
+ p[ 2 ] = ( value & 0xFF0000 ) >> 16;
452
+ p[ 3 ] = ( value & 0xFF000000 ) >> 24;
453
+
454
+ return p32 + 1;
455
+ }
456
+
457
+ /**
458
+ * Writes a signed 32-bit value to a little endian buffer
459
+
460
+ @ingroup MemoryBuffer
461
+ @param dst [out] pointer to the destination buffer, may not be NULL
462
+ @param value [in] host-endian signed 32-bit value
463
+ @returns a pointer to the location four bytes after dst
464
+ @remarks does no validation of the inputs. This simply calls
465
+ POSH_WriteU32ToLittle() with appropriate casting.
466
+ */
467
+ posh_i32_t *
468
+ POSH_WriteI32ToLittle( void *dst, posh_i32_t value )
469
+ {
470
+ return ( posh_i32_t * ) POSH_WriteU32ToLittle( dst, ( posh_u32_t ) value );
471
+ }
472
+
473
+ /**
474
+ * Writes an unsigned 16-bit value to a big endian buffer
475
+
476
+ @ingroup MemoryBuffer
477
+ @param dst [out] pointer to the destination buffer, may not be NULL
478
+ @param value [in] host-endian unsigned 16-bit value
479
+ @returns a pointer to the location two bytes after dst
480
+ @remarks does no validation of the inputs
481
+ */
482
+ posh_u16_t *
483
+ POSH_WriteU16ToBig( void *dst, posh_u16_t value )
484
+ {
485
+ posh_u16_t *p16 = ( posh_u16_t * ) dst;
486
+ posh_byte_t *p = ( posh_byte_t * ) dst;
487
+
488
+ p[ 1 ] = ( value & 0xFF );
489
+ p[ 0 ] = ( value & 0xFF00 ) >> 8;
490
+
491
+ return p16 + 1;
492
+ }
493
+
494
+ /**
495
+ * Writes a signed 16-bit value to a big endian buffer
496
+
497
+ @ingroup MemoryBuffer
498
+ @param dst [out] pointer to the destination buffer, may not be NULL
499
+ @param value [in] host-endian signed 16-bit value
500
+ @returns a pointer to the location two bytes after dst
501
+ @remarks does no validation of the inputs. This simply calls
502
+ POSH_WriteU16ToLittle() with appropriate casting.
503
+ */
504
+ posh_i16_t *
505
+ POSH_WriteI16ToBig( void *dst, posh_i16_t value )
506
+ {
507
+ return ( posh_i16_t * ) POSH_WriteU16ToBig( dst, ( posh_u16_t ) value );
508
+ }
509
+
510
+ /**
511
+ * Writes an unsigned 32-bit value to a big endian buffer
512
+
513
+ @ingroup MemoryBuffer
514
+ @param dst [out] pointer to the destination buffer, may not be NULL
515
+ @param value [in] host-endian unsigned 32-bit value
516
+ @returns a pointer to the location four bytes after dst
517
+ @remarks does no validation of the inputs.
518
+ */
519
+ posh_u32_t *
520
+ POSH_WriteU32ToBig( void *dst, posh_u32_t value )
521
+ {
522
+ posh_u32_t *p32 = ( posh_u32_t * ) dst;
523
+ posh_byte_t *p = ( posh_byte_t * ) dst;
524
+
525
+ p[ 3 ] = ( value & 0xFF );
526
+ p[ 2 ] = ( value & 0xFF00 ) >> 8;
527
+ p[ 1 ] = ( value & 0xFF0000 ) >> 16;
528
+ p[ 0 ] = ( value & 0xFF000000 ) >> 24;
529
+
530
+ return p32 + 1;
531
+ }
532
+
533
+ /**
534
+ * Writes a signed 32-bit value to a big endian buffer
535
+
536
+ @ingroup MemoryBuffer
537
+ @param dst [out] pointer to the destination buffer, may not be NULL
538
+ @param value [in] host-endian signed 32-bit value
539
+ @returns a pointer to the location four bytes after dst
540
+ @remarks does no validation of the inputs. This simply calls
541
+ POSH_WriteU32ToBig() with appropriate casting.
542
+ */
543
+ posh_i32_t *
544
+ POSH_WriteI32ToBig( void *dst, posh_i32_t value )
545
+ {
546
+ return ( posh_i32_t * ) POSH_WriteU32ToBig( dst, ( posh_u32_t ) value );
547
+ }
548
+
549
+ #if defined POSH_64BIT_INTEGER
550
+ /**
551
+ * Writes an unsigned 64-bit value to a little-endian buffer
552
+
553
+ @ingroup SixtyFourBit
554
+ @param dst [out] pointer to the destination buffer, may not be NULL
555
+ @param value [in] host-endian unsigned 64-bit value
556
+ @returns a pointer to the location eight bytes after dst
557
+ @remarks does no validation of the inputs.
558
+ */
559
+ posh_u64_t *
560
+ POSH_WriteU64ToLittle( void *dst, posh_u64_t value )
561
+ {
562
+ posh_u64_t *p64 = ( posh_u64_t * ) dst;
563
+ posh_byte_t *p = ( posh_byte_t * ) dst;
564
+ int i;
565
+
566
+ for ( i = 0; i < 8; i++, value >>= 8 )
567
+ {
568
+ p[ i ] = ( posh_byte_t ) ( value & 0xFF );
569
+ }
570
+
571
+ return p64 + 1;
572
+ }
573
+
574
+ /**
575
+ * Writes a signed 64-bit value to a little-endian buffer
576
+
577
+ @ingroup SixtyFourBit
578
+ @param dst [out] pointer to the destination buffer, may not be NULL
579
+ @param value [in] host-endian unsigned 64-bit value
580
+ @returns a pointer to the location eight bytes after dst
581
+ @remarks does no validation of the inputs.
582
+ */
583
+ posh_i64_t *
584
+ POSH_WriteI64ToLittle( void *dst, posh_i64_t value )
585
+ {
586
+ return ( posh_i64_t * ) POSH_WriteU64ToLittle( dst, ( posh_u64_t ) value );
587
+ }
588
+
589
+ /**
590
+ * Writes an unsigned 64-bit value to a big-endian buffer
591
+
592
+ @ingroup SixtyFourBit
593
+ @param dst [out] pointer to the destination buffer, may not be NULL
594
+ @param value [in] host-endian unsigned 64-bit value
595
+ @returns a pointer to the location eight bytes after dst
596
+ @remarks does no validation of the inputs.
597
+ */
598
+ posh_u64_t *
599
+ POSH_WriteU64ToBig( void *dst, posh_u64_t value )
600
+ {
601
+ posh_u64_t *p64 = ( posh_u64_t * ) dst;
602
+ posh_byte_t *p = ( posh_byte_t * ) dst;
603
+ int i;
604
+
605
+ for ( i = 0; i < 8; i++, value >>= 8 )
606
+ {
607
+ p[ 7-i ] = ( posh_byte_t ) ( value & 0xFF );
608
+ }
609
+
610
+ return p64 + 8;
611
+ }
612
+
613
+ /**
614
+ * Writes a signed 64-bit value to a big-endian buffer
615
+
616
+ @ingroup SixtyFourBit
617
+ @param dst [out] pointer to the destination buffer, may not be NULL
618
+ @param value [in] host-endian signed 64-bit value
619
+ @returns a pointer to the location eight bytes after dst
620
+ @remarks does no validation of the inputs.
621
+ */
622
+ posh_i64_t *
623
+ POSH_WriteI64ToBig( void *dst, posh_i64_t value )
624
+ {
625
+ return ( posh_i64_t * ) POSH_WriteU64ToBig( dst, ( posh_u64_t ) value );
626
+ }
627
+
628
+ #endif /* POSH_64BIT_INTEGER */
629
+
630
+ /* ---------------------------------------------------------------------------*/
631
+ /* IN-MEMORY DESERIALIZATION */
632
+ /* ---------------------------------------------------------------------------*/
633
+
634
+ /**
635
+ * Reads an unsigned 16-bit value from a little-endian buffer
636
+ @ingroup MemoryBuffer
637
+ @param src [in] source buffer
638
+ @returns host-endian unsigned 16-bit value
639
+ */
640
+ posh_u16_t
641
+ POSH_ReadU16FromLittle( const void *src )
642
+ {
643
+ posh_u16_t v = 0;
644
+ posh_byte_t *p = ( posh_byte_t * ) src;
645
+
646
+ v |= p[ 0 ];
647
+ v |= ( ( posh_u16_t ) p[ 1 ] ) << 8;
648
+
649
+ return v;
650
+ }
651
+
652
+ /**
653
+ * Reads a signed 16-bit value from a little-endian buffer
654
+ @ingroup MemoryBuffer
655
+ @param src [in] source buffer
656
+ @returns host-endian signed 16-bit value
657
+ */
658
+ posh_i16_t
659
+ POSH_ReadI16FromLittle( const void *src )
660
+ {
661
+ return ( posh_i16_t ) POSH_ReadU16FromLittle( src );
662
+ }
663
+
664
+ /**
665
+ * Reads an unsigned 32-bit value from a little-endian buffer
666
+ @ingroup MemoryBuffer
667
+ @param src [in] source buffer
668
+ @returns host-endian unsigned 32-bit value
669
+ */
670
+ posh_u32_t
671
+ POSH_ReadU32FromLittle( const void *src )
672
+ {
673
+ posh_u32_t v = 0;
674
+ posh_byte_t *p = ( posh_byte_t * ) src;
675
+
676
+ v |= p[ 0 ];
677
+ v |= ( ( posh_u32_t ) p[ 1 ] ) << 8;
678
+ v |= ( ( posh_u32_t ) p[ 2 ] ) << 16;
679
+ v |= ( ( posh_u32_t ) p[ 3 ] ) << 24;
680
+
681
+ return v;
682
+ }
683
+
684
+ /**
685
+ * Reads a signed 32-bit value from a little-endian buffer
686
+ @ingroup MemoryBuffer
687
+ @param src [in] source buffer
688
+ @returns host-endian signed 32-bit value
689
+ */
690
+ posh_i32_t
691
+ POSH_ReadI32FromLittle( const void *src )
692
+ {
693
+ return ( posh_i32_t ) POSH_ReadU32FromLittle( src );
694
+ }
695
+
696
+
697
+ /**
698
+ * Reads an unsigned 16-bit value from a big-endian buffer
699
+ @ingroup MemoryBuffer
700
+ @param src [in] source buffer
701
+ @returns host-endian unsigned 16-bit value
702
+ */
703
+ posh_u16_t
704
+ POSH_ReadU16FromBig( const void *src )
705
+ {
706
+ posh_u16_t v = 0;
707
+ posh_byte_t *p = ( posh_byte_t * ) src;
708
+
709
+ v |= p[ 1 ];
710
+ v |= ( ( posh_u16_t ) p[ 0 ] ) << 8;
711
+
712
+ return v;
713
+ }
714
+
715
+ /**
716
+ * Reads a signed 16-bit value from a big-endian buffer
717
+ @ingroup MemoryBuffer
718
+ @param src [in] source buffer
719
+ @returns host-endian signed 16-bit value
720
+ */
721
+ posh_i16_t
722
+ POSH_ReadI16FromBig( const void *src )
723
+ {
724
+ return ( posh_i16_t ) POSH_ReadU16FromBig( src );
725
+ }
726
+
727
+ /**
728
+ * Reads an unsigned 32-bit value from a big-endian buffer
729
+ @ingroup MemoryBuffer
730
+ @param src [in] source buffer
731
+ @returns host-endian unsigned 32-bit value
732
+ */
733
+ posh_u32_t
734
+ POSH_ReadU32FromBig( const void *src )
735
+ {
736
+ posh_u32_t v = 0;
737
+ posh_byte_t *p = ( posh_byte_t * ) src;
738
+
739
+ v |= p[ 3 ];
740
+ v |= ( ( posh_u32_t ) p[ 2 ] ) << 8;
741
+ v |= ( ( posh_u32_t ) p[ 1 ] ) << 16;
742
+ v |= ( ( posh_u32_t ) p[ 0 ] ) << 24;
743
+
744
+ return v;
745
+ }
746
+
747
+ /**
748
+ * Reads a signed 32-bit value from a big-endian buffer
749
+ @ingroup MemoryBuffer
750
+ @param src [in] source buffer
751
+ @returns host-endian signed 32-bit value
752
+ */
753
+ posh_i32_t
754
+ POSH_ReadI32FromBig( const void *src )
755
+ {
756
+ return POSH_BigI32( (*(const posh_i32_t*)src ) );
757
+ }
758
+
759
+ #if defined POSH_64BIT_INTEGER
760
+
761
+ /**
762
+ * Reads an unsigned 64-bit value from a little-endian buffer
763
+ @param src [in] source buffer
764
+ @returns host-endian unsigned 32-bit value
765
+ */
766
+ posh_u64_t
767
+ POSH_ReadU64FromLittle( const void *src )
768
+ {
769
+ posh_u64_t v = 0;
770
+ posh_byte_t *p = ( posh_byte_t * ) src;
771
+ int i;
772
+
773
+ for ( i = 0; i < 8; i++ )
774
+ {
775
+ v |= ( ( posh_u64_t ) p[ i ] ) << (i*8);
776
+ }
777
+
778
+ return v;
779
+ }
780
+
781
+ /**
782
+ * Reads a signed 64-bit value from a little-endian buffer
783
+ @param src [in] source buffer
784
+ @returns host-endian signed 32-bit value
785
+ */
786
+ posh_i64_t
787
+ POSH_ReadI64FromLittle( const void *src )
788
+ {
789
+ return ( posh_i64_t ) POSH_ReadU64FromLittle( src );
790
+ }
791
+
792
+ /**
793
+ * Reads an unsigned 64-bit value from a big-endian buffer
794
+ @param src [in] source buffer
795
+ @returns host-endian unsigned 32-bit value
796
+ */
797
+ posh_u64_t
798
+ POSH_ReadU64FromBig( const void *src )
799
+ {
800
+ posh_u64_t v = 0;
801
+ posh_byte_t *p = ( posh_byte_t * ) src;
802
+ int i;
803
+
804
+ for ( i = 0; i < 8; i++ )
805
+ {
806
+ v |= ( ( posh_u64_t ) p[ 7-i ] ) << (i*8);
807
+ }
808
+
809
+ return v;
810
+ }
811
+
812
+ /**
813
+ * Reads an signed 64-bit value from a big-endian buffer
814
+ @param src [in] source buffer
815
+ @returns host-endian signed 32-bit value
816
+ */
817
+ posh_i64_t
818
+ POSH_ReadI64FromBig( const void *src )
819
+ {
820
+ return ( posh_i64_t ) POSH_ReadU64FromBig( src );
821
+ }
822
+
823
+ #endif /* POSH_64BIT_INTEGER */
824
+
825
+ /* ---------------------------------------------------------------------------*/
826
+ /* FLOATING POINT SUPPORT */
827
+ /* ---------------------------------------------------------------------------*/
828
+
829
+ #if !defined POSH_NO_FLOAT
830
+
831
+ /** @ingroup FloatingPoint
832
+ @param[in] f floating point value
833
+ @returns a little-endian bit representation of f
834
+ */
835
+ posh_u32_t
836
+ POSH_LittleFloatBits( float f )
837
+ {
838
+ union
839
+ {
840
+ float f32;
841
+ posh_u32_t u32;
842
+ } u;
843
+
844
+ u.f32 = f;
845
+
846
+ return POSH_LittleU32( u.u32 );
847
+ }
848
+
849
+ /**
850
+ * Extracts raw big-endian bits from a 32-bit floating point value
851
+ *
852
+ @ingroup FloatingPoint
853
+ @param f [in] floating point value
854
+ @returns a big-endian bit representation of f
855
+ */
856
+ posh_u32_t
857
+ POSH_BigFloatBits( float f )
858
+ {
859
+ union
860
+ {
861
+ float f32;
862
+ posh_u32_t u32;
863
+ } u;
864
+
865
+ u.f32 = f;
866
+
867
+ return POSH_BigU32( u.u32 );
868
+ }
869
+
870
+ /**
871
+ * Extracts raw, little-endian bit representation from a 64-bit double.
872
+ *
873
+ @param d [in] 64-bit double precision value
874
+ @param dst [out] 8-byte storage buffer
875
+ @ingroup FloatingPoint
876
+ @returns the raw bits used to represent the value 'd', in the form dst[0]=LSB
877
+ */
878
+ void
879
+ POSH_DoubleBits( double d, posh_byte_t dst[ 8 ] )
880
+ {
881
+ union
882
+ {
883
+ double d64;
884
+ posh_byte_t bytes[ 8 ];
885
+ } u;
886
+
887
+ u.d64 = d;
888
+
889
+ #if defined POSH_LITTLE_ENDIAN
890
+ dst[ 0 ] = u.bytes[ 0 ];
891
+ dst[ 1 ] = u.bytes[ 1 ];
892
+ dst[ 2 ] = u.bytes[ 2 ];
893
+ dst[ 3 ] = u.bytes[ 3 ];
894
+ dst[ 4 ] = u.bytes[ 4 ];
895
+ dst[ 5 ] = u.bytes[ 5 ];
896
+ dst[ 6 ] = u.bytes[ 6 ];
897
+ dst[ 7 ] = u.bytes[ 7 ];
898
+ #else
899
+ dst[ 0 ] = u.bytes[ 7 ];
900
+ dst[ 1 ] = u.bytes[ 6 ];
901
+ dst[ 2 ] = u.bytes[ 5 ];
902
+ dst[ 3 ] = u.bytes[ 4 ];
903
+ dst[ 4 ] = u.bytes[ 3 ];
904
+ dst[ 5 ] = u.bytes[ 2 ];
905
+ dst[ 6 ] = u.bytes[ 1 ];
906
+ dst[ 7 ] = u.bytes[ 0 ];
907
+ #endif
908
+ }
909
+
910
+ /**
911
+ * Creates a double-precision, 64-bit floating point value from a set of raw,
912
+ * little-endian bits
913
+
914
+ @ingroup FloatingPoint
915
+ @param src [in] little-endian byte representation of 64-bit double precision
916
+ floating point value
917
+ @returns double precision floating point representation of the raw bits
918
+ @remarks No error checking is performed, so there are no guarantees that the
919
+ result is a valid number, nor is there any check to ensure that src is
920
+ non-NULL. BE CAREFUL USING THIS.
921
+ */
922
+ double
923
+ POSH_DoubleFromBits( const posh_byte_t src[ 8 ] )
924
+ {
925
+ union
926
+ {
927
+ double d64;
928
+ posh_byte_t bytes[ 8 ];
929
+ } u;
930
+
931
+ #if defined POSH_LITTLE_ENDIAN
932
+ u.bytes[ 0 ] = src[ 0 ];
933
+ u.bytes[ 1 ] = src[ 1 ];
934
+ u.bytes[ 2 ] = src[ 2 ];
935
+ u.bytes[ 3 ] = src[ 3 ];
936
+ u.bytes[ 4 ] = src[ 4 ];
937
+ u.bytes[ 5 ] = src[ 5 ];
938
+ u.bytes[ 6 ] = src[ 6 ];
939
+ u.bytes[ 7 ] = src[ 7 ];
940
+ #else
941
+ u.bytes[ 0 ] = src[ 7 ];
942
+ u.bytes[ 1 ] = src[ 6 ];
943
+ u.bytes[ 2 ] = src[ 5 ];
944
+ u.bytes[ 3 ] = src[ 4 ];
945
+ u.bytes[ 4 ] = src[ 3 ];
946
+ u.bytes[ 5 ] = src[ 2 ];
947
+ u.bytes[ 6 ] = src[ 1 ];
948
+ u.bytes[ 7 ] = src[ 0 ];
949
+ #endif
950
+
951
+ return u.d64;
952
+ }
953
+
954
+ /**
955
+ * Creates a floating point number from little endian bits
956
+ *
957
+ @ingroup FloatingPoint
958
+ @param bits [in] raw floating point bits in little-endian form
959
+ @returns a floating point number based on the given bit representation
960
+ @remarks No error checking is performed, so there are no guarantees that the
961
+ result is a valid number. BE CAREFUL USING THIS.
962
+ */
963
+ float
964
+ POSH_FloatFromLittleBits( posh_u32_t bits )
965
+ {
966
+ union
967
+ {
968
+ float f32;
969
+ posh_u32_t u32;
970
+ } u;
971
+
972
+ u.u32 = bits;
973
+ #if defined POSH_BIG_ENDIAN
974
+ u.u32 = POSH_SwapU32( u.u32 );
975
+ #endif
976
+
977
+ return u.f32;
978
+ }
979
+
980
+ /**
981
+ * Creates a floating point number from big-endian bits
982
+ *
983
+ @ingroup FloatingPoint
984
+ @param bits [in] raw floating point bits in big-endian form
985
+ @returns a floating point number based on the given bit representation
986
+ @remarks No error checking is performed, so there are no guarantees that the
987
+ result is a valid number. BE CAREFUL USING THIS.
988
+ */
989
+ float
990
+ POSH_FloatFromBigBits( posh_u32_t bits )
991
+ {
992
+ union
993
+ {
994
+ float f32;
995
+ posh_u32_t u32;
996
+ } u;
997
+
998
+ u.u32 = bits;
999
+ #if defined POSH_LITTLE_ENDIAN
1000
+ u.u32 = POSH_SwapU32( u.u32 );
1001
+ #endif
1002
+
1003
+ return u.f32;
1004
+ }
1005
+
1006
+ #endif /* !defined POSH_NO_FLOAT */