xref: /petsc/src/sys/classes/viewer/impls/string/stringv.c (revision 9281ddf3762f2d5c362e1f7018c73fc774f3a8d2)
1 #include <petsc/private/viewerimpl.h> /*I  "petscsys.h"  I*/
2 
3 typedef struct {
4   char     *string; /* string where info is stored */
5   char     *head;   /* pointer to beginning of unused portion */
6   size_t    curlen, maxlen;
7   PetscBool ownstring; /* string viewer is responsible for freeing the string */
8 } PetscViewer_String;
9 
10 static PetscErrorCode PetscViewerDestroy_String(PetscViewer viewer)
11 {
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(PETSC_SUCCESS);
18 }
19 
20 /*@C
21   PetscViewerStringSPrintf - Prints information to a `PETSCVIEWERSTRING` `PetscViewer` object
22 
23   Logically Collective; No Fortran Support
24 
25   Input Parameters:
26 + viewer - 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 process maintains a separate string
33 
34 .seealso: [](sec_viewers), `PETSCVIEWERSTRING`, `PetscViewerStringOpen()`, `PetscViewerStringGetStringRead()`, `PetscViewerStringSetString()`
35 @*/
36 PetscErrorCode PetscViewerStringSPrintf(PetscViewer viewer, const char format[], ...)
37 {
38   va_list             Argp;
39   size_t              fullLength;
40   size_t              shift, cshift;
41   PetscBool           isstring;
42   char                tmp[4096];
43   PetscViewer_String *vstr = (PetscViewer_String *)viewer->data;
44 
45   PetscFunctionBegin;
46   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
47   PetscAssertPointer(format, 2);
48   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring));
49   if (!isstring) PetscFunctionReturn(PETSC_SUCCESS);
50   PetscCheck(vstr->string, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Must call PetscViewerStringSetString() before using");
51 
52   va_start(Argp, format);
53   PetscCall(PetscVSNPrintf(tmp, sizeof(tmp), format, &fullLength, Argp));
54   va_end(Argp);
55   PetscCall(PetscStrlen(tmp, &shift));
56   cshift = shift + 1;
57   if (cshift >= vstr->maxlen - vstr->curlen - 1) cshift = vstr->maxlen - vstr->curlen - 1;
58   PetscCall(PetscMemcpy(vstr->head, tmp, cshift));
59   vstr->head[cshift - 1] = '\0';
60   vstr->head += shift;
61   vstr->curlen += shift;
62   PetscFunctionReturn(PETSC_SUCCESS);
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(PETSC_SUCCESS);
91 }
92 
93 static 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(PETSC_SUCCESS);
100 }
101 
102 static 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(PETSC_SUCCESS);
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(PETSC_SUCCESS);
139 }
140 
141 /*@C
142   PetscViewerStringGetStringRead - Returns the string that a `PETSCVIEWERSTRING` uses
143 
144   Logically Collective
145 
146   Input Parameter:
147 . viewer - `PETSCVIEWERSTRING` viewer
148 
149   Output Parameters:
150 + string - the string, optional use NULL if you do not need
151 - len    - the length of the string, optional use NULL if you do
152 
153   Level: advanced
154 
155   Note:
156   Do not write to the string nor free it
157 
158 .seealso: [](sec_viewers), `PetscViewerStringOpen()`, `PETSCVIEWERSTRING`, `PetscViewerStringSetString()`, `PetscViewerStringSPrintf()`,
159           `PetscViewerStringSetOwnString()`
160 @*/
161 PetscErrorCode PetscViewerStringGetStringRead(PetscViewer viewer, const char *string[], size_t *len)
162 {
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(PETSC_SUCCESS);
173 }
174 
175 /*@C
176   PetscViewerStringSetString - sets the string that a string viewer will print to
177 
178   Logically Collective
179 
180   Input Parameters:
181 + viewer - string viewer you wish to attach string to
182 . string - the string to print data into
183 - len    - the length of the string
184 
185   Level: advanced
186 
187   Note:
188   The function does not copy the string, it uses it directly therefore you cannot free
189   the string until the viewer is destroyed. If you call `PetscViewerStringSetOwnString()` the ownership
190   passes to the viewer and it will be responsible for freeing it. In this case the string must be
191   obtained with `PetscMalloc()`.
192 
193 .seealso: [](sec_viewers), `PetscViewerStringOpen()`, `PETSCVIEWERSTRING`, `PetscViewerStringGetStringRead()`, `PetscViewerStringSPrintf()`,
194           `PetscViewerStringSetOwnString()`
195 @*/
196 PetscErrorCode PetscViewerStringSetString(PetscViewer viewer, char string[], size_t len)
197 {
198   PetscViewer_String *vstr = (PetscViewer_String *)viewer->data;
199   PetscBool           isstring;
200 
201   PetscFunctionBegin;
202   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
203   PetscAssertPointer(string, 2);
204   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring));
205   if (!isstring) PetscFunctionReturn(PETSC_SUCCESS);
206   PetscCheck(len > 2, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "String must have length at least 2");
207 
208   PetscCall(PetscArrayzero(string, len));
209   vstr->string = string;
210   vstr->head   = string;
211   vstr->curlen = 0;
212   vstr->maxlen = len;
213   PetscFunctionReturn(PETSC_SUCCESS);
214 }
215 
216 /*@
217   PetscViewerStringSetOwnString - tells the viewer that it now owns the string and is responsible for freeing it
218 
219   Logically Collective
220 
221   Input Parameter:
222 . viewer - string viewer
223 
224   Level: advanced
225 
226   Note:
227   If you call this the string must have been obtained with `PetscMalloc()` and you cannot free the string
228 
229 .seealso: [](sec_viewers), `PetscViewerStringOpen()`, `PETSCVIEWERSTRING`, `PetscViewerStringGetStringRead()`, `PetscViewerStringSPrintf()`,
230           `PetscViewerStringSetString()`
231 @*/
232 PetscErrorCode PetscViewerStringSetOwnString(PetscViewer viewer)
233 {
234   PetscViewer_String *vstr = (PetscViewer_String *)viewer->data;
235   PetscBool           isstring;
236 
237   PetscFunctionBegin;
238   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
239   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring));
240   if (!isstring) PetscFunctionReturn(PETSC_SUCCESS);
241 
242   vstr->ownstring = PETSC_TRUE;
243   PetscFunctionReturn(PETSC_SUCCESS);
244 }
245