Actual source code: stringv.c
1: #include <petsc/private/viewerimpl.h>
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;
10: static PetscErrorCode PetscViewerDestroy_String(PetscViewer viewer)
11: {
12: PetscViewer_String *vstr = (PetscViewer_String *)viewer->data;
14: PetscFunctionBegin;
15: if (vstr->ownstring) PetscCall(PetscFree(vstr->string));
16: PetscCall(PetscFree(vstr));
17: PetscFunctionReturn(PETSC_SUCCESS);
18: }
20: /*@C
21: PetscViewerStringSPrintf - Prints information to a `PETSCVIEWERSTRING` `PetscViewer` object
23: Logically Collective; No Fortran Support
25: Input Parameters:
26: + viewer - a string `PetscViewer`, formed by `PetscViewerStringOpen()`
27: - format - the format of the input
29: Level: developer
31: Note:
32: Though this is collective each MPI process maintains a separate string
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;
45: PetscFunctionBegin;
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");
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: }
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.
70: Collective; No Fortran Support
72: Input Parameters:
73: + comm - the communicator
74: . string - the string to use
75: - len - the string length
77: Output Parameter:
78: . lab - the `PetscViewer`
80: Level: advanced
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: }
93: static PetscErrorCode PetscViewerGetSubViewer_String(PetscViewer viewer, MPI_Comm comm, PetscViewer *sviewer)
94: {
95: PetscViewer_String *vstr = (PetscViewer_String *)viewer->data;
97: PetscFunctionBegin;
98: PetscCall(PetscViewerStringOpen(PETSC_COMM_SELF, vstr->head, vstr->maxlen - vstr->curlen, sviewer));
99: PetscFunctionReturn(PETSC_SUCCESS);
100: }
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;
107: PetscFunctionBegin;
108: vstr->head = iviewer->head;
109: vstr->curlen += iviewer->curlen;
110: PetscCall(PetscViewerDestroy(sviewer));
111: PetscFunctionReturn(PETSC_SUCCESS);
112: }
114: /*MC
115: PETSCVIEWERSTRING - A viewer that writes to a string
117: Level: beginner
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*/
125: PETSC_EXTERN PetscErrorCode PetscViewerCreate_String(PetscViewer v)
126: {
127: PetscViewer_String *vstr;
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: }
141: /*@C
143: PetscViewerStringGetStringRead - Returns the string that a `PETSCVIEWERSTRING` uses
145: Logically Collective
147: Input Parameter:
148: . viewer - `PETSCVIEWERSTRING` viewer
150: Output Parameters:
151: + string - the string, optional use NULL if you do not need
152: - len - the length of the string, optional use NULL if you do
154: Level: advanced
156: Note:
157: Do not write to the string nor free it
159: .seealso: [](sec_viewers), `PetscViewerStringOpen()`, `PETSCVIEWERSTRING`, `PetscViewerStringSetString()`, `PetscViewerStringSPrintf()`,
160: `PetscViewerStringSetOwnString()`
161: @*/
162: PetscErrorCode PetscViewerStringGetStringRead(PetscViewer viewer, const char *string[], size_t *len)
163: {
164: PetscViewer_String *vstr = (PetscViewer_String *)viewer->data;
165: PetscBool isstring;
167: PetscFunctionBegin;
169: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring));
170: PetscCheck(isstring, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Only for PETSCVIEWERSTRING");
171: if (string) *string = vstr->string;
172: if (len) *len = vstr->maxlen;
173: PetscFunctionReturn(PETSC_SUCCESS);
174: }
176: /*@C
178: PetscViewerStringSetString - sets the string that a string viewer will print to
180: Logically Collective
182: Input Parameters:
183: + viewer - string viewer you wish to attach string to
184: . string - the string to print data into
185: - len - the length of the string
187: Level: advanced
189: Note:
190: The function does not copy the string, it uses it directly therefore you cannot free
191: the string until the viewer is destroyed. If you call `PetscViewerStringSetOwnString()` the ownership
192: passes to the viewer and it will be responsible for freeing it. In this case the string must be
193: obtained with `PetscMalloc()`.
195: .seealso: [](sec_viewers), `PetscViewerStringOpen()`, `PETSCVIEWERSTRING`, `PetscViewerStringGetStringRead()`, `PetscViewerStringSPrintf()`,
196: `PetscViewerStringSetOwnString()`
197: @*/
198: PetscErrorCode PetscViewerStringSetString(PetscViewer viewer, char string[], size_t len)
199: {
200: PetscViewer_String *vstr = (PetscViewer_String *)viewer->data;
201: PetscBool isstring;
203: PetscFunctionBegin;
205: PetscAssertPointer(string, 2);
206: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring));
207: if (!isstring) PetscFunctionReturn(PETSC_SUCCESS);
208: PetscCheck(len > 2, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "String must have length at least 2");
210: PetscCall(PetscArrayzero(string, len));
211: vstr->string = string;
212: vstr->head = string;
213: vstr->curlen = 0;
214: vstr->maxlen = len;
215: PetscFunctionReturn(PETSC_SUCCESS);
216: }
218: /*@C
220: PetscViewerStringSetOwnString - tells the viewer that it now owns the string and is responsible for freeing it
222: Logically Collective
224: Input Parameter:
225: . viewer - string viewer
227: Level: advanced
229: Note:
230: If you call this the string must have been obtained with `PetscMalloc()` and you cannot free the string
232: .seealso: [](sec_viewers), `PetscViewerStringOpen()`, `PETSCVIEWERSTRING`, `PetscViewerStringGetStringRead()`, `PetscViewerStringSPrintf()`,
233: `PetscViewerStringSetString()`
234: @*/
235: PetscErrorCode PetscViewerStringSetOwnString(PetscViewer viewer)
236: {
237: PetscViewer_String *vstr = (PetscViewer_String *)viewer->data;
238: PetscBool isstring;
240: PetscFunctionBegin;
242: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring));
243: if (!isstring) PetscFunctionReturn(PETSC_SUCCESS);
245: vstr->ownstring = PETSC_TRUE;
246: PetscFunctionReturn(PETSC_SUCCESS);
247: }