/*---------------------------------------------------------------------------* Project: TwlSDK - tools - defval File: misc.c Copyright 2005-2008 Nintendo. All rights reserved. These coded instructions, statements, and computer programs contain proprietary information of Nintendo of America Inc. and/or Nintendo Company Ltd., and are protected by Federal copyright law. They may not be disclosed to third parties or copied or duplicated in any form, in whole or in part, without the prior written consent of Nintendo. $Date:: 2008-09-17#$ $Rev: 8556 $ $Author: okubata_ryoma $ *---------------------------------------------------------------------------*/ #include "misc.h" /*---------------------------------------------------------------------------* Name: StrDup Description: Error handling version of strdup Arguments: str String to copy Returns: String that was copied *---------------------------------------------------------------------------*/ char *StrDup(const char *str) { char *cp; if (NULL == (cp = strdup(str ? str : ""))) { fprintf(stderr, "Error: No memory."); exit(2); } return cp; } /*---------------------------------------------------------------------------* Name: StrNDup Description: Error-handling version of strdup with character length specification. Arguments: str String to copy len String to copy (Not including '\0') Returns: String that was copied *---------------------------------------------------------------------------*/ char *StrNDup(const char *str, int len) { char *cp; cp = Calloc(len + 1); if (str && len) (void)strncpy(cp, str, len); return cp; // Area having len+1 bytes was allocated with malloc, so there is no need to add '\0' after strncpy. // // Can also support cases where str is NULL } /*---------------------------------------------------------------------------* Name: StrCatDup Description: Allocates room for a concatenated string from the heap area. Arguments: str1 String 1 (When str1 == NULL, treated as "") str2 String 2 (When str2 == NULL, treated as "") Returns: Concatenated string *---------------------------------------------------------------------------*/ char *StrCatDup(const char *str1, const char *str2) { int len1, len2; char *cp; len1 = str1 ? strlen(str1) : 0; len2 = str2 ? strlen(str2) : 0; cp = Calloc(len1 + len2 + 1); if (str1) (void)strcpy(cp, str1); if (str2) (void)strcat(cp, str2); return cp; } /*---------------------------------------------------------------------------* Name: Calloc Description: Error-handling version of calloc (only one argument) Arguments: size Length of area to allocate Returns: Allocated area *---------------------------------------------------------------------------*/ void *Calloc(int size) { void *cp; if (NULL == (cp = calloc(1, size))) { fprintf(stderr, "Error: No memory."); exit(2); } return cp; } /*---------------------------------------------------------------------------* Name: Free Description: NULL-handling version of free Variable *ptr is cleared to NULL Arguments: ptr Area to free Returns: None. *---------------------------------------------------------------------------*/ void Free(void **ptr) { if (NULL != *ptr) { free(*ptr); *ptr = NULL; } return; } /*---------------------------------------------------------------------------* Name: Realloc Description: Error-handling version of realloc Arguments: buffer Original size size Length of area to allocate Returns: Allocated area *---------------------------------------------------------------------------*/ void *Realloc(void *buffer, int size) { void *cp; cp = Calloc(size); if (buffer) { strcpy(cp, buffer); free(buffer); } return cp; } /*---------------------------------------------------------------------------* Name: Fopen Description: Version of fopen with stdin/stdout taken into account. If '-' is specified and also access mode is 'r', set to stdin. If the access mode is 'w', set to stdout. Arguments: name (Pointer to) the pointer to the file buffer mode (Pointer to) the file buffer size Returns: fp File pointer *---------------------------------------------------------------------------*/ FILE *Fopen(const char *filename, const char *mode) { FILE *fp; DebugPrintf("filename=[%s] mode=[%s]\n", filename, mode); if ('-' == filename[0] && '\0' == filename[1]) { fp = (mode[0] == 'r') ? stdin : stdout; } else { if (NULL == (fp = fopen(filename, mode))) { fprintf(stderr, "Error: cannot open %s\n", filename); return NULL; } } DebugPrintf("fp=[%x] stdin=[%x] stdout=[%x]\n", fp, stdin, stdout); return fp; } /*---------------------------------------------------------------------------* Name: Fclose Description: Version of fclose with stdin/stdout taken into account. If NULL, stdin, stdout or stderr, does not close Arguments: fp File pointer Returns: None. *---------------------------------------------------------------------------*/ void Fclose(FILE * fp) { if (fp != NULL && fp != stdin && fp != stdout && fp != stderr) { fclose(fp); } return; } /*---------------------------------------------------------------------------* Name: Fgets Description: Reads the file one line at a time. Unlike the normal fgets, uses dynamic control of the buffer size to precisely read just one line. Arguments: *buffer (Pointer to) the pointer to the file buffer *size (Pointer to) the file buffer size fp The file (If =NULL, reads from stdin) 'buffer' and 'size' are realloc'ed as necessary inside Fgets. Passing 'size' as an argument reuses 'buffer' so that alloc/free processing is reduced. It is expected that the first call will be to set *buffer to NULL. Returns: If successful, returns *buffer. If it fails at the end of file, etc., returns NULL. *---------------------------------------------------------------------------*/ char *Fgets(char **pbuffer, int *pbuffer_size, FILE * fp) { char *buffer; int buffer_size; int buffer_gets; assert(pbuffer); assert(pbuffer_size); buffer = *pbuffer; buffer_size = *pbuffer_size; if (buffer == NULL || buffer_size == 0) { buffer_size = DEFAULT_LINE_BUFFER_SIZE; buffer = Calloc(buffer_size); } buffer_gets = 0; while (NULL != fgets(buffer + buffer_gets, buffer_size - buffer_gets, fp)) { // // If the loaded line reaches the line-end, register the definition value // In loading done by fgets, the end of a line is determined when: // 1) Data could not be loaded up to the very end of the buffer area; // 2) Data could be loaded fully, but the line ends exactly at that location. // buffer_gets = strlen(buffer); if (buffer_gets < buffer_size - 1 || buffer[buffer_gets - 1] == '\n') { *pbuffer = buffer; *pbuffer_size = buffer_size; return buffer; } // // If the loaded line does not reach the end of the line, double the buffer size, and continue reading. // // else { buffer_size *= 2; buffer = Realloc(buffer, buffer_size); } } // Processing at the end of file free(*pbuffer); *pbuffer = NULL; *pbuffer_size = 0; return NULL; } /*---------------------------------------------------------------------------* Name: UnpackFileName Description: Analyzes the file name and divides it into parts: (directory, file base name, file extension) Arguments: path Full path name dir Directory (Including '/' etc.) base File's base name ext File extension (including '.') * * Because dir, base, and ext are allocated from the heap, they must be freed * * When dir, base or ext is NULL, no value is assigned Returns: None. *---------------------------------------------------------------------------*/ void UnpackFileName(const char *path, char **dir, char **base, char **ext) { int i, base_top, ext_top; int path_len = strlen(path); // Search for the position of the final '.' and the path delimiters ext_top = path_len; base_top = 0; for (i = path_len - 1; i >= 0; i--) { if (path[i] == '.' && ext_top == path_len) { ext_top = i; } if (path[i] == '/' || path[i] == '\\' || path[i] == ':') { base_top = i + 1; break; } } // Processing of "." and ".." (In this case, the base is "." or "..", with no extension) if (!strcmp(path + base_top, ".") || !strcmp(path + base_top, "..")) { ext_top = path_len; } // Assign if (dir) *dir = StrNDup(path, base_top); if (base) *base = StrNDup(path + base_top, ext_top - base_top); if (ext) *ext = StrDup(path + ext_top); return; } /*---------------------------------------------------------------------------* Name: SetDebugMode Description: Sets debug mode. Arguments: mode The mode Returns: None. *---------------------------------------------------------------------------*/ static BOOL sDebugMode = FALSE; void SetDebugMode(BOOL mode) { sDebugMode = mode; } /*---------------------------------------------------------------------------* Name: DebugPrintf Description: Debug print Arguments: fmt Printf format ... Variables to print Returns: None. *---------------------------------------------------------------------------*/ void DebugPrintf(const char *fmt, ...) { va_list va; if (sDebugMode) { va_start(va, fmt); vfprintf(stderr, fmt, va); va_end(va); } }