2 // Copyright (c) 1999-2006 by Digital Mars
4 // written by Walter Bright
6 // License for redistribution is by either the Artistic License
7 // in artistic.txt, or the GNU General Public License in gnu.txt.
8 // See the included readme.txt for details.
10 /* NOTE: This file has been patched from the original DMD distribution to
11 work with the GDC compiler.
13 Modified by David Friedman, December 2006
23 #include "gdc_alloca.h"
31 #include <sys/types.h>
44 #if 0 //__SC__ //def DEBUG
45 extern "C" void __cdecl
_assert(void *e
, void *f
, unsigned line
)
47 printf("Assert('%s','%s',%d)\n",e
,f
,line
);
54 /*************************************
55 * Convert wchar string to ascii string.
58 char *wchar2ascii(wchar_t *us
)
60 return wchar2ascii(us
, wcslen(us
));
63 char *wchar2ascii(wchar_t *us
, unsigned len
)
68 p
= (char *)mem
.malloc(len
+ 1);
69 for (i
= 0; i
<= len
; i
++)
74 int wcharIsAscii(wchar_t *us
)
76 return wcharIsAscii(us
, wcslen(us
));
79 int wcharIsAscii(wchar_t *us
, unsigned len
)
83 for (i
= 0; i
<= len
; i
++)
85 if (us
[i
] & ~0xFF) // if high bits set
86 return 0; // it's not ascii
93 /***********************************
94 * Compare length-prefixed strings (bstr).
97 int bstrcmp(unsigned char *b1
, unsigned char *b2
)
99 return (*b1
== *b2
&& memcmp(b1
+ 1, b2
+ 1, *b2
) == 0) ? 0 : 1;
102 /***************************************
103 * Convert bstr into a malloc'd string.
106 char *bstr2str(unsigned char *b
)
112 s
= (char *) mem
.malloc(len
+ 1);
114 return (char *)memcpy(s
,b
+ 1,len
);
117 /**************************************
118 * Print error message and exit.
121 void error(const char *format
, ...)
125 va_start(ap
, format
);
126 fprintf(stderr
, "Error: ");
127 vfprintf(stderr
, format
, ap
);
129 fprintf(stderr
, "\n");
136 void error(const dchar
*format
, ...)
140 va_start(ap
, format
);
141 fprintf(stderr
, "Error: ");
142 vfwprintf(stderr
, format
, ap
);
144 printf(stderr
, "\n");
153 error("out of memory");
156 /**************************************
157 * Print warning message.
160 void warning(const char *format
, ...)
164 va_start(ap
, format
);
165 fprintf(stderr
, "Warning: ");
166 vfprintf(stderr
, format
, ap
);
168 fprintf(stderr
, "\n");
172 /****************************** Object ********************************/
174 int Object::equals(Object
*o
)
179 hash_t
Object::hashCode()
181 return (hash_t
) this;
184 int Object::compare(Object
*obj
)
191 fprintf(stderr
, "%s %p\n", toChars(), this);
194 char *Object::toChars()
199 dchar
*Object::toDchars()
208 int Object::dyncast()
213 void Object::toBuffer(OutBuffer
*b
)
215 b
->writestring("Object");
222 /****************************** String ********************************/
224 String::String(char *str
, int ref
)
226 this->str
= ref
? str
: mem
.strdup(str
);
240 hash_t
String::calcHash(const char *str
, size_t len
)
253 hash
+= *(uint8_t *)str
;
258 hash
+= *(uint16_t *)str
;
263 hash
+= (*(uint16_t *)str
<< 8) +
269 hash
+= *(uint32_t *)str
;
277 hash_t
String::calcHash(const char *str
)
279 return calcHash(str
, strlen(str
));
282 hash_t
String::hashCode()
284 return calcHash(str
, strlen(str
));
287 unsigned String::len()
292 int String::equals(Object
*obj
)
294 return strcmp(str
,((String
*)obj
)->str
) == 0;
297 int String::compare(Object
*obj
)
299 return strcmp(str
,((String
*)obj
)->str
);
302 char *String::toChars()
309 fprintf(stderr
, "String '%s'\n",str
);
313 /****************************** FileName ********************************/
315 FileName::FileName(char *str
, int ref
)
320 char *FileName::combine(char *path
, char *name
)
327 pathlen
= strlen(path
);
328 namelen
= strlen(name
);
329 f
= (char *)mem
.malloc(pathlen
+ 1 + namelen
+ 1);
330 memcpy(f
, path
, pathlen
);
332 if (path
[pathlen
- 1] != '/')
338 if (path
[pathlen
- 1] != '\\' && path
[pathlen
- 1] != ':' && path
[pathlen
- 1] != '/')
343 memcpy(f
+ pathlen
, name
, namelen
+ 1);
347 FileName::FileName(char *path
, char *name
)
348 : String(combine(path
,name
),1)
352 // Split a path into an Array of paths
353 Array
*FileName::splitPath(const char *path
)
355 char c
= 0; // unnecessary initializer is for VC /W4
367 while (isspace(*p
)) // skip leading whitespace
369 buf
.reserve(strlen(p
) + 1); // guess size of path
376 instring
^= 1; // toggle inside/outside of string
389 break; // note that ; cannot appear as part
390 // of a path, quotes won't protect it
392 case 0x1A: // ^Z means end of file
397 continue; // ignore carriage returns
401 buf
.writestring(getenv("HOME"));
406 case '\t': // tabs in filenames?
407 if (!instring
) // if not in string
408 break; // treat as end of path
415 if (buf
.offset
) // if path is not empty
417 buf
.writeByte(0); // to asciiz
418 array
->push(buf
.extractData());
425 hash_t
FileName::hashCode()
428 // We need a different hashCode because it must be case-insensitive
429 size_t len
= strlen(str
);
431 unsigned char *s
= (unsigned char *)str
;
442 hash
+= *(uint8_t *)s
| 0x20;
447 hash
+= *(uint16_t *)s
| 0x2020;
452 hash
+= ((*(uint16_t *)s
<< 8) +
453 ((uint8_t *)s
)[2]) | 0x202020;
458 hash
+= *(uint32_t *)s
| 0x20202020;
465 // darwin HFS is case insensitive, though...
466 return String::hashCode();
470 int FileName::compare(Object
*obj
)
473 return stricmp(str
,((FileName
*)obj
)->str
);
475 return String::compare(obj
);
479 int FileName::equals(Object
*obj
)
482 return stricmp(str
,((FileName
*)obj
)->str
) == 0;
484 return String::equals(obj
);
488 /************************************
489 * Return !=0 if absolute path name.
492 int FileName::absolute(const char *name
)
495 return (*name
== '\\') ||
497 (*name
&& name
[1] == ':');
500 return (*name
== '/');
504 /********************************
505 * Return filename extension (read-only).
506 * Points past '.' of extension.
507 * If there isn't one, return NULL.
510 char *FileName::ext(const char *str
)
513 size_t len
= strlen(str
);
515 e
= (char *)str
+ len
;
541 char *FileName::ext()
546 /********************************
547 * Return mem.malloc'd filename with extension removed.
550 char *FileName::removeExt(const char *str
)
552 const char *e
= ext(str
);
554 { size_t len
= (e
- str
) - 1;
555 char *n
= (char *)mem
.malloc(len
+ 1);
560 return mem
.strdup(str
);
563 /********************************
564 * Return filename name excluding path (read-only).
567 char *FileName::name(const char *str
)
570 size_t len
= strlen(str
);
572 e
= (char *)str
+ len
;
597 char *FileName::name()
602 /**************************************
603 * Return path portion of str.
604 * Path will does not include trailing path separator.
607 char *FileName::path(const char *str
)
620 if (n
[-1] == '\\' || n
[-1] == '/')
625 path
= (char *)mem
.malloc(pathlen
+ 1);
626 memcpy(path
, str
, pathlen
);
631 /**************************************
632 * Replace filename portion of path.
635 char *FileName::replaceName(char *path
, char *name
)
644 n
= FileName::name(path
);
648 namelen
= strlen(name
);
649 f
= (char *)mem
.malloc(pathlen
+ 1 + namelen
+ 1);
650 memcpy(f
, path
, pathlen
);
652 if (path
[pathlen
- 1] != '/')
658 if (path
[pathlen
- 1] != '\\' && path
[pathlen
- 1] != ':' && path
[pathlen
- 1] != '/')
663 memcpy(f
+ pathlen
, name
, namelen
+ 1);
667 /***************************
670 FileName
*FileName::defaultExt(const char *name
, const char *ext
)
677 e
= FileName::ext(name
);
678 if (e
) // if already has an extension
679 return new FileName((char *)name
, 0);
682 extlen
= strlen(ext
);
683 s
= (char *)alloca(len
+ 1 + extlen
+ 1);
686 memcpy(s
+ len
+ 1, ext
, extlen
+ 1);
687 return new FileName(s
, 0);
690 /***************************
693 FileName
*FileName::forceExt(const char *name
, const char *ext
)
700 e
= FileName::ext(name
);
701 if (e
) // if already has an extension
704 extlen
= strlen(ext
);
706 s
= (char *)alloca(len
+ extlen
+ 1);
708 memcpy(s
+ len
, ext
, extlen
+ 1);
709 return new FileName(s
, 0);
712 return defaultExt(name
, ext
); // doesn't have one
715 /******************************
716 * Return !=0 if extensions match.
719 int FileName::equalsExt(const char *ext
)
728 return strcmp(e
,ext
) == 0;
731 return stricmp(e
,ext
) == 0;
735 /*************************************
736 * Copy file from this to to.
739 void FileName::CopyTo(FileName
*to
)
744 file
.touchtime
= mem
.malloc(sizeof(WIN32_FIND_DATAA
)); // keep same file time
747 file
.touchtime
= mem
.malloc(sizeof(struct stat
)); // keep same file time
754 /*************************************
755 * Search Path for file.
757 * cwd if !=0, search current directory before searching path
760 char *FileName::searchPath(Array
*path
, char *name
, int cwd
)
764 return exists(name
) ? name
: NULL
;
774 for (i
= 0; i
< path
->dim
; i
++)
776 char *p
= (char *)path
->data
[i
];
777 char *n
= combine(p
, name
);
786 int FileName::exists(const char *name
)
791 if (stat(name
, &st
) < 0)
793 if (S_ISDIR(st
.st_mode
))
801 dw
= GetFileAttributesA(name
);
804 else if (dw
& FILE_ATTRIBUTE_DIRECTORY
)
812 void FileName::ensurePathExists(const char *path
)
814 //printf("FileName::ensurePathExists(%s)\n", path ? path : "");
819 char *p
= FileName::path(path
);
823 size_t len
= strlen(p
);
824 if (len
> 2 && p
[-1] == ':')
833 if (path
[strlen(path
) - 1] != '\\')
836 if (path
[strlen(path
) - 1] != '\\')
839 //printf("mkdir(%s)\n", path);
843 if (mkdir(path
, 0777))
845 error("cannot create directory %s", path
);
851 /****************************** File ********************************/
853 File::File(FileName
*n
)
868 name
= new FileName(n
, 0);
879 UnmapViewOfFile(buffer
);
893 /*************************************
906 name
= this->name
->toChars();
907 //printf("File::read('%s')\n",name);
908 fd
= open(name
, O_RDONLY
);
911 //printf("\topen error, errno = %d\n",errno);
917 ref
= 0; // we own the buffer now
919 //printf("\tfile opened\n");
922 fprintf(stderr
, "\tfstat error, errno = %d\n",errno
);
926 buffer
= (unsigned char *) mem
.malloc(size
+ 2);
929 fprintf(stderr
, "\tmalloc error, errno = %d\n",errno
);
933 numread
= ::read(fd
, buffer
, size
);
936 fprintf(stderr
, "\tread error, errno = %d\n",errno
);
941 memcpy(touchtime
, &buf
, sizeof(buf
));
945 fprintf(stderr
, "\tclose error, errno = %d\n",errno
);
951 // Always store a wchar ^Z past end of buffer so scanner has a sentinel
952 buffer
[size
] = 0; // ^Z is obsolete, use 0
953 buffer
[size
+ 1] = 0;
974 name
= this->name
->toChars();
975 h
= CreateFileA(name
,GENERIC_READ
,FILE_SHARE_READ
,NULL
,OPEN_EXISTING
,
976 FILE_ATTRIBUTE_NORMAL
| FILE_FLAG_SEQUENTIAL_SCAN
,0);
977 if (h
== INVALID_HANDLE_VALUE
)
984 size
= GetFileSize(h
,NULL
);
985 buffer
= (unsigned char *) mem
.malloc(size
+ 2);
989 if (ReadFile(h
,buffer
,size
,&numread
,NULL
) != TRUE
)
997 if (!GetFileTime(h
, NULL
, NULL
, &((WIN32_FIND_DATAA
*)touchtime
)->ftLastWriteTime
))
1001 if (!CloseHandle(h
))
1006 // Always store a wchar ^Z past end of buffer so scanner has a sentinel
1007 buffer
[size
] = 0; // ^Z is obsolete, use 0
1008 buffer
[size
+ 1] = 0;
1024 /*****************************
1025 * Read a file with memory mapped file I/O.
1039 name
= this->name
->toChars();
1040 hFile
= CreateFile(name
, GENERIC_READ
,
1041 FILE_SHARE_READ
, NULL
,
1042 OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL
, NULL
);
1043 if (hFile
== INVALID_HANDLE_VALUE
)
1045 size
= GetFileSize(hFile
, NULL
);
1046 //printf(" file created, size %d\n", size);
1048 hFileMap
= CreateFileMapping(hFile
,NULL
,PAGE_READONLY
,0,size
,NULL
);
1049 if (CloseHandle(hFile
) != TRUE
)
1052 if (hFileMap
== NULL
)
1055 //printf(" mapping created\n");
1060 buffer
= (unsigned char *)MapViewOfFileEx(hFileMap
, FILE_MAP_READ
,0,0,size
,NULL
);
1061 if (CloseHandle(hFileMap
) != TRUE
)
1063 if (buffer
== NULL
) // mapping view failed
1067 //printf(" buffer = %p\n", buffer);
1072 return GetLastError(); // failure
1076 /*********************************************
1089 name
= this->name
->toChars();
1090 fd
= open(name
, O_CREAT
| O_WRONLY
| O_TRUNC
, 0644);
1094 numwritten
= ::write(fd
, buffer
, len
);
1095 if (len
!= numwritten
)
1098 if (close(fd
) == -1)
1102 { struct utimbuf ubuf
;
1104 ubuf
.actime
= ((struct stat
*)touchtime
)->st_atime
;
1105 ubuf
.modtime
= ((struct stat
*)touchtime
)->st_mtime
;
1106 if (utime(name
, &ubuf
))
1122 name
= this->name
->toChars();
1123 h
= CreateFileA(name
,GENERIC_WRITE
,0,NULL
,CREATE_ALWAYS
,
1124 FILE_ATTRIBUTE_NORMAL
| FILE_FLAG_SEQUENTIAL_SCAN
,NULL
);
1125 if (h
== INVALID_HANDLE_VALUE
)
1128 if (WriteFile(h
,buffer
,len
,&numwritten
,NULL
) != TRUE
)
1131 if (len
!= numwritten
)
1135 SetFileTime(h
, NULL
, NULL
, &((WIN32_FIND_DATAA
*)touchtime
)->ftLastWriteTime
);
1137 if (!CloseHandle(h
))
1149 /*********************************************
1165 name
= this->name
->toChars();
1166 h
= CreateFileA(name
,GENERIC_WRITE
,0,NULL
,OPEN_ALWAYS
,
1167 FILE_ATTRIBUTE_NORMAL
| FILE_FLAG_SEQUENTIAL_SCAN
,NULL
);
1168 if (h
== INVALID_HANDLE_VALUE
)
1172 SetFilePointer(h
, 0, NULL
, FILE_END
);
1173 #else // INVALID_SET_FILE_POINTER doesn't seem to have a definition
1174 if (SetFilePointer(h
, 0, NULL
, FILE_END
) == INVALID_SET_FILE_POINTER
)
1178 if (WriteFile(h
,buffer
,len
,&numwritten
,NULL
) != TRUE
)
1181 if (len
!= numwritten
)
1185 SetFileTime(h
, NULL
, NULL
, &((WIN32_FIND_DATAA
*)touchtime
)->ftLastWriteTime
);
1187 if (!CloseHandle(h
))
1198 /**************************************
1204 error("Error reading file '%s'\n",name
->toChars());
1207 /**************************************
1210 void File::mmreadv()
1219 error("Error writing file '%s'\n",name
->toChars());
1222 void File::appendv()
1225 error("Error appending to file '%s'\n",name
->toChars());
1228 /*******************************************
1229 * Return !=0 if file exists.
1230 * 0: file doesn't exist
1245 name
= this->name
->toChars();
1247 dw
= ((WIN32_FIND_DATAA
*)touchtime
)->dwFileAttributes
;
1249 dw
= GetFileAttributesA(name
);
1252 else if (dw
& FILE_ATTRIBUTE_DIRECTORY
)
1263 ::remove(this->name
->toChars());
1266 DeleteFileA(this->name
->toChars());
1270 Array
*File::match(char *n
)
1272 return match(new FileName(n
, 0));
1275 Array
*File::match(FileName
*n
)
1282 WIN32_FIND_DATAA fileinfo
;
1290 h
= FindFirstFileA(c
,&fileinfo
);
1291 if (h
!= INVALID_HANDLE_VALUE
)
1295 // Glue path together with name
1299 fn
= (char *)mem
.malloc(name
- c
+ strlen(fileinfo
.cFileName
) + 1);
1300 memcpy(fn
, c
, name
- c
);
1301 strcpy(fn
+ (name
- c
), fileinfo
.cFileName
);
1303 f
->touchtime
= mem
.malloc(sizeof(WIN32_FIND_DATAA
));
1304 memcpy(f
->touchtime
, &fileinfo
, sizeof(fileinfo
));
1306 } while (FindNextFileA(h
,&fileinfo
) != FALSE
);
1313 int File::compareTime(File
*f
)
1323 return CompareFileTime(&((WIN32_FIND_DATAA
*)touchtime
)->ftLastWriteTime
, &((WIN32_FIND_DATAA
*)f
->touchtime
)->ftLastWriteTime
);
1332 touchtime
= mem
.calloc(1, sizeof(struct stat
));
1340 touchtime
= mem
.calloc(1, sizeof(WIN32_FIND_DATAA
));
1342 h
= FindFirstFileA(name
->toChars(),(WIN32_FIND_DATAA
*)touchtime
);
1343 if (h
!= INVALID_HANDLE_VALUE
)
1350 void File::checkoffset(size_t offset
, size_t nbytes
)
1352 if (offset
> len
|| offset
+ nbytes
> len
)
1353 error("Corrupt file '%s': offset x%"PRIxSIZE
" off end of file",toChars(),offset
);
1356 char *File::toChars()
1358 return name
->toChars();
1362 /************************* OutBuffer *************************/
1364 OutBuffer::OutBuffer()
1371 OutBuffer::~OutBuffer()
1376 void *OutBuffer::extractData()
1387 void OutBuffer::mark()
1392 void OutBuffer::reserve(unsigned nbytes
)
1394 //printf("OutBuffer::reserve: size = %d, offset = %d, nbytes = %d\n", size, offset, nbytes);
1395 if (size
- offset
< nbytes
)
1397 size
= (offset
+ nbytes
) * 2;
1398 data
= (unsigned char *)mem
.realloc(data
, size
);
1402 void OutBuffer::reset()
1407 void OutBuffer::setsize(unsigned size
)
1412 void OutBuffer::write(const void *data
, unsigned nbytes
)
1415 memcpy(this->data
+ offset
, data
, nbytes
);
1419 void OutBuffer::writebstring(unsigned char *string
)
1421 write(string
,*string
+ 1);
1424 void OutBuffer::writestring(const char *string
)
1426 write(string
,strlen(string
));
1429 void OutBuffer::writedstring(const char *string
)
1432 for (; *string
; string
++)
1434 writedchar(*string
);
1437 write(string
,strlen(string
));
1441 void OutBuffer::writedstring(const wchar_t *string
)
1444 write(string
,wcslen(string
) * sizeof(wchar_t));
1446 for (; *string
; string
++)
1448 writedchar(*string
);
1453 void OutBuffer::prependstring(char *string
)
1456 len
= strlen(string
);
1458 memmove(data
+ len
, data
, offset
);
1459 memcpy(data
, string
, len
);
1463 void OutBuffer::writenl()
1467 write4(0x000A000D); // newline is CR,LF on Microsoft OS's
1469 writeword(0x0A0D); // newline is CR,LF on Microsoft OS's
1480 void OutBuffer::writeByte(unsigned b
)
1483 this->data
[offset
] = (unsigned char)b
;
1487 void OutBuffer::writeUTF8(unsigned b
)
1492 this->data
[offset
] = (unsigned char)b
;
1495 else if (b
<= 0x7FF)
1497 this->data
[offset
+ 0] = (unsigned char)((b
>> 6) | 0xC0);
1498 this->data
[offset
+ 1] = (unsigned char)((b
& 0x3F) | 0x80);
1501 else if (b
<= 0xFFFF)
1503 this->data
[offset
+ 0] = (unsigned char)((b
>> 12) | 0xE0);
1504 this->data
[offset
+ 1] = (unsigned char)(((b
>> 6) & 0x3F) | 0x80);
1505 this->data
[offset
+ 2] = (unsigned char)((b
& 0x3F) | 0x80);
1508 else if (b
<= 0x1FFFFF)
1510 this->data
[offset
+ 0] = (unsigned char)((b
>> 18) | 0xF0);
1511 this->data
[offset
+ 1] = (unsigned char)(((b
>> 12) & 0x3F) | 0x80);
1512 this->data
[offset
+ 2] = (unsigned char)(((b
>> 6) & 0x3F) | 0x80);
1513 this->data
[offset
+ 3] = (unsigned char)((b
& 0x3F) | 0x80);
1516 else if (b
<= 0x3FFFFFF)
1518 this->data
[offset
+ 0] = (unsigned char)((b
>> 24) | 0xF8);
1519 this->data
[offset
+ 1] = (unsigned char)(((b
>> 18) & 0x3F) | 0x80);
1520 this->data
[offset
+ 2] = (unsigned char)(((b
>> 12) & 0x3F) | 0x80);
1521 this->data
[offset
+ 3] = (unsigned char)(((b
>> 6) & 0x3F) | 0x80);
1522 this->data
[offset
+ 4] = (unsigned char)((b
& 0x3F) | 0x80);
1525 else if (b
<= 0x7FFFFFFF)
1527 this->data
[offset
+ 0] = (unsigned char)((b
>> 30) | 0xFC);
1528 this->data
[offset
+ 1] = (unsigned char)(((b
>> 24) & 0x3F) | 0x80);
1529 this->data
[offset
+ 2] = (unsigned char)(((b
>> 18) & 0x3F) | 0x80);
1530 this->data
[offset
+ 3] = (unsigned char)(((b
>> 12) & 0x3F) | 0x80);
1531 this->data
[offset
+ 4] = (unsigned char)(((b
>> 6) & 0x3F) | 0x80);
1532 this->data
[offset
+ 5] = (unsigned char)((b
& 0x3F) | 0x80);
1539 void OutBuffer::writedchar(unsigned b
)
1541 reserve(Dchar_mbmax
* sizeof(dchar
));
1542 offset
= (unsigned char *)Dchar::put((dchar
*)(this->data
+ offset
), (dchar
)b
) -
1546 void OutBuffer::prependbyte(unsigned b
)
1549 memmove(data
+ 1, data
, offset
);
1550 data
[0] = (unsigned char)b
;
1554 void OutBuffer::writeword(unsigned w
)
1557 *(unsigned short *)(this->data
+ offset
) = (unsigned short)w
;
1561 void OutBuffer::writeUTF16(unsigned w
)
1566 *(unsigned short *)(this->data
+ offset
) = (unsigned short)w
;
1569 else if (w
<= 0x10FFFF)
1571 *(unsigned short *)(this->data
+ offset
) = (unsigned short)((w
>> 10) + 0xD7C0);
1572 *(unsigned short *)(this->data
+ offset
+ 2) = (unsigned short)((w
& 0x3FF) | 0xDC00);
1579 void OutBuffer::write4(unsigned w
)
1582 *(uint32_t *)(this->data
+ offset
) = w
;
1586 void OutBuffer::write(OutBuffer
*buf
)
1589 { reserve(buf
->offset
);
1590 memcpy(data
+ offset
, buf
->data
, buf
->offset
);
1591 offset
+= buf
->offset
;
1595 void OutBuffer::write(Object
*obj
)
1599 writestring(obj
->toChars());
1603 void OutBuffer::fill0(unsigned nbytes
)
1606 memset(data
+ offset
,0,nbytes
);
1610 void OutBuffer::align(unsigned size
)
1613 nbytes
= ((offset
+ size
- 1) & ~(size
- 1)) - offset
;
1617 void OutBuffer::vprintf(const char *format
, va_list args
)
1626 psize
= sizeof(buffer
);
1629 va_copy(args_copy
, args
);
1631 count
= _vsnprintf(p
,psize
,format
,args_copy
);
1637 count
= vsnprintf(p
,psize
,format
,args_copy
);
1640 else if (count
>= psize
)
1645 p
= (char *) alloca(psize
); // buffer too small, try again with larger size
1651 void OutBuffer::vprintf(const wchar_t *format
, va_list args
)
1660 psize
= sizeof(buffer
) / sizeof(buffer
[0]);
1664 count
= _vsnwprintf(p
,psize
,format
,args_copy
);
1670 count
= vsnwprintf(p
,psize
,format
,args_copy
);
1673 else if (count
>= psize
)
1678 p
= (dchar
*) alloca(psize
* 2); // buffer too small, try again with larger size
1684 void OutBuffer::printf(const char *format
, ...)
1687 va_start(ap
, format
);
1693 void OutBuffer::printf(const wchar_t *format
, ...)
1696 va_start(ap
, format
);
1702 void OutBuffer::bracket(char left
, char right
)
1705 memmove(data
+ 1, data
, offset
);
1707 data
[offset
+ 1] = right
;
1712 * Insert left at i, and right at j.
1713 * Return index just past right.
1716 unsigned OutBuffer::bracket(unsigned i
, char *left
, unsigned j
, char *right
)
1718 size_t leftlen
= strlen(left
);
1719 size_t rightlen
= strlen(right
);
1720 reserve(leftlen
+ rightlen
);
1721 insert(i
, left
, leftlen
);
1722 insert(j
+ leftlen
, right
, rightlen
);
1723 return j
+ leftlen
+ rightlen
;
1726 void OutBuffer::spread(unsigned offset
, unsigned nbytes
)
1729 memmove(data
+ offset
+ nbytes
, data
+ offset
,
1730 this->offset
- offset
);
1731 this->offset
+= nbytes
;
1734 /****************************************
1735 * Returns: offset + nbytes
1738 unsigned OutBuffer::insert(unsigned offset
, const void *p
, unsigned nbytes
)
1740 spread(offset
, nbytes
);
1741 memmove(data
+ offset
, p
, nbytes
);
1742 return offset
+ nbytes
;
1745 void OutBuffer::remove(unsigned offset
, unsigned nbytes
)
1747 memmove(data
+ offset
, data
+ offset
+ nbytes
, this->offset
- (offset
+ nbytes
));
1748 this->offset
-= nbytes
;
1751 char *OutBuffer::toChars()
1754 return (char *)data
;
1757 /********************************* Bits ****************************/
1776 void Bits::resize(unsigned bitdim
)
1781 allocdim
= (bitdim
+ 31) / 32;
1782 data
= (unsigned *)mem
.realloc(data
, allocdim
* sizeof(data
[0]));
1783 if (this->allocdim
< allocdim
)
1784 memset(data
+ this->allocdim
, 0, (allocdim
- this->allocdim
) * sizeof(data
[0]));
1786 // Clear other bits in last word
1787 mask
= (1 << (bitdim
& 31)) - 1;
1789 data
[allocdim
- 1] &= ~mask
;
1791 this->bitdim
= bitdim
;
1792 this->allocdim
= allocdim
;
1795 void Bits::set(unsigned bitnum
)
1797 data
[bitnum
/ 32] |= 1 << (bitnum
& 31);
1800 void Bits::clear(unsigned bitnum
)
1802 data
[bitnum
/ 32] &= ~(1 << (bitnum
& 31));
1805 int Bits::test(unsigned bitnum
)
1807 return data
[bitnum
/ 32] & (1 << (bitnum
& 31));
1813 memset(data
, ~0, allocdim
* sizeof(data
[0]));
1815 // Clear other bits in last word
1816 mask
= (1 << (bitdim
& 31)) - 1;
1818 data
[allocdim
- 1] &= mask
;
1823 memset(data
, 0, allocdim
* sizeof(data
[0]));
1826 void Bits::copy(Bits
*from
)
1828 assert(bitdim
== from
->bitdim
);
1829 memcpy(data
, from
->data
, allocdim
* sizeof(data
[0]));
1842 void Bits::sub(Bits
*b
)
1846 for (u
= 0; u
< allocdim
; u
++)
1847 data
[u
] &= ~b
->data
[u
];