-
Notifications
You must be signed in to change notification settings - Fork 227
Expand file tree
/
Copy pathPyBUF.java
More file actions
258 lines (243 loc) · 12.4 KB
/
PyBUF.java
File metadata and controls
258 lines (243 loc) · 12.4 KB
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
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
package org.python.core;
/**
* This interface provides a base for the key interface of the buffer API, {@link PyBuffer},
* including symbolic constants used by the consumer of a {@code PyBuffer} to specify its
* requirements and assumptions. The Jython buffer API emulates the CPython buffer API. There are
* two reasons for separating parts of {@code PyBuffer} into this interface:
* <ul>
* <li>The constants defined in CPython have the names {@code PyBUF_SIMPLE}, {@code PyBUF_WRITABLE},
* etc., and the trick of defining ours here means we can write {@code PyBUF.SIMPLE},
* {@code PyBUF.WRITABLE}, etc. so source code looks similar.</li>
* <li>It is not so easy in Java as it is in C to treat a {@code byte} array as storing anything
* other than {@code byte}, and we prepare for the possibility of buffers with a series of different
* primitive types by defining here those methods that would be in common between
* (Byte){@code Buffer} and an assumed future {@code FloatBuffer} or {@code TypedBuffer<T>}.
* (Compare {@code java.nio.Buffer}.)</li>
* </ul>
* It is unlikely any classes would implement {@code PyBUF}, except indirectly through other
* interfaces. Users of the Jython buffer API can mostly overlook the distinction and just use
* {@code PyBuffer}.
*/
public interface PyBUF {
/**
* Determine whether the consumer is entitled to write to the exported storage.
*
* @return true if writing is not allowed, false if it is.
*/
boolean isReadonly();
/**
* The number of dimensions to the buffer. This number is the length of the {@code shape} array.
* The actual storage may be a linear array, but this is the number of dimensions in the
* interpretation that the exporting object gives the data.
*
* @return number of dimensions
*/
int getNdim();
/**
* An array reporting the size of the buffer, considered as a multidimensional array, in each
* dimension and (by its length) giving the number of dimensions. The size of the buffer is its
* size in "items". An item is the amount of buffer content addressed by one index or set of
* indices. In the simplest case an item is a single unit (byte), and there is one dimension. In
* complex cases, the array is multi-dimensional, and the item at each location is multi-unit
* (multi-byte). The consumer must not modify this array. A valid {@code shape} array is always
* returned (difference from CPython).
*
* @return the dimensions of the buffer as an array
*/
int[] getShape();
/**
* The number of bytes stored in each indexable item.
*
* @return the number of bytes comprising each item.
*/
int getItemsize();
/**
* The total number of bytes represented by the view, which will be the product of the elements
* of the {@code shape} array, and the item size in bytes.
*
* @return the total number of bytes represented.
*/
int getLen();
/**
* The {@code strides} array gives the distance in the storage array between adjacent items (in
* each dimension). In the rawest parts of the buffer API, the consumer of the buffer is able to
* navigate the exported storage. The "strides" array is part of the support for interpreting
* the buffer as an n-dimensional array of items. It provides the coefficients of the
* "addressing polynomial". (More on this in the CPython documentation.) The consumer must not
* modify this array. A valid {@code strides} array is always returned (difference from
* CPython).
*
* @return the distance in the storage array between adjacent items (in each dimension)
*/
int[] getStrides();
/**
* The {@code suboffsets} array is a further part of the support for interpreting the buffer as
* an n-dimensional array of items, where the array potentially uses indirect addressing (like a
* real Java array of arrays, in fact). This is only applicable when there is more than 1
* dimension, and it works in conjunction with the {@code strides} array. (More on this in the
* CPython documentation.) When used, {@code suboffsets[k]} is an integer index, not a byte
* offset as in CPython. The consumer must not modify this array. When not needed for navigation
* {@code null} is returned (as in CPython).
*
* @return suboffsets array or {@code null} if not necessary for navigation
*/
int[] getSuboffsets();
/**
* Enquire whether the array is represented contiguously in the backing storage, according to C
* or Fortran ordering. A one-dimensional contiguous array is both.
*
* @param order 'C', 'F' or 'A', as the storage order is C, Fortran or either.
* @return true iff the array is stored contiguously in the order specified
*/
boolean isContiguous(char order);
/* Constants taken from CPython object.h in v3.3 */
/**
* The maximum allowed number of dimensions (CPython restriction).
*/
static final int MAX_NDIM = 64;
/**
* A constant used by the consumer in its call to {@link BufferProtocol#getBuffer(int)} to
* specify that it expects to write to the buffer contents. {@code getBuffer} will raise an
* exception if the exporter's buffer cannot meet this requirement.
*/
static final int WRITABLE = 0x0001;
/**
* A constant used by the consumer in its call to {@link BufferProtocol#getBuffer(int)} to
* specify that it assumes a simple one-dimensional organisation of the exported storage with
* item size of one. {@code getBuffer} will raise an exception if the consumer sets this flag
* and the exporter cannot represent itself as byte array data.
*/
static final int SIMPLE = 0;
/**
* A constant used by the consumer in its call to {@link BufferProtocol#getBuffer(int)} to
* specify that it requires {@link PyBuffer#getFormat()} to return a {@code String} indicating
* the type of the unit. This exists for compatibility with CPython, as in Jython the format is
* always provided by {@code getFormat()}.
*/
static final int FORMAT = 0x0004;
/**
* A constant used by the consumer in its call to {@link BufferProtocol#getBuffer(int)} to
* specify that it is prepared to navigate the buffer as multi-dimensional using the
* {@code shape} array. {@code getBuffer} will raise an exception if consumer does not specify
* the flag but the exporter's buffer cannot be navigated without taking into account its
* multiple dimensions.
*/
static final int ND = 0x0008;
/**
* A constant used by the consumer in its call to {@link BufferProtocol#getBuffer(int)} to
* specify that it expects to use the {@code strides} array. {@code getBuffer} will raise an
* exception if consumer does not specify the flag but the exporter's buffer cannot be navigated
* without using the {@code strides} array.
*/
static final int STRIDES = 0x0010 | ND;
/**
* A constant used by the consumer in its call to {@link BufferProtocol#getBuffer(int)} to
* specify that it will assume C-order organisation of the items. {@code getBuffer} will raise
* an exception if the exporter's buffer is not C-ordered. {@code C_CONTIGUOUS} implies
* {@code STRIDES}.
*/
// It is possible this should have been (0x20|ND) expressing the idea that C-order addressing
// will be assumed *instead of* using a strides array.
static final int C_CONTIGUOUS = 0x0020 | STRIDES;
/**
* A constant used by the consumer in its call to {@link BufferProtocol#getBuffer(int)} to
* specify that it will assume Fortran-order organisation of the items. {@code getBuffer} will
* raise an exception if the exporter's buffer is not Fortran-ordered. {@code F_CONTIGUOUS}
* implies {@code STRIDES}.
*/
static final int F_CONTIGUOUS = 0x0040 | STRIDES;
/**
* A constant used by the consumer in its call to {@link BufferProtocol#getBuffer(int)} to
* specify that it will assume a contiguous organisation of the items, but will enquire which
* organisation it actually is.
*
* {@code getBuffer} will raise an exception if the exporter's buffer is not contiguous.
* {@code ANY_CONTIGUOUS} implies {@code STRIDES}.
*/
// Further CPython strangeness since it uses the strides array to answer the enquiry.
static final int ANY_CONTIGUOUS = 0x0080 | STRIDES;
/**
* A constant used by the consumer in its call to {@link BufferProtocol#getBuffer(int)} to
* specify that it understands the {@code suboffsets} array. {@code getBuffer} will raise an
* exception if consumer does not specify the flag but the exporter's buffer cannot be navigated
* without understanding the {@code suboffsets} array. {@code INDIRECT} implies {@code STRIDES}.
*/
static final int INDIRECT = 0x0100 | STRIDES;
/**
* Equivalent to {@code (ND | WRITABLE)}
*/
static final int CONTIG = ND | WRITABLE;
/**
* Equivalent to {@code ND}
*/
static final int CONTIG_RO = ND;
/**
* Equivalent to {@code (STRIDES | WRITABLE)}
*/
static final int STRIDED = STRIDES | WRITABLE;
/**
* Equivalent to {@code STRIDES}
*/
static final int STRIDED_RO = STRIDES;
/**
* Equivalent to {@code (STRIDES | WRITABLE | FORMAT)}
*/
static final int RECORDS = STRIDES | WRITABLE | FORMAT;
/**
* Equivalent to {@code (STRIDES | FORMAT)}
*/
static final int RECORDS_RO = STRIDES | FORMAT;
/**
* Equivalent to {@code (INDIRECT | WRITABLE | FORMAT)}. Also use this in the request if you
* plan only to use the fully-encapsulated API ({@code byteAt}, {@code storeAt}, {@code copyTo},
* {@code copyFrom}, etc.), without ever calling {@link PyBuffer#getNIOByteBuffer()} or using
* {@link PyBuffer.Pointer}.
*/
static final int FULL = INDIRECT | WRITABLE | FORMAT;
/**
* Equivalent to {@code (INDIRECT | FORMAT)}. Also use this in the request if you plan only to
* use the fully-encapsulated API ({@code byteAt}, {@code copyTo}, etc.), read only, without
* ever calling {@link PyBuffer#getNIOByteBuffer()} or using {@link PyBuffer.Pointer}.
*/
static final int FULL_RO = INDIRECT | FORMAT;
/* Constants for additional feature(s), not standard for CPython */
/**
* A constant used by the consumer in its call to {@link BufferProtocol#getBuffer(int)} to
* specify that it expects to access the buffer contents directly as an array (rather than
* through the purely abstract part of the API). {@code getBuffer} will raise an exception if
* the exporter cannot expose its storage as Java array.
*/
// XXX Pending: @Deprecated
static final int AS_ARRAY = 0x10000000;
/* Constants for readability, not standard for CPython */
/**
* Field mask, used as in {@code if ((flags&NAVIGATION) == STRIDES) ...}. The importance of the
* subset of flags defined by this mask is not so much in their "navigational" character as in
* the way they are treated in a buffer request.
* <p>
* The {@code NAVIGATION} set are used to specify which navigation arrays the consumer will use,
* and therefore the consumer must ask for all those necessary to use the buffer successfully
* (which is a function of the buffer's actual type). Asking for extra ones is not an error,
* since all are supplied (in Jython): asking for too few is an error.
* <p>
* Flags outside the {@code NAVIGATION} set, work the other way round. Asking for one the buffer
* cannot match is an error: not asking for a feature the buffer does not have is an error.
*/
static final int NAVIGATION = SIMPLE | ND | STRIDES | INDIRECT;
/**
* A constant used by the exporter in processing {@link BufferProtocol#getBuffer(int)} to check
* for assumed C-order organisation of the items.
* {@code C_CONTIGUOUS = IS_C_CONTIGUOUS | STRIDES}.
*/
static final int IS_C_CONTIGUOUS = C_CONTIGUOUS & ~STRIDES;
/**
* A constant used by the exporter in processing {@link BufferProtocol#getBuffer(int)} to check
* for assumed C-order Fortran-order organisation of the items.
* {@code F_CONTIGUOUS = IS_F_CONTIGUOUS | STRIDES}.
*/
static final int IS_F_CONTIGUOUS = F_CONTIGUOUS & ~STRIDES;
/**
* Field mask, used as in if {@code ((flags&CONTIGUITY)== ... ) ...}.
*/
static final int CONTIGUITY = (C_CONTIGUOUS | F_CONTIGUOUS | ANY_CONTIGUOUS) & ~STRIDES;
}