/*
- * $RCSId: xc/lib/fontconfig/src/fcstr.c,v 1.10 2002/08/31 22:17:32 keithp Exp $
+ * fontconfig/src/fcstr.c
*
* Copyright © 2000 Keith Packard
*
* representations about the suitability of this software for any purpose. It
* is provided "as is" without express or implied warranty.
*
- * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * THE AUTHOR(S) DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
- * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY SPECIAL, INDIRECT OR
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
+#include "fcint.h"
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
-#include <sys/mman.h>
-#include "fcint.h"
+#ifdef _WIN32
+#include <windows.h>
+#endif
FcChar8 *
FcStrCopy (const FcChar8 *s)
{
- FcChar8 *r;
+ int len;
+ FcChar8 *r;
if (!s)
return 0;
- r = (FcChar8 *) malloc (strlen ((char *) s) + 1);
+ len = strlen ((char *) s) + 1;
+ r = (FcChar8 *) malloc (len);
if (!r)
return 0;
- FcMemAlloc (FC_MEM_STRING, strlen ((char *) s) + 1);
- strcpy ((char *) r, (char *) s);
+ FcMemAlloc (FC_MEM_STRING, len);
+ memcpy (r, s, len);
return r;
}
typedef struct _FcCaseWalker {
const FcChar8 *read;
const FcChar8 *src;
- int len;
FcChar8 utf8[FC_MAX_CASE_FOLD_CHARS + 1];
} FcCaseWalker;
{
w->src = src;
w->read = 0;
- w->len = strlen (src);
}
static FcChar8
{
FcChar32 ucs4;
int slen;
+ int len = strlen((char*)w->src);
- slen = FcUtf8ToUcs4 (w->src - 1, &ucs4, w->len + 1);
+ slen = FcUtf8ToUcs4 (w->src - 1, &ucs4, len + 1);
if (slen <= 0)
return r;
if (FC_MIN_FOLD_CHAR <= ucs4 && ucs4 <= FC_MAX_FOLD_CHAR)
/* consume rest of src utf-8 bytes */
w->src += slen - 1;
- w->len -= slen - 1;
/* read from temp buffer */
w->utf8[dlen] = '\0';
w->read = 0;
}
r = *w->src++;
- --w->len;
if ((r & 0xc0) == 0xc0)
return FcStrCaseWalkerLong (w, r);
do
{
r = *w->src++;
- --w->len;
} while (r == ' ');
if ((r & 0xc0) == 0xc0)
return 0;
}
+static FcBool
+FcCharIsPunct (const FcChar8 c)
+{
+ if (c < '0')
+ return FcTrue;
+ if (c <= '9')
+ return FcFalse;
+ if (c < 'A')
+ return FcTrue;
+ if (c <= 'Z')
+ return FcFalse;
+ if (c < 'a')
+ return FcTrue;
+ if (c <= 'z')
+ return FcFalse;
+ if (c <= '~')
+ return FcTrue;
+ return FcFalse;
+}
+
/*
* Is the head of s1 equal to s2?
*/
return 0;
}
+/*
+ * Does s1 contain an instance of s2 on a word boundary (ignoring case)?
+ */
+
+const FcChar8 *
+FcStrContainsWord (const FcChar8 *s1, const FcChar8 *s2)
+{
+ FcBool wordStart = FcTrue;
+ int s1len = strlen ((char *) s1);
+ int s2len = strlen ((char *) s2);
+
+ while (s1len >= s2len)
+ {
+ if (wordStart &&
+ FcStrIsAtIgnoreCase (s1, s2) &&
+ (s1len == s2len || FcCharIsPunct (s1[s2len])))
+ {
+ return s1;
+ }
+ wordStart = FcFalse;
+ if (FcCharIsPunct (*s1))
+ wordStart = FcTrue;
+ s1++;
+ s1len--;
+ }
+ return 0;
+}
+
const FcChar8 *
FcStrStrIgnoreCase (const FcChar8 *s1, const FcChar8 *s2)
{
++ s1;
++ s2;
}
-
- return 0;
+ /* never reached. */
}
int
void
FcStrBufInit (FcStrBuf *buf, FcChar8 *init, int size)
{
- buf->buf = init;
+ if (init)
+ {
+ buf->buf = init;
+ buf->size = size;
+ } else
+ {
+ buf->buf = buf->buf_static;
+ buf->size = sizeof (buf->buf_static);
+ }
buf->allocated = FcFalse;
buf->failed = FcFalse;
buf->len = 0;
- buf->size = size;
}
void
{
FcChar8 *ret;
- ret = malloc (buf->len + 1);
+ if (buf->failed)
+ ret = NULL;
+ else
+ ret = malloc (buf->len + 1);
if (ret)
{
FcMemAlloc (FC_MEM_STRING, buf->len + 1);
return ret;
}
+FcChar8 *
+FcStrBufDoneStatic (FcStrBuf *buf)
+{
+ FcStrBufChar (buf, '\0');
+
+ if (buf->failed)
+ return NULL;
+
+ return buf->buf;
+}
+
FcBool
FcStrBufChar (FcStrBuf *buf, FcChar8 c)
{
FcChar8 *new;
int size;
+ if (buf->failed)
+ return FcFalse;
+
if (buf->allocated)
{
size = buf->size * 2;
}
else
{
- size = buf->size + 1024;
+ size = buf->size + 64;
new = malloc (size);
if (new)
{
if (*s == '~')
{
FcChar8 *home = FcConfigHome ();
+ FcChar8 *full;
int size;
if (!home)
return 0;
size = strlen ((char *) home) + strlen ((char *) s);
- new = (FcChar8 *) malloc (size);
- if (!new)
+ full = (FcChar8 *) malloc (size);
+ if (!full)
return 0;
- FcMemAlloc (FC_MEM_STRING, size);
- strcpy ((char *) new, (char *) home);
- strcat ((char *) new, (char *) s + 1);
+ strcpy ((char *) full, (char *) home);
+ strcat ((char *) full, (char *) s + 1);
+ new = FcStrCanonFilename (full);
+ free (full);
}
else
- {
- int size = strlen ((char *) s) + 1;
- new = (FcChar8 *) malloc (size);
- if (!new)
- return 0;
- FcMemAlloc (FC_MEM_STRING, size);
- strcpy ((char *) new, (const char *) s);
- }
+ new = FcStrCanonFilename (s);
return new;
}
return FcStrCopy (slash + 1);
}
-FcStrSet *
-FcStrSetCreate (void)
+static FcChar8 *
+FcStrCanonAbsoluteFilename (const FcChar8 *s)
{
- FcStrSet *set = malloc (sizeof (FcStrSet));
- if (!set)
- return 0;
- FcMemAlloc (FC_MEM_STRSET, sizeof (FcStrSet));
- set->ref = 1;
- set->num = 0;
- set->size = 0;
- set->storage = FcStorageDynamic;
- set->u.strs = 0;
- return set;
+ FcChar8 *file;
+ FcChar8 *f;
+ const FcChar8 *slash;
+ int size;
+
+ size = strlen ((char *) s) + 1;
+ file = malloc (size);
+ if (!file)
+ return NULL;
+ FcMemAlloc (FC_MEM_STRING, size);
+ slash = NULL;
+ f = file;
+ for (;;) {
+ if (*s == '/' || *s == '\0')
+ {
+ if (slash)
+ {
+ switch (s - slash) {
+ case 1:
+ f -= 1; /* squash // and trim final / from file */
+ break;
+ case 2:
+ if (!strncmp ((char *) slash, "/.", 2))
+ {
+ f -= 2; /* trim /. from file */
+ }
+ break;
+ case 3:
+ if (!strncmp ((char *) slash, "/..", 3))
+ {
+ f -= 3; /* trim /.. from file */
+ while (f > file) {
+ if (*--f == '/')
+ break;
+ }
+ }
+ break;
+ }
+ }
+ slash = s;
+ }
+ if (!(*f++ = *s++))
+ break;
+ }
+ return file;
}
+
+#ifdef _WIN32
+/*
+ * Convert '\\' to '/' , remove double '/'
+ */
+static void
+FcConvertDosPath (char *str)
+{
+ size_t len = strlen (str);
+ char *p = str;
+ char *dest = str;
+ char *end = str + len;
+ char last = 0;
+
+ if (*p == '\\')
+ {
+ *p = '/';
+ p++;
+ dest++;
+ }
+ while (p < end)
+ {
+ if (*p == '\\')
+ *p = '/';
+
+ if (*p != '/'
+ || last != '/')
+ {
+ *dest++ = *p;
+ }
-static FcChar8 * strset_buf = 0;
-static int strset_buf_ptr = 0, strset_buf_count = 0;
-static int * strset_idx = 0;
-static int strset_idx_ptr = 0, strset_idx_count = 0;
-static FcStrSet * strsets = 0;
-static int strset_ptr = 0, strset_count = 0;
+ last = *p;
+ p++;
+ }
-void FcStrSetClearStatic()
-{
- strset_buf = 0; strset_buf_ptr = 0; strset_buf_count = 0;
- strset_idx = 0; strset_idx_ptr = 0; strset_idx_count = 0;
- strsets = 0; strset_ptr = 0; strset_count = 0;
+ *dest = 0;
}
+#endif
FcChar8 *
-FcStrSetGet (const FcStrSet *set, int i)
+FcStrCanonFilename (const FcChar8 *s)
{
- int index;
- switch (set->storage)
+#ifdef _WIN32
+ FcChar8 full[FC_MAX_FILE_LEN + 2];
+ int size = GetFullPathName (s, sizeof (full) -1,
+ full, NULL);
+
+ if (size == 0)
+ perror ("GetFullPathName");
+
+ FcConvertDosPath (full);
+ return FcStrCanonAbsoluteFilename (full);
+#else
+ if (s[0] == '/')
+ return FcStrCanonAbsoluteFilename (s);
+ else
{
- case FcStorageStatic:
- index = strset_idx[set->u.stridx_offset];
- if (index == -1)
- return 0;
- return &strset_buf[index];
- case FcStorageDynamic:
- return set->u.strs[i];
- default:
- return 0;
+ FcChar8 *full;
+ FcChar8 *file;
+
+ FcChar8 cwd[FC_MAX_FILE_LEN + 2];
+ if (getcwd ((char *) cwd, FC_MAX_FILE_LEN) == NULL)
+ return NULL;
+ strcat ((char *) cwd, "/");
+ full = FcStrPlus (cwd, s);
+ file = FcStrCanonAbsoluteFilename (full);
+ FcStrFree (full);
+ return file;
}
+#endif
}
+
FcStrSet *
-FcStrSetPtrU (const FcStrSetPtr set)
+FcStrSetCreate (void)
{
- switch (set.storage)
- {
- case FcStorageStatic:
- return &strsets[set.u.stat];
- case FcStorageDynamic:
- return (FcStrSet *)set.u.dyn;
- default:
+ FcStrSet *set = malloc (sizeof (FcStrSet));
+ if (!set)
return 0;
- }
-}
-
-FcStrSetPtr
-FcStrSetPtrCreateDynamic (const FcStrSet * set)
-{
- FcStrSetPtr new;
-
- new.storage = FcStorageDynamic;
- new.u.dyn = (FcStrSet *)set;
- return new;
+ FcMemAlloc (FC_MEM_STRSET, sizeof (FcStrSet));
+ set->ref = 1;
+ set->num = 0;
+ set->size = 0;
+ set->strs = 0;
+ return set;
}
static FcBool
FcStrFree (s);
return FcTrue;
}
- if (set->num == set->size || set->storage == FcStorageStatic)
+ if (set->num == set->size)
{
FcChar8 **strs = malloc ((set->size + 2) * sizeof (FcChar8 *));
if (!strs)
return FcFalse;
FcMemAlloc (FC_MEM_STRSET, (set->size + 2) * sizeof (FcChar8 *));
- set->size = set->size + 1;
- if (set->storage == FcStorageDynamic)
+ if (set->num)
+ memcpy (strs, set->strs, set->num * sizeof (FcChar8 *));
+ if (set->strs)
{
- if (set->num)
- memcpy (strs, set->u.strs, set->num * sizeof (FcChar8 *));
- if (set->u.strs)
- free (set->u.strs);
+ FcMemFree (FC_MEM_STRSET, (set->size + 1) * sizeof (FcChar8 *));
+ free (set->strs);
}
- else
- {
- if (set->num)
- memcpy (strs, strset_idx+set->u.stridx_offset,
- set->num * sizeof (FcChar8 *));
- set->storage = FcStorageDynamic;
- }
- set->u.strs = strs;
+ set->size = set->size + 1;
+ set->strs = strs;
}
- set->u.strs[set->num++] = s;
- set->u.strs[set->num] = 0;
+ set->strs[set->num++] = s;
+ set->strs[set->num] = 0;
return FcTrue;
}
int i;
for (i = 0; i < set->num; i++)
- if (!FcStrCmp (FcStrSetGet(set, i), s))
+ if (!FcStrCmp (set->strs[i], s))
return FcTrue;
return FcFalse;
}
if (sa->num != sb->num)
return FcFalse;
for (i = 0; i < sa->num; i++)
- if (!FcStrSetMember (sb, FcStrSetGet(sa, i)))
+ if (!FcStrSetMember (sb, sa->strs[i]))
return FcFalse;
return FcTrue;
}
int i;
for (i = 0; i < set->num; i++)
- if (!FcStrCmp (FcStrSetGet(set, i), s))
+ if (!FcStrCmp (set->strs[i], s))
{
- if (set->storage == FcStorageDynamic)
- FcStrFree (set->u.strs[i]);
+ FcStrFree (set->strs[i]);
/*
* copy remaining string pointers and trailing
* NULL
*/
- memmove (FcStrSetGet(set, i), FcStrSetGet(set, i+1),
+ memmove (&set->strs[i], &set->strs[i+1],
(set->num - i) * sizeof (FcChar8 *));
set->num--;
return FcTrue;
{
int i;
- if (set->storage == FcStorageDynamic)
+ for (i = 0; i < set->num; i++)
+ FcStrFree (set->strs[i]);
+ if (set->strs)
{
- for (i = 0; i < set->num; i++)
- FcStrFree (set->u.strs[i]);
- FcMemFree (FC_MEM_STRSET, (set->size) * sizeof (FcChar8 *));
- if (set->u.strs)
- free (set->u.strs);
- FcMemFree (FC_MEM_STRSET, sizeof (FcStrSet));
+ FcMemFree (FC_MEM_STRSET, (set->size + 1) * sizeof (FcChar8 *));
+ free (set->strs);
}
+ FcMemFree (FC_MEM_STRSET, sizeof (FcStrSet));
free (set);
}
}
-static int _FcStrSetSort_helper (const void * a, const void * b)
-{
- return FcStrCmp (&strset_buf[(int)a],
- &strset_buf[(int)b]);
-}
-
-void
-FcStrSetSort (FcStrSet * set)
-{
- switch (set->storage)
- {
- case FcStorageDynamic:
- qsort (set->u.strs, set->num, sizeof (FcChar8 *),
- (int (*)(const void *, const void *)) FcStrCmp);
- break;
- case FcStorageStatic:
- qsort (strset_idx+set->u.stridx_offset, set->num, sizeof (int),
- _FcStrSetSort_helper);
- break;
- default:
- break;
- }
-}
-
-FcBool
-FcStrSetPrepareSerialize (const FcStrSet *set)
-{
- int i;
-
- if (!set)
- return FcTrue;
-
- strset_count ++;
- strset_idx_count += set->num;
- for (i = 0; i < set->num; i++)
- {
- if (FcStrSetGet(set, i))
- strset_buf_count += strlen(FcStrSetGet(set, i));
- }
-
- return FcTrue;
-}
-
-FcStrSetPtr
-FcStrSetSerialize (FcStrSet *set)
-{
- FcStrSet * new;
- FcStrSetPtr newp;
- int i;
-
- if (!strsets)
- {
- strsets = malloc (strset_count * sizeof(FcStrSet));
- if (!strsets) goto bail1;
- strset_idx = malloc (strset_idx_count * sizeof(int));
- if (!strset_idx) goto bail2;
- strset_buf = malloc (strset_buf_count * sizeof (FcChar8));
- if (!strset_buf) goto bail3;
- }
-
- if (!set)
- return FcStrSetPtrCreateDynamic(0);
-
- newp.storage = FcStorageStatic;
- newp.u.stat = strset_ptr;
-
- new = &strsets[strset_ptr++];
- new->ref = set->ref;
- new->num = set->num;
- new->size = set->num;
- new->storage = FcStorageStatic;
- new->u.stridx_offset = strset_idx_ptr;
- for (i = 0; i < set->num; i++)
- {
- FcChar8 * s = FcStrSetGet(set, i);
-
- if (s)
- {
- memcpy(strset_buf+strset_buf_ptr, s,
- strlen((char *)s));
- strset_idx[strset_idx_ptr++] = strset_buf_ptr;
- strset_buf_ptr += strlen((char *)s)+1;
- }
- else
- strset_idx[strset_idx_ptr++] = -1;
- }
-
- if (strset_ptr > strset_count || strset_idx_ptr > strset_idx_count)
- return FcStrSetPtrCreateDynamic(0);
-
- // problem with multiple ptrs to the same StrSet.
- // should hash StrSets or something.
- // FcStrSetDestroy (set);
-
- return newp;
-
- bail3:
- free (strset_idx);
- bail2:
- free (strsets);
- bail1:
- return FcStrSetPtrCreateDynamic(0);
-}
-
-FcBool
-FcStrSetRead (int fd, FcCache metadata)
-{
- strsets = mmap(NULL,
- metadata.strsets_length * sizeof (FcStrSet),
- PROT_READ,
- MAP_SHARED, fd, metadata.strsets_offset);
- if (strsets == MAP_FAILED)
- goto bail;
- strset_count = strset_ptr = metadata.strsets_length;
-
- strset_idx = mmap(NULL,
- metadata.strsets_idx_length * sizeof (int),
- PROT_READ,
- MAP_SHARED, fd, metadata.strsets_idx_offset);
- if (strset_idx == MAP_FAILED)
- goto bail1;
- strset_idx_count = strset_idx_ptr = metadata.strsets_length;
-
- strset_buf = mmap(NULL,
- metadata.strset_buf_length * sizeof (char),
- PROT_READ,
- MAP_SHARED, fd, metadata.strset_buf_offset);
- if (strset_buf == MAP_FAILED)
- goto bail2;
- strset_buf_count = strset_buf_ptr = metadata.strset_buf_length;
-
- return FcTrue;
-
- bail2:
- munmap (strset_idx, metadata.strsets_idx_length * sizeof (int));
- bail1:
- munmap (strsets, metadata.strsets_length * sizeof (FcStrSet));
- bail:
- return FcFalse;
-}
-
-FcBool
-FcStrSetWrite (int fd, FcCache *metadata)
-{
- metadata->strsets_length = strset_ptr;
- metadata->strsets_offset = FcCacheNextOffset(fd);
- if (strset_ptr > 0)
- {
- lseek (fd, metadata->strsets_offset, SEEK_SET);
- if (write (fd, strsets, strset_ptr * sizeof(FcStrSet)) == -1)
- return FcFalse;
- }
-
- metadata->strsets_idx_length = strset_idx_ptr;
- metadata->strsets_idx_offset = FcCacheNextOffset(fd);
- if (strset_idx_ptr > 0)
- {
- lseek (fd, metadata->strsets_idx_offset, SEEK_SET);
- if (write (fd, strset_idx, strset_idx_ptr * sizeof (int)) == -1)
- return FcFalse;
- }
-
- metadata->strset_buf_offset = FcCacheNextOffset(fd);
- metadata->strset_buf_length = strset_buf_ptr;
- if (strset_buf_ptr > 0)
- {
- lseek (fd, metadata->strset_buf_offset, SEEK_SET);
- if (write (fd, strset_buf,
- metadata->strset_buf_length * sizeof (char)) == -1)
- return FcFalse;
- }
-
- return FcTrue;
-}
-
FcStrList *
FcStrListCreate (FcStrSet *set)
{
{
if (list->n >= list->set->num)
return 0;
- return FcStrSetGet(list->set, list->n++);
+ return list->set->strs[list->n++];
}
void
FcMemFree (FC_MEM_STRLIST, sizeof (FcStrList));
free (list);
}
+
+#define __fcstr__
+#include "fcaliastail.h"
+#undef __fcstr__