Actual source code: stringv.c

      1: #include <petsc/private/viewerimpl.h>

      3: typedef struct {
      4:   char     *string; /* string where info is stored */
      5:   char     *head;   /* pointer to beginning of unused portion */
      6:   size_t    curlen, maxlen;
      7:   PetscBool ownstring; /* string viewer is responsible for freeing the string */
      8: } PetscViewer_String;

     10: static PetscErrorCode PetscViewerDestroy_String(PetscViewer viewer)
     11: {
     12:   PetscViewer_String *vstr = (PetscViewer_String *)viewer->data;

     14:   PetscFunctionBegin;
     15:   if (vstr->ownstring) PetscCall(PetscFree(vstr->string));
     16:   PetscCall(PetscFree(vstr));
     17:   PetscFunctionReturn(PETSC_SUCCESS);
     18: }

     20: /*@C
     21:   PetscViewerStringSPrintf - Prints information to a `PETSCVIEWERSTRING` `PetscViewer` object

     23:   Logically Collective; No Fortran Support

     25:   Input Parameters:
     26: + viewer - a string `PetscViewer`, formed by `PetscViewerStringOpen()`
     27: - format - the format of the input

     29:   Level: developer

     31:   Note:
     32:   Though this is collective each MPI process maintains a separate string

     34: .seealso: [](sec_viewers), `PETSCVIEWERSTRING`, `PetscViewerStringOpen()`, `PetscViewerStringGetStringRead()`, `PetscViewerStringSetString()`
     35: @*/
     36: PetscErrorCode PetscViewerStringSPrintf(PetscViewer viewer, const char format[], ...)
     37: {
     38:   va_list             Argp;
     39:   size_t              fullLength;
     40:   size_t              shift, cshift;
     41:   PetscBool           isstring;
     42:   char                tmp[4096];
     43:   PetscViewer_String *vstr = (PetscViewer_String *)viewer->data;

     45:   PetscFunctionBegin;
     47:   PetscAssertPointer(format, 2);
     48:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring));
     49:   if (!isstring) PetscFunctionReturn(PETSC_SUCCESS);
     50:   PetscCheck(vstr->string, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Must call PetscViewerStringSetString() before using");

     52:   va_start(Argp, format);
     53:   PetscCall(PetscVSNPrintf(tmp, sizeof(tmp), format, &fullLength, Argp));
     54:   va_end(Argp);
     55:   PetscCall(PetscStrlen(tmp, &shift));
     56:   cshift = shift + 1;
     57:   if (cshift >= vstr->maxlen - vstr->curlen - 1) cshift = vstr->maxlen - vstr->curlen - 1;
     58:   PetscCall(PetscMemcpy(vstr->head, tmp, cshift));
     59:   vstr->head[cshift - 1] = '\0';
     60:   vstr->head += shift;
     61:   vstr->curlen += shift;
     62:   PetscFunctionReturn(PETSC_SUCCESS);
     63: }

     65: /*@C
     66:   PetscViewerStringOpen - Opens a string as a `PETSCVIEWERSTRING` `PetscViewer`. This is a very
     67:   simple `PetscViewer`; information on the object is simply stored into
     68:   the string in a fairly nice way.

     70:   Collective; No Fortran Support

     72:   Input Parameters:
     73: + comm   - the communicator
     74: . string - the string to use
     75: - len    - the string length

     77:   Output Parameter:
     78: . lab - the `PetscViewer`

     80:   Level: advanced

     82: .seealso: [](sec_viewers), `PETSCVIEWERSTRING`, `PetscViewerDestroy()`, `PetscViewerStringSPrintf()`, `PetscViewerStringGetStringRead()`, `PetscViewerStringSetString()`
     83: @*/
     84: PetscErrorCode PetscViewerStringOpen(MPI_Comm comm, char string[], size_t len, PetscViewer *lab) PeNS
     85: {
     86:   PetscFunctionBegin;
     87:   PetscCall(PetscViewerCreate(comm, lab));
     88:   PetscCall(PetscViewerSetType(*lab, PETSCVIEWERSTRING));
     89:   PetscCall(PetscViewerStringSetString(*lab, string, len));
     90:   PetscFunctionReturn(PETSC_SUCCESS);
     91: }

     93: static PetscErrorCode PetscViewerGetSubViewer_String(PetscViewer viewer, MPI_Comm comm, PetscViewer *sviewer)
     94: {
     95:   PetscViewer_String *vstr = (PetscViewer_String *)viewer->data;

     97:   PetscFunctionBegin;
     98:   PetscCall(PetscViewerStringOpen(PETSC_COMM_SELF, vstr->head, vstr->maxlen - vstr->curlen, sviewer));
     99:   PetscFunctionReturn(PETSC_SUCCESS);
    100: }

    102: static PetscErrorCode PetscViewerRestoreSubViewer_String(PetscViewer viewer, MPI_Comm comm, PetscViewer *sviewer)
    103: {
    104:   PetscViewer_String *iviewer = (PetscViewer_String *)(*sviewer)->data;
    105:   PetscViewer_String *vstr    = (PetscViewer_String *)viewer->data;

    107:   PetscFunctionBegin;
    108:   vstr->head = iviewer->head;
    109:   vstr->curlen += iviewer->curlen;
    110:   PetscCall(PetscViewerDestroy(sviewer));
    111:   PetscFunctionReturn(PETSC_SUCCESS);
    112: }

    114: /*MC
    115:    PETSCVIEWERSTRING - A viewer that writes to a string

    117:   Level: beginner

    119: .seealso: [](sec_viewers), `PetscViewerStringOpen()`, `PetscViewerStringSPrintf()`, `PetscViewerSocketOpen()`, `PetscViewerDrawOpen()`, `PETSCVIEWERSOCKET`,
    120:           `PetscViewerCreate()`, `PetscViewerASCIIOpen()`, `PetscViewerBinaryOpen()`, `PETSCVIEWERBINARY`, `PETSCVIEWERDRAW`,
    121:           `PetscViewerMatlabOpen()`, `VecView()`, `DMView()`, `PetscViewerMatlabPutArray()`, `PETSCVIEWERASCII`, `PETSCVIEWERMATLAB`,
    122:           `PetscViewerFileSetName()`, `PetscViewerFileSetMode()`, `PetscViewerFormat`, `PetscViewerType`, `PetscViewerSetType()`
    123: M*/

    125: PETSC_EXTERN PetscErrorCode PetscViewerCreate_String(PetscViewer v)
    126: {
    127:   PetscViewer_String *vstr;

    129:   PetscFunctionBegin;
    130:   v->ops->destroy          = PetscViewerDestroy_String;
    131:   v->ops->view             = NULL;
    132:   v->ops->flush            = NULL;
    133:   v->ops->getsubviewer     = PetscViewerGetSubViewer_String;
    134:   v->ops->restoresubviewer = PetscViewerRestoreSubViewer_String;
    135:   PetscCall(PetscNew(&vstr));
    136:   v->data      = (void *)vstr;
    137:   vstr->string = NULL;
    138:   PetscFunctionReturn(PETSC_SUCCESS);
    139: }

    141: /*@C
    142:   PetscViewerStringGetStringRead - Returns the string that a `PETSCVIEWERSTRING` uses

    144:   Logically Collective

    146:   Input Parameter:
    147: . viewer - `PETSCVIEWERSTRING` viewer

    149:   Output Parameters:
    150: + string - the string, optional use `NULL` if you do not need
    151: - len    - the length of the string, optional use `NULL` if you do not need it

    153:   Level: advanced

    155:   Note:
    156:   Do not write to the string nor free it

    158:   Fortran Note:
    159:   Copies the current contents of the `PETSCVIEWERSTRING` viewer string

    161: .seealso: [](sec_viewers), `PetscViewerStringOpen()`, `PETSCVIEWERSTRING`, `PetscViewerStringSetString()`, `PetscViewerStringSPrintf()`,
    162:           `PetscViewerStringSetOwnString()`
    163: @*/
    164: PetscErrorCode PetscViewerStringGetStringRead(PetscViewer viewer, const char *string[], size_t *len) PeNS
    165: {
    166:   PetscViewer_String *vstr = (PetscViewer_String *)viewer->data;
    167:   PetscBool           isstring;

    169:   PetscFunctionBegin;
    171:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring));
    172:   PetscCheck(isstring, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Only for PETSCVIEWERSTRING");
    173:   if (string) *string = vstr->string;
    174:   if (len) *len = vstr->maxlen;
    175:   PetscFunctionReturn(PETSC_SUCCESS);
    176: }

    178: /*@C
    179:   PetscViewerStringSetString - sets the string that a string viewer will print to

    181:   Logically Collective

    183:   Input Parameters:
    184: + viewer - string viewer you wish to attach string to
    185: . string - the string to print data into
    186: - len    - the length of the string

    188:   Level: advanced

    190:   Note:
    191:   The function does not copy the string, it uses it directly therefore you cannot free
    192:   the string until the viewer is destroyed. If you call `PetscViewerStringSetOwnString()` the ownership
    193:   passes to the viewer and it will be responsible for freeing it. In this case the string must be
    194:   obtained with `PetscMalloc()`.

    196: .seealso: [](sec_viewers), `PetscViewerStringOpen()`, `PETSCVIEWERSTRING`, `PetscViewerStringGetStringRead()`, `PetscViewerStringSPrintf()`,
    197:           `PetscViewerStringSetOwnString()`
    198: @*/
    199: PetscErrorCode PetscViewerStringSetString(PetscViewer viewer, char string[], size_t len) PeNS
    200: {
    201:   PetscViewer_String *vstr = (PetscViewer_String *)viewer->data;
    202:   PetscBool           isstring;

    204:   PetscFunctionBegin;
    206:   PetscAssertPointer(string, 2);
    207:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring));
    208:   if (!isstring) PetscFunctionReturn(PETSC_SUCCESS);
    209:   PetscCheck(len > 2, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "String must have length at least 2");

    211:   PetscCall(PetscArrayzero(string, len));
    212:   vstr->string = string;
    213:   vstr->head   = string;
    214:   vstr->curlen = 0;
    215:   vstr->maxlen = len;
    216:   PetscFunctionReturn(PETSC_SUCCESS);
    217: }

    219: /*@
    220:   PetscViewerStringSetOwnString - tells the viewer that it now owns the string and is responsible for freeing it with `PetscFree()`

    222:   Logically Collective

    224:   Input Parameter:
    225: . viewer - string viewer

    227:   Level: advanced

    229:   Note:
    230:   If you call this the string must have been obtained with `PetscMalloc()` and you cannot free the string

    232: .seealso: [](sec_viewers), `PetscViewerStringOpen()`, `PETSCVIEWERSTRING`, `PetscViewerStringGetStringRead()`, `PetscViewerStringSPrintf()`,
    233:           `PetscViewerStringSetString()`
    234: @*/
    235: PetscErrorCode PetscViewerStringSetOwnString(PetscViewer viewer)
    236: {
    237:   PetscViewer_String *vstr = (PetscViewer_String *)viewer->data;
    238:   PetscBool           isstring;

    240:   PetscFunctionBegin;
    242:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring));
    243:   if (!isstring) PetscFunctionReturn(PETSC_SUCCESS);

    245:   vstr->ownstring = PETSC_TRUE;
    246:   PetscFunctionReturn(PETSC_SUCCESS);
    247: }