ParseDataSource.cpp

// ParseDataSource.cpp
//
// Author David Barrett-Lennard
// (C)opyright Cedanet Pty Ltd 2009

@import "Ceda/cxCedaScript/cxCedaScript.h"
@import "Ceda/cxPersistStore/pref.h"
@import "Ceda/cxPersistStore/IPrefVisitor.h"
@import "Ceda/cxPersistStore/xmap.h"
@import "Ceda/cxObject/Object.h"
@import "Ceda/cxObject/IObjectVisitor.h"
@import "Ceda/cxObject/WCSpace.h"
@import "Ceda/cxObject/PrintReflectedVariable.h"
#include "Ceda/cxUtils/Tracer.h"
#include <assert.h>

///////////////////////////////////////////////////////////////////////////////////////////////////
// ParseDataSource1

namespace ParseDataSource1
{
    $model+ Point
    {
        ceda::float32 x;
        ceda::float32 y;
    };
}

namespace ceda
{
    mImplement_xmap(true,true,false,ceda::string16,ParseDataSource1::Point,false,false)
}

namespace ParseDataSource1
{
    $struct+ X isa ceda::IPersistable :
        model
        {
            ceda::int32 x1;
            ceda::int32 x2;
            ceda::float32 x3;
        }
    {
    };
    
    $model+ Rect
    {
        Point p1;
        Point p2;
    };

    $model+ Circle
    {
        Point c;
        ceda::float32 r; 
    };
    
    $model+ Polygon
    {
        ceda::xvector<Point> V;
    };

    $variant+ Shape
    {
        default Circle(Point(0,0),1);
        Point; 
        Rect; 
        Circle; 
        Polygon;
    };
    
    $variant+ BasicType
    {
        default 0;
        ceda::int32;
        ceda::float64;
        ceda::xstring;
    };
    
    $enum+ Color
    {
        red,green,blue
    };

    $variant+ VColor
    {
        default red();
        void red;
        void green;
        void blue;
        void white;
    };
    
    $variant+ VNamedTypes
    {
        default a(0);
        ceda::int32 a;
        ceda::int32 b;    
    };
    
    $variant+ VariantWithPtr
    {
        default 0;
        ceda::int32;
        ceda::pref<ceda::IObject>;
    };

    $struct+ LT <<-os>> isa ceda::IPersistable :
        model
        {
            bool b;
            ceda::int8 i8;
            ceda::int16 i16;
            ceda::int32 i32;
            ceda::int64 i64;
            ceda::uint8 ui8;
            ceda::uint16 ui16;
            ceda::uint32 ui32;
            ceda::uint64 ui64;
            ceda::float32 f32;
            ceda::float64 f64;
            ceda::char8 c8;
            ceda::char16 c16;
            ceda::string8 s8;
            ceda::string16 s16;
            ceda::int32 A[4];
            Point p;
            Point P[5];
            Color color[10];
            ceda::xvector<ceda::int32> L;
            ceda::xvector<ceda::pref<ceda::IObject> > Lx;
            Shape S;
            ceda::xvector<Shape> ShapeList;
            ceda::xvector<BasicType> BTs;
            ceda::xvector<VNamedTypes> Vn;
            ceda::xvector<VColor> Vc;
            ceda::xvector<VariantWithPtr> Vp;
            ceda::xmap<ceda::string16,Point> M;
        }
    {
    };


    void Test(const ceda::xstring& s)
    {
        Tracer() << "\n\nParsing string " << s << '\n';

        ceda::xstring errorMsg;
        ceda::ptr<ceda::IObject> obj = ParseDataSourceFromString(s, errorMsg);

        ceda::TracerX os;
        os << "obj = " << obj << '\n';
        if (obj)
        {
            PrintInstance(os, obj);
            os << '\n';
        }
        if (!errorMsg.empty())
        {
            os << "errorMsg = " << errorMsg << '\n';
        }
    }

