xref: /petsc/src/sys/classes/viewer/impls/string/stringv.c (revision d3c69ad0bb09681fda0ed612cc8275184ea14744)
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 PetscViewer string.
23 
24     Logically Collective on PetscViewer (Hmmm, each processor maintains a separate string)
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     Fortran Note:
33     This routine is not supported in Fortran.
34 
35 .seealso: `PetscViewerStringOpen()`, `PetscViewerStringGetStringRead()`, `PetscViewerStringSetString()`, `PETSCVIEWERSTRING`
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(0);
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,4096,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(PetscStrncpy(vstr->head,tmp,cshift));
60   vstr->head   += shift;
61   vstr->curlen += shift;
62   PetscFunctionReturn(0);
63 }
64 
65 /*@C
66     PetscViewerStringOpen - Opens a string as a 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
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     Fortran Note:
83     This routine is not supported in Fortran.
84 
85 .seealso: `PetscViewerDestroy()`, `PetscViewerStringSPrintf()`, `PetscViewerStringGetStringRead()`, `PetscViewerStringSetString()`, `PETSCVIEWERSTRING`
86 @*/
87 PetscErrorCode  PetscViewerStringOpen(MPI_Comm comm,char string[],size_t len,PetscViewer *lab)
88 {
89   PetscFunctionBegin;
90   PetscCall(PetscViewerCreate(comm,lab));
91   PetscCall(PetscViewerSetType(*lab,PETSCVIEWERSTRING));
92   PetscCall(PetscViewerStringSetString(*lab,string,len));
93   PetscFunctionReturn(0);
94 }
95 
96 PetscErrorCode PetscViewerGetSubViewer_String(PetscViewer viewer,MPI_Comm comm,PetscViewer *sviewer)
97 {
98   PetscViewer_String *vstr = (PetscViewer_String*)viewer->data;
99 
100   PetscFunctionBegin;
101   PetscCall(PetscViewerStringOpen(PETSC_COMM_SELF,vstr->head,vstr->maxlen-vstr->curlen,sviewer));
102   PetscFunctionReturn(0);
103 }
104 
105 PetscErrorCode PetscViewerRestoreSubViewer_String(PetscViewer viewer,MPI_Comm comm,PetscViewer *sviewer)
106 {
107   PetscViewer_String *iviewer = (PetscViewer_String*)(*sviewer)->data;
108   PetscViewer_String *vstr    = (PetscViewer_String*)viewer->data;
109 
110   PetscFunctionBegin;
111   vstr->head    = iviewer->head;
112   vstr->curlen += iviewer->curlen;
113   PetscCall(PetscViewerDestroy(sviewer));
114   PetscFunctionReturn(0);
115 }
116 
117 /*MC
118    PETSCVIEWERSTRING - A viewer that writes to a string
119 
120 .seealso: `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 
125   Level: beginner
126 M*/
127 
128 PETSC_EXTERN PetscErrorCode PetscViewerCreate_String(PetscViewer v)
129 {
130   PetscViewer_String *vstr;
131 
132   PetscFunctionBegin;
133   v->ops->destroy          = PetscViewerDestroy_String;
134   v->ops->view             = NULL;
135   v->ops->flush            = NULL;
136   v->ops->getsubviewer     = PetscViewerGetSubViewer_String;
137   v->ops->restoresubviewer = PetscViewerRestoreSubViewer_String;
138   PetscCall(PetscNewLog(v,&vstr));
139   v->data                  = (void*)vstr;
140   vstr->string             = NULL;
141   PetscFunctionReturn(0);
142 }
143 
144 /*@C
145 
146    PetscViewerStringGetStringRead - Returns the string that a string viewer uses
147 
148    Logically Collective on PetscViewer
149 
150   Input Parameter:
151 .   viewer - string viewer
152 
153   Output Parameters:
154 +    string - the string, optional use NULL if you do not need
155 -   len - the length of the string, optional use NULL if you do
156 
157   Notes: Do not write to the string nor free it
158 
159   Level: advanced
160 
161 .seealso: `PetscViewerStringOpen()`, `PETSCVIEWERSTRING`, `PetscViewerStringSetString()`, `PetscViewerStringSPrintf()`,
162           `PetscViewerStringSetOwnString()`
163 @*/
164 PetscErrorCode  PetscViewerStringGetStringRead(PetscViewer viewer,const char *string[],size_t *len)
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(0);
176 }
177 
178 /*@C
179 
180    PetscViewerStringSetString - sets the string that a string viewer will print to
181 
182    Logically Collective on PetscViewer
183 
184   Input Parameters:
185 +   viewer - string viewer you wish to attach string to
186 .   string - the string to print data into
187 -   len - the length of the string
188 
189   Notes: The function does not copy the string, it uses it directly therefore you cannot free
190    the string until the viewer is destroyed. If you call PetscViewerStringSetOwnString() the ownership
191    passes to the viewer and it will be responsable for freeing it. In this case the string must be
192    obtained with PetscMalloc().
193 
194   Level: advanced
195 
196 .seealso: `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(0);
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(0);
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 on PetscViewer
224 
225   Input Parameters:
226 .   viewer - string viewer
227 
228   Notes: If you call this the string must have been obtained with PetscMalloc() and you cannot free the string
229 
230   Level: advanced
231 
232 .seealso: `PetscViewerStringOpen()`, `PETSCVIEWERSTRING`, `PetscViewerStringGetStringRead()`, `PetscViewerStringSPrintf()`,
233           `PetscViewerStringSetString()`
234 @*/
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(0);
244 
245   vstr->ownstring = PETSC_TRUE;
246   PetscFunctionReturn(0);
247 }
248