xref: /petsc/src/sys/classes/viewer/impls/string/stringv.c (revision d5b43468fb8780a8feea140ccd6fa3e6a50411cc)
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 on viewer
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     Fortran Note:
36     This routine is not supported in Fortran.
37 
38 .seealso: `PETSCVIEWERSTRING`, `PetscViewerStringOpen()`, `PetscViewerStringGetStringRead()`, `PetscViewerStringSetString()`
39 @*/
40 PetscErrorCode PetscViewerStringSPrintf(PetscViewer viewer, const char format[], ...)
41 {
42   va_list             Argp;
43   size_t              fullLength;
44   size_t              shift, cshift;
45   PetscBool           isstring;
46   char                tmp[4096];
47   PetscViewer_String *vstr = (PetscViewer_String *)viewer->data;
48 
49   PetscFunctionBegin;
50   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
51   PetscValidCharPointer(format, 2);
52   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring));
53   if (!isstring) PetscFunctionReturn(0);
54   PetscCheck(vstr->string, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Must call PetscViewerStringSetString() before using");
55 
56   va_start(Argp, format);
57   PetscCall(PetscVSNPrintf(tmp, 4096, format, &fullLength, Argp));
58   va_end(Argp);
59   PetscCall(PetscStrlen(tmp, &shift));
60   cshift = shift + 1;
61   if (cshift >= vstr->maxlen - vstr->curlen - 1) cshift = vstr->maxlen - vstr->curlen - 1;
62   PetscCall(PetscStrncpy(vstr->head, tmp, cshift));
63   vstr->head += shift;
64   vstr->curlen += shift;
65   PetscFunctionReturn(0);
66 }
67 
68 /*@C
69     PetscViewerStringOpen - Opens a string as a `PETSCVIEWERSTRING` `PetscViewer`. This is a very
70     simple `PetscViewer`; information on the object is simply stored into
71     the string in a fairly nice way.
72 
73     Collective
74 
75     Input Parameters:
76 +   comm - the communicator
77 .   string - the string to use
78 -   len    - the string length
79 
80     Output Parameter:
81 .   lab - the `PetscViewer`
82 
83     Level: advanced
84 
85     Fortran Note:
86     This routine is not supported in Fortran.
87 
88 .seealso: `PETSCVIEWERSTRING`, `PetscViewerDestroy()`, `PetscViewerStringSPrintf()`, `PetscViewerStringGetStringRead()`, `PetscViewerStringSetString()`
89 @*/
90 PetscErrorCode PetscViewerStringOpen(MPI_Comm comm, char string[], size_t len, PetscViewer *lab)
91 {
92   PetscFunctionBegin;
93   PetscCall(PetscViewerCreate(comm, lab));
94   PetscCall(PetscViewerSetType(*lab, PETSCVIEWERSTRING));
95   PetscCall(PetscViewerStringSetString(*lab, string, len));
96   PetscFunctionReturn(0);
97 }
98 
99 PetscErrorCode PetscViewerGetSubViewer_String(PetscViewer viewer, MPI_Comm comm, PetscViewer *sviewer)
100 {
101   PetscViewer_String *vstr = (PetscViewer_String *)viewer->data;
102 
103   PetscFunctionBegin;
104   PetscCall(PetscViewerStringOpen(PETSC_COMM_SELF, vstr->head, vstr->maxlen - vstr->curlen, sviewer));
105   PetscFunctionReturn(0);
106 }
107 
108 PetscErrorCode PetscViewerRestoreSubViewer_String(PetscViewer viewer, MPI_Comm comm, PetscViewer *sviewer)
109 {
110   PetscViewer_String *iviewer = (PetscViewer_String *)(*sviewer)->data;
111   PetscViewer_String *vstr    = (PetscViewer_String *)viewer->data;
112 
113   PetscFunctionBegin;
114   vstr->head = iviewer->head;
115   vstr->curlen += iviewer->curlen;
116   PetscCall(PetscViewerDestroy(sviewer));
117   PetscFunctionReturn(0);
118 }
119 
120 /*MC
121    PETSCVIEWERSTRING - A viewer that writes to a string
122 
123   Level: beginner
124 
125 .seealso: `PetscViewerStringOpen()`, `PetscViewerStringSPrintf()`, `PetscViewerSocketOpen()`, `PetscViewerDrawOpen()`, `PETSCVIEWERSOCKET`,
126           `PetscViewerCreate()`, `PetscViewerASCIIOpen()`, `PetscViewerBinaryOpen()`, `PETSCVIEWERBINARY`, `PETSCVIEWERDRAW`,
127           `PetscViewerMatlabOpen()`, `VecView()`, `DMView()`, `PetscViewerMatlabPutArray()`, `PETSCVIEWERASCII`, `PETSCVIEWERMATLAB`,
128           `PetscViewerFileSetName()`, `PetscViewerFileSetMode()`, `PetscViewerFormat`, `PetscViewerType`, `PetscViewerSetType()`
129 M*/
130 
131 PETSC_EXTERN PetscErrorCode PetscViewerCreate_String(PetscViewer v)
132 {
133   PetscViewer_String *vstr;
134 
135   PetscFunctionBegin;
136   v->ops->destroy          = PetscViewerDestroy_String;
137   v->ops->view             = NULL;
138   v->ops->flush            = NULL;
139   v->ops->getsubviewer     = PetscViewerGetSubViewer_String;
140   v->ops->restoresubviewer = PetscViewerRestoreSubViewer_String;
141   PetscCall(PetscNew(&vstr));
142   v->data      = (void *)vstr;
143   vstr->string = NULL;
144   PetscFunctionReturn(0);
145 }
146 
147 /*@C
148 
149    PetscViewerStringGetStringRead - Returns the string that a `PETSCVIEWERSTRING` uses
150 
151    Logically Collective on viewer
152 
153   Input Parameter:
154 .   viewer -  `PETSCVIEWERSTRING` viewer
155 
156   Output Parameters:
157 +    string - the string, optional use NULL if you do not need
158 -   len - the length of the string, optional use NULL if you do
159 
160   Note:
161   Do not write to the string nor free it
162 
163   Level: advanced
164 
165 .seealso: `PetscViewerStringOpen()`, `PETSCVIEWERSTRING`, `PetscViewerStringSetString()`, `PetscViewerStringSPrintf()`,
166           `PetscViewerStringSetOwnString()`
167 @*/
168 PetscErrorCode PetscViewerStringGetStringRead(PetscViewer viewer, const char *string[], size_t *len)
169 {
170   PetscViewer_String *vstr = (PetscViewer_String *)viewer->data;
171   PetscBool           isstring;
172 
173   PetscFunctionBegin;
174   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
175   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring));
176   PetscCheck(isstring, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Only for PETSCVIEWERSTRING");
177   if (string) *string = vstr->string;
178   if (len) *len = vstr->maxlen;
179   PetscFunctionReturn(0);
180 }
181 
182 /*@C
183 
184    PetscViewerStringSetString - sets the string that a string viewer will print to
185 
186    Logically Collective on viewer
187 
188   Input Parameters:
189 +   viewer - string viewer you wish to attach string to
190 .   string - the string to print data into
191 -   len - the length of the string
192 
193   Note: The function does not copy the string, it uses it directly therefore you cannot free
194    the string until the viewer is destroyed. If you call `PetscViewerStringSetOwnString()` the ownership
195    passes to the viewer and it will be responsable for freeing it. In this case the string must be
196    obtained with `PetscMalloc()`.
197 
198   Level: advanced
199 
200 .seealso: `PetscViewerStringOpen()`, `PETSCVIEWERSTRING`, `PetscViewerStringGetStringRead()`, `PetscViewerStringSPrintf()`,
201           `PetscViewerStringSetOwnString()`
202 @*/
203 PetscErrorCode PetscViewerStringSetString(PetscViewer viewer, char string[], size_t len)
204 {
205   PetscViewer_String *vstr = (PetscViewer_String *)viewer->data;
206   PetscBool           isstring;
207 
208   PetscFunctionBegin;
209   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
210   PetscValidCharPointer(string, 2);
211   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring));
212   if (!isstring) PetscFunctionReturn(0);
213   PetscCheck(len > 2, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "String must have length at least 2");
214 
215   PetscCall(PetscArrayzero(string, len));
216   vstr->string = string;
217   vstr->head   = string;
218   vstr->curlen = 0;
219   vstr->maxlen = len;
220   PetscFunctionReturn(0);
221 }
222 
223 /*@C
224 
225    PetscViewerStringSetOwnString - tells the viewer that it now owns the string and is responsible for freeing it
226 
227    Logically Collective on viewer
228 
229   Input Parameters:
230 .   viewer - string viewer
231 
232   Note:
233   If you call this the string must have been obtained with `PetscMalloc()` and you cannot free the string
234 
235   Level: advanced
236 
237 .seealso: `PetscViewerStringOpen()`, `PETSCVIEWERSTRING`, `PetscViewerStringGetStringRead()`, `PetscViewerStringSPrintf()`,
238           `PetscViewerStringSetString()`
239 @*/
240 PetscErrorCode PetscViewerStringSetOwnString(PetscViewer viewer)
241 {
242   PetscViewer_String *vstr = (PetscViewer_String *)viewer->data;
243   PetscBool           isstring;
244 
245   PetscFunctionBegin;
246   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
247   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring));
248   if (!isstring) PetscFunctionReturn(0);
249 
250   vstr->ownstring = PETSC_TRUE;
251   PetscFunctionReturn(0);
252 }
253