File: duk_hbufobj.h

package info (click to toggle)
duktape 2.7.0-2
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, forky, sid, trixie
  • size: 21,160 kB
  • sloc: ansic: 215,359; python: 5,961; javascript: 4,555; makefile: 477; cpp: 205
file content (137 lines) | stat: -rw-r--r-- 5,560 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
/*
 *  Heap Buffer object representation.  Used for all Buffer variants.
 */

#if !defined(DUK_HBUFOBJ_H_INCLUDED)
#define DUK_HBUFOBJ_H_INCLUDED

#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)

/* All element accessors are host endian now (driven by TypedArray spec). */
#define DUK_HBUFOBJ_ELEM_UINT8        0
#define DUK_HBUFOBJ_ELEM_UINT8CLAMPED 1
#define DUK_HBUFOBJ_ELEM_INT8         2
#define DUK_HBUFOBJ_ELEM_UINT16       3
#define DUK_HBUFOBJ_ELEM_INT16        4
#define DUK_HBUFOBJ_ELEM_UINT32       5
#define DUK_HBUFOBJ_ELEM_INT32        6
#define DUK_HBUFOBJ_ELEM_FLOAT32      7
#define DUK_HBUFOBJ_ELEM_FLOAT64      8
#define DUK_HBUFOBJ_ELEM_MAX          8

#if defined(DUK_USE_ASSERTIONS)
DUK_INTERNAL_DECL void duk_hbufobj_assert_valid(duk_hbufobj *h);
#define DUK_HBUFOBJ_ASSERT_VALID(h) \
	do { \
		duk_hbufobj_assert_valid((h)); \
	} while (0)
#else
#define DUK_HBUFOBJ_ASSERT_VALID(h) \
	do { \
	} while (0)
#endif

/* Get the current data pointer (caller must ensure buf != NULL) as a
 * duk_uint8_t ptr.  Note that the result may be NULL if the underlying
 * buffer has zero size and is not a fixed buffer.
 */
#define DUK_HBUFOBJ_GET_SLICE_BASE(heap, h) \
	(DUK_ASSERT_EXPR((h) != NULL), \
	 DUK_ASSERT_EXPR((h)->buf != NULL), \
	 (((duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR((heap), (h)->buf)) + (h)->offset))

/* True if slice is full, i.e. offset is zero and length covers the entire
 * buffer.  This status may change independently of the duk_hbufobj if
 * the underlying buffer is dynamic and changes without the hbufobj
 * being changed.
 */
#define DUK_HBUFOBJ_FULL_SLICE(h) \
	(DUK_ASSERT_EXPR((h) != NULL), \
	 DUK_ASSERT_EXPR((h)->buf != NULL), \
	 ((h)->offset == 0 && (h)->length == DUK_HBUFFER_GET_SIZE((h)->buf)))

/* Validate that the whole slice [0,length[ is contained in the underlying
 * buffer.  Caller must ensure 'buf' != NULL.
 */
#define DUK_HBUFOBJ_VALID_SLICE(h) \
	(DUK_ASSERT_EXPR((h) != NULL), \
	 DUK_ASSERT_EXPR((h)->buf != NULL), \
	 ((h)->offset + (h)->length <= DUK_HBUFFER_GET_SIZE((h)->buf)))

/* Validate byte read/write for virtual 'offset', i.e. check that the
 * offset, taking into account h->offset, is within the underlying
 * buffer size.  This is a safety check which is needed to ensure
 * that even a misconfigured duk_hbufobj never causes memory unsafe
 * behavior (e.g. if an underlying dynamic buffer changes after being
 * setup).  Caller must ensure 'buf' != NULL.
 */
#define DUK_HBUFOBJ_VALID_BYTEOFFSET_INCL(h, off) \
	(DUK_ASSERT_EXPR((h) != NULL), DUK_ASSERT_EXPR((h)->buf != NULL), ((h)->offset + (off) < DUK_HBUFFER_GET_SIZE((h)->buf)))

#define DUK_HBUFOBJ_VALID_BYTEOFFSET_EXCL(h, off) \
	(DUK_ASSERT_EXPR((h) != NULL), DUK_ASSERT_EXPR((h)->buf != NULL), ((h)->offset + (off) <= DUK_HBUFFER_GET_SIZE((h)->buf)))

/* Clamp an input byte length (already assumed to be within the nominal
 * duk_hbufobj 'length') to the current dynamic buffer limits to yield
 * a byte length limit that's safe for memory accesses.  This value can
 * be invalidated by any side effect because it may trigger a user
 * callback that resizes the underlying buffer.
 */
#define DUK_HBUFOBJ_CLAMP_BYTELENGTH(h, len) (DUK_ASSERT_EXPR((h) != NULL), duk_hbufobj_clamp_bytelength((h), (len)))

/* Typed arrays have virtual indices, ArrayBuffer and DataView do not. */
#define DUK_HBUFOBJ_HAS_VIRTUAL_INDICES(h) ((h)->is_typedarray)

struct duk_hbufobj {
	/* Shared object part. */
	duk_hobject obj;

	/* Underlying buffer (refcounted), may be NULL. */
	duk_hbuffer *buf;

	/* .buffer reference to an ArrayBuffer, may be NULL. */
	duk_hobject *buf_prop;

	/* Slice and accessor information.
	 *
	 * Because the underlying buffer may be dynamic, these may be
	 * invalidated by the buffer being modified so that both offset
	 * and length should be validated before every access.  Behavior
	 * when the underlying buffer has changed doesn't need to be clean:
	 * virtual 'length' doesn't need to be affected, reads can return
	 * zero/NaN, and writes can be ignored.
	 *
	 * Note that a data pointer cannot be precomputed because 'buf' may
	 * be dynamic and its pointer unstable.
	 */

	duk_uint_t offset; /* byte offset to buf */
	duk_uint_t length; /* byte index limit for element access, exclusive */
	duk_uint8_t shift; /* element size shift:
	                    *   0 = u8/i8
	                    *   1 = u16/i16
	                    *   2 = u32/i32/float
	                    *   3 = double
	                    */
	duk_uint8_t elem_type; /* element type */
	duk_uint8_t is_typedarray;
};

DUK_INTERNAL_DECL duk_uint_t duk_hbufobj_clamp_bytelength(duk_hbufobj *h_bufobj, duk_uint_t len);
DUK_INTERNAL_DECL void duk_hbufobj_push_uint8array_from_plain(duk_hthread *thr, duk_hbuffer *h_buf);
DUK_INTERNAL_DECL void duk_hbufobj_push_validated_read(duk_hthread *thr,
                                                       duk_hbufobj *h_bufobj,
                                                       duk_uint8_t *p,
                                                       duk_small_uint_t elem_size);
DUK_INTERNAL_DECL void duk_hbufobj_validated_write(duk_hthread *thr,
                                                   duk_hbufobj *h_bufobj,
                                                   duk_uint8_t *p,
                                                   duk_small_uint_t elem_size);
DUK_INTERNAL_DECL void duk_hbufobj_promote_plain(duk_hthread *thr, duk_idx_t idx);

#else /* DUK_USE_BUFFEROBJECT_SUPPORT */

/* nothing */

#endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
#endif /* DUK_HBUFOBJ_H_INCLUDED */