int indexAlloced;
int sorted;
+ int langNum;
};
struct entryInfo {
struct indexEntry {
struct entryInfo info;
void * data;
- int length; /* Computable, but why bother */
+ int length; /* Computable, but why bother? */
};
struct sprintfTag {
while (headerNextIterator(headerIter, &tag, &type, &ptr, &count)) {
headerAddEntry(res, tag, type, ptr, count);
- if (type == RPM_STRING_ARRAY_TYPE) free(ptr);
+ if (type == RPM_STRING_ARRAY_TYPE ||
+ type == RPM_I18NSTRING_TYPE) free(ptr);
}
res->sorted = 1;
/* This assumes you only headerLoad() something you headerUnload()-ed */
h->sorted = 1;
+ h->langNum = -1;
pe = (struct entryInfo *) p;
dataStart = (char *) (pe + h->indexUsed);
/*case RPM_INT64_TYPE: type = "INT64_TYPE"; break;*/
case RPM_STRING_TYPE: type = "STRING_TYPE"; break;
case RPM_STRING_ARRAY_TYPE: type = "STRING_ARRAY_TYPE"; break;
+ case RPM_I18NSTRING_TYPE: type = "I18N_STRING_TYPE"; break;
default: type = "(unknown)"; break;
}
break;
case RPM_STRING_TYPE:
case RPM_STRING_ARRAY_TYPE:
+ case RPM_I18NSTRING_TYPE:
while (c--) {
fprintf(f, " Data: %.3d %s\n", ct++, (char *) dp);
dp = strchr(dp, 0);
}
/* fallthrough */
case RPM_STRING_ARRAY_TYPE:
- *type = RPM_STRING_ARRAY_TYPE;
+ case RPM_I18NSTRING_TYPE:
i = entry->info.count;
tableSize = i * sizeof(char *);
ptrEntry = *p = malloc(tableSize + entry->length);
int headerGetEntry(Header h, int_32 tag, int_32 * type, void **p, int_32 * c)
{
- int_32 t = RPM_NULL_TYPE;
- int rc;
+ struct indexEntry * entry;
+ char * chptr;
+ int i;
- rc = headerGetRawEntry(h, tag, &t, p, c);
- if (rc && type) *type = t;
+ if (!p) return headerIsEntry(h, tag);
- return rc;
+ /* First find the tag */
+ entry = findEntry(h, tag, RPM_NULL_TYPE);
+ if (!entry) {
+ *p = NULL;
+ return 0;
+ }
+
+ if (entry->info.type == RPM_I18NSTRING_TYPE) {
+ if (h->langNum == -1) headerResetLang(h);
+
+ if (type) *type = RPM_STRING_TYPE;
+ if (c) *c = entry->info.count;
+
+ chptr = entry->data;
+ for (i = 0; i < h->langNum; i++)
+ chptr += strlen(chptr) + 1;
+
+ *p = chptr;
+ } else {
+ copyEntry(entry, type, p, c);
+ }
+
+ return 1;
}
/********************************************************************/
h->indexUsed = 0;
h->sorted = 0;
+ h->langNum = -1;
return (Header) h;
}
exit(1);
case RPM_STRING_ARRAY_TYPE:
+ case RPM_I18NSTRING_TYPE:
/* This is like RPM_STRING_TYPE, except it's *always* an array */
/* Compute sum of length of all strings, including null terminators */
i = count;
switch (type) {
case RPM_STRING_ARRAY_TYPE:
+ case RPM_I18NSTRING_TYPE:
/* Otherwise, p is char** */
i = c;
src = (char **) srcPtr;
return 1;
}
+int headerAddI18NString(Header h, int_32 tag, char * string, char * lang) {
+ struct indexEntry * table, * entry;
+ char * charArray[2];
+ char * chptr;
+ char ** strArray;
+ int length;
+ int ghosts;
+ int i, langNum;
+ char * buf;
+
+ table = findEntry(h, HEADER_I18NTABLE, RPM_STRING_ARRAY_TYPE);
+ entry = findEntry(h, tag, RPM_I18NSTRING_TYPE);
+
+ if (!table && entry) {
+ return 0; /* this shouldn't ever happen!! */
+ }
+
+ if (!table && !entry) {
+ if (!lang) {
+ charArray[0] = "C";
+ if (!headerAddEntry(h, HEADER_I18NTABLE, RPM_STRING_ARRAY_TYPE,
+ &charArray, 1)) return 0;
+ } else {
+ charArray[0] = "C";
+ charArray[1] = lang;
+ if (!headerAddEntry(h, HEADER_I18NTABLE, RPM_STRING_ARRAY_TYPE,
+ &charArray, 2)) return 0;
+ }
+ table = findEntry(h, HEADER_I18NTABLE, RPM_STRING_ARRAY_TYPE);
+ }
+
+ if (!lang) lang = "C";
+
+ chptr = table->data;
+ for (langNum = 0; langNum < table->info.count; langNum++) {
+ if (!strcmp(chptr, lang)) break;
+ chptr += strlen(chptr) + 1;
+ }
+
+ if (langNum >= table->info.count) {
+ length = strlen(lang) + 1;
+ table->data = realloc(table->data, table->length + length);
+ memcpy(((char *)table->data) + table->length, lang, length);
+ table->length += length;
+ table->info.count++;
+ }
+
+ if (!entry) {
+ strArray = alloca(sizeof(*strArray) * langNum);
+ for (i = 0; i < langNum; i++)
+ strArray[i] = "";
+ strArray[langNum] = string;
+ return headerAddEntry(h, tag, RPM_I18NSTRING_TYPE, strArray,
+ langNum + 1);
+ } else if (langNum >= entry->info.count) {
+ ghosts = langNum - entry->info.count;
+
+ length = strlen(string) + 1 + ghosts;
+ entry->data = realloc(entry->data, entry->length + length);
+
+ memset(((char *)entry->data) + entry->length, '\0', ghosts);
+ strcpy(((char *)entry->data) + entry->length + ghosts, string);
+
+ entry->length += length;
+ entry->info.count = langNum + 1;
+ } else {
+ /* tricky... we need to add one to the middle (or beginning). This
+ will replace an existing entry as well */
+ buf = malloc(strlen(string) + entry->length);
+
+ chptr = entry->data, length = 0;
+ for (i = 0; i < langNum; i++)
+ length += strlen(chptr + length) + 1;
+
+ memcpy(buf, entry->data, length);
+ strcpy(buf + length, string);
+ i = strlen(chptr + length) + 1;
+ memcpy(buf + strlen(string) + 1, entry->data + length + i,
+ entry->length - length - i);
+
+ free(entry->data);
+ entry->data = buf;
+ entry->length += length;
+ }
+
+ return 0;
+}
+
int headerModifyEntry(Header h, int_32 tag, int_32 type, void *p, int_32 c)
{
struct indexEntry *entry;
return 0;
}
- /* free after we've grabbed the new data in case the two are intertwined
- -- that's a bad idea but at least we won't break */
+ /* free after we've grabbed the new data in case the two are intertwined;
+ that's a bad idea but at least we won't break */
oldData = entry->data;
entry->info.count = c;
return result;
}
+
+void headerSetLangPath(Header h, char * lang) {
+ char * buf, * chptr, * start, * next;
+ struct indexEntry * table;
+ int langNum;
+
+ table = findEntry(h, HEADER_I18NTABLE, RPM_STRING_ARRAY_TYPE);
+
+ if (!lang || !table) {
+ h->langNum = -1;
+ return;
+ }
+
+ buf = alloca(strlen(lang) + 1);
+ strcpy(buf, lang);
+
+ start = buf;
+ while (start) {
+ chptr = strchr(start, ':');
+ if (chptr) *chptr = '\0';
+
+ next = table->data;
+ for (langNum = 0; langNum < table->info.count; langNum++) {
+ if (!strcmp(next, start)) break;
+ next += strlen(next) + 1;
+ }
+
+ if (langNum < table->info.count) {
+ h->langNum = langNum;
+ break;
+ }
+
+ if (chptr)
+ start = chptr + 1;
+ else
+ start = NULL;
+ }
+
+ if (!start)
+ h->langNum = -1;
+}
+
+void headerResetLang(Header h) {
+ char * str;
+
+ if ((str = getenv("LANGUAGE"))) {
+ headerSetLangPath(h, str);
+ return;
+ }
+
+ headerSetLangPath(h, getenv("LANG"));
+}
#define HEADER_DUMP_INLINE 1
-/* I18N items need an RPM_STRING_TYPE entry (used by default) and an
- RPM_18NSTRING_TYPE table added. Dups are okay, but only defined for
- iteration (with the exceptions noted below) */
+/* Duplicate tags are okay, but only defined for iteration (with the
+ exceptions noted below). While you are allowed to add i18n string
+ arrays through this function, you probably don't mean to. See
+ headerAddI18NString() instead */
int headerAddEntry(Header h, int_32 tag, int_32 type, void *p, int_32 c);
int headerModifyEntry(Header h, int_32 tag, int_32 type, void *p, int_32 c);
+/* For the C locale, lang should be *NULL*. Here are the rules:
+
+ 1) If the tag isn't in the Header, it's added with the passed string
+ as a version.
+ 2) If the tag occurs multiple times in entry, which tag is affected
+ by the operation is undefined.
+ 2) If the tag is in the header w/ this language, the entry is
+ *replaced* (like headerModifyEntry()).
+
+ This function is intended to just "do the right thing". If you need
+ more fine grained control use headerAddEntry() and headerModifyEntry()
+ but be careful!
+*/
+int headerAddI18NString(Header h, int_32 tag, char * string, char * lang);
+
/* Appends item p to entry w/ tag and type as passed. Won't work on
RPM_STRING_TYPE. Any pointers from headerGetEntry() for this entry
are invalid after this call has been made! */
int_32 *tag, int_32 *type, void **p, int_32 *c);
void headerFreeIterator(HeaderIterator iter);
+/* reexamines LANGUAGE and LANG settings to set a new language for the
+ header; this only needs to be called if LANGUAGE or LANG may have changed
+ since the first headerGetEntry() on the header */
+void headerResetLang(Header h);
+/* sets the language path for the header; this doesn't need to be done if
+ the LANGUAGE or LANG enivronment variable are correct */
+void headerSetLangPath(Header h, char * lang);
+
Header headerCopy(Header h);
void headerSort(Header h);