util: simplifications and doc fixes
* add `qe_shell_match` to replace `fnmatch` * fix some documentation errors
This commit is contained in:
parent
2109b2b536
commit
ca1eb2ff88
3 changed files with 85 additions and 63 deletions
52
qe-manual.md
52
qe-manual.md
|
|
@ -214,7 +214,7 @@ Note: `size` must be strictly positive and `pos` must be in range: `0 <= pos < s
|
|||
|
||||
Note: this function does not set a null terminator at offset `pos`.
|
||||
|
||||
### `int buf_avail(buf_t *bp);`
|
||||
### `int buf_avail(const buf_t *bp);`
|
||||
|
||||
Compute the number of bytes available in the destination array
|
||||
|
||||
|
|
@ -576,6 +576,8 @@ Get the numerical value associated with a codepoint
|
|||
Return the corresponding numerical value, or 255 for none
|
||||
ie: `'0'` -> `0`, `'1'` -> `1`, `'a'` -> 10, `'Z'` -> 35
|
||||
|
||||
Note: only ASCII digits are supported
|
||||
|
||||
### `int qe_findchar(const char *str, char32_t c);`
|
||||
|
||||
Test if a codepoint value is part of a set of ASCII characters
|
||||
|
|
@ -615,6 +617,8 @@ Range test for codepoint values
|
|||
|
||||
Return a boolean value indicating if the codepoint is inside the range
|
||||
|
||||
Note: both boundaries are included in the range
|
||||
|
||||
### `int qe_isalnum(char32_t c);`
|
||||
|
||||
Test if a codepoint represents a letter or a digit
|
||||
|
|
@ -683,7 +687,7 @@ Test if a codepoint represents blank space
|
|||
|
||||
Return a boolean value indicating if the codepoint is blank space
|
||||
|
||||
Note: only ASCII blanks and non-breaking-space are supported
|
||||
Note: only ASCII blanks (SPC and TAB) and non-breaking-space are supported
|
||||
|
||||
### `int qe_isdigit(char32_t c);`
|
||||
|
||||
|
|
@ -845,10 +849,7 @@ Note: only ASCII letters are supported
|
|||
Free the allocated memory pointed to by a pointer whose address is passed.
|
||||
|
||||
* argument `pp` the address of a possibly null pointer. This pointer is set
|
||||
to `NULL` after freeing the memory. If the pointer memory is null,
|
||||
nothing happens.
|
||||
|
||||
* argument `n` the number of bytes to allocate in addition to the size of type `T`.
|
||||
to `NULL` after freeing the memory. If the pointer is null, nothing happens.
|
||||
|
||||
Note: this function is implemented as a macro.
|
||||
|
||||
|
|
@ -936,17 +937,6 @@ The objects are initialized to all bits zero.
|
|||
|
||||
Note: this function is implemented as a macro.
|
||||
|
||||
### `T *qe_mallocz_array(type T, size_t n);`
|
||||
|
||||
Allocate memory for an object of type `T` with `n` extra bytes.
|
||||
The object and the extra space is initialized to all bits zero.
|
||||
|
||||
* argument `T` the type of the object to allocate.
|
||||
|
||||
* argument `n` the number of bytes to allocate in addition to the size of type `T`.
|
||||
|
||||
Note: this function is implemented as a macro.
|
||||
|
||||
### `void *qe_mallocz_bytes(size_t size);`
|
||||
|
||||
Allocate a block of memory of a given size in bytes initialized
|
||||
|
|
@ -957,6 +947,17 @@ to all bits zero.
|
|||
Return a pointer to allocated memory, aligned on the maximum
|
||||
alignment size.
|
||||
|
||||
### `T *qe_mallocz_hack(type T, size_t n);`
|
||||
|
||||
Allocate memory for an object of type `T` with `n` extra bytes.
|
||||
The object and the extra space are initialized to all bits zero.
|
||||
|
||||
* argument `T` the type of the object to allocate.
|
||||
|
||||
* argument `n` the number of bytes to allocate in addition to the size of type `T`.
|
||||
|
||||
Note: this function is implemented as a macro.
|
||||
|
||||
### `T *qe_realloc_array(T **pp, size_t new_len);`
|
||||
|
||||
Reallocate a block of memory to a different size.
|
||||
|
|
@ -1946,7 +1947,7 @@ Get the next match in a directory enumeration.
|
|||
* argument `filename_size_max` the length if the `filename` destination
|
||||
array in bytes.
|
||||
|
||||
Return `0` if there is a match, `-1` if no more files matche the pattern.
|
||||
Return `0` if there is a match, `-1` if no more files match the pattern.
|
||||
|
||||
### `FindFileState *find_file_open(const char *path, const char *pattern, int flags);`
|
||||
|
||||
|
|
@ -2374,6 +2375,21 @@ and insertion sort for small chunks. The GNU lib C on linux also
|
|||
has a function `qsort_r()` with similar semantics but a different
|
||||
calling convention.
|
||||
|
||||
### `int qe_shell_match(const char *string, const char *pattern);`
|
||||
|
||||
Test whether a filename or pathname matches a shell-style pattern
|
||||
|
||||
* argument `string` a valid pointer to a string representing a
|
||||
filename
|
||||
|
||||
* argument `pattern` a valid pointer to a file pattern using `?`
|
||||
and `*` with the classic semantics used by unix shells
|
||||
|
||||
Return non zero if `string` matches `pattern`.
|
||||
|
||||
Note: this function is a simplified version of POSIX function
|
||||
`fnmatch` defined in header `<fnmatch.h>`
|
||||
|
||||
### `int qe_skip_spaces(const char **pp);`
|
||||
|
||||
Skip white space at the beginning of the string pointed to by `*pp`.
|
||||
|
|
|
|||
43
util.c
43
util.c
|
|
@ -2,7 +2,7 @@
|
|||
* Utilities for qemacs.
|
||||
*
|
||||
* Copyright (c) 2001 Fabrice Bellard.
|
||||
* Copyright (c) 2002-2025 Charlie Gordon.
|
||||
* Copyright (c) 2002-2026 Charlie Gordon.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
|
|
@ -35,38 +35,40 @@
|
|||
#include "config.h" /* for CONFIG_WIN32 */
|
||||
#include "util.h"
|
||||
|
||||
#ifdef CONFIG_WIN32
|
||||
|
||||
/* XXX: not sufficient, but OK for basic operations */
|
||||
// XXX: should use own own function in all cases
|
||||
int fnmatch(const char *pattern, const char *string, int flags) {
|
||||
int qe_shell_match(const char *string, const char *pattern) {
|
||||
/*@API utils
|
||||
Test whether a filename or pathname matches a shell-style pattern
|
||||
@argument `string` a valid pointer to a string representing a
|
||||
filename
|
||||
@argument `pattern` a valid pointer to a file pattern using `?`
|
||||
and `*` with the classic semantics used by unix shells
|
||||
@return non zero if `string` matches `pattern`.
|
||||
@note this function is a simplified version of POSIX function
|
||||
`fnmatch` defined in header `<fnmatch.h>`
|
||||
*/
|
||||
char c;
|
||||
while ((c = *pattern++) != '\0') {
|
||||
if (c == '*') {
|
||||
if (*pattern == '\0')
|
||||
return 0;
|
||||
return 1;
|
||||
while (*string) {
|
||||
if (!fnmatch(pattern, string))
|
||||
return 0;
|
||||
if (qe_shell_match(string, pattern))
|
||||
return 1;
|
||||
string++;
|
||||
}
|
||||
return FNM_NOMATCH;
|
||||
return 0;
|
||||
} else
|
||||
if (c == '?') {
|
||||
if (*string++ == '\0')
|
||||
return FNM_NOMATCH;
|
||||
return 0;
|
||||
} else
|
||||
if (c != *string++) {
|
||||
return FNM_NOMATCH;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return *string ? FNM_NOMATCH : 0;
|
||||
return *string == '\0';
|
||||
}
|
||||
|
||||
#else
|
||||
#include <fnmatch.h>
|
||||
#endif
|
||||
|
||||
#define MAX_FILENAME_SIZE 1024 /* Size for a filename buffer */
|
||||
|
||||
struct FindFileState {
|
||||
|
|
@ -89,6 +91,7 @@ FindFileState *find_file_open(const char *path, const char *pattern, int flags)
|
|||
semantics used by unix shells
|
||||
@return a pointer to an opaque FindFileState structure.
|
||||
*/
|
||||
// XXX: should check if pattern has wildcards
|
||||
FindFileState *s;
|
||||
|
||||
s = qe_mallocz(FindFileState);
|
||||
|
|
@ -108,8 +111,9 @@ int find_file_next(FindFileState *s, char *filename, int filename_size_max) {
|
|||
@argument `filename` a valid pointer to an array for the file name.
|
||||
@argument `filename_size_max` the length if the `filename` destination
|
||||
array in bytes.
|
||||
@return `0` if there is a match, `-1` if no more files matche the pattern.
|
||||
@return `0` if there is a match, `-1` if no more files match the pattern.
|
||||
*/
|
||||
// XXX: should match wildcards in directory names
|
||||
struct dirent *dirent;
|
||||
const char *p;
|
||||
|
||||
|
|
@ -169,8 +173,7 @@ int find_file_next(FindFileState *s, char *filename, int filename_size_max) {
|
|||
if (s->flags & FF_ONLYDIR)
|
||||
continue;
|
||||
}
|
||||
// XXX: should use our own fnmatch version
|
||||
if (fnmatch(s->pattern, dirent->d_name, 0) == 0) {
|
||||
if (qe_shell_match(dirent->d_name, s->pattern)) {
|
||||
makepath(filename, filename_size_max,
|
||||
s->dirpath, dirent->d_name);
|
||||
return 0;
|
||||
|
|
|
|||
53
util.h
53
util.h
|
|
@ -2,7 +2,7 @@
|
|||
* Utilities for qemacs.
|
||||
*
|
||||
* Copyright (c) 2000-2001 Fabrice Bellard.
|
||||
* Copyright (c) 2000-2025 Charlie Gordon.
|
||||
* Copyright (c) 2000-2026 Charlie Gordon.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
|
|
@ -47,21 +47,6 @@
|
|||
#define MAX_WORD_SIZE 128
|
||||
#define MAX_FILENAME_SIZE 1024
|
||||
|
||||
/* string arrays */
|
||||
typedef struct StringItem {
|
||||
void *opaque; /* opaque data that the user can use */
|
||||
char selected; /* true if selected */
|
||||
char group; /* used to group sorted items */
|
||||
char str[1];
|
||||
} StringItem;
|
||||
|
||||
typedef struct StringArray {
|
||||
int nb_allocated;
|
||||
int nb_items;
|
||||
StringItem **items;
|
||||
} StringArray;
|
||||
#define NULL_STRINGARRAY { 0, 0, NULL }
|
||||
|
||||
typedef struct FindFileState FindFileState;
|
||||
|
||||
#define FF_PATH 0x010 /* enumerate path argument */
|
||||
|
|
@ -73,6 +58,7 @@ typedef struct FindFileState FindFileState;
|
|||
FindFileState *find_file_open(const char *path, const char *pattern, int flags);
|
||||
int find_file_next(FindFileState *s, char *filename, int filename_size_max);
|
||||
void find_file_close(FindFileState **sp);
|
||||
int qe_shell_match(const char *pattern, const char *string);
|
||||
int is_directory(const char *path);
|
||||
int is_filepattern(const char *filespec);
|
||||
char *canonicalize_path(char *buf, int buf_size, const char *path);
|
||||
|
|
@ -107,6 +93,7 @@ static inline int qe_digit_value(char32_t c) {
|
|||
@argument `c` a codepoint value
|
||||
@return the corresponding numerical value, or 255 for none
|
||||
ie: `'0'` -> `0`, `'1'` -> `1`, `'a'` -> 10, `'Z'` -> 35
|
||||
@note: only ASCII digits are supported
|
||||
*/
|
||||
return c < 128 ? qe_digit_value__[c] : 255;
|
||||
}
|
||||
|
|
@ -118,6 +105,7 @@ static inline int qe_inrange(char32_t c, char32_t a, char32_t b) {
|
|||
@argument `a` the minimum codepoint value for the range
|
||||
@argument `b` the maximum codepoint value for the range
|
||||
@return a boolean value indicating if the codepoint is inside the range
|
||||
@note: both boundaries are included in the range
|
||||
*/
|
||||
//return c >= a && c <= b;
|
||||
//CG: assuming a <= b and wrap around semantics for (c - a) and (b - a)
|
||||
|
|
@ -140,7 +128,7 @@ static inline int qe_isblank(char32_t c) {
|
|||
Test if a codepoint represents blank space
|
||||
@argument `c` a codepoint value
|
||||
@return a boolean value indicating if the codepoint is blank space
|
||||
@note: only ASCII blanks and non-breaking-space are supported
|
||||
@note: only ASCII blanks (SPC and TAB) and non-breaking-space are supported
|
||||
*/
|
||||
return (c == ' ' || c == '\t' || c == 160);
|
||||
}
|
||||
|
|
@ -501,10 +489,10 @@ T *qe_malloc_hack(type T, size_t n);
|
|||
@note this function is implemented as a macro.
|
||||
*/
|
||||
|
||||
T *qe_mallocz_array(type T, size_t n);
|
||||
T *qe_mallocz_hack(type T, size_t n);
|
||||
/*@API memory
|
||||
Allocate memory for an object of type `T` with `n` extra bytes.
|
||||
The object and the extra space is initialized to all bits zero.
|
||||
The object and the extra space are initialized to all bits zero.
|
||||
@argument `T` the type of the object to allocate.
|
||||
@argument `n` the number of bytes to allocate in addition to the size of type `T`.
|
||||
@note this function is implemented as a macro.
|
||||
|
|
@ -535,9 +523,7 @@ void qe_free(T **pp);
|
|||
/*@API memory
|
||||
Free the allocated memory pointed to by a pointer whose address is passed.
|
||||
@argument `pp` the address of a possibly null pointer. This pointer is set
|
||||
to `NULL` after freeing the memory. If the pointer memory is null,
|
||||
nothing happens.
|
||||
@argument `n` the number of bytes to allocate in addition to the size of type `T`.
|
||||
to `NULL` after freeing the memory. If the pointer is null, nothing happens.
|
||||
@note this function is implemented as a macro.
|
||||
*/
|
||||
#endif
|
||||
|
|
@ -575,6 +561,21 @@ void qe_free(T **pp);
|
|||
|
||||
// XXX: Should unify these string packages but keep API simple
|
||||
|
||||
/* string arrays */
|
||||
typedef struct StringItem {
|
||||
void *opaque; /* opaque data that the user can use */
|
||||
char selected; /* true if selected */
|
||||
char group; /* used to group sorted items */
|
||||
char str[1];
|
||||
} StringItem;
|
||||
|
||||
typedef struct StringArray {
|
||||
int nb_allocated;
|
||||
int nb_items;
|
||||
StringItem **items;
|
||||
} StringArray;
|
||||
#define NULL_STRINGARRAY { 0, 0, NULL }
|
||||
|
||||
StringItem *set_string(StringArray *cs, int index, const char *str, int group);
|
||||
StringItem *add_string(StringArray *cs, const char *str, int group);
|
||||
int remove_string(StringArray *cs, const char *str);
|
||||
|
|
@ -634,7 +635,7 @@ static inline buf_t *buf_attach(buf_t *bp, char *buf, int size, int pos) {
|
|||
return bp;
|
||||
}
|
||||
|
||||
static inline int buf_avail(buf_t *bp) {
|
||||
static inline int buf_avail(const buf_t *bp) {
|
||||
/*@API buf
|
||||
Compute the number of bytes available in the destination array
|
||||
@argument `bp` a valid pointer to fixed length buffer
|
||||
|
|
@ -650,11 +651,13 @@ static inline int buf_put_byte(buf_t *bp, unsigned char ch) {
|
|||
@argument `ch` a byte
|
||||
@return the number of bytes actually written.
|
||||
*/
|
||||
if (bp->pos + 1 < bp->size) {
|
||||
bp->pos++;
|
||||
if (bp->pos < bp->size) {
|
||||
bp->buf[bp->len++] = ch;
|
||||
bp->buf[bp->len] = '\0';
|
||||
return 1;
|
||||
}
|
||||
return bp->pos++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int buf_write(buf_t *bp, const void *src, int size);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue