Actual source code: stringv.c


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

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

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

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

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

 24:     Logically Collective; No Fortran Support

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

 30:     Level: developer

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

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

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

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

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

 71:     Collective; No Fortran Support

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

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

 81:     Level: advanced

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

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

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

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

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

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

118:   Level: beginner

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

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

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

142: /*@C

144:    PetscViewerStringGetStringRead - Returns the string that a `PETSCVIEWERSTRING` uses

146:    Logically Collective

148:   Input Parameter:
149: .   viewer -  `PETSCVIEWERSTRING` viewer

151:   Output Parameters:
152: +    string - the string, optional use NULL if you do not need
153: -   len - the length of the string, optional use NULL if you do

155:   Level: advanced

157:   Note:
158:   Do not write to the string nor free it

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

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

177: /*@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)
200: {
201:   PetscViewer_String *vstr = (PetscViewer_String *)viewer->data;
202:   PetscBool           isstring;

204:   PetscFunctionBegin;
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: /*@C

221:    PetscViewerStringSetOwnString - tells the viewer that it now owns the string and is responsible for freeing it

223:    Logically Collective

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

228:   Level: advanced

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

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

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

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