xref: /petsc/src/sys/classes/viewer/impls/string/stringv.c (revision ea5adb04736709a5de7232935ec423727733e36c)
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 {
13   PetscViewer_String *vstr = (PetscViewer_String *)viewer->data;
14 
15   PetscFunctionBegin;
16   if (vstr->ownstring) PetscCall(PetscFree(vstr->string));
17   PetscCall(PetscFree(vstr));
18   PetscFunctionReturn(0);
19 }
20 
21 /*@C
22     PetscViewerStringSPrintf - Prints information to a `PETSCVIEWERSTRING` `PetscViewer` object
23 
24     Logically Collective; No Fortran Support
25 
26     Input Parameters:
27 +   v - a string `PetscViewer`, formed by `PetscViewerStringOpen()`
28 -   format - the format of the input
29 
30     Level: developer
31 
32     Note:
33     Though this is collective each MPI rank maintains a separate string
34 
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;
45 
46   PetscFunctionBegin;
47   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
48   PetscValidCharPointer(format, 2);
49   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring));
50   if (!isstring) PetscFunctionReturn(0);
51   PetscCheck(vstr->string, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Must call PetscViewerStringSetString() before using");
52 
53   va_start(Argp, format);
54   PetscCall(PetscVSNPrintf(tmp, 4096, 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(PetscStrncpy(vstr->head, tmp, cshift));
60   vstr->head += shift;
61   vstr->curlen += shift;
62   PetscFunctionReturn(0);
63 }
64 
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.
69 
70     Collective; No Fortran Support
71 
72     Input Parameters:
73 +   comm - the communicator
74 .   string - the string to use
75 -   len    - the string length
76 
77     Output Parameter:
78 .   lab - the `PetscViewer`
79 
80     Level: advanced
81 
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(0);
91 }
92 
93 PetscErrorCode PetscViewerGetSubViewer_String(PetscViewer viewer, MPI_Comm comm, PetscViewer *sviewer)
94 {
95   PetscViewer_String *vstr = (PetscViewer_String *)viewer->data;
96 
97   PetscFunctionBegin;
98   PetscCall(PetscViewerStringOpen(PETSC_COMM_SELF, vstr->head, vstr->maxlen - vstr->curlen, sviewer));
99   PetscFunctionReturn(0);
100 }
101 
102 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;
106 
107   PetscFunctionBegin;
108   vstr->head = iviewer->head;
109   vstr->curlen += iviewer->curlen;
110   PetscCall(PetscViewerDestroy(sviewer));
111   PetscFunctionReturn(0);
112 }
113 
114 /*MC
115    PETSCVIEWERSTRING - A viewer that writes to a string
116 
117   Level: beginner
118 
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*/
124 
125 PETSC_EXTERN PetscErrorCode PetscViewerCreate_String(PetscViewer v)
126 {
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(PetscNew(&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
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   Level: advanced
155 
156   Note:
157   Do not write to the string nor free it
158 
159 .seealso: [](sec_viewers), `PetscViewerStringOpen()`, `PETSCVIEWERSTRING`, `PetscViewerStringSetString()`, `PetscViewerStringSPrintf()`,
160           `PetscViewerStringSetOwnString()`
161 @*/
162 PetscErrorCode PetscViewerStringGetStringRead(PetscViewer viewer, const char *string[], size_t *len)
163 {
164   PetscViewer_String *vstr = (PetscViewer_String *)viewer->data;
165   PetscBool           isstring;
166 
167   PetscFunctionBegin;
168   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
169   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring));
170   PetscCheck(isstring, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Only for PETSCVIEWERSTRING");
171   if (string) *string = vstr->string;
172   if (len) *len = vstr->maxlen;
173   PetscFunctionReturn(0);
174 }
175 
176 /*@C
177 
178    PetscViewerStringSetString - sets the string that a string viewer will print to
179 
180    Logically Collective
181 
182   Input Parameters:
183 +   viewer - string viewer you wish to attach string to
184 .   string - the string to print data into
185 -   len - the length of the string
186 
187   Level: advanced
188 
189   Note:
190   The function does not copy the string, it uses it directly therefore you cannot free
191   the string until the viewer is destroyed. If you call `PetscViewerStringSetOwnString()` the ownership
192   passes to the viewer and it will be responsable for freeing it. In this case the string must be
193   obtained with `PetscMalloc()`.
194 
195 .seealso: [](sec_viewers), `PetscViewerStringOpen()`, `PETSCVIEWERSTRING`, `PetscViewerStringGetStringRead()`, `PetscViewerStringSPrintf()`,
196           `PetscViewerStringSetOwnString()`
197 @*/
198 PetscErrorCode PetscViewerStringSetString(PetscViewer viewer, char string[], size_t len)
199 {
200   PetscViewer_String *vstr = (PetscViewer_String *)viewer->data;
201   PetscBool           isstring;
202 
203   PetscFunctionBegin;
204   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
205   PetscValidCharPointer(string, 2);
206   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring));
207   if (!isstring) PetscFunctionReturn(0);
208   PetscCheck(len > 2, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "String must have length at least 2");
209 
210   PetscCall(PetscArrayzero(string, len));
211   vstr->string = string;
212   vstr->head   = string;
213   vstr->curlen = 0;
214   vstr->maxlen = len;
215   PetscFunctionReturn(0);
216 }
217 
218 /*@C
219 
220    PetscViewerStringSetOwnString - tells the viewer that it now owns the string and is responsible for freeing it
221 
222    Logically Collective
223 
224   Input Parameters:
225 .   viewer - string viewer
226 
227   Level: advanced
228 
229   Note:
230   If you call this the string must have been obtained with `PetscMalloc()` and you cannot free the string
231 
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;
239 
240   PetscFunctionBegin;
241   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
242   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring));
243   if (!isstring) PetscFunctionReturn(0);
244 
245   vstr->ownstring = PETSC_TRUE;
246   PetscFunctionReturn(0);
247 }
248