    void Run()
    {
        Tracer() << "ParseDataSource example 1\n";
        ceda::TraceIndenter indent;

        ceda::CSpaceCreator cspace;
        ceda::CSpaceLock lock;       // Exclusive lock

        Test(@str
        (
            blah
        ));

        Test(@str
        (
            ParseDataSource1.X(10,20,3.14)
        ));

        Test(@str
        (
            ParseDataSource1.X{x2=10 x1=20}
        ));

        // M = { (10,Point(0,0)), (15,Point(12,-2)) }

        Test(@str
        (
            ParseDataSource1.LT
            {
                b = false
                i8 = -8
                i16 = -16
                i32 = -32
                i64 = -64
                ui8 = 8
                ui16 = 16
                ui32 = 32
                ui64 = 64
                f32 = 32.5
                f64 = 64.5
                c8 = 'a'
                c16 = 'b'
                s8 = "hello"
                s16 = "hi"
                A = [10,20,30,40]
                p = (100,200)
                P = [ {y=10 x=2}, (5,4), Point(1,2), ParseDataSource1::Point(3,4), ParseDataSource1.Point{x=5 y=5+1} ]
                color = [ green, red, 0,1,2, blue, red, 1,1,1 ]
                L = [1,2,3]
                Lx = [ ParseDataSource1.X(1,2,3), ParseDataSource1.X(10,20,30), ParseDataSource1.LT{} ]
                S = ParseDataSource1::Rect(Point(0,0),(10,15))
                ShapeList = [Point(1,2), Circle(Point(0,0),5), Rect{p1={x=0 y=1} p2=Point(8,3*4)} ]
                BTs = [int32(23), float64(21.0), xstring("one two three")]
                Vn = [a(10), b(3), a(-16)]
                Vc = [red, green, white, red, blue]
                Vp = [ int32 10, pref ParseDataSource1.X(1,2,3) ]
                M = { 
                        "cat" -> Point(0,0), 
                        "dog" -> Point(12,-2), 
                        "frog" -> (1,1)
                    }
            }
        ));
    }
}

namespace ParseFieldPath
{
    $struct+ Y isa ceda::IObject :
        model
        {
            ceda::int32 x;
            ceda::ptr<ceda::IObject> p;
        }
    {
    };

    $struct+ X isa ceda::IPersistable :
        model
        {
            ceda::int32 x1;
            ceda::int32 x2;
            ceda::float32 x3;
        }
    {
    };
    
    $model+ Point
    {
        ceda::int32 x;
        ceda::int32 y;
    };
    
    $enum+ Color
    {
        red,green,blue
    };

    $struct+ LT <<-os>> isa ceda::IPersistable :
        model
        {
            bool b;
            ceda::int8 i8;
            ceda::int16 i16;
            ceda::int32 i32;
            ceda::int64 i64;
            ceda::uint8 ui8;
            ceda::uint16 ui16;
            ceda::uint32 ui32;
            ceda::uint64 ui64;
            ceda::float32 f32;
            ceda::float64 f64;
            ceda::char8 c8;
            ceda::char16 c16;
            ceda::string8 s8;
            ceda::string16 s16;
            ceda::int32 A[4];
            Point p;
            Point P[2];
            Color color[10];
            ceda::xvector<ceda::int32> L;
            ceda::xvector<ceda::pref<ceda::IObject> > Lx;
        }
    {
    };


    void Test(const ceda::xstring& s, const ceda::xvector<ceda::xstring>& paths)
    {
        Tracer() << "\n\nParsing string " << s << '\n';

        ceda::xstring errorMsg;
        ceda::ptr<ceda::IObject> obj = ParseDataSourceFromString(s, errorMsg);

        ceda::TracerX os;
        os << "obj = " << obj << '\n';
        if (obj)
        {
            PrintInstance(os, obj);
            os << '\n';
        }
        if (!errorMsg.empty())
        {
            os << "errorMsg = " << errorMsg << '\n';
        }

        if (obj)
        {
            for (int i=0 ; i < paths.size() ; ++i)
            {
                bool writeAccess = false;
                ceda::ReflectionByteCode rbc;
                void* addr = NavigatePathToField(obj,paths[i],rbc,false,errorMsg);

                if (addr && !rbc.IsNull())
                {
                    os << "Field " << paths[i] << " = ";
                    PrintReflectedVariable(os, rbc, addr);
                    os << '\n';
                }
                if (!errorMsg.empty())
                {
                    os << "errorMsg = " << errorMsg << '\n';
                }
            }
        }
    }

