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 responsible 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(PETSC_SUCCESS); 19 } 20 21 /*@C 22 PetscViewerStringSPrintf - Prints information to a `PETSCVIEWERSTRING` `PetscViewer` object 23 24 Logically Collective; No Fortran Support 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 Note: 33 Though this is collective each MPI process maintains a separate string 34 35 .seealso: [](sec_viewers), `PETSCVIEWERSTRING`, `PetscViewerStringOpen()`, `PetscViewerStringGetStringRead()`, `PetscViewerStringSetString()` 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(PETSC_SUCCESS); 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, sizeof(tmp), 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(PetscMemcpy(vstr->head, tmp, cshift)); 60 vstr->head[cshift - 1] = '\0'; 61 vstr->head += shift; 62 vstr->curlen += shift; 63 PetscFunctionReturn(PETSC_SUCCESS); 64 } 65 66 /*@C 67 PetscViewerStringOpen - Opens a string as a `PETSCVIEWERSTRING` `PetscViewer`. This is a very 68 simple `PetscViewer`; information on the object is simply stored into 69 the string in a fairly nice way. 70 71 Collective; No Fortran Support 72 73 Input Parameters: 74 + comm - the communicator 75 . string - the string to use 76 - len - the string length 77 78 Output Parameter: 79 . lab - the `PetscViewer` 80 81 Level: advanced 82 83 .seealso: [](sec_viewers), `PETSCVIEWERSTRING`, `PetscViewerDestroy()`, `PetscViewerStringSPrintf()`, `PetscViewerStringGetStringRead()`, `PetscViewerStringSetString()` 84 @*/ 85 PetscErrorCode PetscViewerStringOpen(MPI_Comm comm, char string[], size_t len, PetscViewer *lab) 86 { 87 PetscFunctionBegin; 88 PetscCall(PetscViewerCreate(comm, lab)); 89 PetscCall(PetscViewerSetType(*lab, PETSCVIEWERSTRING)); 90 PetscCall(PetscViewerStringSetString(*lab, string, len)); 91 PetscFunctionReturn(PETSC_SUCCESS); 92 } 93 94 PetscErrorCode PetscViewerGetSubViewer_String(PetscViewer viewer, MPI_Comm comm, PetscViewer *sviewer) 95 { 96 PetscViewer_String *vstr = (PetscViewer_String *)viewer->data; 97 98 PetscFunctionBegin; 99 PetscCall(PetscViewerStringOpen(PETSC_COMM_SELF, vstr->head, vstr->maxlen - vstr->curlen, sviewer)); 100 PetscFunctionReturn(PETSC_SUCCESS); 101 } 102 103 PetscErrorCode PetscViewerRestoreSubViewer_String(PetscViewer viewer, MPI_Comm comm, PetscViewer *sviewer) 104 { 105 PetscViewer_String *iviewer = (PetscViewer_String *)(*sviewer)->data; 106 PetscViewer_String *vstr = (PetscViewer_String *)viewer->data; 107 108 PetscFunctionBegin; 109 vstr->head = iviewer->head; 110 vstr->curlen += iviewer->curlen; 111 PetscCall(PetscViewerDestroy(sviewer)); 112 PetscFunctionReturn(PETSC_SUCCESS); 113 } 114 115 /*MC 116 PETSCVIEWERSTRING - A viewer that writes to a string 117 118 Level: beginner 119 120 .seealso: [](sec_viewers), `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 M*/ 125 126 PETSC_EXTERN PetscErrorCode PetscViewerCreate_String(PetscViewer v) 127 { 128 PetscViewer_String *vstr; 129 130 PetscFunctionBegin; 131 v->ops->destroy = PetscViewerDestroy_String; 132 v->ops->view = NULL; 133 v->ops->flush = NULL; 134 v->ops->getsubviewer = PetscViewerGetSubViewer_String; 135 v->ops->restoresubviewer = PetscViewerRestoreSubViewer_String; 136 PetscCall(PetscNew(&vstr)); 137 v->data = (void *)vstr; 138 vstr->string = NULL; 139 PetscFunctionReturn(PETSC_SUCCESS); 140 } 141 142 /*@C 143 144 PetscViewerStringGetStringRead - Returns the string that a `PETSCVIEWERSTRING` uses 145 146 Logically Collective 147 148 Input Parameter: 149 . viewer - `PETSCVIEWERSTRING` viewer 150 151 Output Parameters: 152 + string - the string, optional use NULL if you do not need 153 - len - the length of the string, optional use NULL if you do 154 155 Level: advanced 156 157 Note: 158 Do not write to the string nor free it 159 160 .seealso: [](sec_viewers), `PetscViewerStringOpen()`, `PETSCVIEWERSTRING`, `PetscViewerStringSetString()`, `PetscViewerStringSPrintf()`, 161 `PetscViewerStringSetOwnString()` 162 @*/ 163 PetscErrorCode PetscViewerStringGetStringRead(PetscViewer viewer, const char *string[], size_t *len) 164 { 165 PetscViewer_String *vstr = (PetscViewer_String *)viewer->data; 166 PetscBool isstring; 167 168 PetscFunctionBegin; 169 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1); 170 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring)); 171 PetscCheck(isstring, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Only for PETSCVIEWERSTRING"); 172 if (string) *string = vstr->string; 173 if (len) *len = vstr->maxlen; 174 PetscFunctionReturn(PETSC_SUCCESS); 175 } 176 177 /*@C 178 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 @*/ 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(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 /*@C 220 221 PetscViewerStringSetOwnString - tells the viewer that it now owns the string and is responsible for freeing it 222 223 Logically Collective 224 225 Input Parameters: 226 . viewer - string viewer 227 228 Level: advanced 229 230 Note: 231 If you call this the string must have been obtained with `PetscMalloc()` and you cannot free the string 232 233 .seealso: [](sec_viewers), `PetscViewerStringOpen()`, `PETSCVIEWERSTRING`, `PetscViewerStringGetStringRead()`, `PetscViewerStringSPrintf()`, 234 `PetscViewerStringSetString()` 235 @*/ 236 PetscErrorCode PetscViewerStringSetOwnString(PetscViewer viewer) 237 { 238 PetscViewer_String *vstr = (PetscViewer_String *)viewer->data; 239 PetscBool isstring; 240 241 PetscFunctionBegin; 242 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1); 243 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring)); 244 if (!isstring) PetscFunctionReturn(PETSC_SUCCESS); 245 246 vstr->ownstring = PETSC_TRUE; 247 PetscFunctionReturn(PETSC_SUCCESS); 248 } 249