Esempio n. 1
0
int
parsePrintfFormat( const char **fmt_p, struct printf_fmt_info *info )
{
	if( ! **fmt_p ) {
		return FALSE;
	}

		/* find the first '%' character */
	while( **fmt_p && **fmt_p != '%' ) {
		(*fmt_p)++;
	}
		/* end of string */
	if( ! **fmt_p) {
		return FALSE;
	}
		/* now skip the '%' itself */
	(*fmt_p)++;
	if( ! **fmt_p ) {
		return FALSE;
	}

		/* clear out the struct we were passed */
	if( ! info ) {
		return FALSE;
	}
	memset( info, '\0', sizeof(struct printf_fmt_info) );

		/* First, look for modifying flags */
	while( **fmt_p && isFlagChar(**fmt_p) ) {
		switch( **fmt_p ) {
		case '#':
				/* The value should be converted to an "alternate form" */
			info->is_alt = 1;
			break;

		case '0':
				/* The value should be zero padded */
			info->is_pad = 1;
			break;

		case '-':
				/* The converted value is to be left adjusted */
			info->is_left = 1;
			break;

		case ' ':
				/* A blank should be left before a positive number */
			info->is_space = 1;
			break;

		case '+':
				/* A sign (+ or -) always placed before a number */
			info->is_signed = 1;
			break;

		case '\'':
				/* Show grouping in numbers if the locale information
				   indicates any.  */
			info->is_grouped = 1;
			break;
		}
		(*fmt_p)++;
	}
		

		/* Now, find the width, if any */
	if( **fmt_p == '*' ) {
			/* Width is given in an argument, we don't support this yet */
    } else if( isdigit(**fmt_p) ) {
			/* Width is a constant */
		info->width = consumeInt( fmt_p );
	}
	if( ! **fmt_p ) {
		return FALSE;
	}

		/* Next, find the precision, if any.  storing a negative value
		   means nothing was specified, a 0 is if the format really
		   says 0 */
	info->precision = -1;
	if( **fmt_p == '.') {
			/* found a precision.  first, skip past the '.' */
		(*fmt_p)++;
		if( ! **fmt_p ) {
			return FALSE;
		}
		if( **fmt_p == '*') {
				/* Precision is set as is an argument, we don't
				   support this yet, either.  */
		} else if( isdigit(**fmt_p) ) {
			info->precision = consumeInt( fmt_p );
		}
    }
	if( ! **fmt_p ) {
		return FALSE;
	}

		/* Next come the optional length modifiers  */
	while( **fmt_p && isLengthChar(**fmt_p) ) {
		switch( **fmt_p ) {
		case 'h':
				/* integer conversions are short int's */
			info->is_short = 1;
			break;

		case 'l':
			if( info->is_long ) {
					/* 'll' means long long */
				info->is_long_long = 1;
			} else {
					/* 'l' just means long int */
				info->is_long = 1;
			}
			break;

		case 'L':
				/* float conversion is a long double */
			info->is_long_double = 1;
			break;

		case 'q':
				/* "quad-precision", treat as long long */
			info->is_long_long = 1;
			break;

		case 'j':
		case 'z':
		case 't':
				/* we recognize these, but don't really do anything
				   with them yet */
			break;
		}
		(*fmt_p)++;
	}
	if( ! **fmt_p ) {
		return FALSE;
	}

		/* FINALLY, get the type of conversion for this format string! */
	info->fmt_letter = **fmt_p;

		/* since we consumed it, we should advance our pointer */
	(*fmt_p)++;
	
		/* Now that we have the conversion character, set our type */
	switch( info->fmt_letter ) {

			/* Standard types */
	case 'd':
	case 'i':
	case 'o':
	case 'u':
	case 'x':
	case 'X':
		info->type = PFT_INT;
		break;

	case 'e':
	case 'E':
	case 'f':
	case 'F':
	case 'g':
	case 'G':
	case 'a':
	case 'A':
		info->type = PFT_FLOAT;
		break;

	case 'c':
		info->type = PFT_CHAR;
		break;

	case 's':
		info->type = PFT_STRING;
		break;


			/* Some weird special cases mentioned in the man page */
    case 'p':
		info->type = PFT_POINTER;
		break;

    case 'n':
			/* don't really support this, but treat like an int */
		info->type = PFT_INT;
		break;

    case 'C':
		info->type = PFT_CHAR;
		info->is_long = 1;
		break;

    case 'S':
		info->type = PFT_STRING;
		info->is_long = 1;
		break;
		
    case 'V':
    case 'v':
		info->type = PFT_VALUE;
		break;

    case '%':
			/* literal '%' char!  in this case, we just want to
			   recursively call ourselves and keep parsing, since we
			   want to treat this like any other string literal we'd
			   skip over.  we've already moved the fmt_p, and we'll
			   re-initialize the info struct... */
		return parsePrintfFormat( fmt_p, info );
		break;

    default:
      /* An unknown conversion char!  */
		info->type = PFT_NONE;
		return FALSE;
		break;
    }
	return TRUE;
}
Esempio n. 2
0
void CFormat::SetCurrentField(const wxString& value)
{
	wxCHECK_RET(m_fieldStart < m_format.Length(),
		wxT("Setting field in already completed string: ") + m_format);

	if (value.Length()) {
		m_result += value;
	}

	enum {
		PosNone = 0,
		PosStart,
		PosFlags,
		PosWidth,
		PosPrecision,
		PosLength,
		PosEnd
	} pos = PosNone;

	// Format strings are expected to follow the folllowing structure:
	// 	%[Flags][Width][.Precision][Length]<Type>
	for (size_t i = m_fieldStart + m_fieldLength; i < m_format.Length(); ++i) {
		const wxChar c = m_format[i];

		if (pos >= PosStart) {
			m_fieldLength++;

			if ((pos <= PosFlags) && isFlagChar(c)) {
				pos = PosFlags;
			} else if ((pos <= PosWidth) && isIntChar(c)) {
				pos = PosWidth;
			} else if ((pos < PosPrecision) && (c == wxT('.'))) {
				pos = PosPrecision;
			} else if ((pos == PosPrecision) && isIntChar(c)) {
				// Nothing to do ...
			} else if ((pos < PosLength) && isLengthChar(c)) {
				pos = PosLength;
			} else if ((pos == PosLength) && isLengthChar(c) && (c == m_format[i - 1])) {
				// Nothing to do ...
			} else if ((pos <= PosLength) && isTypeChar(c)) {
				pos = PosEnd;
				break;
			} else if ((pos <= PosLength) && (c == wxT('%'))) {
				// Append the %*% to the result
				m_result += wxT("%");
				
				pos = PosNone;
			} else {
				// Field is broken ...
				break;
			}
		} else if (c == wxT('%')) {
			const size_t offset = m_fieldStart + m_fieldLength;
			// If there was anything before this, then prepend it.
			if (offset < i) {
				m_result += m_format.Mid(offset, i - offset);
			}

			// Starting a new format string
			pos = PosStart;
			m_fieldStart = i;
			m_fieldLength = 1;
		} else {
			// Normal text, nothing to do ...
		}
	}

	if (pos == PosNone) {
		// No fields left
		m_result += m_format.Mid(m_fieldStart + m_fieldLength);
		
		m_fieldStart = m_fieldLength = m_format.Length();
	} else if (pos != PosEnd) {
		// A partial field was found ...
		wxFAIL_MSG(wxT("Invalid field in format string: ") + m_format);
		wxASSERT_MSG(m_fieldStart + m_fieldLength <= m_format.Length(),
			wxT("Invalid field-start/length in format string: ") + m_format);

		// Prepend the parsed part of the format-string
		m_result += m_format.Mid(m_fieldStart, m_fieldLength);

		// Return an empty string the next time GetCurrentField is called
		m_skipCount++;

		// Anything left to do?
		if (!IsReady()) {
			// Find the next format string
			SetCurrentField(wxEmptyString);
		}
	}
}