typedef struct grbs_snapshot_s {
	grbs_t *grbs;

	/* number of objects saved */
	long N2nets, Npoints, Narcs, Nlines;


	/* these are pointing into buff and hold arrays of saved objects */
	grbs_2net_t *saved_2net;
	grbs_point_t *saved_point;
	grbs_arc_t *saved_arc;
	grbs_line_t *saved_line;


	/* these are pointing into buff and hold the original pointer for each saved
	   object, so that ->saved_pt[N]'s original pointer is ->ptr_2net[N] */
	void **ptr_2net;
	void **ptr_point;
	void **ptr_arc;
	void **ptr_line;

	/* links are preserved via object memcpy(); also preserve list heads */
	gdl_list_t save_all_2nets;
	gdl_list_t save_all_points;
	gdl_list_t save_all_arcs;
	gdl_list_t save_all_lines;

	long orig_uids; /* the value of grbs->uids on snapshot; any object with a higher ID is a new object */

	char buff[1]; /* overallocated to host all objects */
} grbs_snapshot_t;


/* Allocate and save a snapshot of grbs */
grbs_snapshot_t *grbs_snapshot_save(grbs_t *grbs);

/* Restore the state of grbs from a previously saved snapshot */
int grbs_snapshot_restore(grbs_snapshot_t *snap);

/* Discard and free snapshot */
void grbs_snapshot_free(grbs_snapshot_t *snap);

/* Call cmp_cb() for every pair of orig and new objects (points, arcs,
   lines and twonets), for realized objects (not ->new).
   If orig_obj is NULL, new_obj has been created; if new_obj is NULL,
   orig_obj has been deleted. Runs for points, arcs and lines. */
void grbs_snapshot_cmp(grbs_snapshot_t *snap, void (*cmp_cb)(void *uctx, grbs_obj_type_t type, void *orig_obj, void *new_obj), void *uctx);

/* Note: it is safe to save pointers and raw data because of libualloc. On
   restore all saved raw data are copied back to the saved pointers, list
   heads restored and all object pointers not handled by this are added
   to to the free list for reuse. This would't work if we'd free objects
   while making modifications. */
