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
PetscViewerDestroy_String(PetscViewer viewer)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 @*/
PetscViewerStringSPrintf(PetscViewer viewer,const char format[],...)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 @*/
PetscViewerStringOpen(MPI_Comm comm,char string[],size_t len,PetscViewer * lab)84 PetscErrorCode PetscViewerStringOpen(MPI_Comm comm, char string[], size_t len, PetscViewer *lab) PeNS
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
PetscViewerGetSubViewer_String(PetscViewer viewer,MPI_Comm comm,PetscViewer * sviewer)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
PetscViewerRestoreSubViewer_String(PetscViewer viewer,MPI_Comm comm,PetscViewer * sviewer)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
PetscViewerCreate_String(PetscViewer v)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 not need it
152
153 Level: advanced
154
155 Note:
156 Do not write to the string nor free it
157
158 Fortran Note:
159 Copies the current contents of the `PETSCVIEWERSTRING` viewer string
160
161 .seealso: [](sec_viewers), `PetscViewerStringOpen()`, `PETSCVIEWERSTRING`, `PetscViewerStringSetString()`, `PetscViewerStringSPrintf()`,
162 `PetscViewerStringSetOwnString()`
163 @*/
PetscViewerStringGetStringRead(PetscViewer viewer,const char * string[],size_t * len)164 PetscErrorCode PetscViewerStringGetStringRead(PetscViewer viewer, const char *string[], size_t *len) PeNS
165 {
166 PetscViewer_String *vstr = (PetscViewer_String *)viewer->data;
167 PetscBool isstring;
168
169 PetscFunctionBegin;
170 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
171 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring));
172 PetscCheck(isstring, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Only for PETSCVIEWERSTRING");
173 if (string) *string = vstr->string;
174 if (len) *len = vstr->maxlen;
175 PetscFunctionReturn(PETSC_SUCCESS);
176 }
177
178 /*@C
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 @*/
PetscViewerStringSetString(PetscViewer viewer,char string[],size_t len)199 PetscErrorCode PetscViewerStringSetString(PetscViewer viewer, char string[], size_t len) PeNS
200 {
201 PetscViewer_String *vstr = (PetscViewer_String *)viewer->data;
202 PetscBool isstring;
203
204 PetscFunctionBegin;
205 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
206 PetscAssertPointer(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 /*@
220 PetscViewerStringSetOwnString - tells the viewer that it now owns the string and is responsible for freeing it with `PetscFree()`
221
222 Logically Collective
223
224 Input Parameter:
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 @*/
PetscViewerStringSetOwnString(PetscViewer viewer)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(PETSC_SUCCESS);
244
245 vstr->ownstring = PETSC_TRUE;
246 PetscFunctionReturn(PETSC_SUCCESS);
247 }
248