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 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 @*/ 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 @*/ 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 } 92 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 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 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 143 PetscViewerStringGetStringRead - Returns the string that a `PETSCVIEWERSTRING` uses 144 145 Logically Collective 146 147 Input Parameter: 148 . viewer - `PETSCVIEWERSTRING` viewer 149 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 153 154 Level: advanced 155 156 Note: 157 Do not write to the string nor free it 158 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; 166 167 PetscFunctionBegin; 168 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1); 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 } 175 176 /*@C 177 178 PetscViewerStringSetString - sets the string that a string viewer will print to 179 180 Logically Collective 181 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 186 187 Level: advanced 188 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()`. 194 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; 202 203 PetscFunctionBegin; 204 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1); 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"); 209 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 } 217 218 /*@C 219 220 PetscViewerStringSetOwnString - tells the viewer that it now owns the string and is responsible for freeing it 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 @*/ 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