Ticket #2589: no-cparser-GUI.diff

File no-cparser-GUI.diff, 15.3 KB (added by Josh, 10 years ago)

A start at replacing cparser in the GUI code.

  • source/gui/GUIbase.cpp

     
    1 /* Copyright (C) 2009 Wildfire Games.
     1/* Copyright (C) 2014 Wildfire Games.
    22 * This file is part of 0 A.D.
    33 *
    44 * 0 A.D. is free software: you can redistribute it and/or modify
     
    2121
    2222#include "precompiled.h"
    2323
    24 #include <string>
    25 
     24#include "ps/CLogger.h"
    2625#include "GUI.h"
    2726
    2827//--------------------------------------------------------
     
    6261
    6362bool CClientArea::SetClientArea(const CStr& Value)
    6463{
    65     // This might lack incredible speed, but since all XML files
    66     //  are read at startup, reading 100 client areas will be
    67     //  negligible in the loading time.
     64    /* ClientAreas contain a left, top, right, and bottom
     65     *  for example: "50%-150 10%+9 50%+150 10%+25" means
     66     *  the left edge is at 50% minus 150 pixels, the top
     67     *  edge is at 10% plus 9 pixels, the right edge is at
     68     *  50% plus 150 pixels, and the bottom edge is at 10%
     69     *  plus 25 pixels.
     70     * All four coordinates are required and can be
     71     *  defined only in pixels, only in percents, or some
     72     *  combination of both.
     73     */
    6874
    69     // Setup parser to parse the value
    70 
    71     // One of the four values:
    72     //  will give outputs like (in argument):
    73     //  (200) <== no percent, just the first $value
    74     //  (200) (percent) <== just the percent
    75     //  (200) (percent) (100) <== percent PLUS pixel
    76     //  (200) (percent) (-100) <== percent MINUS pixel
    77     //  (200) (percent) (100) (-100) <== Both PLUS and MINUS are used, INVALID
    78     /*
    79     string one_value = "_[-_$arg(_minus)]$value[$arg(percent)%_[+_$value]_[-_$arg(_minus)$value]_]";
    80     string four_values = one_value + "$arg(delim)" +
    81                          one_value + "$arg(delim)" +
    82                          one_value + "$arg(delim)" +
    83                          one_value + "$arg(delim)_"; // it's easier to just end with another delimiter
    84     */
    85     // Don't use the above strings, because they make this code go very slowly
    86     const char* four_values =
    87         "_[-_$arg(_minus)]$value[$arg(percent)%_[+_$value]_[-_$arg(_minus)$value]_]" "$arg(delim)"
    88         "_[-_$arg(_minus)]$value[$arg(percent)%_[+_$value]_[-_$arg(_minus)$value]_]" "$arg(delim)"
    89         "_[-_$arg(_minus)]$value[$arg(percent)%_[+_$value]_[-_$arg(_minus)$value]_]" "$arg(delim)"
    90         "_[-_$arg(_minus)]$value[$arg(percent)%_[+_$value]_[-_$arg(_minus)$value]_]" "$arg(delim)"
    91         "_";
    92     CParser& parser (CParserCache::Get(four_values));
    93 
    94     CParserLine line;
    95     line.ParseString(parser, Value);
    96 
    97     if (!line.m_ParseOK)
    98         return false;
    99 
    100     int arg_count[4] = {0,0,0,0}; // argument counts for the four values
    101     int arg_start[4] = {0,0,0,0}; // location of first argument, [0] is always 0
    102 
    103     // Divide into the four piles (delimiter is an argument named "delim")
    104     for (int i=0, valuenr=0; i<(int)line.GetArgCount(); ++i)
     75    // Check the input is only numeric
     76    const char* input = Value.c_str();
     77    CStr buffer = "";
     78    unsigned int coord = 0;
     79    float pixels[4] = {0, 0, 0, 0};
     80    float percents[4] = {0, 0, 0, 0};
     81    for (unsigned int i = 0; i < Value.length(); i++)
    10582    {
    106         std::string str;
    107         line.GetArgString(i, str);
    108         if (str == "delim")
     83        switch (input[i])
    10984        {
    110             if (valuenr==0)
    111             {
    112                 arg_count[0] = i;
    113                 arg_start[1] = i+1;
    114             }
    115             else
    116             {
    117                 if (valuenr!=3)
    118                 {
    119                     ENSURE(valuenr <= 2);
    120                     arg_start[valuenr+1] = i+1;
    121                     arg_count[valuenr] = arg_start[valuenr+1] - arg_start[valuenr] - 1;
    122                 }
    123                 else
    124                     arg_count[3] = (int)line.GetArgCount() - arg_start[valuenr] - 1;
    125             }
    126 
    127             ++valuenr;
     85        case '.':
     86        case '0':
     87        case '1':
     88        case '2':
     89        case '3':
     90        case '4':
     91        case '5':
     92        case '6':
     93        case '7':
     94        case '8':
     95        case '9':
     96            buffer.push_back(input[i]);
     97            break;
     98        case '+':
     99            pixels[coord] += buffer.ToFloat();
     100            buffer = "+";
     101            break;
     102        case '-':
     103            pixels[coord] += buffer.ToFloat();
     104            buffer = "-";
     105            break;
     106        case '%':
     107            percents[coord] += buffer.ToFloat();
     108            buffer = "";
     109            break;
     110        case ' ':
     111            pixels[coord] += buffer.ToFloat();
     112            buffer = "";
     113            coord++;
     114            break;
     115        default:
     116            LOGWARNING(L"ClientArea definitions may only contain numerics. Your input: '%s'", Value.c_str());
     117            return false;
    128118        }
     119        if (coord > 3)
     120        {
     121            LOGWARNING(L"Too many CClientArea parameters (4 max). Your input: '%s'", Value.c_str());
     122            return false;
     123        }
    129124    }
    130125
    131     // Iterate argument
    132    
    133     // This is the scheme:
    134     // 1 argument = Just pixel value
    135     // 2 arguments = Just percent value
    136     // 3 arguments = percent and pixel
    137     // 4 arguments = INVALID
    138 
    139     // Default to 0
    140     float values[4][2] = {{0.f,0.f},{0.f,0.f},{0.f,0.f},{0.f,0.f}};
    141     for (int v=0; v<4; ++v)
     126    if (coord < 3)
    142127    {
    143         if (arg_count[v] == 1)
    144         {
    145             std::string str;
    146             line.GetArgString(arg_start[v], str);
     128        LOGWARNING(L"Too few CClientArea parameters (4 min). Your input: '%s'", Value.c_str());
     129        return false;
     130    }
    147131
    148             if (!line.GetArgFloat(arg_start[v], values[v][1]))
    149                 return false;
    150         }
    151         else
    152         if (arg_count[v] == 2)
    153         {
    154             if (!line.GetArgFloat(arg_start[v], values[v][0]))
    155                 return false;
    156         }
    157         else
    158         if (arg_count[v] == 3)
    159         {
    160             if (!line.GetArgFloat(arg_start[v], values[v][0]) ||
    161                 !line.GetArgFloat(arg_start[v]+2, values[v][1]))
    162                 return false;
     132    // Now that we're at the end of the string, flush the remaining buffer.
     133    pixels[coord] += buffer.ToFloat();
    163134
    164         }
    165         else return false;
    166     }
    167 
    168     // Now store the values[][] in the right place
    169     pixel.left =        values[0][1];
    170     pixel.top =         values[1][1];
    171     pixel.right =       values[2][1];
    172     pixel.bottom =      values[3][1];
    173     percent.left =      values[0][0];
    174     percent.top =       values[1][0];
    175     percent.right =     values[2][0];
    176     percent.bottom =    values[3][0];
     135    // Now store the coords in the right place
     136    pixel.left =        pixels[0];
     137    pixel.top =         pixels[1];
     138    pixel.right =       pixels[2];
     139    pixel.bottom =      pixels[3];
     140    percent.left =      percents[0];
     141    percent.top =       percents[1];
     142    percent.right =     percents[2];
     143    percent.bottom =    percents[3];
    177144    return true;
    178145}
    179146
  • source/gui/GUIutil.cpp

     
    1 /* Copyright (C) 2012 Wildfire Games.
     1/* Copyright (C) 2014 Wildfire Games.
    22 * This file is part of 0 A.D.
    33 *
    44 * 0 A.D. is free software: you can redistribute it and/or modify
     
    2323#include "GUI.h"
    2424#include "GUIManager.h"
    2525#include "maths/Matrix3D.h"
    26 #include "ps/Parser.h"
    2726
    2827extern int g_xres, g_yres;
    2928
     
    6160template <>
    6261bool __ParseString<CRect>(const CStrW& Value, CRect &Output)
    6362{
    64     // Use the parser to parse the values
    65     CParser& parser (CParserCache::Get("_$value_$value_$value_$value_"));
    66 
    67     CParserLine line;
    68     line.ParseString(parser, Value.ToUTF8());
    69     if (!line.m_ParseOK)
     63    const unsigned int NUM_COORDS = 4;
     64    float coords[NUM_COORDS];
     65    std::wstringstream stream;
     66    stream.str(Value);
     67    // Parse each coordinate
     68    for (unsigned int i = 0; i < NUM_COORDS; i++)
    7069    {
    71         // Parsing failed
    72         return false;
    73     }
    74     float values[4];
    75     for (int i=0; i<4; ++i)
    76     {
    77         if (!line.GetArgFloat(i, values[i]))
     70        if (stream.eof())
    7871        {
    79             // Parsing failed
     72            LOGWARNING(L"Too few CRect parameters (min %i). Your input: '%s'", NUM_COORDS, Value.ToUTF8().c_str());
    8073            return false;
    8174        }
     75        stream >> coords[i];
     76        if ((stream.rdstate() & std::wstringstream::failbit) != 0)
     77        {
     78            LOGWARNING(L"Unable to parse CRect parameters. Your input: '%s'", Value.ToUTF8().c_str());
     79            return false;
     80        }
    8281    }
    8382
     83    if (!stream.eof())
     84    {
     85        LOGWARNING(L"Too many CRect parameters (max %i). Your input: '%s'", NUM_COORDS, Value.ToUTF8().c_str());
     86        return false;
     87    }
     88
    8489    // Finally the rectangle values
    85     Output = CRect(values[0], values[1], values[2], values[3]);
     90    Output = CRect(coords[0], coords[1], coords[2], coords[3]);
     91
    8692    return true;
    8793}
    8894
     
    119125template <>
    120126bool __ParseString<CSize>(const CStrW& Value, CSize &Output)
    121127{
    122     // Use the parser to parse the values
    123     CParser& parser (CParserCache::Get("_$value_$value_"));
    124 
    125     CParserLine line;
    126     line.ParseString(parser, Value.ToUTF8());
    127     if (!line.m_ParseOK)
     128    const unsigned int NUM_COORDS = 2;
     129    float coords[NUM_COORDS];
     130    std::wstringstream stream;
     131    stream.str(Value);
     132    // Parse each coordinate
     133    for (unsigned int i = 0; i < NUM_COORDS; i++)
    128134    {
    129         // Parsing failed
    130         return false;
     135        if (stream.eof())
     136        {
     137            LOGWARNING(L"Too few CSize parameters (min %i). Your input: '%s'", NUM_COORDS, Value.ToUTF8().c_str());
     138            return false;
     139        }
     140        stream >> coords[i];
     141        if ((stream.rdstate() & std::wstringstream::failbit) != 0)
     142        {
     143            LOGWARNING(L"Unable to parse CSize parameters. Your input: '%s'", Value.ToUTF8().c_str());
     144            return false;
     145        }
    131146    }
    132147
    133     float x, y;
     148    Output.cx = coords[0];
     149    Output.cy = coords[1];
    134150
    135     // x
    136     if (!line.GetArgFloat(0, x))
     151    if (!stream.eof())
    137152    {
    138         // TODO Gee: Parsing failed
     153        LOGWARNING(L"Too many CSize parameters (max %i). Your input: '%s'", NUM_COORDS, Value.ToUTF8().c_str());
    139154        return false;
    140155    }
    141156
    142     // y
    143     if (!line.GetArgFloat(1, y))
    144     {
    145         // TODO Gee: Parsing failed
    146         return false;
    147     }
    148 
    149     Output.cx = x;
    150     Output.cy = y;
    151    
    152157    return true;
    153158}
    154159
     
    155160template <>
    156161bool __ParseString<CPos>(const CStrW& Value, CPos &Output)
    157162{
    158     CParser& parser (CParserCache::Get("_[-$arg(_minus)]$value_[-$arg(_minus)]$value_"));
     163    const unsigned int NUM_COORDS = 2;
     164    float coords[NUM_COORDS];
     165    std::wstringstream stream;
     166    stream.str(Value);
     167    // Parse each coordinate
     168    for (unsigned int i = 0; i < NUM_COORDS; i++)
     169    {
     170        if (stream.eof())
     171        {
     172            LOGWARNING(L"Too few CPos parameters (min %i). Your input: '%s'", NUM_COORDS, Value.ToUTF8().c_str());
     173            return false;
     174        }
     175        stream >> coords[i];
     176        if ((stream.rdstate() & std::wstringstream::failbit) != 0)
     177        {
     178            LOGWARNING(L"Unable to parse CPos parameters. Your input: '%s'", Value.ToUTF8().c_str());
     179            return false;
     180        }
     181    }
    159182
    160     CParserLine line;
    161     line.ParseString(parser, Value.ToUTF8());
    162     if (!line.m_ParseOK)
    163         return false;
     183    Output.x = coords[0];
     184    Output.y = coords[1];
    164185
    165     float x, y;
    166     if (!line.GetArgFloat(0, x))
     186    if (!stream.eof())
     187    {
     188        LOGWARNING(L"Too many CPos parameters (max %i). Your input: '%s'", NUM_COORDS, Value.ToUTF8().c_str());
    167189        return false;
    168     if (!line.GetArgFloat(1, y))
    169         return false;
     190    }
    170191
    171     Output.x = x;
    172     Output.y = y;
    173 
    174192    return true;
    175193}
    176194
  • source/gui/GUIutil.h

     
    3737//  Includes / Compiler directives
    3838//--------------------------------------------------------
    3939#include "GUIbase.h"
    40 #include "ps/Parser.h"
    4140// TODO Gee: New
    4241#include "ps/Overlay.h"
    4342#include "CGUI.h"
  • source/gui/IGUIObject.cpp

     
    2222#include "precompiled.h"
    2323#include "GUI.h"
    2424
    25 #include "ps/Parser.h"
    26 
    2725#include "gui/scripting/JSInterface_IGUIObject.h"
    2826#include "gui/scripting/JSInterface_GUITypes.h"
    2927#include "scriptinterface/ScriptInterface.h"
  • source/gui/tests/test_ParseString.h

     
    1 /* Copyright (C) 2013 Wildfire Games.
     1/* Copyright (C) 2014 Wildfire Games.
    22 * This file is part of 0 A.D.
    33 *
    44 * 0 A.D. is free software: you can redistribute it and/or modify
     
    1818#include "lib/self_test.h"
    1919
    2020#include "gui/GUIbase.h"
     21#include "gui/GUIutil.h"
     22#include "ps/CLogger.h"
    2123
    2224class TestGuiParseString : public CxxTest::TestSuite
    2325{
     
    2426public:
    2527    void test_clientarea()
    2628    {
     29        TestLogger nolog;
    2730        CClientArea ca;
    28         TS_ASSERT(ca.SetClientArea("0 1 2 3"));
    29         TS_ASSERT_EQUALS(ca, CClientArea(CRect(0, 1, 2, 3), CRect(0, 0, 0, 0)));
    3031
    31         TS_ASSERT(ca.SetClientArea("5% 10%+1 20%-2 3"));
    32         TS_ASSERT_EQUALS(ca, CClientArea(CRect(0, 1, -2, 3), CRect(5, 10, 20, 0)));
     32        // Test only pixels
     33        TS_ASSERT(ca.SetClientArea("0.0 -10 20.0 -30"));
     34        TS_ASSERT_EQUALS(ca, CClientArea(CRect(0, -10, 20, -30), CRect(0, 0, 0, 0)));
    3335
    34         TS_ASSERT(!ca.SetClientArea("0+5% 1 2 3"));
     36        // Test only pixels, but with math
     37        TS_ASSERT(ca.SetClientArea("0 -100-10+100 20+200-200 -30"));
     38        TS_ASSERT_EQUALS(ca, CClientArea(CRect(0, -10, 20, -30), CRect(0, 0, 0, 0)));
    3539
    36         TS_ASSERT(!ca.SetClientArea("5%+10-10 1 2 3"));
     40        // Test only percent
     41        TS_ASSERT(ca.SetClientArea("-5% 10.0% -20% 30.0%"));
     42        TS_ASSERT_EQUALS(ca, CClientArea(CRect(0, 0, 0, 0), CRect(-5, 10, -20, 30)));
    3743
    38         TS_ASSERT(ca.SetClientArea("5% 10%-1 -20%-2 3"));
    39         TS_ASSERT_EQUALS(ca, CClientArea(CRect(0, -1, -2, 3), CRect(5, 10, -20, 0)));
     44        // Test only percent, but with math
     45        TS_ASSERT(ca.SetClientArea("15%-5%-15% 10% -20% 30%+500%-500%"));
     46        TS_ASSERT_EQUALS(ca, CClientArea(CRect(0, 0, 0, 0), CRect(-5, 10, -20, 30)));
    4047
    41         TS_ASSERT(!ca.SetClientArea("5% 10%+1 -20%-2 3")); // parser bug
     48        // Test mixed
     49        TS_ASSERT(ca.SetClientArea("5% -10 -20% 30"));
     50        TS_ASSERT_EQUALS(ca, CClientArea(CRect(0, -10, 0, 30), CRect(5, 0, -20, 0)));
     51
     52        // Test mixed with math
     53        TS_ASSERT(ca.SetClientArea("5%+10%-10% 30%-10-30% 50-20%-50 30-100+100"));
     54        TS_ASSERT_EQUALS(ca, CClientArea(CRect(0, -10, 0, 30), CRect(5, 0, -20, 0)));
     55
     56        // Test for fail with too many/few parameters
     57        TS_ASSERT(!ca.SetClientArea("10 20 30 40 50"));
     58        TS_ASSERT(!ca.SetClientArea("10 20 30"));
     59
     60        // Test for fail with garbage data
     61        TS_ASSERT(!ca.SetClientArea("Hello world!"));
     62        TS_ASSERT(!ca.SetClientArea("abc 123 xyz 789"));
     63        TS_ASSERT(!ca.SetClientArea("300 wide, 400 high"));
    4264    }
     65
     66    void test_rect()
     67    {
     68        TestLogger nolog;
     69        CRect test;
     70
     71        TS_ASSERT(__ParseString(CStrW(L"0.0 10.0 20.0 30.0"), test));
     72        TS_ASSERT_EQUALS(CRect(0.0, 10.0, 20.0, 30.0), test);
     73
     74        TS_ASSERT(!__ParseString(CStrW(L"0 10 20"), test));
     75        TS_ASSERT(!__ParseString(CStrW(L"0 10 20 30 40"), test));
     76        TS_ASSERT(!__ParseString(CStrW(L"0,0 10,0 20,0 30,0"), test));
     77    }
     78
     79    void test_size()
     80    {
     81        TestLogger nolog;
     82        CSize test;
     83
     84        TS_ASSERT(__ParseString(CStrW(L"0.0 10.0"), test));
     85        TS_ASSERT_EQUALS(CSize(0.0, 10.0), test);
     86
     87        TS_ASSERT(!__ParseString(CStrW(L"0"), test));
     88        TS_ASSERT(!__ParseString(CStrW(L"0 10 20"), test));
     89        TS_ASSERT(!__ParseString(CStrW(L"0,0 10,0"), test));
     90    }
     91
     92    void test_pos()
     93    {
     94        TestLogger nolog;
     95        CPos test;
     96
     97        TS_ASSERT(__ParseString(CStrW(L"0.0 10.0"), test));
     98        TS_ASSERT_EQUALS(CPos(0.0, 10.0), test);
     99
     100        TS_ASSERT(!__ParseString(CStrW(L"0"), test));
     101        TS_ASSERT(!__ParseString(CStrW(L"0 10 20"), test));
     102        TS_ASSERT(!__ParseString(CStrW(L"0,0 10,0"), test));
     103    }
    43104};
  • binaries/data/mods/public/gui/session/session.xml

     
    532532        </object>
    533533
    534534        <object name="tradeStatistics" size="20 90 100%-20 168">
    535             <object name="landTraders" size="0 0   100% 50%" type="text" style="ModernLabelText" text_align="left" ghost="true" />
     535            <object name="landTraders" size="0 0 100% 50%" type="text" style="ModernLabelText" text_align="left" ghost="true" />
    536536            <object name="shipTraders" size="0 50% 100% 100%" type="text" style="ModernLabelText" text_align="left" ghost="true" />
    537537        </object>
    538538