xref: /petsc/src/sys/classes/viewer/impls/string/stringv.c (revision 11a5261e40035b7c793f2783a2ba6c7cd4f3b077)
1 
2 #include <petsc/private/viewerimpl.h> /*I  "petscsys.h"  I*/
3 
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 responsable for freeing the string */
9 } PetscViewer_String;
10 
11 static PetscErrorCode PetscViewerDestroy_String(PetscViewer viewer) {
12   PetscViewer_String *vstr = (PetscViewer_String *)viewer->data;
13 
14   PetscFunctionBegin;
15   if (vstr->ownstring) PetscCall(PetscFree(vstr->string));
16   PetscCall(PetscFree(vstr));
17   PetscFunctionReturn(0);
18 }
19 
20 /*@C
21     PetscViewerStringSPrintf - Prints information to a `PETSCVIEWERSTRING` `PetscViewer` object
22 
23     Logically Collective on viewer
24 
25     Input Parameters:
26 +   v - a string `PetscViewer`, formed by `PetscViewerStringOpen()`
27 -   format - the format of the input
28 
29     Level: developer
30 
31     Note:
32     Though this is collective each MPI rank maintains a separate string
33 
34     Fortran Note:
35     This routine is not supported in Fortran.
36 
37 .seealso: `PETSCVIEWERSTRING`, `PetscViewerStringOpen()`, `PetscViewerStringGetStringRead()`, `PetscViewerStringSetString()`
38 @*/
39 PetscErrorCode PetscViewerStringSPrintf(PetscViewer viewer, const char format[], ...) {
40   va_list             Argp;
41   size_t              fullLength;
42   size_t              shift, cshift;
43   PetscBool           isstring;
44   char                tmp[4096];
45   PetscViewer_String *vstr = (PetscViewer_String *)viewer->data;
46 
47   PetscFunctionBegin;
48   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
49   PetscValidCharPointer(format, 2);
50   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring));
51   if (!isstring) PetscFunctionReturn(0);
52   PetscCheck(vstr->string, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Must call PetscViewerStringSetString() before using");
53 
54   va_start(Argp, format);
55   PetscCall(PetscVSNPrintf(tmp, 4096, format, &fullLength, Argp));
56   va_end(Argp);
57   PetscCall(PetscStrlen(tmp, &shift));
58   cshift = shift + 1;
59   if (cshift >= vstr->maxlen - vstr->curlen - 1) cshift = vstr->maxlen - vstr->curlen - 1;
60   PetscCall(PetscStrncpy(vstr->head, tmp, cshift));
61   vstr->head += shift;
62   vstr->curlen += shift;
63   PetscFunctionReturn(0);
64 }
65 
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.
70 
71     Collective
72 
73     Input Parameters:
74 +   comm - the communicator
75 .   string - the string to use
76 -   len    - the string length
77 
78     Output Parameter:
79 .   lab - the `PetscViewer`
80 
81     Level: advanced
82 
83     Fortran Note:
84     This routine is not supported in Fortran.
85 
86 .seealso: `PETSCVIEWERSTRING`, `PetscViewerDestroy()`, `PetscViewerStringSPrintf()`, `PetscViewerStringGetStringRead()`, `PetscViewerStringSetString()`
87 @*/
88 PetscErrorCode PetscViewerStringOpen(MPI_Comm comm, char string[], size_t len, PetscViewer *lab) {
89   PetscFunctionBegin;
90   PetscCall(PetscViewerCreate(comm, lab));
91   PetscCall(PetscViewerSetType(*lab, PETSCVIEWERSTRING));
92   PetscCall(PetscViewerStringSetString(*lab, string, len));
93   PetscFunctionReturn(0);
94 }
95 
96 PetscErrorCode PetscViewerGetSubViewer_String(PetscViewer viewer, MPI_Comm comm, PetscViewer *sviewer) {
97   PetscViewer_String *vstr = (PetscViewer_String *)viewer->data;
98 
99   PetscFunctionBegin;
100   PetscCall(PetscViewerStringOpen(PETSC_COMM_SELF, vstr->head, vstr->maxlen - vstr->curlen, sviewer));
101   PetscFunctionReturn(0);
102 }
103 
104 PetscErrorCode PetscViewerRestoreSubViewer_String(PetscViewer viewer, MPI_Comm comm, PetscViewer *sviewer) {
105   PetscViewer_String *iviewer = (PetscViewer_String *)(*sviewer)->data;
106   PetscViewer_String *vstr    = (PetscViewer_String *)viewer->data;
107 
108   PetscFunctionBegin;
109   vstr->head = iviewer->head;
110   vstr->curlen += iviewer->curlen;
111   PetscCall(PetscViewerDestroy(sviewer));
112   PetscFunctionReturn(0);
113 }
114 
115 /*MC
116    PETSCVIEWERSTRING - A viewer that writes to a string
117 
118   Level: beginner
119 
120 .seealso: `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*/
125 
126 PETSC_EXTERN PetscErrorCode PetscViewerCreate_String(PetscViewer v) {
127   PetscViewer_String *vstr;
128 
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(PetscNewLog(v, &vstr));
136   v->data      = (void *)vstr;
137   vstr->string = NULL;
138   PetscFunctionReturn(0);
139 }
140 
141 /*@C
142 
143    PetscViewerStringGetStringRead - Returns the string that a `PETSCVIEWERSTRING` uses
144 
145    Logically Collective on viewer
146 
147   Input Parameter:
148 .   viewer -  `PETSCVIEWERSTRING` viewer
149 
150   Output Parameters:
151 +    string - the string, optional use NULL if you do not need
152 -   len - the length of the string, optional use NULL if you do
153 
154   Note:
155   Do not write to the string nor free it
156 
157   Level: advanced
158 
159 .seealso: `PetscViewerStringOpen()`, `PETSCVIEWERSTRING`, `PetscViewerStringSetString()`, `PetscViewerStringSPrintf()`,
160           `PetscViewerStringSetOwnString()`
161 @*/
162 PetscErrorCode PetscViewerStringGetStringRead(PetscViewer viewer, const char *string[], size_t *len) {
163   PetscViewer_String *vstr = (PetscViewer_String *)viewer->data;
164   PetscBool           isstring;
165 
166   PetscFunctionBegin;
167   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
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(0);
173 }
174 
175 /*@C
176 
177    PetscViewerStringSetString - sets the string that a string viewer will print to
178 
179    Logically Collective on viewer
180 
181   Input Parameters:
182 +   viewer - string viewer you wish to attach string to
183 .   string - the string to print data into
184 -   len - the length of the string
185 
186   Note: The function does not copy the string, it uses it directly therefore you cannot free
187    the string until the viewer is destroyed. If you call `PetscViewerStringSetOwnString()` the ownership
188    passes to the viewer and it will be responsable for freeing it. In this case the string must be
189    obtained with `PetscMalloc()`.
190 
191   Level: advanced
192 
193 .seealso: `PetscViewerStringOpen()`, `PETSCVIEWERSTRING`, `PetscViewerStringGetStringRead()`, `PetscViewerStringSPrintf()`,
194           `PetscViewerStringSetOwnString()`
195 @*/
196 PetscErrorCode PetscViewerStringSetString(PetscViewer viewer, char string[], size_t len) {
197   PetscViewer_String *vstr = (PetscViewer_String *)viewer->data;
198   PetscBool           isstring;
199 
200   PetscFunctionBegin;
201   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
202   PetscValidCharPointer(string, 2);
203   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring));
204   if (!isstring) PetscFunctionReturn(0);
205   PetscCheck(len > 2, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "String must have length at least 2");
206 
207   PetscCall(PetscArrayzero(string, len));
208   vstr->string = string;
209   vstr->head   = string;
210   vstr->curlen = 0;
211   vstr->maxlen = len;
212   PetscFunctionReturn(0);
213 }
214 
215 /*@C
216 
217    PetscViewerStringSetOwnString - tells the viewer that it now owns the string and is responsible for freeing it
218 
219    Logically Collective on viewer
220 
221   Input Parameters:
222 .   viewer - string viewer
223 
224   Note:
225   If you call this the string must have been obtained with `PetscMalloc()` and you cannot free the string
226 
227   Level: advanced
228 
229 .seealso: `PetscViewerStringOpen()`, `PETSCVIEWERSTRING`, `PetscViewerStringGetStringRead()`, `PetscViewerStringSPrintf()`,
230           `PetscViewerStringSetString()`
231 @*/
232 PetscErrorCode PetscViewerStringSetOwnString(PetscViewer viewer) {
233   PetscViewer_String *vstr = (PetscViewer_String *)viewer->data;
234   PetscBool           isstring;
235 
236   PetscFunctionBegin;
237   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
238   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring));
239   if (!isstring) PetscFunctionReturn(0);
240 
241   vstr->ownstring = PETSC_TRUE;
242   PetscFunctionReturn(0);
243 }
244