diff --git a/src/util.c b/src/util.c index b7ab0a4..803fcd4 100644 --- a/src/util.c +++ b/src/util.c @@ -15,6 +15,7 @@ #include #include #include +#include int div_up(int n, int div) { @@ -176,3 +177,103 @@ int str2ascii(const char *icharset, const char *input, char **output) return ISO_SUCCESS; } +static int valid_d_char(char c) +{ + return (c >= '0' && c <= '9') || (c >= 'A' && c <= 'Z') || (c == '_'); +} + +void iso_dirid(char *src, int maxlen) +{ + size_t len, i; + + len = strlen(src); + if (len > maxlen) { + src[maxlen] = '\0'; + len = maxlen; + } + for (i = 0; i < len; i++) { + char c = toupper(src[i]); + src[i] = valid_d_char(c) ? c : '_'; + } +} + +void iso_1_fileid(char *src) +{ + char *dot; /* Position of the last dot in the filename, will be used to + calculate lname and lext. */ + int lname, lext, pos, i; + + dot = strrchr(src, '.'); + + lext = dot ? strlen(dot + 1) : 0; + lname = strlen(src) - lext - (dot ? 1 : 0); + + /* If we can't build a filename, return. */ + if (lname == 0 && lext == 0) { + return; + } + + pos = 0; + /* Convert up to 8 characters of the filename. */ + for (i = 0; i < lname && i < 8; i++) { + char c = toupper(src[i]); + src[pos++] = valid_d_char(c) ? c : '_'; + } + + /* This dot is mandatory, even if there is no extension. */ + src[pos++] = '.'; + + /* Convert up to 3 characters of the extension, if any. */ + for (i = 0; i < lext && i < 3; i++) { + char c = toupper(src[lname + 1 + i]); + src[pos++] = valid_d_char(c) ? c : '_'; + } + src[pos] = '\0'; +} + +void iso_2_fileid(char *src) +{ + char *dot; + int lname, lext, lnname, lnext, pos, i; + + if (!src) + return; + + dot = strrchr(src, '.'); + + /* + * Since the maximum length can be divided freely over the name and + * extension, we need to calculate their new lengths (lnname and + * lnext). If the original filename is too long, we start by trimming + * the extension, but keep a minimum extension length of 3. + */ + if (dot == NULL || *(dot + 1) == '\0') { + lname = strlen(src); + lnname = (lname > 30) ? 30 : lname; + lext = lnext = 0; + } else { + lext = strlen(dot + 1); + lname = strlen(src) - lext - 1; + lnext = (strlen(src) > 31 && lext > 3) + ? (lname < 27 ? 30 - lname : 3) : lext; + lnname = (strlen(src) > 31) ? 30 - lnext : lname; + } + + if (lnname == 0 && lnext == 0) { + return; + } + + pos = 0; + /* Convert up to lnname characters of the filename. */ + for (i = 0; i < lnname; i++) { + char c = toupper(src[i]); + src[pos++] = valid_d_char(c) ? c : '_'; + } + src[pos++] = '.'; + /* Convert up to lnext characters of the extension, if any. */ + for (i = 0; i < lnext; i++) { + char c = toupper(src[lname + 1 + i]); + src[pos++] = valid_d_char(c) ? c : '_'; + } + src[pos] = '\0'; +} diff --git a/src/util.h b/src/util.h index 9c77a71..93dc390 100644 --- a/src/util.h +++ b/src/util.h @@ -13,6 +13,49 @@ extern inline int div_up(int n, int div); extern inline int round_up(int n, int mul); +/** + * Convert a given string from any input charset to ASCII + * + * @param icharset + * Input charset. Must be supported by iconv + * @param input + * Input string + * @param ouput + * Location where the pointer to the ouput string will be stored + * @return + * 1 on success, < 0 on error + */ int str2ascii(const char *icharset, const char *input, char **output); +/** + * Ensure a given string is a valid ISO directory identifier, modifying + * it if needed. + * + * @param src + * The identifier, in ASCII encoding. It may be modified by the function. + * @param maxlen + * Maximum length supported by current iso level. + */ +void iso_dirid(char *src, int maxlen); + +/** + * Ensure a given string is a valid ISO level 1 file identifier, in 8.3 + * format, modifying it if needed. + * Note that version number is not added to the file name + * + * @param src + * The identifier, in ASCII encoding. It may be modified by the function. + */ +void iso_1_fileid(char *src); + +/** + * Ensure a given string is a valid ISO level 2 file identifier, modifying it + * if needed. + * Note that version number is not added to the file name + * + * @param src + * The identifier, in ASCII encoding. It may be modified by the function. + */ +void iso_2_fileid(char *src); + #endif /*LIBISO_UTIL_H_*/