~ubuntu-branches/ubuntu/lucid/bin-prot/lucid

« back to all changes in this revision

Viewing changes to lib/read_stubs.c

  • Committer: Bazaar Package Importer
  • Author(s): Stefano Zacchiroli
  • Date: 2008-05-09 15:24:37 UTC
  • Revision ID: james.westby@ubuntu.com-20080509152437-7gils45p37xcs40c
Tags: upstream-1.0.5
ImportĀ upstreamĀ versionĀ 1.0.5

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* File: read_stubs.c
 
2
 
 
3
    Copyright (C) 2007-
 
4
 
 
5
      Jane Street Holding, LLC
 
6
      Author: Markus Mottl
 
7
      email: mmottl\@janestcapital.com
 
8
      WWW: http://www.janestcapital.com/ocaml
 
9
 
 
10
   This library is free software; you can redistribute it and/or
 
11
   modify it under the terms of the GNU Lesser General Public
 
12
   License as published by the Free Software Foundation; either
 
13
   version 2 of the License, or (at your option) any later version.
 
14
 
 
15
   This library is distributed in the hope that it will be useful,
 
16
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
17
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
18
   Lesser General Public License for more details.
 
19
 
 
20
   You should have received a copy of the GNU Lesser General Public
 
21
   License along with this library; if not, write to the Free Software
 
22
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
23
*/
 
24
 
 
25
/* Stubs for reading basic values in the binary protocol */
 
26
 
 
27
#include "common_stubs.h"
 
28
 
 
29
/* Initialisation */
 
30
 
 
31
static value *v_exc_Error = NULL;
 
32
static value *v_exc_Read_error = NULL;
 
33
 
 
34
CAMLprim value bin_prot_unsafe_read_c_init_stub(value __unused v_unit)
 
35
{
 
36
  v_exc_Error = caml_named_value("Bin_prot.Unsafe_read_c.Error");
 
37
  return Val_unit;
 
38
}
 
39
 
 
40
CAMLprim value bin_prot_read_ml_init_stub(value __unused v_unit)
 
41
{
 
42
  v_exc_Read_error = caml_named_value("Bin_prot.Common.Read_error");
 
43
  return Val_unit;
 
44
}
 
45
 
 
46
 
 
47
/* Raising errors */
 
48
 
 
49
/* Constant values come from the order of variants in common.ml */
 
50
#define READ_ERROR_NEG_INT8 0
 
51
#define READ_ERROR_INT_CODE 1
 
52
#define READ_ERROR_INT_OVERFLOW 2
 
53
#define READ_ERROR_NAT0_CODE 3
 
54
#define READ_ERROR_NAT0_OVERFLOW 4
 
55
#define READ_ERROR_INT32_CODE 5
 
56
#define READ_ERROR_INT64_CODE 6
 
57
#define READ_ERROR_NATIVEINT_CODE 7
 
58
#define READ_ERROR_UNIT_CODE 8
 
59
#define READ_ERROR_BOOL_CODE 9
 
60
#define READ_ERROR_OPTION_CODE 10
 
61
#define READ_ERROR_STRING_TOO_LONG 11
 
62
#define READ_ERROR_VARIANT_TAG 12
 
63
#define READ_ERROR_ARRAY_TOO_LONG 13
 
64
 
 
65
static inline value raise_Error(int loc) Noreturn;
 
66
 
 
67
static inline value raise_Error(int loc)
 
68
{
 
69
  caml_raise_with_arg(*v_exc_Error, Val_int(loc));
 
70
}
 
71
 
 
72
static inline void raise_Read_error(int loc, unsigned long pos) Noreturn;
 
73
 
 
74
static inline void raise_Read_error(int loc, unsigned long pos)
 
75
{
 
76
  value v_exc = caml_alloc_small(3, 0);
 
77
  Field(v_exc, 0) = *v_exc_Read_error;
 
78
  Field(v_exc, 1) = Val_int(loc);
 
79
  Field(v_exc, 2) = Val_long(pos);
 
80
  caml_raise(v_exc);
 
81
}
 
82
 
 
83
 
 
84
/* Utility macros */
 
85
 
 
86
#define MK_DO_READ(SIZE, TYPE) \
 
87
  static inline __pure TYPE do_read_int##SIZE(char **sptr_ptr) \
 
