#ifndef WEASELJSON_H
#define WEASELJSON_H

#ifdef __cplusplus
extern "C" {
#endif

struct WeaselJsonCallbacks {
  void (*on_begin_object)(void *data);
  void (*on_end_object)(void *data);
  void (*on_begin_string)(void *data);
  /** May be called multiple times per string if not all string data is
   * available yet. The string data provided is unescaped. */
  void (*on_string_data)(void *data, const char *buf, int len);
  void (*on_end_string)(void *data);
  void (*on_begin_array)(void *data);
  void (*on_end_array)(void *data);
  void (*on_begin_number)(void *data);
  /** May be called multiple times per number if not all number data is
   * available yet */
  void (*on_number_data)(void *data, const char *buf, int len);
  void (*on_end_number)(void *data);
  void (*on_true_literal)(void *data);
  void (*on_false_literal)(void *data);
  void (*on_null_literal)(void *data);
};

enum WeaselJsonStatus {
  /** Accept input */
  WeaselJson_OK,
  /** Consumed all available input. Call WeaselJsonParser_parse with more data
     to provide more input, or call with length 0 to indicate end of data */
  WeaselJson_AGAIN,
  /** Invalid json */
  WeaselJson_REJECT,
  /** json is too deeply nested */
  WeaselJson_OVERFLOW,
};

typedef struct WeaselJsonParser WeaselJsonParser;

/** Create a parser. Increasing stack size increases memory usage but also
 * increases the depth of nested json accepted. `callbacks` and `data` must
 * outlive the returned parser. */
WeaselJsonParser *WeaselJsonParser_create(int stackSize,
                                          const WeaselJsonCallbacks *callbacks,
                                          void *data);

/** Restore the parser to its newly-created state */
void WeaselJsonParser_reset(WeaselJsonParser *parser);

/** Destroy the parser */
void WeaselJsonParser_destroy(WeaselJsonParser *parser);

/** Incrementally parse `len` more bytes starting at `buf`. `buf` may be
 * modified. Call with `len` 0 to indicate end of data */
WeaselJsonStatus WeaselJsonParser_parse(WeaselJsonParser *parser, char *buf,
                                        int len);

#ifdef __cplusplus
}
#endif

#endif
