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: }