88
  { \
 
89
    return *(TYPE *) *sptr_ptr; \
 
90
  }
 
91
 
 
92
#define MK_GEN_SAFE_READ(NAME, SIZE, TYPE, LEN, CHECK) \
 
93
  static inline TYPE safe_read_##NAME##SIZE(char **sptr_ptr, char *eptr) \
 
94
  { \
 
95
    char *sptr = *sptr_ptr; \
 
96
    char *next = sptr + LEN; \
 
97
    TYPE n; \
 
98
    if (unlikely(next > eptr)) \
 
99
      caml_raise_constant(*v_bin_prot_exc_Buffer_short); \
 
100
    n = do_read_int##SIZE(sptr_ptr); \
 
101
    CHECK \
 
102
    *sptr_ptr = next; \
 
103
    return n; \
 
104
  }
 
105
 
 
106
#define MK_SAFE_READ(SIZE, TYPE, LEN, CHECK) \
 
107
  MK_DO_READ(SIZE, TYPE) \
 
108
  MK_GEN_SAFE_READ(int, SIZE, TYPE, LEN, CHECK)
 
109
 
 
110
#define MK_GEN_SAFE_NAT0_READ(PREF, SIZE, TYPE, LEN, CHECK) \
 
111
  MK_GEN_SAFE_READ(PREF##nat0_, SIZE, unsigned TYPE, LEN, CHECK)
 
112
 
 
113
#define MK_SAFE_NAT0_READ(SIZE, TYPE, LEN, CHECK) \
 
114
  MK_GEN_SAFE_NAT0_READ(, SIZE, TYPE, LEN, CHECK)
 
115
 
 
116
#define MK_ML_READER(NAME) \
 
117
  CAMLprim value ml_read_##NAME##_stub(value v_buf, value v_pos_ref) \
 
118
  { \
 
119
    CAMLparam2(v_buf, v_pos_ref); \
 
120
      struct caml_ba_array *buf = Caml_ba_array_val(v_buf); \
 
121
      char *start = buf->data; \
 
122
      long pos = Long_val(Field(v_pos_ref, 0)); \
 
123
      char *sptr = start + pos; \
 
124
      char **sptr_ptr = &sptr; \
 
125
      char *eptr = start + *buf->dim; \
 
126
      value v_res; \
 
127
      if (unlikely(pos < 0)) caml_array_bound_error(); \
 
128
      v_res = read_##NAME##_stub(sptr_ptr, eptr); \
 
129
      Field(v_pos_ref, 0) = Val_long(sptr - start); \
 
130
    CAMLreturn(v_res); \
 
131
  }
 
132
 
 
133
 
 
134
/* Reading OCaml integers */
 
135
 
 
136
MK_DO_READ(8, char)
 
137
 
 
138
MK_GEN_SAFE_READ(neg_int, 8, char, 1,
 
139
  if (unlikely(n >= 0)) {
 
140
    *sptr_ptr = sptr - 1;
 
141
    raise_Error(READ_ERROR_NEG_INT8);
 
142
  })
 
143
 
 
144
MK_SAFE_READ(16, short, 2,)
 
145
 
 
146
#ifdef ARCH_SIXTYFOUR
 
147
  MK_SAFE_READ(32, int, 4,)
 
148
#else
 
149
  MK_DO_READ(32, int)
 
150
  MK_GEN_SAFE_READ(int, 32, int, 4,
 
151
    if (unlikely(n < -0x40000000l || n > 0x3FFFFFFFl)) {
 
152
      *sptr_ptr = sptr - 1;
 
153
      raise_Error(READ_ERROR_INT_OVERFLOW);
 
154
    })
 
155
  MK_GEN_SAFE_READ(nocheck_int, 32, int, 4,)
 
156
#endif
 
157
 
 
158
#ifdef ARCH_SIXTYFOUR
 
159
  MK_SAFE_READ(64, long, 8,
 
160
    if (unlikely(n < -0x4000000000000000L || n > 0x3FFFFFFFFFFFFFFFL)) {
 
161
      *sptr_ptr = sptr - 1;
 
162
      raise_Error(READ_ERROR_INT_OVERFLOW);
 
163
    })
 
164
  MK_GEN_SAFE_READ(nocheck_int, 64, long, 8,)
 
165
#endif
 
166
 
 
167
static inline long read_int(char **sptr_ptr, char *eptr)
 
168
{
 
169
  char *sptr = *sptr_ptr;
 
170
  int code;
 
171
  if (unlikely(sptr >= eptr)) caml_raise_constant(*v_bin_prot_exc_Buffer_short);
 
172
  code = *sptr;
 
173
  *sptr_ptr = sptr + 1;
 
174
  if (likely(code >= 0)) return code;
 
175
  if (likely(code == CODE_INT16)) return safe_read_int16(sptr_ptr, eptr);
 
176
  if (likely(code == CODE_NEG_INT8)) return safe_read_neg_int8(sptr_ptr, eptr);
 
177
  if (likely(code == CODE_INT32)) return safe_read_int32(sptr_ptr, eptr);
 
178
#ifdef ARCH_SIXTYFOUR
 
179
  if (likely(code == CODE_INT64)) return safe_read_int64(sptr_ptr, eptr);
 
180
#endif
 
181
  *sptr_ptr = sptr;
 
182
  raise_Error(READ_ERROR_INT_CODE);
 
183
}
 
184
 
 
185
CAMLprim value read_int_stub(char **sptr_ptr, char *eptr)
 
186
{
 
187
  return Val_long(read_int(sptr_ptr, eptr));
 
188
}
 
189
 
 
190
 
 
191
/* Non-negative OCaml integers */
 
192
 
 
193
MK_SAFE_NAT0_READ(16, short, 2,)
 
194
 
 
195
#ifdef ARCH_SIXTYFOUR
 
196
  MK_SAFE_NAT0_READ(32, int, 4,)
 
197
#else
 
198
  MK_SAFE_NAT0_READ(32, int, 4,
 
199
    if (unlikely(n > 0x3FFFFFFFl)) {
 
200
      *sptr_ptr = sptr - 1;
 
201
      raise_Error(READ_ERROR_NAT0_OVERFLOW);
 
202
    })
 
203
  MK_GEN_SAFE_NAT0_READ(nocheck, 32, int, 4,)
 
204
#endif
 
205
 
 
206
#ifdef ARCH_SIXTYFOUR
 
207
  MK_SAFE_NAT0_READ(64, long, 8,
 
208
    if (unlikely(n > 0x3FFFFFFFFFFFFFFFL)) {
 
209
      *sptr_ptr = sptr - 1;
 
210
      raise_Error(READ_ERROR_NAT0_OVERFLOW);
 
211
    })
 
212
  MK_GEN_SAFE_NAT0_READ(nocheck, 64, long, 8,)
 
213
#endif
 
214
 
 
215
static inline unsigned long read_nat0(char **sptr_ptr, char *eptr)
 
216
{
 
217
  char *sptr = *sptr_ptr;
 
218
  int code;
 
219
  if (unlikely(sptr >= eptr)) caml_raise_constant(*v_bin_prot_exc_Buffer_short);
 
220
  code = *sptr;
 
221
  *sptr_ptr = sptr + 1;
 
222
  if (likely(code >= 0)) return code;
 
223
  if (likely(code == CODE_INT16)) return safe_read_nat0_16(sptr_ptr, eptr);
 
224
  if (likely(code == CODE_INT32)) return safe_read_nat0_32(sptr_ptr, eptr);
 
225
#ifdef ARCH_SIXTYFOUR
 
226
  if (likely(code == CODE_INT64)) return safe_read_nat0_64(sptr_ptr, eptr);
 
227
#endif
 
228
  *sptr_ptr = sptr;
 
229
  raise_Error(READ_ERROR_NAT0_CODE);
 
230
}
 
231
 
 
232
CAMLprim value read_nat0_stub(char **sptr_ptr, char *eptr)
 
233
{
 
234
  return Val_long(read_nat0(sptr_ptr, eptr));
 
235
}
 
236
 
 
237
 
 
238
/* Reading 32bit integers */
 
239
 
 
240
static inline long read_int32(char **sptr_ptr, char *eptr)
 
241
{
 
242
  char *sptr = *sptr_ptr;
 
243
  int code;
 
244
  if (unlikely(sptr >= eptr)) caml_raise_constant(*v_bin_prot_exc_Buffer_short);
 
245
  code = *sptr;
 
246
  *sptr_ptr = sptr + 1;
 
247
  if (likely(code >= 0)) return code;
 
248
  if (likely(code == CODE_INT16)) return safe_read_int16(sptr_ptr, eptr);
 
249
  if (likely(code == CODE_NEG_INT8)) return safe_read_neg_int8(sptr_ptr, eptr);
 
250
  if (likely(code == CODE_INT32))
 
251
#ifdef ARCH_SIXTYFOUR
 
252
    return safe_read_int32(sptr_ptr, eptr);
 
253
#else
 
254
    return safe_read_nocheck_int32(sptr_ptr, eptr);
 
255
#endif
 
256
  *sptr_ptr = sptr;
 
257
  raise_Error(READ_ERROR_INT32_CODE);
 
258
}
 
259
 
 
260
CAMLprim value read_int32_stub(char **sptr_ptr, char *eptr)
 
261
{
 
262
  return caml_copy_int32(read_int32(sptr_ptr, eptr));
 
263
}
 
264
 
 
265
 
 
266
/* Reading 64bit integers */
 
267
 
 
268
#ifdef ARCH_INT64_TYPE
 
269
#include "int64_native.h"
 
270
#else
 
271
#include "int64_emul.h"
 
272
#endif
 
273
 
 
274
static inline int64 read_int64(char **sptr_ptr, char *eptr)
 
275
{
 
276
  char *sptr = *sptr_ptr;
 
277
  int code;
 
278
  if (unlikely(sptr >= eptr)) caml_raise_constant(*v_bin_prot_exc_Buffer_short);
 
279
  code = *sptr;
 
280
  *sptr_ptr = sptr + 1;
 
281
  if (likely(code >= 0))
 
282
#ifdef ARCH_SIXTYFOUR
 
283
    return code;
 
284
  if (likely(code == CODE_INT16)) return safe_read_int16(sptr_ptr, eptr);
 
285
  if (likely(code == CODE_NEG_INT8)) return safe_read_neg_int8(sptr_ptr, eptr);
 
286
  if (likely(code == CODE_INT32)) return safe_read_int32(sptr_ptr, eptr);
 
287
  if (likely(code == CODE_INT64)) return safe_read_nocheck_int64(sptr_ptr, eptr);
 
288
#else
 
289
    return I64_literal(0, code);
 
290
  if (likely(code == CODE_INT16))
 
291
    return I64_of_int32(safe_read_int16(sptr_ptr, eptr));
 
292
  if (likely(code == CODE_NEG_INT8))
 
293
    return I64_literal(0xFFFFFFFF, safe_read_neg_int8(sptr_ptr, eptr));
 
294
  if (likely(code == CODE_INT32))
 
295
    return I64_of_int32(safe_read_nocheck_int32(sptr_ptr, eptr));
 
296
  if (likely(code == CODE_INT64)) {
 
297
    unsigned int l = safe_read_nocheck_int32(sptr_ptr, eptr);
 
298
    return I64_literal(safe_read_nocheck_int32(sptr_ptr, eptr), l);
 
299
  }
 
300
#endif
 
301
  *sptr_ptr = sptr;
 
302
  raise_Error(READ_ERROR_INT64_CODE);
 
303
}
 
304
 
 
305
CAMLprim value read_int64_stub(char **sptr_ptr, char *eptr)
 
306
{
 
307
  return caml_copy_int64(read_int64(sptr_ptr, eptr));
 
308
}
 
309
 
 
310
 
 
311
/* Reading nativeints */
 
312
 
 
313
static inline long read_nativeint(char **sptr_ptr, char *eptr)
 
314
{
 
315
  char *sptr = *sptr_ptr;
 
316
  int code;
 
317
  if (unlikely(sptr >= eptr)) caml_raise_constant(*v_bin_prot_exc_Buffer_short);
 
318
  code = *sptr;
 
319
  *sptr_ptr = sptr + 1;
 
320
  if (likely(code >= 0)) return code;
 
321
  if (likely(code == CODE_INT16)) return safe_read_int16(sptr_ptr, eptr);
 
322
  if (likely(code == CODE_NEG_INT8)) return safe_read_neg_int8(sptr_ptr, eptr);
 
323
#ifdef ARCH_SIXTYFOUR
 
324
  if (likely(code == CODE_INT32)) return safe_read_int32(sptr_ptr, eptr);
 
325
  if (likely(code == CODE_INT64)) return safe_read_nocheck_int64(sptr_ptr, eptr);
 
326
#else
 
327
  if (likely(code == CODE_INT32)) return safe_read_nocheck_int32(sptr_ptr, eptr);
 
328
#endif
 
329
  *sptr_ptr = sptr;
 
330
  raise_Error(READ_ERROR_NATIVEINT_CODE);
 
331
}
 
332
 
 
333
CAMLprim value read_nativeint_stub(char **sptr_ptr, char *eptr)
 
334
{
 
335
  return caml_copy_nativeint(read_nativeint(sptr_ptr, eptr));
 
336
}
 
337
 
 
338
 
 
339
/* Reading unsigned short words */
 
340
 
 
341
CAMLprim value read_uint16_stub(char **sptr_ptr, char *eptr)
 
342
{
 
343
  unsigned short res = safe_read_nat0_16(sptr_ptr, eptr);
 
344
  return Val_int(res);
 
345
}
 
346
 
 
347
 
 
348
/* Reading unit value */
 
349
 
 
350
CAMLprim value read_unit_stub(char **sptr_ptr, char *eptr)
 
351
{
 
352
  char *sptr = *sptr_ptr;
 
353
  int res;
 
354
  if (unlikely(sptr >= eptr)) caml_raise_constant(*v_bin_prot_exc_Buffer_short);
 
355
  res = *sptr;
 
356
  if (res == 0) { *sptr_ptr = ++sptr; return Val_unit; }
 
357
  raise_Error(READ_ERROR_UNIT_CODE);
 
358
}
 
359
 
 
360
 
 
361
/* Reading booleans and options */
 
362
 
 
363
#define READ_ZERO_OR_ONE(NAME, CODE) \
 
364
  CAMLprim value read_##NAME##_stub(char **sptr_ptr, char *eptr) \
 
365
  { \
 
366
    char *sptr = *sptr_ptr; \
 
367
    int res; \
 
368
    if (unlikely(sptr >= eptr)) \
 
369
      caml_raise_constant(*v_bin_prot_exc_Buffer_short); \
 
370
    res = *sptr; \
 
371
    if (res == 0) { *sptr_ptr = ++sptr; return Val_int(0); } \
 
372
    if (res == 1) { *sptr_ptr = ++sptr; return Val_int(1); } \
 
373
    raise_Error(CODE); \
 
374
  }
 
375
 
 
376
READ_ZERO_OR_ONE(bool, READ_ERROR_BOOL_CODE)
 
377
READ_ZERO_OR_ONE(option_bool, READ_ERROR_OPTION_CODE)
 
378
 
 
379
 
 
380
/* Reading characters */
 
381
 
 
382
CAMLprim value read_char_stub(char **sptr_ptr, char *eptr)
 
383
{
 
384
  char *sptr = *sptr_ptr;
 
385
  int res;
 
386
  if (unlikely(sptr >= eptr)) caml_raise_constant(*v_bin_prot_exc_Buffer_short);
 
387
  res = *sptr;
 
388
  *sptr_ptr = ++sptr;
 
389
  return Val_int(res);
 
390
}
 
391
 
 
392
 
 
393
/* Reading strings */
 
394
 
 
395
CAMLprim value read_string_stub(char **sptr_ptr, char *eptr)
 
396
{
 
397
  value v_res;
 
398
  char *start = *sptr_ptr;
 
399
  unsigned long len = read_nat0(sptr_ptr, eptr);
 
400
  char *sptr = *sptr_ptr;
 
401
  char *next = sptr + len;
 
402
  if (unlikely(len > Bsize_wsize(Max_wosize) - 1)) {
 
403
    *sptr_ptr = start;
 
404
    raise_Error(READ_ERROR_STRING_TOO_LONG);
 
405
  }
 
406
  if (unlikely(next > eptr)) caml_raise_constant(*v_bin_prot_exc_Buffer_short);
 
407
  *sptr_ptr = next;
 
408
  v_res = caml_alloc_string(len);
 
409
  memcpy(String_val(v_res), sptr, len);
 
410
  return v_res;
 
411
}
 
412
 
 
413
 
 
414
/* Reading floats and float arrays */
 
415
 
 
416
CAMLprim inline value read_float_stub(char **sptr_ptr, char *eptr)
 
417
{
 
418
  char *sptr = *sptr_ptr;
 
419
  char *next = sptr + sizeof(double);
 
420
  if (unlikely(next > eptr)) caml_raise_constant(*v_bin_prot_exc_Buffer_short);
 
421
  *sptr_ptr = next;
 
422
  return caml_copy_double(*(double *) sptr);
 
423
}
 
424
 
 
425
MK_ML_READER(float)
 
426
 
 
427
CAMLprim value read_float_array_stub(char **sptr_ptr, char *eptr)
 
428
{
 
429
  char *start = *sptr_ptr;
 
430
  unsigned long len = read_nat0(sptr_ptr, eptr);
 
431
  unsigned long tot_size;
 
432
  unsigned long wsize;
 
433
  char *sptr;
 
434
  char *next;
 
435
  value v_res;
 
436
  if (unlikely(len == 0)) return Atom(0);
 
437
  wsize = len * Double_wosize;
 
438
  if (unlikely(wsize > Max_wosize)) {
 
439
    *sptr_ptr = start;
 
440
    raise_Error(READ_ERROR_ARRAY_TOO_LONG);
 
441
  }
 
442
  sptr = *sptr_ptr;
 
443
  tot_size = len * sizeof(double);
 
444
  next = sptr + tot_size;
 
445
  if (unlikely(next > eptr)) caml_raise_constant(*v_bin_prot_exc_Buffer_short);
 
446
  *sptr_ptr = next;
 
447
  v_res = caml_alloc(wsize, Double_array_tag);
 
448
  memcpy((double *) v_res, sptr, tot_size);
 
449
  return v_res;
 
450
}
 
451
 
 
452
CAMLprim value ml_read_float_array_stub(value v_buf, value v_pos_ref)
 
453
{
 
454
  CAMLparam2(v_buf, v_pos_ref);
 
455
    struct caml_ba_array *buf = Caml_ba_array_val(v_buf);
 
456
    char *start = buf->data;
 
457
    long pos = Long_val(Field(v_pos_ref, 0));
 
458
    char *sptr = start + pos;
 
459
    char **sptr_ptr = &sptr;
 
460
    char *eptr = start + *buf->dim;
 
461
    value v_res;
 
462
    unsigned long len;
 
463
    unsigned long tot_size;
 
464
    unsigned long wsize;
 
465
    char *next;
 
466
    if (unlikely(pos < 0)) caml_array_bound_error();
 
467
    len = read_nat0(sptr_ptr, eptr);
 
468
    if (unlikely(len == 0)) {
 
469
      Field(v_pos_ref, 0) = Val_long(sptr - start);
 
470
      CAMLreturn(Atom(0));
 
471
    }
 
472
    wsize = len * Double_wosize;
 
473
    if (unlikely(wsize > Max_wosize))
 
474
      raise_Read_error(READ_ERROR_ARRAY_TOO_LONG, pos);
 
475
    tot_size = len * sizeof(double);
 
476
    next = sptr + tot_size;
 
477
    if (unlikely(next > eptr)) caml_raise_constant(*v_bin_prot_exc_Buffer_short);
 
478
    v_res = caml_alloc(wsize, Double_array_tag);
 
479
    memcpy((double *) v_res, sptr, tot_size);
 
480
    Field(v_pos_ref, 0) = Val_long(next - start);
 
481
  CAMLreturn(v_res);
 
482
}
 
483
 
 
484
 
 
485
/* Reading polymorphic variants */
 
486
 
 
487
CAMLprim value read_variant_tag_stub(char **sptr_ptr, char *eptr)
 
488
{
 
489
  char *sptr = *sptr_ptr;
 
490
  char *next = sptr + 4;
 
491
  int n;
 
492
  if (unlikely(next > eptr)) caml_raise_constant(*v_bin_prot_exc_Buffer_short);
 
493
  n = *(int *) sptr;
 
494
  if (likely(Is_long(n))) {
 
495
    *sptr_ptr = next;
 
496
    return (value) n;
 
497
  }
 
498
  raise_Error(READ_ERROR_VARIANT_TAG);
 
499
}
 
500
 
 
501
CAMLprim value ml_read_variant_tag_stub(value v_buf, value v_pos_ref)
 
502
{
 
503
  struct caml_ba_array *buf = Caml_ba_array_val(v_buf);
 
504
  char *start = buf->data;
 
505
  long pos = Long_val(Field(v_pos_ref, 0));
 
506
  char *sptr = start + pos;
 
507
  int next_pos = pos + 4;
 
508
  int n;
 
509
  if (unlikely(pos < 0)) caml_array_bound_error();
 
510
  if (unlikely(next_pos > *buf->dim))
 
511
    caml_raise_constant(*v_bin_prot_exc_Buffer_short);
 
512
  n = *(int *) sptr;
 
513
  if (likely(Is_long(n))) {
 
514
    Field(v_pos_ref, 0) = Val_long(next_pos);
 
515
    return (value) n;
 
516
  }
 
517
  else raise_Read_error(READ_ERROR_VARIANT_TAG, pos);
 
518
}
 
519
 
 
520
 
 
521
/* Reading bigarrays */
 
522
 
 
523
#define MK_BA1_READER(NAME, TYPE, TFLAG) \
 
524
  CAMLprim inline value read_##NAME##_stub(char **sptr_ptr, char *eptr) \
 
525
  { \
 
526
    unsigned long len = read_nat0(sptr_ptr, eptr); \
 
527
    int tot_size = len * sizeof(TYPE); \
 
528
    char *sptr = *sptr_ptr; \
 
529
    char *next = sptr + tot_size; \
 
530
    intnat dim; \
 
531
    value v_res; \
 
532
    if (unlikely(next > eptr)) \
 
533
      caml_raise_constant(*v_bin_prot_exc_Buffer_short); \
 
534
    dim = len; \
 
535
    v_res = \
 
536
      caml_ba_alloc( \
 
537
        CAML_BA_##TFLAG | CAML_BA_FORTRAN_LAYOUT, 1, NULL, &dim); \
 
538
    *sptr_ptr = next; \
 
539
    if (unlikely(tot_size > 65536)) { \
 
540
      Begin_roots1(v_res); \
 
541
      caml_enter_blocking_section(); \
 
542
        memcpy((TYPE *) Caml_ba_data_val(v_res), sptr, tot_size); \
 
543
      caml_leave_blocking_section(); \
 
544
      End_roots(); \
 
545
    } else memcpy((TYPE *) Caml_ba_data_val(v_res), sptr, tot_size); \
 
546
    return v_res; \
 
547
  } \
 
548
  \
 
549
  MK_ML_READER(NAME)
 
550
 
 
551
MK_BA1_READER(bigstring, char, UINT8)
 
552
 
 
553
#define MK_VEC_MAT_READERS(NAME, TYPE, TFLAG) \
 
554
  MK_BA1_READER(NAME##_vec, TYPE, TFLAG) \
 
555
  \
 
556
  CAMLprim inline value read_##NAME##_mat_stub(char **sptr_ptr, char *eptr) \
 
557
  { \
 
558
    unsigned long dim1 = read_nat0(sptr_ptr, eptr); \
 
559
    unsigned long dim2 = read_nat0(sptr_ptr, eptr); \
 
560
    unsigned long size = dim1 * dim2; \
 
561
    int tot_size = size * sizeof(TYPE); \
 
562
    char *sptr = *sptr_ptr; \
 
563
    char *next = sptr + tot_size; \
 
564
    intnat dims[2]; \
 
565
    value v_res; \
 
566
    if (unlikely(next > eptr)) \
 
567
      caml_raise_constant(*v_bin_prot_exc_Buffer_short); \
 
568
    dims[0] = dim1; \
 
569
    dims[1] = dim2; \
 
570
    v_res = \
 
571
      caml_ba_alloc( \
 
572
        CAML_BA_##TFLAG | CAML_BA_FORTRAN_LAYOUT, 2, NULL, dims); \
 
573
    *sptr_ptr = next; \
 
574
    if (unlikely(tot_size > 65536)) { \
 
575
      Begin_roots1(v_res); \
 
576
      caml_enter_blocking_section(); \
 
577
        memcpy((TYPE *) Caml_ba_data_val(v_res), sptr, tot_size); \
 
578
      caml_leave_blocking_section(); \
 
579
      End_roots(); \
 
580
    } else memcpy((TYPE *) Caml_ba_data_val(v_res), sptr, tot_size); \
 
581
    return v_res; \
 
582
  } \
 
583
  \
 
584
  MK_ML_READER(NAME##_mat)
 
585
 
 
586
MK_VEC_MAT_READERS(float32, float, FLOAT32)
 
587
MK_VEC_MAT_READERS(float64, double, FLOAT64)