|
|
1.1 root 1: /*
2: Hatari - str.c
3:
4: This file is distributed under the GNU Public License, version 2 or at
5: your option any later version. Read the file gpl.txt for details.
6:
7: String functions.
8: */
1.1.1.3 ! root 9: const char Str_fileid[] = "Hatari str.c : " __DATE__ " " __TIME__;
1.1 root 10:
1.1.1.3 ! root 11: #include <stdio.h>
1.1 root 12: #include <ctype.h>
13: #include <stdbool.h>
1.1.1.3 ! root 14: #include <SDL_types.h>
! 15: #include "configuration.h"
1.1 root 16: #include "str.h"
17:
18:
19: /**
20: * Remove whitespace from beginning and end of a string.
21: * Returns the trimmed string (string content is moved
22: * so that it still starts from the same address)
23: */
24: char *Str_Trim(char *buffer)
25: {
26: int i, linelen;
27:
28: if (buffer == NULL)
29: return NULL;
30:
31: linelen = strlen(buffer);
32:
33: for (i = 0; i < linelen; i++)
34: {
35: if (!isspace(buffer[i]))
36: break;
37: }
38:
39: if (i > 0 && i < linelen)
40: {
41: linelen -= i;
42: memmove(buffer, buffer + i, linelen);
43: }
44:
45: for (i = linelen; i > 0; i--)
46: {
47: if (!isspace(buffer[i-1]))
48: break;
49: }
50:
51: buffer[i] = '\0';
52:
53: return buffer;
54: }
55:
56:
57: /**
58: * Convert a string to uppercase in place.
59: */
60: char *Str_ToUpper(char *pString)
61: {
62: char *str = pString;
63: while (*str)
64: {
65: *str = toupper(*str);
66: str++;
67: }
68: return pString;
69: }
70:
71:
72: /**
73: * Convert string to lowercase
74: */
75: char *Str_ToLower(char *pString)
76: {
77: char *str = pString;
78: while (*str)
79: {
80: *str = tolower(*str);
81: str++;
82: }
83: return pString;
84: }
85:
86:
87: /**
88: * truncate string at first unprintable char (e.g. newline)
89: */
90: char *Str_Trunc(char *pString)
91: {
92: int i = 0;
93: char *str = pString;
94: while (str[i] != '\0')
95: {
96: if (!isprint((unsigned)str[i]))
97: {
98: str[i] = '\0';
99: break;
100: }
101: i++;
102: }
103: return pString;
104: }
105:
106:
107: /**
108: * check if string is valid hex number.
109: */
110: bool Str_IsHex(const char *str)
111: {
112: int i = 0;
113: while (str[i] != '\0' && str[i] != ' ')
114: {
115: if (!isxdigit((unsigned)str[i]))
116: return false;
117: i++;
118: }
119: return true;
120: }
1.1.1.3 ! root 121:
! 122:
! 123:
! 124: /**
! 125: * Parse a number assuming it's in the configured default number base
! 126: * unless prefixed. '$' prefix means hexadecimal, '#' decimal, and '%'
! 127: * binary. For range parsing and DebugUI, the value needs to be unsiged.
! 128: * Return true for success and false for error.
! 129: */
! 130: bool Str_GetNumber(const char *value, Uint32 *number)
! 131: {
! 132: const char *str;
! 133: char prefix;
! 134: int i;
! 135:
! 136: if (isxdigit(value[0]))
! 137: {
! 138: switch (ConfigureParams.Log.nNumberBase) {
! 139: case 16:
! 140: prefix = '$';
! 141: break;
! 142: case 2:
! 143: prefix = '%';
! 144: break;
! 145: case 10:
! 146: default:
! 147: prefix = '#';
! 148: break;
! 149: }
! 150: }
! 151: else
! 152: prefix = *value++;
! 153:
! 154: switch (prefix) {
! 155: case '$': /* hexadecimal */
! 156: if (sscanf(value, "%x", number) != 1)
! 157: {
! 158: fprintf(stderr, "Invalid hexadecimal value '%s'!\n", value);
! 159: return false;
! 160: }
! 161: break;
! 162: case '%': /* binary */
! 163: *number = 0;
! 164: for (str = value, i = 0; *str && i < 32; str++, i++)
! 165: {
! 166: *number <<= 1;
! 167: switch (*str) {
! 168: case '0':
! 169: break;
! 170: case '1':
! 171: *number |= 1;
! 172: break;
! 173: default:
! 174: fprintf(stderr, "Invalid binary value '%s'!\n", value);
! 175: return false;
! 176: }
! 177: }
! 178: if (*str || !i)
! 179: {
! 180: fprintf(stderr, "Invalid number of binary digits in '%s'!\n", value);
! 181: return false;
! 182: }
! 183: break;
! 184: case '#':
! 185: default: /* decimal */
! 186: if (sscanf(value, "%u", number) != 1)
! 187: {
! 188: fprintf(stderr, "Invalid decimal value '%s'!\n", value);
! 189: return false;
! 190: }
! 191: }
! 192: return true;
! 193: }
! 194:
! 195:
! 196: /**
! 197: * Get a an adress range, eg. "$fa0000-$fa0100"
! 198: * returns:
! 199: * 0 if OK,
! 200: * -1 if not syntaxically a range,
! 201: * -2 if values are invalid,
! 202: * -3 if syntaxically range, but not value-wise.
! 203: */
! 204: static int getRange(char *str1, Uint32 *lower, Uint32 *upper)
! 205: {
! 206: bool fDash = false;
! 207: char *str2 = str1;
! 208: int ret = 0;
! 209:
! 210: while (*str2)
! 211: {
! 212: if (*str2 == '-')
! 213: {
! 214: *str2++ = '\0';
! 215: fDash = true;
! 216: break;
! 217: }
! 218: str2++;
! 219: }
! 220: if (!fDash)
! 221: return -1;
! 222:
! 223: if (!Str_GetNumber(str1, lower))
! 224: ret = -2;
! 225: else if (!Str_GetNumber(str2, upper))
! 226: ret = -2;
! 227: else if (*lower > *upper)
! 228: ret = -3;
! 229: *--str2 = '-';
! 230: return ret;
! 231: }
! 232:
! 233:
! 234: /**
! 235: * Parse an adress range, eg. "$fa0000[-$fa0100]" + show appropriate warnings
! 236: * returns:
! 237: * -1 if invalid address or range,
! 238: * 0 if single address,
! 239: * +1 if a range.
! 240: */
! 241: int Str_ParseRange(char *str, Uint32 *lower, Uint32 *upper)
! 242: {
! 243: switch (getRange(str, lower, upper))
! 244: {
! 245: case 0:
! 246: return 1;
! 247: case -1:
! 248: /* single address, not a range */
! 249: if (!Str_GetNumber(str, lower))
! 250: return -1;
! 251: return 0;
! 252: case -2:
! 253: fprintf(stderr,"Invalid address values in '%s'!\n", str);
! 254: return -1;
! 255: case -3:
! 256: fprintf(stderr,"Invalid range (%x > %x)!\n", *lower, *upper);
! 257: return -1;
! 258: }
! 259: fprintf(stderr, "INTERNAL ERROR: Unknown getRange() return value.\n");
! 260: return -1;
! 261: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.