/* ICU package data file format (.dat files) ------------------------------- ***
Description of the data format after the usual ICU data file header (UDataInfo etc.).
Format version 1
A .dat package file contains a simple Table of Contents of item names, followed by the items themselves:
1. ToC table
uint32_t count; - number of items UDataOffsetTOCEntry entry[count]; - pair of uint32_t values per item: uint32_t nameOffset; - offset of the item name uint32_t dataOffset; - offset of the item data both are byte offsets from the beginning of the data
2. item name strings
All item names are stored as char * strings in one block between the ToC table and the data items.
3. data items
The data items are stored following the item names block. Each data item is 16-aligned. The data items are stored in the sorted order of their names.
Therefore, the top of the name strings block is the offset of the first item, the length of the last item is the difference between its offset and the .dat file length, and the length of all previous items is the difference between its offset and the next one.
line = (char *)uprv_malloc(sizeof(char) * LINE_BUFFER_SIZE); if (line == nullptr) {
fprintf(stderr, "gencmn: unable to allocate memory for line buffer of size %d\n", LINE_BUFFER_SIZE); exit(U_MEMORY_ALLOCATION_ERROR);
}
linePtr = line;
maxSize = max_size;
if (destDir == nullptr) {
destDir = u_getDataDirectory();
} if (name == nullptr) {
name = COMMON_DATA_NAME;
} if (type == nullptr) {
type = DATA_TYPE;
} if (source == nullptr) {
source = ".";
}
if (dataFile == nullptr) {
in = T_FileStream_stdin();
} else {
in = T_FileStream_open(dataFile, "r"); if(in == nullptr) {
fprintf(stderr, "gencmn: unable to open input file %s\n", dataFile); exit(U_FILE_ACCESS_ERROR);
}
}
if (verbose) { if(sourceTOC) {
printf("generating %s_%s.c (table of contents source file)\n", name, type);
} else {
printf("generating %s.%s (common data file with table of contents)\n", name, type);
}
}
/* read the list of files and get their lengths */ while((s != nullptr && *s != 0) || (s=T_FileStream_readLine(in, (line=linePtr),
LINE_BUFFER_SIZE))!=nullptr) { /* remove trailing newline characters and parse space separated items */ if (s != nullptr && *s != 0) {
line=s;
} else {
s=line;
} while(*s!=0) { if(*s==' ') {
*s=0;
++s; break;
} elseif(*s=='\r' || *s=='\n') {
*s=0; break;
}
++s;
}
if(fileCount==0) {
fprintf(stderr, "gencmn: no files listed in %s\n", dataFile == nullptr ? "" : dataFile); return;
}
/* sort the files by basename */
qsort(files, fileCount, sizeof(File), compareFiles);
if(!sourceTOC) {
UNewDataMemory *out;
/* determine the offsets of all basenames and files in this common one */
basenameOffset=4+8*fileCount;
fileOffset=(basenameOffset+(basenameTotal+15))&~0xf; for(i=0; i<fileCount; ++i) {
files[i].fileOffset=fileOffset;
fileOffset+=(files[i].fileSize+15)&~0xf;
files[i].basenameOffset=basenameOffset;
basenameOffset+=files[i].basenameLength;
}
/* copy the files */ for(i=0; i<fileCount; ++i) { /* pad to 16-align the next file */
length&=0xf; if(length!=0) {
udata_writePadding(out, 16-length);
}
if(fileCount==fileMax) {
fileMax += CHUNK_FILE_COUNT;
files = static_cast<File*>(uprv_realloc(files, fileMax * sizeof(files[0]))); /* note: never freed. */ if(files==nullptr) {
fprintf(stderr, "pkgdata/gencmn: Could not allocate %u bytes for %d files\n", static_cast<unsignedint>(fileMax * sizeof(files[0])), fileCount); exit(U_MEMORY_ALLOCATION_ERROR);
}
}
if(!sourceTOC) {
FileStream *file;
if(uprv_pathIsAbsolute(filename)) {
fprintf(stderr, "gencmn: Error: absolute path encountered. Old style paths are not supported. Use relative paths such as 'fur.res' or 'translit%cfur.res'.\n\tBad path: '%s'\n", U_FILE_SEP_CHAR, filename); exit(U_ILLEGAL_ARGUMENT_ERROR);
}
fullPath = pathToFullPath(filename, source); /* store the pathname */
length = static_cast<uint32_t>(uprv_strlen(filename) + 1 + uprv_strlen(name) + 1);
s=allocString(length);
uprv_strcpy(s, name);
uprv_strcat(s, U_TREE_ENTRY_SEP_STRING);
uprv_strcat(s, filename);
/* get the basename */
fixDirToTreePath(s);
files[fileCount].basename=s;
files[fileCount].basenameLength=length;
files[fileCount].pathname=fullPath;
basenameTotal+=length;
/* try to open the file */
file=T_FileStream_open(fullPath, "rb"); if(file==nullptr) {
fprintf(stderr, "gencmn: unable to open listed file %s\n", fullPath); exit(U_FILE_ACCESS_ERROR);
}
/* get the file length */
length=T_FileStream_size(file); if(T_FileStream_error(file) || length<=20) {
fprintf(stderr, "gencmn: unable to get length of listed file %s\n", fullPath); exit(U_FILE_ACCESS_ERROR);
}
T_FileStream_close(file);
/* do not add files that are longer than maxSize */ if(maxSize && length>maxSize) { if (verbose) {
printf("%s ignored (size %ld > %ld)\n", fullPath, static_cast<long>(length), static_cast<long>(maxSize));
} return;
}
files[fileCount].fileSize=length;
} else { char *t; /* get and store the basename */ /* need to include the package name */
length = static_cast<uint32_t>(uprv_strlen(filename) + 1 + uprv_strlen(name) + 1);
s=allocString(length);
uprv_strcpy(s, name);
uprv_strcat(s, U_TREE_ENTRY_SEP_STRING);
uprv_strcat(s, filename);
fixDirToTreePath(s);
files[fileCount].basename=s; /* turn the basename into an entry point name and store in the pathname field */
t=files[fileCount].pathname=allocString(length); while(--length>0) { if(*s=='.' || *s=='-' || *s=='/') {
*t='_';
} else {
*t=*s;
}
++s;
++t;
}
*t=0;
}
++fileCount;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.