#ifdef PETSC_RCS_HEADER
static char vcid[] = "$Id: aoserialize.c,v 1.3 2000/01/10 03:15:40 knepley Exp $";
#endif

#include "src/dm/ao/aoimpl.h"      /*I "petscao.h"  I*/

#undef  __FUNCT__
#define __FUNCT__ "AOSerialize"
/*@ 
  AOSerialize - This function stores or recreates an application ordering using a viewer for a binary file.

  Collective on comm

  Input Parameters:
+ comm   - The communicator for the ordering object
. viewer - The viewer context
- store  - This flag is PETSC_TRUE is data is being written, otherwise it will be read

  Output Parameter:
. ao     - The ordering

  Level: beginner

.keywords: serialize, ordering
.seealso: VecSerialize()
@*/
int AOSerialize(MPI_Comm comm, AO *ao, PetscViewer viewer, PetscTruth store)
{
  int      (*serialize)(MPI_Comm, AO *, PetscViewer, PetscTruth);
  int        fd, len;
  char      *name;
  PetscTruth match;
  int        ierr;

  PetscFunctionBegin;
  PetscValidHeaderSpecific(viewer, PETSC_VIEWER_COOKIE);
  PetscValidPointer(ao);

  ierr = PetscTypeCompare((PetscObject) viewer, PETSC_VIEWER_BINARY, &match);                             CHKERRQ(ierr);
  if (match == PETSC_FALSE) SETERRQ(PETSC_ERR_ARG_WRONG, "Must be binary viewer");
  ierr = PetscViewerBinaryGetDescriptor(viewer, &fd);                                                     CHKERRQ(ierr);

  if (store) {
    PetscValidHeaderSpecific(*ao, AO_COOKIE);
    ierr = PetscStrlen((*ao)->class_name, &len);                                                          CHKERRQ(ierr);
    ierr = PetscBinaryWrite(fd, &len,                   1,   PETSC_INT,  0);                              CHKERRQ(ierr);
    ierr = PetscBinaryWrite(fd,  (*ao)->class_name,     len, PETSC_CHAR, 0);                              CHKERRQ(ierr);
    ierr = PetscStrlen((*ao)->serialize_name, &len);                                                      CHKERRQ(ierr);
    ierr = PetscBinaryWrite(fd, &len,                   1,   PETSC_INT,  0);                              CHKERRQ(ierr);
    ierr = PetscBinaryWrite(fd,  (*ao)->serialize_name, len, PETSC_CHAR, 0);                              CHKERRQ(ierr);
    ierr = PetscFListFind(comm, AOSerializeList, (*ao)->serialize_name, (void (**)(void)) &serialize);    CHKERRQ(ierr);
    if (!serialize) SETERRQ(PETSC_ERR_ARG_WRONG, "Type cannot be serialized");
    ierr = (*serialize)(comm, ao, viewer, store);                                                         CHKERRQ(ierr);
  } else {
    ierr = PetscBinaryRead(fd, &len,    1,   PETSC_INT);                                                  CHKERRQ(ierr);
    ierr = PetscMalloc((len+1) * sizeof(char), &name);                                                    CHKERRQ(ierr);
    name[len] = 0;
    ierr = PetscBinaryRead(fd,  name,   len, PETSC_CHAR);                                                 CHKERRQ(ierr);
    ierr = PetscStrcmp(name, "AO", &match);                                                               CHKERRQ(ierr);
    ierr = PetscFree(name);                                                                               CHKERRQ(ierr);
    if (match == PETSC_FALSE) SETERRQ(PETSC_ERR_ARG_WRONG, "Non-ordering object");
    /* Dispatch to the correct routine */
    if (!AOSerializeRegisterAllCalled) {
      ierr = AOSerializeRegisterAll(PETSC_NULL);                                                          CHKERRQ(ierr);
    }
    if (!AOSerializeList) SETERRQ(PETSC_ERR_ARG_CORRUPT, "Could not find table of methods");
    ierr = PetscBinaryRead(fd, &len,    1,   PETSC_INT);                                                  CHKERRQ(ierr);
    ierr = PetscMalloc((len+1) * sizeof(char), &name);                                                    CHKERRQ(ierr);
    name[len] = 0;
    ierr = PetscBinaryRead(fd,  name,   len, PETSC_CHAR);                                                 CHKERRQ(ierr);
    ierr = PetscFListFind(comm, AOSerializeList, name, (void (**)(void)) &serialize);                     CHKERRQ(ierr);
    if (!serialize) SETERRQ(PETSC_ERR_ARG_WRONG, "Type cannot be serialized");
    ierr = (*serialize)(comm, ao, viewer, store);                                                         CHKERRQ(ierr);
    ierr = PetscStrfree((*ao)->serialize_name);                                                           CHKERRQ(ierr);
    (*ao)->serialize_name = name;
  }

  PetscFunctionReturn(0);
}
