feat(job-array-one-based-index): bounded job-identity and element-selection parser in libxce (task 1.1)

parse_jobsel() parses c-a-ts-seq with an optional [k] or [a-b] under a
fixed grammar and check order (syntax, field widths, array-identity
alignment, element bound, reversed range), saturating digits so an
oversized number cannot wrap; plus is_array_tag(), jobsel_element_id(),
jobsel_strerror() and JOBID_FIELD_MAX_* constants. The selection-cases
conformance table runs in the libxce suite.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Rongsong Shen 2026-10-01 09:01:57 +00:00
parent 590860f73d
commit 6e6c599d27
Signed by untrusted user: rshen
GPG key ID: 80533536B0EB651C
6 changed files with 501 additions and 1 deletions

View file

@ -218,6 +218,65 @@ extern int parse_jobid(uint64_t*, char*);
extern uint64_t array_jobid(uint64_t);
extern uint64_t array_idx(uint64_t);
/*
* Bounded job-identity / element-selection parser (job-array-one-based-index,
* Req 1.5, 5.7, 5.8, 5.12, 5.14, 5.15, 8.1).
*
* Grammar: optional leading/trailing spaces or tabs, then
* `num-num-num-num` (cluster-apiserver-timestamp-sequence), optionally
* followed by `[num]` or `[num-num]`. `num` is one or more decimal digits
* (leading zeros allowed, no sign, no inner whitespace).
*
* Checks, in this order; only the first failure is reported:
* JOBSEL_ESYNTAX grammar (5.15)
* JOBSEL_EWIDTH a field wider than its bit width (5.14)
* JOBSEL_EALIGN element part present but sequence % 32768 != 0 (5.8)
* JOBSEL_EINDEX an element number above JOBID_FIELD_MAX_INDEX (5.7)
* JOBSEL_EREVERSED range whose last number is below its first (5.5)
* Digits are accumulated with an overflow guard, so oversized numbers fail
* the width or index check instead of wrapping.
*
* On JOBSEL_OK: BARE -> `key` is the exact untagged ID, lo == hi == 0;
* SINGLE -> `key` is the array ID (tag 0, low 15 bits clear), lo == hi == k;
* RANGE -> `key` is the array ID, [lo, hi]. A NULL `text` is
* JOBSEL_ESYNTAX; `out` must not be NULL.
*/
#define JOBID_FIELD_MAX_CLUSTER MAX_CLUSTER_ID
#define JOBID_FIELD_MAX_APISERVER MAX_APISERVER_ID
#define JOBID_FIELD_MAX_TIMESTAMP (UMAX_BITS(N_TIMESTAMP_BITS))
#define JOBID_FIELD_MAX_SEQUENCE (UMAX_BITS(N_SEQUENCE_BITS))
#define JOBID_FIELD_MAX_INDEX MAX_ARRAY_IDX
typedef enum {
JOBSEL_OK = 0,
JOBSEL_ESYNTAX, /* 5.15 */
JOBSEL_EWIDTH, /* 5.14 */
JOBSEL_EALIGN, /* 5.8 */
JOBSEL_EINDEX, /* 5.7 */
JOBSEL_EREVERSED /* 5.5 */
} jobsel_err_t;
typedef enum {
JOBSEL_BARE = 0,
JOBSEL_SINGLE,
JOBSEL_RANGE
} jobsel_form_t;
typedef struct {
uint64_t key; /* BARE: the exact (untagged) ID; else the array ID */
jobsel_form_t form;
uint32_t lo; /* SINGLE: lo == hi == k */
uint32_t hi;
} jobsel_t;
extern jobsel_err_t parse_jobsel(const char* text, jobsel_t* out);
extern const char* jobsel_strerror(jobsel_err_t err);
/* Non-zero iff the ID's tag equals TAG_JOB_ARRAY (tags 2 and 3 are not). */
extern int is_array_tag(uint64_t jobid);
/* Element ID of number k (masked to 15 bits) in the array `s->key`; 0 if
* `s` is NULL. */
extern uint64_t jobsel_element_id(const jobsel_t* s, uint32_t k);
/*
* xce_units_mode_t / xce_format_bytes_human() / xce_is_bytes_valued_resource()
* / xce_format_units_value() -- scheduler-sim-diagnostics spec, task 7 (Req