String CSSPrimitiveValue::getStringValue() const
{
    switch (m_type) {
        case CSS_STRING:
        case CSS_ATTR:
        case CSS_URI:
        case CSS_PARSER_VARIABLE:
            return m_value.string;
        case CSS_IDENT:
            return valueOrPropertyName(m_value.ident);
        default:
            break;
    }

    return String();
}
String CSSPrimitiveValue::getStringValue(ExceptionCode& ec) const
{
    ec = 0;
    switch (m_type) {
        case CSS_STRING:
        case CSS_ATTR:
        case CSS_URI:
        case CSS_PARSER_VARIABLE:
            return m_value.string;
        case CSS_IDENT:
            return valueOrPropertyName(m_value.ident);
        default:
            ec = INVALID_ACCESS_ERR;
            break;
    }

    return String();
}
CSSParserValue CSSPrimitiveValue::parserValue() const
{
    // We only have to handle a subset of types.
    CSSParserValue value;
    value.id = 0;
    value.isInt = false;
    value.unit = CSSPrimitiveValue::CSS_IDENT;
    switch (m_type) {
        case CSS_NUMBER:
        case CSS_PERCENTAGE:
        case CSS_EMS:
        case CSS_EXS:
        case CSS_PX:
        case CSS_CM:
        case CSS_MM:
        case CSS_IN:
        case CSS_PT:
        case CSS_PC:
        case CSS_DEG:
        case CSS_RAD:
        case CSS_GRAD:
        case CSS_MS:
        case CSS_S:
        case CSS_HZ:
        case CSS_KHZ:
        case CSS_DIMENSION:
            value.fValue = m_value.num;
            value.unit = m_type;
            break;
        case CSS_STRING:
        case CSS_URI:
        case CSS_PARSER_VARIABLE_FUNCTION_SYNTAX:
        case CSS_PARSER_VARIABLE_EQUALS_SYNTAX:
        case CSS_PARSER_VARIABLE_DOLLAR_SYNTAX:
        case CSS_PARSER_HEXCOLOR:
            value.string.characters = const_cast<UChar*>(m_value.string->characters());
            value.string.length = m_value.string->length();
            value.unit = m_type;
            break;
        case CSS_IDENT: {
            value.id = m_value.ident;
            String name = valueOrPropertyName(m_value.ident);
            value.string.characters = const_cast<UChar*>(name.characters());
            value.string.length = name.length();
            break;
        }
        case CSS_PARSER_OPERATOR:
            value.iValue = m_value.ident;
            value.unit = CSSParserValue::Operator;
            break;
        case CSS_PARSER_INTEGER:
            value.fValue = m_value.num;
            value.unit = CSSPrimitiveValue::CSS_NUMBER;
            value.isInt = true;
            break;
        case CSS_UNKNOWN:
        case CSS_ATTR:
        case CSS_COUNTER:
        case CSS_RECT:
        case CSS_RGBCOLOR:
        case CSS_PAIR:
#if ENABLE(DASHBOARD_SUPPORT)
        case CSS_DASHBOARD_REGION:
#endif
            ASSERT_NOT_REACHED();
            break;
    }
    
    return value;
}
String CSSPrimitiveValue::cssText() const
{
    // FIXME: return the original value instead of a generated one (e.g. color
    // name if it was specified) - check what spec says about this
    String text;
    switch (m_type) {
        case CSS_UNKNOWN:
            // FIXME
            break;
        case CSS_NUMBER:
        case CSS_PARSER_INTEGER:
            text = String::number(m_value.num);
            break;
        case CSS_PERCENTAGE:
            text = String::format("%.6lg%%", m_value.num);
            break;
        case CSS_EMS:
            text = String::format("%.6lgem", m_value.num);
            break;
        case CSS_EXS:
            text = String::format("%.6lgex", m_value.num);
            break;
        case CSS_PX:
            text = String::format("%.6lgpx", m_value.num);
            break;
        case CSS_CM:
            text = String::format("%.6lgcm", m_value.num);
            break;
        case CSS_MM:
            text = String::format("%.6lgmm", m_value.num);
            break;
        case CSS_IN:
            text = String::format("%.6lgin", m_value.num);
            break;
        case CSS_PT:
            text = String::format("%.6lgpt", m_value.num);
            break;
        case CSS_PC:
            text = String::format("%.6lgpc", m_value.num);
            break;
        case CSS_DEG:
            text = String::format("%.6lgdeg", m_value.num);
            break;
        case CSS_RAD:
            text = String::format("%.6lgrad", m_value.num);
            break;
        case CSS_GRAD:
            text = String::format("%.6lggrad", m_value.num);
            break;
        case CSS_MS:
            text = String::format("%.6lgms", m_value.num);
            break;
        case CSS_S:
            text = String::format("%.6lgs", m_value.num);
            break;
        case CSS_HZ:
            text = String::format("%.6lghz", m_value.num);
            break;
        case CSS_KHZ:
            text = String::format("%.6lgkhz", m_value.num);
            break;
        case CSS_DIMENSION:
            // FIXME
            break;
        case CSS_STRING:
            text = quoteStringIfNeeded(m_value.string);
            break;
        case CSS_URI:
            text = "url(" + quoteURLIfNeeded(m_value.string) + ")";
            break;
        case CSS_IDENT:
            text = valueOrPropertyName(m_value.ident);
            break;
        case CSS_ATTR:
            // FIXME
            break;
        case CSS_COUNTER:
            text = "counter(";
            text += String::number(m_value.num);
            text += ")";
            // FIXME: Add list-style and separator
            break;
        case CSS_RECT: {
            Rect* rectVal = getRectValue();
            text = "rect(";
            text += rectVal->top()->cssText() + " ";
            text += rectVal->right()->cssText() + " ";
            text += rectVal->bottom()->cssText() + " ";
            text += rectVal->left()->cssText() + ")";
            break;
        }
        case CSS_RGBCOLOR:
        case CSS_PARSER_HEXCOLOR: {
            RGBA32 rgbColor = m_value.rgbcolor;
            if (m_type == CSS_PARSER_HEXCOLOR)
                Color::parseHexColor(m_value.string, rgbColor);
            Color color(rgbColor);
            text = (color.alpha() < 0xFF) ? "rgba(" : "rgb(";
            text += String::number(color.red()) + ", ";
            text += String::number(color.green()) + ", ";
            text += String::number(color.blue());
            if (color.alpha() < 0xFF)
                text += ", " + String::number(static_cast<float>(color.alpha()) / 0xFF);
            text += ")";
            break;
        }
        case CSS_PAIR:
            text = m_value.pair->first()->cssText();
            text += " ";
            text += m_value.pair->second()->cssText();
            break;
#if ENABLE(DASHBOARD_SUPPORT)
        case CSS_DASHBOARD_REGION:
            for (DashboardRegion* region = getDashboardRegionValue(); region; region = region->m_next.get()) {
                if (!text.isEmpty())
                    text.append(' ');
                text += "dashboard-region(";
                text += region->m_label;
                if (region->m_isCircle)
                    text += " circle";
                else if (region->m_isRectangle)
                    text += " rectangle";
                else
                    break;
                if (region->top()->m_type == CSS_IDENT && region->top()->getIdent() == CSSValueInvalid) {
                    ASSERT(region->right()->m_type == CSS_IDENT);
                    ASSERT(region->bottom()->m_type == CSS_IDENT);
                    ASSERT(region->left()->m_type == CSS_IDENT);
                    ASSERT(region->right()->getIdent() == CSSValueInvalid);
                    ASSERT(region->bottom()->getIdent() == CSSValueInvalid);
                    ASSERT(region->left()->getIdent() == CSSValueInvalid);
                } else {
                    text.append(' ');
                    text += region->top()->cssText() + " ";
                    text += region->right()->cssText() + " ";
                    text += region->bottom()->cssText() + " ";
                    text += region->left()->cssText();
                }
                text += ")";
            }
            break;
#endif
        case CSS_PARSER_VARIABLE_FUNCTION_SYNTAX:
            text = "-webkit-var(";
            text += m_value.string;
            text += ")";
            break;
        case CSS_PARSER_VARIABLE_EQUALS_SYNTAX:
            text = "=";
            text += m_value.string;
            text += "=";
            break;
        case CSS_PARSER_VARIABLE_DOLLAR_SYNTAX:
            text = "$";
            text += m_value.string;
            break;
        case CSS_PARSER_OPERATOR:
            char c = static_cast<char>(m_value.ident);
            text = String(&c, 1U);
            break;
    }
    return text;
}