Pointwise Plugin SDK
pwpPlatform.cxx
Go to the documentation of this file.
1 /****************************************************************************
2  *
3  * runtime Plugin platform dependent function calls
4  *
5  * Proprietary software product of Pointwise, Inc.
6  * Copyright (c) 1995-2018 Pointwise, Inc.
7  * All rights reserved.
8  *
9  ***************************************************************************/
10 
11 #include <string.h>
12 #include <sys/stat.h>
13 
14 #if defined(WINDOWS)
15 # include <io.h>
16 # include <direct.h>
17 # include <malloc.h>
18 #else
19 # include <stdlib.h>
20 #endif /* WINDOWS */
21 
22 #include "pwpPlatform.h"
23 
24 #if defined(WINDOWS)
25 
26 # define sysTextMode 't'
27 # define sysBinaryMode 'b'
28 # define sysFileno(fp) _fileno(fp)
29 
30 #else /* *nix or mac */
31 
32 # define sysTextMode '\0'
33 # define sysBinaryMode 'b'
34 # define sysFileno(fp) fileno(fp)
35 
36 #endif /* WINDOWS */
37 
38 
39 #define strOK(ss) ((ss) && (ss[0]))
40 #define chrAPPEND(p,c) ((p && c) ? (*p++ = c) : 0)
41 
42 #define isMODE(allBits,modeBits) (((allBits) & (modeBits)) == modeBits)
43 
44 #if !defined(FILENAME_MAX)
45 # define FILENAME_MAX 512
46 #endif
47 
48 
49 #ifdef WINDOWS
50 
51 
52 static wchar_t *
53 utf8ToU16(const char *s)
54 {
55  wchar_t *result = 0;
56  size_t element = 0;
57  if (0 != s) {
58  size_t len;
59  len = ::strlen(s) + 1;
60  result = (wchar_t *)::malloc(len * sizeof(wchar_t));
61  //
62  // UTF-8 is a specific scheme for mapping a sequence of 1-4 bytes to a
63  // number from 0x000000 to 0x10FFFF:
64  //
65  // 00000000 -- 0000007F: 0xxxxxxx
66  // 00000080 -- 000007FF: 110xxxxx 10xxxxxx
67  // 00000800 -- 0000FFFF: 1110xxxx 10xxxxxx 10xxxxxx
68  // 00010000 -- 001FFFFF: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
69  //
70  // where the x's are the bits to be extracted from the sequence and
71  // combined to form the final value.
72  //
73  while ('\0' != *s) {
74  unsigned char c = (unsigned char)*s;
75  switch (0xF0 & c) {
76  // No indicator, so just convert
77  default:
78  result[element] = (wchar_t)c;
79  ++s;
80  break;
81  // Possible two byte utf8 character
82  case 0xC0:
83  case 0xD0:
84  // Two byte character 110xxxxx 10xxxxxx
85  if (0x80 == (*(s + 1) & 0xC0)) {
86  result[element] = (wchar_t)(
87  ((c & 0x1F) << 6) | (*(s + 1) & 0x3F));
88  s += 2;
89  }
90  // Doesn't have the second byte correct, so leave as is
91  else {
92  result[element] = (wchar_t)c;
93  ++s;
94  }
95  break;
96  // Possible three byte utf8 character
97  case 0xE0:
98  // Three byte character 1110xxxx 10xxxxxx 10xxxxxx
99  if (0x80 == (*(s + 1) & 0xC0) && 0x80 == (*(s + 2) & 0xC0)) {
100  result[element] = (wchar_t)(((c & 0x0F) << 12) |
101  ((*(s + 1) & 0x3F) << 6) | (*(s + 2) & 0x3F));
102  s += 3;
103  }
104  // Doesn't have the second and third byte correct, so leave as
105  // is
106  else {
107  result[element] = (wchar_t)c;
108  ++s;
109  }
110  break;
111  // Four byte case which can't be compressed into 16 bits, so just
112  // convert the bytes as is
113  case 0xF0:
114  result[element] = (wchar_t)c;
115  ++s;
116  break;
117  }
118  ++element;
119  }
120  }
121  else {
122  result = (wchar_t *)::malloc(sizeof(wchar_t));
123  }
124  result[element] = 0;
125  return result;
126 }
127 
128 
129 #ifdef NOT_NEEDED
130 static wchar_t *
131 utf8ToU16Old(const char *s)
132 {
133  wchar_t *result = 0;
134  size_t len;
135  size_t element = 0;
136  if (0 != s) {
137  len = ::strlen(s) + 1;
138  result = (wchar_t *)::malloc(len * sizeof(wchar_t));
139  //
140  // UTF-8 is a specific scheme for mapping a sequence of 1-4 bytes to a
141  // number from 0x000000 to 0x10FFFF:
142  //
143  // 00000000 -- 0000007F: 0xxxxxxx
144  // 00000080 -- 000007FF: 110xxxxx 10xxxxxx
145  // 00000800 -- 0000FFFF: 1110xxxx 10xxxxxx 10xxxxxx
146  // 00010000 -- 001FFFFF: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
147  //
148  // where the x's are the bits to be extracted from the sequence and
149  // combined to form the final value.
150  //
151  while ('\0' != *s) {
152  unsigned char c = (unsigned char)*s;
153  // Not an encoded character.
154  if (0xC0 > c) {
155  result[element] = (wchar_t)c;
156  ++s;
157  }
158  // Possible 2-byte utf-8 character
159  else if (0xE0 > c) {
160  // Two byte character 110xxxxx 10xxxxxx
161  if (0x80 == (*(s + 1) & 0xC0)) {
162  result[element] = (wchar_t)(
163  (c & 0x1F) << 6 | (*(s + 1) & 0x3F));
164  s += 2;
165  }
166  // Doesn't have the second byte correct, so leave as is
167  else {
168  result[element] = (wchar_t)c;
169  ++s;
170  }
171  }
172  // Possible 3-byte utf-8 character
173  else if (0xF0 > c) {
174  // Three byte character 1110xxxx 10xxxxxx 10xxxxxx
175  if (0x80 == (*(s + 1) & 0xC0) && 0x80 == (*(s + 2) & 0xC)) {
176  result[element] = (wchar_t)(((c & 0x0F) << 12) |
177  ((*(s + 1) & 0x3F) << 6) | (*(s + 2) & 0x3F));
178  s += 3;
179  }
180  // Doesn't have the second and third byte correct, so leave as
181  // is
182  else {
183  result[element] = (wchar_t)c;
184  ++s;
185  }
186  }
187  // Can't convert a 4-byte sequence down to 16 bits so just treat
188  // each byte as is
189  else {
190  result[element] = (wchar_t)c;
191  ++s;
192  }
193  ++element;
194  }
195  }
196  else {
197  result = (wchar_t *)::malloc(sizeof(wchar_t));
198  }
199  result[element] = 0;
200  return result;
201 }
202 #endif /* NOT_NEEDED */
203 #endif /* WINDOWS */
204 
205 
206 FILE *
207 pwpFileOpen(const char *filename, int mode)
208 {
209  FILE *ret = 0;
210  while (strOK(filename)) {
211  char modeStr[4] = {0,0,0,0};
212  char *p = modeStr;
213  // get base mode
214  if (isMODE(mode, pwpRead)) {
215  chrAPPEND(p, 'r');
216  }
217  else if (isMODE(mode, pwpWrite)) {
218  chrAPPEND(p, 'w');
219  }
220  else if (isMODE(mode, pwpAppend)) {
221  chrAPPEND(p, 'a');
222  }
223  else {
224  break; // error
225  }
226 
227  // get extended mode
228  if (isMODE(mode, pwpPlus_)) {
229  chrAPPEND(p, '+');
230  }
231 
232  // get format
233  if (isMODE(mode, pwpBinary) || isMODE(mode, pwpUnformatted)) {
235  }
236  else if (isMODE(mode, pwpFormatted) || isMODE(mode, pwpAscii)) {
238  }
239  else {
240  break; // error
241  }
242 
243 #ifdef WINDOWS
244  wchar_t *wname = utf8ToU16(filename);
245  wchar_t *wmode = utf8ToU16(modeStr);
246  if (wname && wmode) {
247  ret = ::_wfopen(wname, wmode);
248  ::free(wname);
249  ::free(wmode);
250  }
251  else {
252  ret = 0;
253  }
254 #else
255  ret = fopen(filename, modeStr);
256 #endif /* WINDOWS */
257  break; // force exit from while()
258  }
259  return ret;
260 }
261 
262 
263 int
264 pwpFileClose(FILE *fp)
265 {
266  int ret = sysEOF;
267  if (fp) {
268  ret = fclose(fp);
269  }
270  return ret;
271 }
272 
273 
274 int
275 pwpFileEof(FILE *fp)
276 {
277  return fp ? feof(fp) : 0;
278 }
279 
280 
281 int
282 pwpFileFlush(FILE *fp)
283 {
284  return fp ? fflush(fp) : -1;
285 }
286 
287 
288 int
289 pwpFileGetpos(FILE *fp, sysFILEPOS *pos)
290 {
291  int ret = -1;
292  if (fp && pos) {
293  ret = fgetpos(fp, pos);
294  }
295  return ret;
296 }
297 
298 
299 int
300 pwpFileSetpos(FILE *fp, const sysFILEPOS *pos)
301 {
302  int ret = -1;
303  if (fp && pos) {
304  ret = fsetpos(fp, pos);
305  }
306  return ret;
307 }
308 
309 
310 int
311 pwpFileGetSize(FILE *fp, size_t *size)
312 {
313  struct stat buf;
314  int ret = 0;
315  if (0 == fp || 0 == size) {
316  ret = -1;
317  }
318  else if (0 != fstat(sysFileno(fp), &buf)) {
319  *size = 0;
320  ret = -1;
321  }
322  else {
323  *size = (size_t)buf.st_size;
324  }
325  return ret;
326 }
327 
328 
329 int
330 pwpFilenameGetSize(const char *filename, size_t *size)
331 {
332 #ifdef WINDOWS
333  struct _stat buf;
334 #else
335  struct stat buf;
336 #endif /* WINDOWS */
337  int ret = 0;
338  if (0 == filename || 0 == size) {
339  ret = -1;
340  }
341 #ifdef WINDOWS
342  else {
343  wchar_t *wname = utf8ToU16(filename);
344  if (0 == wname) {
345  ret = -1;
346  }
347  else {
348  if (0 != ::_wstat(wname, &buf)) {
349  *size = 0;
350  ret = -1;
351  }
352  else {
353  *size = (size_t)buf.st_size;
354  }
355  ::free(wname);
356  }
357  }
358 #else
359  else if (0 != stat(filename, &buf)) {
360  *size = 0;
361  ret = -1;
362  }
363  else {
364  *size = (size_t)buf.st_size;
365  }
366 #endif /* WINDOWS */
367  return ret;
368 }
369 
370 
371 size_t
372 pwpFileRead(void *buf, size_t size, size_t count, FILE *fp)
373 {
374  size_t ret = 0;
375  if (buf && size && count && fp) {
376  ret = fread(buf, size, count, fp);
377  }
378  return ret;
379 }
380 
381 
382 size_t
383 pwpFileWrite(const void *buf, size_t size, size_t count, FILE *fp)
384 {
385  size_t ret = 0;
386  if (buf && size && count && fp) {
387  ret = fwrite(buf, size, count, fp);
388  }
389  return ret;
390 }
391 
392 
393 size_t
394 pwpFileWriteStr(const char *str, FILE *fp)
395 {
396  return str ? pwpFileWrite(str, strlen(str), 1, fp) : 0;
397 }
398 
399 
400 void
401 pwpFileRewind(FILE *fp)
402 {
403  if (fp) {
404  rewind(fp);
405  }
406 }
407 
408 
409 int
410 pwpFileDelete(const char *filename)
411 {
412  int ret = 0;
413  if (strOK(filename)) {
414 #ifdef WINDOWS
415  wchar_t *wname = utf8ToU16(filename);
416  if (0 == wname) {
417  ret = -1;
418  }
419  else {
420  ret = ::_wunlink(wname);
421  ::free(wname);
422  }
423 #else
424  ret = unlink(filename);
425 #endif /* WINDOWS */
426  }
427  return ret;
428 }
429 
430 
431 #define MAXSTACK 50
432 #ifdef WINDOWS
433 static wchar_t * dirStack[MAXSTACK+1] = { 0 };
434 #else
435 static char * dirStack[MAXSTACK+1] = { 0 };
436 #endif /* WINDOWS */
437 
438 static int stackCnt = 0;
439 
440 
441 int
442 pwpCwdPush(const char *dir)
443 {
444  int ret = -1;
445  if (dir && dir[0] && (stackCnt < MAXSTACK)) {
446 #ifdef WINDOWS
447  wchar_t *pCwd = ::_wgetcwd(0, FILENAME_MAX);
448  if (pCwd) {
449  wchar_t *wdir = utf8ToU16(dir);
450  if (wdir) {
451  if (0 == ::_wchdir(wdir)) {
452  dirStack[stackCnt++] = pCwd;
453  ret = 0;
454  }
455  else {
456  free(pCwd);
457  }
458  }
459  else {
460  free(pCwd);
461  }
462  }
463 #else
464  char *pCwd = getcwd(0, FILENAME_MAX);
465  if (pCwd) {
466  if (0 == chdir(dir)) {
467  dirStack[stackCnt++] = pCwd;
468  ret = 0;
469  }
470  else {
471  free(pCwd);
472  }
473  }
474 #endif /* WINDOWS */
475  }
476  return ret;
477 }
478 
479 
480 int
482 {
483  int ret = -1;
484  if ((0 < stackCnt) && (0 != dirStack[--stackCnt])) {
485 #ifdef WINDOWS
486  ret = ::_wchdir(dirStack[stackCnt]);
487 #else
488  ret = chdir(dirStack[stackCnt]);
489 #endif /* WINDOWS */
490  free(dirStack[stackCnt]);
491  dirStack[stackCnt] = 0;
492  }
493  return ret;
494 }
int pwpFileEof(FILE *fp)
Queries end-of-file status.
static int stackCnt
int pwpFileClose(FILE *fp)
Closes a file opened with pwpFileOpen().
size_t pwpFileWriteStr(const char *str, FILE *fp)
Write a null-terminated string to a file.
#define MAXSTACK
int pwpFileSetpos(FILE *fp, const sysFILEPOS *pos)
Set the current file position.
FILE * pwpFileOpen(const char *filename, int mode)
Opens a file for I/O.
size_t pwpFileRead(void *buf, size_t size, size_t count, FILE *fp)
Read an collection of data items from a file.
fpos_t sysFILEPOS
File position data type.
Definition: pwpPlatform.h:53
static char * dirStack[50+1]
#define sysFileno(fp)
Definition: pwpPlatform.cxx:34
Cross Platform Functions.
#define sysTextMode
Definition: pwpPlatform.cxx:32
int pwpFileFlush(FILE *fp)
Flush a file to disk.
int pwpCwdPop(void)
Restore the current directory.
int pwpFileGetpos(FILE *fp, sysFILEPOS *pos)
Query the current file position.
#define sysEOF
End-of-file value.
Definition: pwpPlatform.h:52
#define isMODE(allBits, modeBits)
Definition: pwpPlatform.cxx:42
size_t pwpFileWrite(const void *buf, size_t size, size_t count, FILE *fp)
Write an collection of data items to a file.
#define chrAPPEND(p, c)
Definition: pwpPlatform.cxx:40
void pwpFileRewind(FILE *fp)
Reset position to the beginning of the file.
int pwpFileDelete(const char *filename)
Delete a file.
int pwpFilenameGetSize(const char *filename, size_t *size)
Get the file&#39;s size in bytes.
#define FILENAME_MAX
Definition: pwpPlatform.cxx:45
int pwpCwdPush(const char *dir)
Change the current directory.
#define strOK(ss)
Definition: pwpPlatform.cxx:39
#define sysBinaryMode
Definition: pwpPlatform.cxx:33
int pwpFileGetSize(FILE *fp, size_t *size)
Get the file&#39;s size in bytes.