]> err.no Git - sope/blob - libFoundation/Foundation/common.m
Drop apache 1 build-dependency
[sope] / libFoundation / Foundation / common.m
1 /* 
2    common.m
3
4    Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
5    All rights reserved.
6
7    Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
8            Mircea Oancea <mircea@jupiter.elcom.pub.ro>
9            Florin Mihaila <phil@pathcom.com>
10            Bogdan Baliuc <stark@protv.ro>
11
12    This file is part of libFoundation.
13
14    Permission to use, copy, modify, and distribute this software and its
15    documentation for any purpose and without fee is hereby granted, provided
16    that the above copyright notice appear in all copies and that both that
17    copyright notice and this permission notice appear in supporting
18    documentation.
19
20    We disclaim all warranties with regard to this software, including all
21    implied warranties of merchantability and fitness, in no event shall
22    we be liable for any special, indirect or consequential damages or any
23    damages whatsoever resulting from loss of use, data or profits, whether in
24    an action of contract, negligence or other tortious action, arising out of
25    or in connection with the use or performance of this software.
26 */
27
28 #include <Foundation/common.h>
29 #include <Foundation/NSString.h>
30 #include <Foundation/NSData.h>
31 #include <Foundation/NSPosixFileDescriptor.h>
32 #include <Foundation/NSFileManager.h>
33 #include <Foundation/NSException.h>
34 #include <Foundation/NSThread.h>
35 #include <Foundation/NSAutoreleasePool.h>
36 #include <Foundation/NSPathUtilities.h>
37
38 #include "PrivateThreadData.h"
39 #include "NSCalendarDateScanf.h"
40
41 #include <Foundation/exceptions/GeneralExceptions.h>
42 #include <extensions/PrintfFormatScanner.h>
43 #include <extensions/PrintfScannerHandler.h>
44
45 #include "config.h"
46
47 #if HAVE_WINDOWS_H
48 #  include <windows.h>
49 #endif
50
51 #ifndef O_BINARY
52 #  if HAVE_WINDOWS_H
53 #    warning defined O_BINARY
54 #  endif
55 #  define O_BINARY 0
56 #endif
57
58 #include <errno.h>
59
60 /* Windows Support */
61
62 #if defined(__MINGW32__)
63
64 NSString *NSWindowsWideStringToString(LPWSTR _wstr)
65 {
66   unsigned char cstr[256];
67   int           result;
68
69   result = WideCharToMultiByte(CP_ACP,
70                                0,
71                                _wstr,        /* the wide string */
72                                -1,           /* determine length of _wstr */
73                                cstr,         /* destination */
74                                sizeof(cstr), /* buffer size */
75                                NULL, /* insert char if char could not be conv */
76                                NULL  /* pointer to flag: couldNotBeConverted */);
77   return [NSString stringWithCString:cstr];
78 }
79
80 LPWSTR NSStringToWindowsWideString(NSString *_str)
81 {
82   LPWSTR wstr    = NULL;
83   int    wstrlen = 0;
84   int    result  = 0;
85   LPCSTR cstr;
86   int    cstrlen = [_str cStringLength];
87
88   cstr = malloc(cstrlen + 1);
89   [_str getCString:cstr]; cstr[cstrlen] = '\0';
90   
91   // first determine required buffer size
92   wstrlen = MultiByteToWideChar(CP_ACP,      /* ANSI Code Conversion */
93                                 0,           /* conversion flags     */
94                                 cstr,        /* ANSI string          */
95                                 cstrlen + 1, /* ANSI string length + zero byte */
96                                 wstr,        /* destination          */
97                                 0);          /* Shall determine required size */
98
99   // allocate buffer
100   wstr = NSZoneMalloc(NULL, sizeof(WCHAR) * (wstrlen + 1));
101   
102   result = MultiByteToWideChar(CP_ACP,      /* ANSI Code Conversion */
103                                0,           /* conversion flags     */
104                                cstr,        /* ANSI string          */
105                                cstrlen + 1, /* ANSI string length + zero byte */
106                                wstr,        /* destination          */
107                                wstrlen);    /* destination buffer size */
108   free(cstr);
109 #if !LIB_FOUNDATION_BOEHM_GC
110   [NSAutoreleasedPointer autoreleasePointer:wstr];
111 #endif
112   return wstr;
113 }
114
115 #endif
116
117 /* File reading */
118
119 void *NSReadContentsOfFile(NSString *_path, unsigned _extraCapacity,
120                            unsigned *len)
121 {
122     unsigned char *bytes = NULL;
123 #if defined(__MINGW32__)
124     HANDLE fh;
125     DWORD  sizeLow, sizeHigh;
126     DWORD  got;
127
128     if (len) *len = 0;
129     
130     fh = CreateFile([_path fileSystemRepresentation],
131                     GENERIC_READ,          /* assume read access  */
132                     FILE_SHARE_READ,       /* multiple read lock  */
133                     NULL,                  /* security attributes */
134                     OPEN_EXISTING,         /* fail if file does not exist */
135                     FILE_ATTRIBUTE_NORMAL, /* access normal file  */
136                     NULL);                 /* template file (not used)    */
137     if (fh == INVALID_HANDLE_VALUE)
138         // could not open file
139         return NULL;
140
141     sizeLow = GetFileSize(fh, &sizeHigh);
142     if ((sizeLow == 0xFFFFFFFF) && (GetLastError() != NO_ERROR)) {
143         // could not stat file
144         CloseHandle(fh);
145         return NULL;
146     }
147     NSCAssert(sizeHigh == 0, @"cannot handle 64bit filesizes yet");
148
149     bytes = NSZoneMallocAtomic(NULL, sizeLow + _extraCapacity);
150     if (!ReadFile(fh, bytes, sizeLow, &got, NULL)) {
151         if (bytes) {
152             lfFree(bytes);
153             bytes = NULL;
154         }
155     }
156     CloseHandle(fh);
157
158     if (len) *len = bytes ? sizeLow : 0;
159 #else /* !mingw32 */
160     int         fd;
161     struct stat fstat_buf;
162     int         got;
163     unsigned    plen;
164     char        *path;
165     
166     if (len) *len = 0;
167     plen = [_path cStringLength];
168     path = malloc(plen + 1);
169     [_path getCString:path]; path[plen] = '\0';
170     
171     if ((fd = open(path, O_RDONLY|O_BINARY, 0)) == -1) {
172         //fprintf(stderr, "couldn't open file '%s'\n", path ? path : "<NULL>");
173         if (path) free(path);
174         return NULL;
175     }
176     
177     if (path) free(path);
178     
179     if (fstat(fd, &fstat_buf) == -1) {
180         // NSLog(@"couldn't stat fd %i file '%@'", fd, _path ? _path : nil);
181         close(fd);
182         return NULL;
183     }
184
185     bytes = NSZoneMallocAtomic(NULL, fstat_buf.st_size + _extraCapacity);
186     if (bytes) {
187         if ((got = read(fd, bytes, fstat_buf.st_size)) != fstat_buf.st_size) {
188             if (bytes) {
189                 lfFree(bytes);
190                 bytes = NULL;
191             }
192         }
193     }
194     close(fd);
195     
196     if (len) *len = bytes ? fstat_buf.st_size : 0;
197 #endif
198     return bytes;
199 }
200
201 /* Non OpenStep useful things */
202
203 void vaRelease(id obj, ...)
204 {
205     va_list args;
206     id next_obj;
207         
208     va_start(args, obj);
209     next_obj = obj;
210     while (next_obj) {
211         RELEASE(next_obj);
212         next_obj = va_arg(args, id);
213     }
214     va_end(args);
215 }
216
217 BOOL writeToFile(NSString *path, NSData *data, BOOL atomically)
218 {
219     const void    *bytes    = [data bytes];
220     int           len       = [data length];
221     volatile BOOL result    = YES;
222     NSString      *filename = nil;
223     
224 #if defined(__MINGW32__)
225     HANDLE fh;
226     DWORD  wroteBytes;
227
228     filename = atomically ? [path stringByAppendingString:@".tmp"] : path;
229     
230     fh = CreateFile([filename fileSystemRepresentation],
231                     GENERIC_WRITE,         /* assume write access  */
232                     0,                     /* exclusive lock       */
233                     NULL,                  /* security attributes  */
234                     CREATE_ALWAYS,         /* create a new file    */
235                     FILE_ATTRIBUTE_NORMAL, /* access normal file   */
236                     NULL);                 /* template file (not used) */
237     if (fh == INVALID_HANDLE_VALUE) {
238         fprintf(stderr, "Could not create file for writing %s: %s\n",
239                 [filename fileSystemRepresentation], strerror(errno));
240         return NO;
241     }
242
243     if (!WriteFile(fh, bytes, len, &wroteBytes, NULL)) {
244         fprintf(stderr,
245                 "Failed to write %i bytes to %s, only wrote %li bytes\n",
246                 len, [filename fileSystemRepresentation], wroteBytes);
247         CloseHandle(fh);
248         return NO;
249     }
250     CloseHandle(fh);
251 #else
252     int fd;
253     
254     filename = atomically ? [path stringByAppendingString:@"~"] : path;
255     
256     fd = open([filename fileSystemRepresentation],
257               O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0666);
258     if (fd == -1) {
259         fprintf(stderr, "Could not open file for writing %s: %s\n",
260                 [filename fileSystemRepresentation], strerror(errno));
261         return NO;
262     }
263
264     if (write(fd, bytes, len) != len) {
265         fprintf(stderr, "Failed to write %i bytes to %s: %s\n",
266                 len, [filename fileSystemRepresentation], strerror(errno));
267         close(fd);
268         return NO;
269     }
270     close(fd);
271 #endif
272         
273     if (atomically) {
274         NSFileManager *fileManager = nil;
275         
276         fileManager = [NSFileManager defaultManager];
277
278         NS_DURING {
279             [fileManager removeFileAtPath:path handler:nil];
280             result = [fileManager movePath:filename toPath:path handler:nil];
281         }
282         NS_HANDLER {
283             fprintf(stderr, "Could not move file %s to file %s\n",
284                     [filename fileSystemRepresentation],
285                     [path fileSystemRepresentation]);
286             result = NO;
287         }
288         NS_ENDHANDLER;
289     }
290     return result;
291 }
292
293 char *Ltoa(long nr, char *str, int base)
294 {
295     char buff[34], rest, is_negative;
296     int ptr;
297
298     ptr = 32;
299     buff[33] = '\0';
300     if(nr < 0) {
301         is_negative = 1;
302         nr = -nr;
303     }
304     else
305         is_negative = 0;
306
307     while(nr != 0) {
308         rest = nr % base;
309         if(rest > 9)
310             rest += 'A' - 10;
311         else
312             rest += '0';
313         buff[ptr--] = rest;
314         nr /= base;
315     }
316     if(ptr == 32)
317         buff[ptr--] = '0';
318     if(is_negative)
319         buff[ptr--] = '-';
320
321     Strcpy(str, &buff[ptr+1]);
322
323     return(str);
324 }
325
326 unsigned hashjb(const char* name, int len)
327 {
328   register unsigned long hash = 0, i = 0;
329   register unsigned char ch;
330
331   for (; (ch = *name++); i ^= 1) {
332     if (i)
333       hash *= ch;
334     else
335       hash += ch;
336   }
337   hash += ((hash & 0xffff0000) >> 16);
338   hash += ((hash & 0x0000ff00) >> 8);
339   return hash & (len - 1);
340 }
341
342 NSString* Asprintf(NSString* format, ...)
343 {
344     id string;
345     va_list ap;
346
347     va_start(ap, format);
348     string = Avsprintf(format, ap);
349     va_end(ap);
350     return string;
351 }
352
353 NSString* Avsprintf(NSString* format, va_list args)
354 {
355     // THREADING
356     static id ofmt = nil;
357     id objectFormat, formatScanner, string;
358
359     if (ofmt) {
360         objectFormat = ofmt;
361         ofmt = nil;
362     }
363     else
364         objectFormat = [[FSObjectFormat alloc] init];
365     
366     formatScanner = [[PrintfFormatScanner alloc] init];
367
368     [formatScanner setFormatScannerHandler:objectFormat];
369     string = [formatScanner stringWithFormat:format arguments:args];
370
371     if (ofmt == nil) ofmt = objectFormat;
372     else RELEASE(objectFormat);
373     RELEASE(formatScanner);
374
375     return string;
376 }
377
378 /* Moved the THROW here from common.h to avoid recursion in the definition of
379    memoryExhaustedException. */
380 void __raiseMemoryException (void* pointer, int size)
381 {
382     [[memoryExhaustedException setPointer:&pointer memorySize:size] raise];
383 }
384
385
386 /*
387   Local Variables:
388   c-basic-offset: 4
389   tab-width: 8
390   End:
391 */