    void Run()
    {
        Tracer() << "\nParseFieldPath example 1\n";
        ceda::TraceIndenter indent;

        ceda::CSpaceCreator cspace;
        ceda::CSpaceLock lock;       // Exclusive lock

        ceda::xvector<ceda::xstring> paths;
        paths += ".x";
        paths += ".p";
        paths += ".p.x";
        paths += ".p.p";
        paths += ".p.p.x";
        paths += ".p.p.p.x";
        Test(@str
        (
            ParseFieldPath.Y(10,
                ParseFieldPath.Y(20,
                    ParseFieldPath.Y(30,null) ) )
        ), paths);

        paths.clear();
        paths += ".x1";
        paths += ".x2";
        paths += ".x3";
        Test(@str
        (
            ParseFieldPath.X(10,20,3.14)
        ), paths);

        paths.clear();
        paths += ".b";
        paths += ".i8";
        paths += ".i16";
        paths += ".i32";
        paths += ".i64";
        paths += ".ui8";
        paths += ".ui16";
        paths += ".ui32";
        paths += ".ui64";
        paths += ".f32";
        paths += ".f64";
        paths += ".c8";
        paths += ".c16";
        paths += ".s8";
        paths += ".s16";
        paths += ".A";
        paths += ".A[-1]";
        paths += ".A[0]";
        paths += ".A[1]";
        paths += ".A[2]";
        paths += ".A[2+1]";
        paths += ".A[4]";
        paths += ".p";
        paths += ".p.x";
        paths += ".p.y";
        paths += ".P";
        paths += ".P[0]";
        paths += ".P[0].x";
        paths += ".P[0].y";
        paths += ".P[1]";
        paths += ".P[1].x";
        paths += ".P[1].y";
        paths += ".color";
        paths += ".color[0]";
        paths += ".color[1]";
        paths += ".color[2]";
        paths += ".L";
        paths += ".L[0]";
        paths += ".L[1]";
        paths += ".L[2]";
        paths += ".L[3]";
        paths += ".Lx";
        paths += ".Lx[0]";
        paths += ".Lx[1]";
        paths += ".Lx[2]";
        paths += ".Lx[0].x1";
        paths += ".Lx[2].s8";
        paths += ".Lx[2].A[0]";
        
        Test(@str
        (
            ParseFieldPath.LT
            {
                b = false
                i8 = -8
                i16 = -16
                i32 = -32
                i64 = -64
                ui8 = 8
                ui16 = 16
                ui32 = 32
                ui64 = 64
                f32 = 32.5
                f64 = 64.5
                c8 = 'a'
                c16 = 'b'
                s8 = "hello"
                s16 = "hi"
                A = [10,20,30,40]
                p = (100,200)
                P = [ {y=10 x=2}, (5,4) ]
                color = [ green, red, 0,1,2, blue, red, 1,1,1 ]
                L = [1,2,3]
                Lx = [ ParseFieldPath.X(1,2,3), ParseFieldPath.X(10,20,30), ParseFieldPath.LT{} ]
            }
        ), paths);

        @if (false)
        {
            Test(@str
            (
                ParseFieldPath.X{x2=10 x1=20}
            ));

        }
    }
}

///////////////////////////////////////////////////////////////////////////////////////////////////
namespace ParseDataSource
{
    void Run()
    {
        ParseDataSource1::Run();
        ParseFieldPath::Run();
    }
}