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