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)
 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

153:   Level: advanced

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

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

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

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

178:   Logically Collective

180:   Input Parameters:
181: + viewer - string viewer you wish to attach string to
182: . string - the string to print data into
183: - len    - the length of the string

185:   Level: advanced

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

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

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

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

216: /*@C
217:   PetscViewerStringSetOwnString - tells the viewer that it now owns the string and is responsible for freeing it

219:   Logically Collective

221:   Input Parameter:
222: . viewer - string viewer

224:   Level: advanced

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

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

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

242:   vstr->ownstring = PETSC_TRUE;
243:   PetscFunctionReturn(PETSC_SUCCESS);
244: }