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
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
|
'\"
'\" Copyright (c) 1998 Sun Microsystems, Inc.
'\" Copyright (c) 1999 Scriptics Corporation
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\"
'\" RCS: @(#) $Id: re_syntax.n,v 1.6 2005/01/05 16:38:54 dkf Exp $
'\"
.so man.macros
.TH re_syntax n "8.1" Tcl "Tcl Built-In Commands"
.BS
.SH NAME
re_syntax \- Syntax of Tcl regular expressions
.BE
.SH DESCRIPTION
.PP
A \fIregular expression\fR describes strings of characters.
It's a pattern that matches certain strings and doesn't match others.
.SH "DIFFERENT FLAVORS OF REs"
Regular expressions (``RE''s), as defined by POSIX, come in two
flavors: \fIextended\fR REs (``EREs'') and \fIbasic\fR REs (``BREs'').
EREs are roughly those of the traditional \fIegrep\fR, while BREs are
roughly those of the traditional \fIed\fR. This implementation adds
a third flavor, \fIadvanced\fR REs (``AREs''), basically EREs with
some significant extensions.
.PP
This manual page primarily describes AREs. BREs mostly exist for
backward compatibility in some old programs; they will be discussed at
the end. POSIX EREs are almost an exact subset of AREs. Features of
AREs that are not present in EREs will be indicated.
.SH "REGULAR EXPRESSION SYNTAX"
.PP
Tcl regular expressions are implemented using the package written by
Henry Spencer, based on the 1003.2 spec and some (not quite all) of
the Perl5 extensions (thanks, Henry!). Much of the description of
regular expressions below is copied verbatim from his manual entry.
.PP
An ARE is one or more \fIbranches\fR,
separated by `\fB|\fR',
matching anything that matches any of the branches.
.PP
A branch is zero or more \fIconstraints\fR or \fIquantified atoms\fR,
concatenated.
It matches a match for the first, followed by a match for the second, etc;
an empty branch matches the empty string.
.PP
A quantified atom is an \fIatom\fR possibly followed
by a single \fIquantifier\fR.
Without a quantifier, it matches a match for the atom.
The quantifiers,
and what a so-quantified atom matches, are:
.RS 2
.TP 6
\fB*\fR
a sequence of 0 or more matches of the atom
.TP
\fB+\fR
a sequence of 1 or more matches of the atom
.TP
\fB?\fR
a sequence of 0 or 1 matches of the atom
.TP
\fB{\fIm\fB}\fR
a sequence of exactly \fIm\fR matches of the atom
.TP
\fB{\fIm\fB,}\fR
a sequence of \fIm\fR or more matches of the atom
.TP
\fB{\fIm\fB,\fIn\fB}\fR
a sequence of \fIm\fR through \fIn\fR (inclusive) matches of the atom;
\fIm\fR may not exceed \fIn\fR
.TP
\fB*? +? ?? {\fIm\fB}? {\fIm\fB,}? {\fIm\fB,\fIn\fB}?\fR
\fInon-greedy\fR quantifiers,
which match the same possibilities,
but prefer the smallest number rather than the largest number
of matches (see \fBMATCHING\fR)
.RE
.PP
The forms using \fB{\fR and \fB}\fR are known as \fIbound\fRs. The
numbers \fIm\fR and \fIn\fR are unsigned decimal integers with
permissible values from 0 to 255 inclusive.
.PP
An atom is one of:
.RS 2
.TP 6
\fB(\fIre\fB)\fR
(where \fIre\fR is any regular expression) matches a match for
\fIre\fR, with the match noted for possible reporting
.TP
\fB(?:\fIre\fB)\fR
as previous, but does no reporting (a ``non-capturing'' set of
parentheses)
.TP
\fB()\fR
matches an empty string, noted for possible reporting
.TP
\fB(?:)\fR
matches an empty string, without reporting
.TP
\fB[\fIchars\fB]\fR
a \fIbracket expression\fR, matching any one of the \fIchars\fR (see
\fBBRACKET EXPRESSIONS\fR for more detail)
.TP
\fB.\fR
matches any single character
.TP
\fB\e\fIk\fR
(where \fIk\fR is a non-alphanumeric character) matches that character
taken as an ordinary character, e.g. \e\e matches a backslash
character
.TP
\fB\e\fIc\fR
where \fIc\fR is alphanumeric (possibly followed by other characters),
an \fIescape\fR (AREs only), see \fBESCAPES\fR below
.TP
\fB{\fR
when followed by a character other than a digit, matches the
left-brace character `\fB{\fR'; when followed by a digit, it is the
beginning of a \fIbound\fR (see above)
.TP
\fIx\fR
where \fIx\fR is a single character with no other significance,
matches that character.
.RE
.PP
A \fIconstraint\fR matches an empty string when specific conditions
are met. A constraint may not be followed by a quantifier. The
simple constraints are as follows; some more constraints are described
later, under \fBESCAPES\fR.
.RS 2
.TP 8
\fB^\fR
matches at the beginning of a line
.TP
\fB$\fR
matches at the end of a line
.TP
\fB(?=\fIre\fB)\fR
\fIpositive lookahead\fR (AREs only), matches at any point where a
substring matching \fIre\fR begins
.TP
\fB(?!\fIre\fB)\fR
\fInegative lookahead\fR (AREs only), matches at any point where no
substring matching \fIre\fR begins
.RE
.PP
The lookahead constraints may not contain back references (see later),
and all parentheses within them are considered non-capturing.
.PP
An RE may not end with `\fB\e\fR'.
.SH "BRACKET EXPRESSIONS"
A \fIbracket expression\fR is a list of characters enclosed in
`\fB[\|]\fR'. It normally matches any single character from the list
(but see below). If the list begins with `\fB^\fR', it matches any
single character (but see below) \fInot\fR from the rest of the list.
.PP
If two characters in the list are separated by `\fB\-\fR', this is
shorthand for the full \fIrange\fR of characters between those two
(inclusive) in the collating sequence, e.g. \fB[0\-9]\fR in Unicode
matches any conventional decimal digit. Two ranges may not share an
endpoint, so e.g. \fBa\-c\-e\fR is illegal. Ranges are very
collating-sequence-dependent, and portable programs should avoid
relying on them.
.PP
To include a literal \fB]\fR or \fB\-\fR in the list, the simplest
method is to enclose it in \fB[.\fR and \fB.]\fR to make it a
collating element (see below). Alternatively, make it the first
character (following a possible `\fB^\fR'), or (AREs only) precede it
with `\fB\e\fR'. Alternatively, for `\fB\-\fR', make it the last
character, or the second endpoint of a range. To use a literal
\fB\-\fR as the first endpoint of a range, make it a collating element
or (AREs only) precede it with `\fB\e\fR'. With the exception of
these, some combinations using \fB[\fR (see next paragraphs), and
escapes, all other special characters lose their special significance
within a bracket expression.
.PP
Within a bracket expression, a collating element (a character, a
multi-character sequence that collates as if it were a single
character, or a collating-sequence name for either) enclosed in
\fB[.\fR and \fB.]\fR stands for the sequence of characters of that
collating element. The sequence is a single element of the bracket
expression's list. A bracket expression in a locale that has
multi-character collating elements can thus match more than one
character. So (insidiously), a bracket expression that starts with
\fB^\fR can match multi-character collating elements even if none of
them appear in the bracket expression! (\fINote:\fR Tcl currently has
no multi-character collating elements. This information is only for
illustration.)
.PP
For example, assume the collating sequence includes a \fBch\fR
multi-character collating element. Then the RE \fB[[.ch.]]*c\fR (zero
or more \fBch\fP's followed by \fBc\fP) matches the first five
characters of `\fBchchcc\fR'. Also, the RE \fB[^c]b\fR matches all of
`\fBchb\fR' (because \fB[^c]\fR matches the multi-character \fBch\fR).
.PP
Within a bracket expression, a collating element enclosed in \fB[=\fR
and \fB=]\fR is an equivalence class, standing for the sequences of
characters of all collating elements equivalent to that one, including
itself. (If there are no other equivalent collating elements, the
treatment is as if the enclosing delimiters were `\fB[.\fR'\& and
`\fB.]\fR'.) For example, if \fBo\fR and \fB\o'o^'\fR are the members
of an equivalence class, then `\fB[[=o=]]\fR', `\fB[[=\o'o^'=]]\fR',
and `\fB[o\o'o^']\fR'\& are all synonymous. An equivalence class may
not be an endpoint of a range. (\fINote:\fR Tcl currently implements
only the Unicode locale. It doesn't define any equivalence classes.
The examples above are just illustrations.)
.PP
Within a bracket expression, the name of a \fIcharacter class\fR
enclosed in \fB[:\fR and \fB:]\fR stands for the list of all
characters (not all collating elements!) belonging to that class.
Standard character classes are:
.IP \fBalpha\fR 8
A letter.
.IP \fBupper\fR 8
An upper-case letter.
.IP \fBlower\fR 8
A lower-case letter.
.IP \fBdigit\fR 8
A decimal digit.
.IP \fBxdigit\fR 8
A hexadecimal digit.
.IP \fBalnum\fR 8
An alphanumeric (letter or digit).
.IP \fBprint\fR 8
An alphanumeric (same as alnum).
.IP \fBblank\fR 8
A space or tab character.
.IP \fBspace\fR 8
A character producing white space in displayed text.
.IP \fBpunct\fR 8
A punctuation character.
.IP \fBgraph\fR 8
A character with a visible representation.
.IP \fBcntrl\fR 8
A control character.
.PP
A locale may provide others. (Note that the current Tcl
implementation has only one locale: the Unicode locale.) A character
class may not be used as an endpoint of a range.
.PP
There are two special cases of bracket expressions: the bracket
expressions \fB[[:<:]]\fR and \fB[[:>:]]\fR are constraints, matching
empty strings at the beginning and end of a word respectively.
'\" note, discussion of escapes below references this definition of word
A word is defined as a sequence of word characters that is neither
preceded nor followed by word characters. A word character is an
\fIalnum\fR character or an underscore (\fB_\fR). These special
bracket expressions are deprecated; users of AREs should use
constraint escapes instead (see below).
.SH ESCAPES
Escapes (AREs only), which begin with a \fB\e\fR followed by an
alphanumeric character, come in several varieties: character entry,
class shorthands, constraint escapes, and back references. A \fB\e\fR
followed by an alphanumeric character but not constituting a valid
escape is illegal in AREs. In EREs, there are no escapes: outside a
bracket expression, a \fB\e\fR followed by an alphanumeric character
merely stands for that character as an ordinary character, and inside
a bracket expression, \fB\e\fR is an ordinary character. (The latter
is the one actual incompatibility between EREs and AREs.)
.PP
Character-entry escapes (AREs only) exist to make it easier to specify
non-printing and otherwise inconvenient characters in REs:
.RS 2
.TP 5
\fB\ea\fR
alert (bell) character, as in C
.TP
\fB\eb\fR
backspace, as in C
.TP
\fB\eB\fR
synonym for \fB\e\fR to help reduce backslash doubling in some
applications where there are multiple levels of backslash processing
.TP
\fB\ec\fIX\fR
(where \fIX\fR is any character) the character whose low-order 5 bits
are the same as those of \fIX\fR, and whose other bits are all zero
.TP
\fB\ee\fR
the character whose collating-sequence name is `\fBESC\fR', or failing
that, the character with octal value 033
.TP
\fB\ef\fR
formfeed, as in C
.TP
\fB\en\fR
newline, as in C
.TP
\fB\er\fR
carriage return, as in C
.TP
\fB\et\fR
horizontal tab, as in C
.TP
\fB\eu\fIwxyz\fR
(where \fIwxyz\fR is exactly four hexadecimal digits) the Unicode
character \fBU+\fIwxyz\fR in the local byte ordering
.TP
\fB\eU\fIstuvwxyz\fR
(where \fIstuvwxyz\fR is exactly eight hexadecimal digits) reserved
for a somewhat-hypothetical Unicode extension to 32 bits
.TP
\fB\ev\fR
vertical tab, as in C are all available.
.TP
\fB\ex\fIhhh\fRl opt">);
assert(src_size[u] > 0);
}
#endif
/* Copy the size vector so we can modify it */
H5V_vector_cpy(n, size, _size);
/* Compute stride vectors for source and destination */
#ifdef NO_INLINED_CODE
dst_start = H5V_hyper_stride(n, size, dst_size, dst_offset, dst_stride);
src_start = H5V_hyper_stride(n, size, src_size, src_offset, src_stride);
#else /* NO_INLINED_CODE */
/* in-line version of two calls to H5V_hyper_stride() */
{
hsize_t dst_acc; /*accumulator */
hsize_t src_acc; /*accumulator */
int ii; /*counter */
/* init */
dst_stride[n-1] = 1;
src_stride[n-1] = 1;
dst_start = dst_offset ? dst_offset[n-1] : 0;
src_start = src_offset ? src_offset[n-1] : 0;
/* Unroll loop for common cases */
switch(n) {
case 2:
tmp1 = (dst_size[1] - size[1]);
tmp2 = (src_size[1] - size[1]);
assert (tmp1<((hsize_t)1<<(8*sizeof(hssize_t)-1)));
assert (tmp2<((hsize_t)1<<(8*sizeof(hssize_t)-1)));
dst_stride[0] = (hssize_t)tmp1; /*overflow checked*/
src_stride[0] = (hssize_t)tmp2; /*overflow checked*/
dst_acc = dst_size[1];
src_acc = src_size[1];
dst_start += dst_acc * (dst_offset ? dst_offset[0] : 0);
src_start += src_acc * (src_offset ? src_offset[0] : 0);
break;
case 3:
tmp1 = (dst_size[2] - size[2]);
tmp2 = (src_size[2] - size[2]);
assert (tmp1<((hsize_t)1<<(8*sizeof(hssize_t)-1)));
assert (tmp2<((hsize_t)1<<(8*sizeof(hssize_t)-1)));
dst_stride[1] = (hssize_t)tmp1; /*overflow checked*/
src_stride[1] = (hssize_t)tmp2; /*overflow checked*/
dst_acc = dst_size[2];
src_acc = src_size[2];
dst_start += dst_acc * (dst_offset ? dst_offset[1] : 0);
src_start += src_acc * (src_offset ? src_offset[1] : 0);
tmp1 = dst_acc * (dst_size[1] - size[1]);
tmp2 = src_acc * (src_size[1] - size[1]);
assert (tmp1<((hsize_t)1<<(8*sizeof(hssize_t)-1)));
assert (tmp2<((hsize_t)1<<(8*sizeof(hssize_t)-1)));
dst_stride[0] = (hssize_t)tmp1; /*overflow checked*/
src_stride[0] = (hssize_t)tmp2; /*overflow checked*/
dst_acc *= dst_size[1];
src_acc *= src_size[1];
dst_start += dst_acc * (dst_offset ? dst_offset[0] : 0);
src_start += src_acc * (src_offset ? src_offset[0] : 0);
break;
case 4:
tmp1 = (dst_size[3] - size[3]);
tmp2 = (src_size[3] - size[3]);
assert (tmp1<((hsize_t)1<<(8*sizeof(hssize_t)-1)));
assert (tmp2<((hsize_t)1<<(8*sizeof(hssize_t)-1)));
dst_stride[2] = (hssize_t)tmp1; /*overflow checked*/
src_stride[2] = (hssize_t)tmp2; /*overflow checked*/
dst_acc = dst_size[3];
src_acc = src_size[3];
dst_start += dst_acc * (dst_offset ? dst_offset[2] : 0);
src_start += src_acc * (src_offset ? src_offset[2] : 0);
tmp1 = dst_acc * (dst_size[2] - size[2]);
tmp2 = src_acc * (src_size[2] - size[2]);
assert (tmp1<((hsize_t)1<<(8*sizeof(hssize_t)-1)));
assert (tmp2<((hsize_t)1<<(8*sizeof(hssize_t)-1)));
dst_stride[1] = (hssize_t)tmp1; /*overflow checked*/
src_stride[1] = (hssize_t)tmp2; /*overflow checked*/
dst_acc *= dst_size[2];
src_acc *= src_size[2];
dst_start += dst_acc * (dst_offset ? dst_offset[1] : 0);
src_start += src_acc * (src_offset ? src_offset[1] : 0);
tmp1 = dst_acc * (dst_size[1] - size[1]);
tmp2 = src_acc * (src_size[1] - size[1]);
assert (tmp1<((hsize_t)1<<(8*sizeof(hssize_t)-1)));
assert (tmp2<((hsize_t)1<<(8*sizeof(hssize_t)-1)));
dst_stride[0] = (hssize_t)tmp1; /*overflow checked*/
src_stride[0] = (hssize_t)tmp2; /*overflow checked*/
dst_acc *= dst_size[1];
src_acc *= src_size[1];
dst_start += dst_acc * (dst_offset ? dst_offset[0] : 0);
src_start += src_acc * (src_offset ? src_offset[0] : 0);
break;
default:
/* others */
for (ii=(int)(n-2), dst_acc=1, src_acc=1; ii>=0; --ii) {
tmp1 = dst_acc * (dst_size[ii+1] - size[ii+1]);
tmp2 = src_acc * (src_size[ii+1] - size[ii+1]);
assert (tmp1<((hsize_t)1<<(8*sizeof(hssize_t)-1)));
assert (tmp2<((hsize_t)1<<(8*sizeof(hssize_t)-1)));
dst_stride[ii] = (hssize_t)tmp1; /*overflow checked*/
src_stride[ii] = (hssize_t)tmp2; /*overflow checked*/
dst_acc *= dst_size[ii+1];
src_acc *= src_size[ii+1];
dst_start += dst_acc * (dst_offset ? dst_offset[ii] : 0);
src_start += src_acc * (src_offset ? src_offset[ii] : 0);
}
break;
} /* end switch */
}
#endif /* NO_INLINED_CODE */
/* Optimize the strides as a pair */
H5V_stride_optimize2(&n, &elmt_size, size, dst_stride, src_stride);
/* Perform the copy in terms of stride */
status = H5V_stride_copy(n, elmt_size, size,
dst_stride, dst+dst_start, src_stride, src+src_start);
FUNC_LEAVE(status);
}
/*-------------------------------------------------------------------------
* Function: H5V_stride_fill
*
* Purpose: Fills all bytes of a hyperslab with the same value using
* memset().
*
* Return: Non-negative on success/Negative on failure
*
* Programmer: Robb Matzke
* Saturday, October 11, 1997
*
* Modifications:
*
*-------------------------------------------------------------------------
*/
herr_t
H5V_stride_fill(unsigned n, hsize_t elmt_size, const hsize_t *size,
const hssize_t *stride, void *_dst, unsigned fill_value)
{
uint8_t *dst = (uint8_t*)_dst; /*cast for ptr arithmetic */
hsize_t idx[H5V_HYPER_NDIMS]; /*1-origin indices */
hsize_t nelmts; /*number of elements to fill */
hsize_t i; /*counter */
int j; /*counter */
hbool_t carry; /*subtraction carray value */
FUNC_ENTER(H5V_stride_fill, FAIL);
assert (elmt_size < SIZET_MAX);
H5V_vector_cpy(n, idx, size);
nelmts = H5V_vector_reduce_product(n, size);
for (i=0; i<nelmts; i++) {
/* Copy an element */
HDmemset(dst, (signed)fill_value, (size_t)elmt_size);
/* Decrement indices and advance pointer */
for (j=(int)(n-1), carry=TRUE; j>=0 && carry; --j) {
dst += stride[j];
if (--idx[j])
carry = FALSE;
else
idx[j] = size[j];
}
}
FUNC_LEAVE(SUCCEED);
}
/*-------------------------------------------------------------------------
* Function: H5V_stride_copy
*
* Purpose: Uses DST_STRIDE and SRC_STRIDE to advance through the arrays
* DST and SRC while copying bytes from SRC to DST. This
* function minimizes the number of calls to memcpy() by
* combining various strides, but it will never touch memory
* outside the hyperslab defined by the strides.
*
* Note: If the src_stride is all zero and elmt_size is one, then it's
* probably more efficient to use H5V_stride_fill() instead.
*
* Return: Non-negative on success/Negative on failure
*
* Programmer: Robb Matzke
* Saturday, October 11, 1997
*
* Modifications:
*
*-------------------------------------------------------------------------
*/
herr_t
H5V_stride_copy(unsigned n, hsize_t elmt_size, const hsize_t *size,
const hssize_t *dst_stride, void *_dst,
const hssize_t *src_stride, const void *_src)
{
uint8_t *dst = (uint8_t*)_dst; /*cast for ptr arithmetic*/
const uint8_t *src = (const uint8_t*) _src; /*cast for ptr arithmetic*/
hsize_t idx[H5V_HYPER_NDIMS]; /*1-origin indices */
hsize_t nelmts; /*num elements to copy */
hsize_t i; /*counter */
int j; /*counters */
hbool_t carry; /*carray for subtraction*/
FUNC_ENTER(H5V_stride_copy, FAIL);
assert (elmt_size<SIZET_MAX);
if (n) {
H5V_vector_cpy(n, idx, size);
nelmts = H5V_vector_reduce_product(n, size);
for (i=0; i<nelmts; i++) {
/* Copy an element */
HDmemcpy(dst, src, (size_t)elmt_size);
/* Decrement indices and advance pointers */
for (j=(int)(n-1), carry=TRUE; j>=0 && carry; --j) {
src += src_stride[j];
dst += dst_stride[j];
if (--idx[j])
carry = FALSE;
else
idx[j] = size[j];
}
}
} else {
assert(elmt_size==(hsize_t)((size_t)elmt_size)); /*check for overflow*/
HDmemcpy (dst, src, (size_t)elmt_size);
HRETURN (SUCCEED);
}
FUNC_LEAVE(SUCCEED);
}
/*-------------------------------------------------------------------------
* Function: H5V_stride_copy2
*
* Purpose: Similar to H5V_stride_copy() except the source and
* destination each have their own dimensionality and size and
* we copy exactly NELMTS elements each of size ELMT_SIZE. The
* size counters wrap if NELMTS is more than a size counter.
*
* Return: Non-negative on success/Negative on failure
*
* Programmer: Robb Matzke
* Saturday, October 11, 1997
*
* Modifications:
*
*-------------------------------------------------------------------------
*/
herr_t
H5V_stride_copy2(hsize_t nelmts, hsize_t elmt_size,
/* destination */
int dst_n, const hsize_t *dst_size,
const hssize_t *dst_stride,
void *_dst,
/* source */
int src_n, const hsize_t *src_size,
const hssize_t *src_stride,
const void *_src)
{
uint8_t *dst = (uint8_t *) _dst;
const uint8_t *src = (const uint8_t *) _src;
hsize_t dst_idx[H5V_HYPER_NDIMS];
hsize_t src_idx[H5V_HYPER_NDIMS];
hsize_t i;
int j;
hbool_t carry;
FUNC_ENTER(H5V_stride_copy2, FAIL);
assert (elmt_size < SIZET_MAX);
H5V_vector_cpy(dst_n, dst_idx, dst_size);
H5V_vector_cpy(src_n, src_idx, src_size);
for (i=0; i<nelmts; i++) {
/* Copy an element */
HDmemcpy(dst, src, (size_t)elmt_size);
/* Decrement indices and advance pointers */
for (j=dst_n-1, carry=TRUE; j>=0 && carry; --j) {
dst += dst_stride[j];
if (--dst_idx[j]) carry = FALSE;
else dst_idx[j] = dst_size[j];
}
for (j=src_n-1, carry=TRUE; j>=0 && carry; --j) {
src += src_stride[j];
if (--src_idx[j]) carry = FALSE;
else src_idx[j] = src_size[j];
}
}
FUNC_LEAVE(SUCCEED);
}
/*-------------------------------------------------------------------------
* Function: H5V_array_fill
*
* Purpose: Fills all bytes of an array with the same value using
* memset(). Increases amount copied by power of two until the
* halfway point is crossed, then copies the rest in one swoop.
*
* Return: Non-negative on success/Negative on failure
*
* Programmer: Quincey Koziol
* Thursday, June 18, 1998
*
* Modifications:
*
*-------------------------------------------------------------------------
*/
herr_t
H5V_array_fill(void *_dst, const void *src, size_t size, size_t count)
{
size_t copy_size; /* size of the buffer to copy */
size_t copy_items; /* number of items currently copying*/
size_t items_left; /* number of items left to copy */
uint8_t *dst=(uint8_t*)_dst;/* alias for pointer arithmetic */
FUNC_ENTER(H5V_array_fill, FAIL);
assert (dst);
assert (src);
assert (size < SIZET_MAX && size > 0);
assert (count < SIZET_MAX && count > 0);
HDmemcpy(dst, src, size); /* copy first item */
/* Initialize counters, etc. while compensating for first element copied */
copy_size = size;
copy_items = 1;
items_left = count - 1;
dst += size;
/* copy until we've copied at least half of the items */
while (items_left >= copy_items)
{
HDmemcpy(dst, _dst, copy_size); /* copy the current chunk */
dst += copy_size; /* move the offset for the next chunk */
items_left -= copy_items; /* decrement the number of items left */
copy_size *= 2; /* increase the size of the chunk to copy */
copy_items *= 2; /* increase the count of items we are copying */
} /* end while */
if (items_left > 0) /* if there are any items left to copy */
HDmemcpy(dst, _dst, items_left * size);
FUNC_LEAVE(SUCCEED);
} /* H5V_array_fill() */
/*-------------------------------------------------------------------------
* Function: H5V_array_offset
*
* Purpose: Given a coordinate description of a location in an array, this
* function returns the byte offset of the coordinate.
*
* The dimensionality of the whole array, the hyperslab, and the
* returned stride array is N. The whole array dimensions are
* TOTAL_SIZE and the coordinate is at offset OFFSET.
*
* Return: Success: Byte offset from beginning of array to start
* of striding.
*
* Failure: abort() -- should never fail
*
* Programmer: Quincey Koziol
* Tuesday, June 22, 1999
*
* Modifications:
*
*-------------------------------------------------------------------------
*/
hsize_t
H5V_array_offset(unsigned n, const hsize_t *total_size, const hssize_t *offset)
{
hsize_t skip; /*starting point byte offset */
hsize_t acc; /*accumulator */
int i; /*counter */
FUNC_ENTER(H5V_array_stride, (HDabort(), 0));
assert(n <= H5V_HYPER_NDIMS);
assert(total_size);
assert(offset);
/* others */
for (i=(int)(n-1), acc=1, skip=0; i>=0; --i) {
skip += acc * offset[i];
acc *= total_size[i];
}
FUNC_LEAVE(skip);
}
|