c api header file
This commit is contained in:
parent
23c73f8513
commit
b86ba42811
1 changed files with 159 additions and 0 deletions
159
include/tally.h
Normal file
159
include/tally.h
Normal file
|
|
@ -0,0 +1,159 @@
|
|||
/* Tally calculation engine - C ABI.
|
||||
*
|
||||
* Hand-written rather than generated: Zig no longer emits reliable C headers, and this
|
||||
* file is the contract a Swift, C or JNI consumer compiles against. `c_abi_test.c`
|
||||
* links against the real library through this header, so the two cannot drift apart
|
||||
* without a build failure.
|
||||
*
|
||||
* Three rules:
|
||||
*
|
||||
* 1. A session owns the memory. There is no per-result free function; freeing the
|
||||
* session releases everything, including any result still borrowed from it.
|
||||
* 2. A result is borrowed. The bytes stay valid until the next call on the same
|
||||
* session. Copy them before calling again.
|
||||
* 3. One session, one thread at a time. Sessions share nothing, so a thread may hold
|
||||
* its own. This library takes no locks.
|
||||
*
|
||||
* Results are JSON. On failure the payload is {"ok":false,"error":"..."}, worded by the
|
||||
* engine so every frontend says the same thing.
|
||||
*/
|
||||
|
||||
#ifndef TALLY_H
|
||||
#define TALLY_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Value of tally_abi_version() this header was written against. Compare at startup:
|
||||
* a prebuilt library can fall out of step with the code calling it. */
|
||||
#define TALLY_ABI_VERSION 5u
|
||||
|
||||
/* How a call ended. Evaluation failing is a normal outcome (TALLY_EVAL_ERROR) with the
|
||||
* reason in the JSON, not an exceptional one.
|
||||
*
|
||||
* For every call that hands back a result: TALLY_OK and TALLY_EVAL_ERROR leave JSON in
|
||||
* *out_ptr / *out_len. TALLY_OUT_OF_MEMORY leaves an empty, NUL-terminated string there
|
||||
* - never the previous call's result - and the session stays usable. A call refused
|
||||
* with TALLY_INVALID_ARGUMENT may leave the out-parameters untouched; read nothing. */
|
||||
typedef enum {
|
||||
TALLY_OK = 0,
|
||||
TALLY_EVAL_ERROR = 1,
|
||||
TALLY_OUT_OF_MEMORY = 2,
|
||||
TALLY_INVALID_ARGUMENT = 3
|
||||
} tally_status;
|
||||
|
||||
/* Which evaluator runs, chosen per call. */
|
||||
typedef enum {
|
||||
TALLY_MODE_STANDARD = 0,
|
||||
TALLY_MODE_PROGRAMMER = 1
|
||||
} tally_mode;
|
||||
|
||||
/* Everything a frontend decides about interpretation and display. The display fields
|
||||
* are the caller's to choose: the engine holds no digit budget of its own, because a
|
||||
* phone screen, a terminal and a clipboard want different ones.
|
||||
*
|
||||
* Zero-initialising this struct is NOT the same as the defaults. Read the current
|
||||
* configuration with tally_session_config() and modify that. */
|
||||
typedef struct {
|
||||
uint16_t bits; /* 8, 16, 32, 64 or 128; anything else is refused */
|
||||
uint8_t is_signed; /* read programmer values as two's complement */
|
||||
uint8_t big_endian; /* byte order of the hex and ASCII rows */
|
||||
uint8_t separators; /* thousands separators in rendered integers */
|
||||
uint8_t never_abbreviate; /* ignore max_integer_digits; print every digit */
|
||||
uint16_t fraction_digits;
|
||||
uint16_t max_integer_digits;
|
||||
uint16_t significant_digits;
|
||||
uint16_t scientific_below_exponent;
|
||||
} tally_config;
|
||||
|
||||
/* A calculator that remembers things: variables, the last answer, and one buffer for
|
||||
* whatever it last said. Opaque. */
|
||||
typedef struct tally_session tally_session;
|
||||
|
||||
/* Create a session, or NULL when there is no memory for one. */
|
||||
tally_session *tally_session_new(void);
|
||||
|
||||
/* Release a session and everything it owns. NULL is accepted. */
|
||||
void tally_session_free(tally_session *session);
|
||||
|
||||
/* Replace the configuration. Refuses a width that is not one of the five supported. */
|
||||
tally_status tally_session_configure(tally_session *session, const tally_config *config);
|
||||
|
||||
/* Read the configuration, including defaults never set by the caller. */
|
||||
tally_status tally_session_config(tally_session *session, tally_config *out);
|
||||
|
||||
/* Evaluate an expression. Strings are (pointer, length); nothing is null-terminated.
|
||||
*
|
||||
* On TALLY_OK and TALLY_EVAL_ERROR, *out_ptr and *out_len describe JSON borrowed from the
|
||||
* session until its next call; see tally_status for the other two. The length is
|
||||
* authoritative; the bytes also carry a NUL just past it, so a caller whose next step
|
||||
* wants a C string (printf, JNI's NewStringUTF) does not have to copy them first. */
|
||||
tally_status tally_eval(tally_session *session,
|
||||
const uint8_t *expr_ptr,
|
||||
size_t expr_len,
|
||||
int mode,
|
||||
const uint8_t **out_ptr,
|
||||
size_t *out_len);
|
||||
|
||||
/* What tally_eval would answer, changing nothing: an assignment is not stored and Ans
|
||||
* keeps the last committed answer. For a screen that answers as the user types. Same
|
||||
* arguments, same JSON, same borrowing rule. Added in ABI version 2. */
|
||||
tally_status tally_preview(tally_session *session,
|
||||
const uint8_t *expr_ptr,
|
||||
size_t expr_len,
|
||||
int mode,
|
||||
const uint8_t **out_ptr,
|
||||
size_t *out_len);
|
||||
|
||||
/* The unit categories and their units, as JSON borrowed like any other result. Fill a
|
||||
* picker from this rather than retyping the engine's tables. Each unit carries its
|
||||
* canonical "name", a display "label" ("Meter per second"; added in ABI version 4), its
|
||||
* "aliases", and whether it converts "exact"ly. */
|
||||
tally_status tally_unit_catalog(tally_session *session,
|
||||
const uint8_t **out_ptr,
|
||||
size_t *out_len);
|
||||
|
||||
/* A value in every unit of unit's category: {"ok":true,"input":"100","from":"C",
|
||||
* "category":"temperature","results":[{"unit":"F","display":"212","exact":true,...}]}.
|
||||
* The value is an expression, previewed, so nothing in the session changes; a row that
|
||||
* cannot be converted carries its own "error". Borrowed like any other result. Added in
|
||||
* ABI version 3. */
|
||||
tally_status tally_convert(tally_session *session,
|
||||
const uint8_t *value_ptr,
|
||||
size_t value_len,
|
||||
const uint8_t *unit_ptr,
|
||||
size_t unit_len,
|
||||
const uint8_t **out_ptr,
|
||||
size_t *out_len);
|
||||
|
||||
/* The session's variables and Ans, exactly, as JSON borrowed like any other result:
|
||||
* exact values as fractions with every digit, inexact ones as their IEEE-754 bits. Give
|
||||
* it to tally_session_load - in this process or a later one - to put them back. The
|
||||
* configuration is not included; it is the caller's to set. Added in ABI version 5. */
|
||||
tally_status tally_session_save(tally_session *session,
|
||||
const uint8_t **out_ptr,
|
||||
size_t *out_len);
|
||||
|
||||
/* Replace the session's variables and Ans with a saved state. All or nothing: on any
|
||||
* status but TALLY_OK the session is unchanged. Text that is not a saved state, or that
|
||||
* names a variable an assignment could not have made, is TALLY_INVALID_ARGUMENT. Any
|
||||
* result still borrowed from the session is invalidated. Added in ABI version 5. */
|
||||
tally_status tally_session_load(tally_session *session,
|
||||
const uint8_t *state_ptr,
|
||||
size_t state_len);
|
||||
|
||||
/* The product version. Static storage; do not free. out_len may be NULL. */
|
||||
const uint8_t *tally_version(size_t *out_len);
|
||||
|
||||
/* The ABI version, which moves independently of the product version. */
|
||||
uint32_t tally_abi_version(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* TALLY_H */
|
||||
Loading…
Add table
Reference in a new issue