xref: /petsc/src/sys/classes/viewer/impls/string/stringv.c (revision 7c561f0977de51325d9fcc8e06f17306dbb264cc)
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 responsible 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(PETSC_SUCCESS);
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(PETSC_SUCCESS);
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, 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 }
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; No Fortran Support
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 .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 }
93 
94 PetscErrorCode PetscViewerGetSubViewer_String(PetscViewer viewer, MPI_Comm comm, PetscViewer *sviewer)
95 {
96   PetscViewer_String *vstr = (PetscViewer_String *)viewer->data;
97 
98   PetscFunctionBegin;
99   PetscCall(PetscViewerStringOpen(PETSC_COMM_SELF, vstr->head, vstr->maxlen - vstr->curlen, sviewer));
100   PetscFunctionReturn(PETSC_SUCCESS);
101 }
102 
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;
107 
108   PetscFunctionBegin;
109   vstr->head = iviewer->head;
110   vstr->curlen += iviewer->curlen;
111   PetscCall(PetscViewerDestroy(sviewer));
112   PetscFunctionReturn(PETSC_SUCCESS);
113 }
114 
115 /*MC
116    PETSCVIEWERSTRING - A viewer that writes to a string
117 
118   Level: beginner
119 
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*/
125 
126 PETSC_EXTERN PetscErrorCode PetscViewerCreate_String(PetscViewer v)
127 {
128   PetscViewer_String *vstr;
129 
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 }
141 
142 /*@C
143 
144    PetscViewerStringGetStringRead - Returns the string that a `PETSCVIEWERSTRING` uses
145 
146    Logically Collective
147 
148   Input Parameter:
149 .   viewer -  `PETSCVIEWERSTRING` viewer
150 
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
154 
155   Level: advanced
156 
157   Note:
158   Do not write to the string nor free it
159 
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;
167 
168   PetscFunctionBegin;
169   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
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 }
176 
177 /*@C
178 
179    PetscViewerStringSetString - sets the string that a string viewer will print to
180 
181    Logically Collective
182 
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
187 
188   Level: advanced
189 
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()`.
195 
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;
203 
204   PetscFunctionBegin;
205   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
206   PetscValidCharPointer(string, 2);
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");
210 
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 }
218 
219 /*@C
220 
221    PetscViewerStringSetOwnString - tells the viewer that it now owns the string and is responsible for freeing it
222 
223    Logically Collective
224 
225   Input Parameters:
226 .   viewer - string viewer
227 
228   Level: advanced
229 
230   Note:
231   If you call this the string must have been obtained with `PetscMalloc()` and you cannot free the string
232 
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;
240 
241   PetscFunctionBegin;
242   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
243   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring));
244   if (!isstring) PetscFunctionReturn(PETSC_SUCCESS);
245 
246   vstr->ownstring = PETSC_TRUE;
247   PetscFunctionReturn(PETSC_SUCCESS);
248 }
249