Author Topic: -+{ Challenge }+- Serialize Xdata  (Read 8859 times)

0 Members and 1 Guest are viewing this topic.

It's Alive!

  • BricsCAD
  • Needs a day job
  • Posts: 6956
  • AKA Daniel
-+{ Challenge }+- Serialize Xdata
« on: January 22, 2010, 04:59:02 AM »
Serialize the Xdata from all the entities (modelspace)  in the attached drawing, then read the data back into memory.
Format or language does not matter, only that you can read/write your data

There are five xdata elements attached to each point, including the app name (myxdata)
How fast can you doit?

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: -+{ Challenge }+- Serialize Xdata
« Reply #1 on: January 22, 2010, 05:04:36 AM »

How fast can you doit?


about 3 months I think :)


[added:] hmmmm
Non Autodesk DWG.  This DWG file was saved by a software application that was
not developed or licensed by Autodesk.
:)
« Last Edit: January 22, 2010, 05:12:29 AM by Kerry Brown »
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

--> Donate to theSwamp<--

frtfff

  • Bull Frog
  • Posts: 215
Re: -+{ Challenge }+- Serialize Xdata
« Reply #2 on: January 22, 2010, 05:19:59 AM »
 :kewl:

It's Alive!

  • BricsCAD
  • Needs a day job
  • Posts: 6956
  • AKA Daniel
Re: -+{ Challenge }+- Serialize Xdata
« Reply #3 on: January 22, 2010, 05:47:37 AM »
... hmmmm
Non Autodesk DWG.  This DWG file was saved by a software application that was
not developed or licensed by Autodesk.
:)

Ha, yeah Bricscad has a cooler xdata editor   :-)

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: -+{ Challenge }+- Serialize Xdata
« Reply #4 on: January 22, 2010, 06:33:07 AM »


ok,

I'll try a Lisp hack.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

--> Donate to theSwamp<--

grrrr

  • Mosquito
  • Posts: 8
Re: -+{ Challenge }+- Serialize Xdata
« Reply #5 on: January 22, 2010, 06:54:28 AM »
hello dan,
where is the problem.
try in lisp and spend 2 hours.

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: -+{ Challenge }+- Serialize Xdata
« Reply #6 on: January 22, 2010, 07:02:38 AM »
Well, not quite 2 hours

'Wanda' grabbed it in 14 seconds ... a bit slow, but thats to be expected.

Code: [Select]
(defun c:kdub_doit (/ start ss datalist datafilename datalist
                    itemdata readdatalist linecount elapsedtime)
  ;; codeHimBelonga kdub@theSwamp 20100122
  (setq start (getvar "millisecs"))
  (if (setq ss (ssget "X" '((-3 ("myxdata")))))
    (progn (setq datalist     '()
                 datafilename "c:/Test_DoIt_MyXData.txt"
           )
           (close (open datafilename "W"))
           ;;------------------------------
           ;; Collect the Data
           (foreach item (kdub:ss->entlist ss)
             (if (setq itemdata
                        (cdr
                          (cadr
                            (assoc -3
                                   (setq ent (entget item '("myxdata")))
                            )
                          )
                        )
                 )
               (setq datalist (cons itemdata datalist))
             )
           )
           ;;------------------------------
           ;; Write it Out
           (kdub:list-to-textfile
             datafilename
             (mapcar 'vl-prin1-to-string (reverse datalist))
           )
           ;;------------------------------
           ;; Read it Back
           (setq readdatalist (mapcar 'read
                                      (kdub:textfile-to-list datafilename)
                              )
                 linecount    (length readdatalist)
                 elapsedtime  (itoa (- (getvar "millisecs") start))
           )
    )
  )
  (princ (strcat "\n "
                 (itoa linecount)
                 " Objects Collected in : "
                 elapsedtime
                 " Milliseconds."
         )
  )
  (princ)
)
(princ)

LIBRARY STUFF
Code: [Select]
;;;------------------------------------------------------------------
;;;------------------------------------------------------------------
;;;
(defun kdub:ss->entlist (ss / i returnval)
  (if (and ss (< 0 (sslength ss)))
    (progn (setq i 0)
           (repeat (sslength ss)
             (setq returnval (cons (ssname ss i) returnval)
                   i         (1+ i)
             )
           )
    )
  )
  (if returnval
    (reverse returnval)
    nil
  )
)

;;;------------------------------------------------------------------
;;;------------------------------------------------------------------
;;;
(defun kdub:textfile-to-list (filename      /
                              fileobject    filefound
                              filesystem    openfileas
                              returnvalue
                             )
  (if (setq filefound (findfile filename))
    (progn (setq filesystem (vlax-create-object "Scripting.FileSystemObject")
                 fileobject (vlax-invoke filesystem "GetFile" filefound)
                 openfileas (vlax-invoke fileobject "OpenAsTextStream" 1 0)
           )
           (while (= (vlax-get openfileas "AtEndOfStream") 0)
             (setq returnvalue (cons (vlax-invoke openfileas "ReadLine")
                                     returnvalue
                               )
             )
           )
           (vlax-invoke openfileas "Close")
           (vlax-release-object openfileas)
           (vlax-release-object fileobject)
           (vlax-release-object filesystem)
           (reverse returnvalue)
    )
    nil
  )
)

;;;------------------------------------------------------------------
;;;------------------------------------------------------------------
;;;
(defun kdub:list-to-textfile (filename      datalist
                              /             fileobject
                              filefound     filesystem
                              openfileas    returnvalue
                             )
  (if (setq filefound (findfile filename))
    (progn (setq filesystem (vlax-create-object "Scripting.FileSystemObject")
                 fileobject (vlax-invoke filesystem "GetFile" filefound)
                 openfileas (vlax-invoke fileobject "OpenAsTextStream" 2 0)
           )
           (foreach line datalist
             (vlax-invoke openfileas "WriteLine" line)
           )
           (vlax-invoke openfileas "Close")
           (vlax-release-object openfileas)
           (vlax-release-object fileobject)
           (vlax-release-object filesystem)
           t
    )
    nil
  )
)
;;;------------------------------------------------------------------
;;;------------------------------------------------------------------
;;;

and the piccy to proove it :)
« Last Edit: January 22, 2010, 07:31:26 AM by Kerry Brown »
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

--> Donate to theSwamp<--

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: -+{ Challenge }+- Serialize Xdata
« Reply #7 on: January 22, 2010, 07:10:51 AM »


Dan, I don't have BricsCad installed yet .. be interesting to compare times when I do.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

--> Donate to theSwamp<--

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: -+{ Challenge }+- Serialize Xdata
« Reply #8 on: January 22, 2010, 07:18:22 AM »
< ..> There are five xdata elements attached to each point, including the app name (myxdata)

Dan
I only get 4 elements attached each point ????

Piccy attached:  8204 kB file :)
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

--> Donate to theSwamp<--

It's Alive!

  • BricsCAD
  • Needs a day job
  • Posts: 6956
  • AKA Daniel
Re: -+{ Challenge }+- Serialize Xdata
« Reply #9 on: January 22, 2010, 07:39:06 AM »
4 + the appname  :-)

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: -+{ Challenge }+- Serialize Xdata
« Reply #10 on: January 22, 2010, 07:41:58 AM »
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

--> Donate to theSwamp<--

It's Alive!

  • BricsCAD
  • Needs a day job
  • Posts: 6956
  • AKA Daniel
Re: -+{ Challenge }+- Serialize Xdata
« Reply #11 on: January 22, 2010, 07:53:27 AM »
Nice !
Quote

 ; Autocad 100000 Objects Collected in : 7878 Milliseconds.
 ; Autocad 100000 Objects Collected in : 7956 Milliseconds.
 ; Autocad 100000 Objects Collected in : 7878 Milliseconds.
 
 ; Bricscad 100000 Objects Collected in : 10185 Milliseconds. <---?
 ; Bricscad 100000 Objects Collected in : 5959 Milliseconds.
 ; Bricscad 100000 Objects Collected in : 5990 Milliseconds.

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: -+{ Challenge }+- Serialize Xdata
« Reply #12 on: January 22, 2010, 07:56:31 AM »


Whoa, what sort of beast are you running there ??  :?
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

--> Donate to theSwamp<--

gile

  • Water Moccasin
  • Posts: 2233
  • Marseille, France
Re: -+{ Challenge }+- Serialize Xdata
« Reply #13 on: January 22, 2010, 08:13:15 AM »
Hi,

If I don't misundertand the challenge, here're my C# 2 cents

Code: [Select]
using System;
using System.IO;
using System.Text;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Runtime;
using acadApp = Autodesk.AutoCAD.ApplicationServices.Application;

namespace SerializeChallenge
{
    public class Class1
    {

        [CommandMethod("Test")]
        public void Test()
        {
            DateTime t0 = DateTime.Now;
            Document doc = acadApp.DocumentManager.MdiActiveDocument;
            Database db = doc.Database;
            Editor ed = doc.Editor;
            string filename = "C:\\SerializeChallenge.txt";
            using (Transaction tr = db.TransactionManager.StartTransaction())
            {
                BlockTable bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead);
                BlockTableRecord btr = (BlockTableRecord)tr.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForRead);
                using (TextWriter writer = new StreamWriter(filename))
                {
                    foreach (ObjectId id in btr)
                    {
                        Entity ent = (Entity)tr.GetObject(id, OpenMode.ForRead, false);
                        ResultBuffer resbuf = ent.XData;
                        if (resbuf == null)
                            continue;
                        TypedValue[] datas = resbuf.AsArray();
                        StringBuilder sb = new StringBuilder(datas.Length);
                        foreach (TypedValue tv in datas)
                        {
                            sb.Append(tv.Value);
                            sb.Append(" ");
                        }
                        writer.WriteLine(sb.ToString());
                    }
                    writer.Close();
                }
                tr.Commit();
            }
            using (TextReader reader = new StreamReader(filename))
            {
                string line = reader.ReadToEnd();
            }
            DateTime t1 = DateTime.Now;
            TimeSpan ts = t1 - t0;
            ed.WriteMessage("\nEllapsed milliseconds: " + ts.TotalMilliseconds.ToString());
        }
    }
}

Quote
Commande: test

Ellapsed milliseconds: 2062.5
Commande:
TEST
Ellapsed milliseconds: 2031.25
Commande:
TEST
Ellapsed milliseconds: 2031.25
Commande:
TEST
Ellapsed milliseconds: 2015.625
Speaking English as a French Frog

It's Alive!

  • BricsCAD
  • Needs a day job
  • Posts: 6956
  • AKA Daniel
Re: -+{ Challenge }+- Serialize Xdata
« Reply #14 on: January 22, 2010, 08:15:46 AM »

It's Alive!

  • BricsCAD
  • Needs a day job
  • Posts: 6956
  • AKA Daniel
Re: -+{ Challenge }+- Serialize Xdata
« Reply #15 on: January 22, 2010, 08:32:55 AM »
...If I don't misundertand the challenge, here're my C# 2 cents....
The data needs to be in the same format as before it was serialized. I.e.
you would need to read the data back into a Resultbuffer/TypedVale[]

gile

  • Water Moccasin
  • Posts: 2233
  • Marseille, France
Re: -+{ Challenge }+- Serialize Xdata
« Reply #16 on: January 22, 2010, 02:02:03 PM »
I try using an XML file, it's not very fast :|

Code: [Select]
using System;
using System.Text;
using System.Xml;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.Runtime;
using acadApp = Autodesk.AutoCAD.ApplicationServices.Application;

namespace SerializeChallenge
{
    public class Class1
    {
        [CommandMethod("Test")]
        public void Test()
        {
            DateTime t0 = DateTime.Now;
            Document doc = acadApp.DocumentManager.MdiActiveDocument;
            Database db = doc.Database;
            Editor ed = doc.Editor;
            string filename = "C:\\SerializeChallenge.xml";
            XmlTextWriter writer = new XmlTextWriter(filename, Encoding.UTF8);
            writer.Formatting = Formatting.Indented;
            writer.WriteStartDocument();
            writer.WriteStartElement("SerializeChallenge");
            using (Transaction tr = db.TransactionManager.StartTransaction())
            {
                BlockTable bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead);
                BlockTableRecord btr =
                    (BlockTableRecord)tr.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForRead);
                foreach (ObjectId id in btr)
                {
                    Entity ent = (Entity)tr.GetObject(id, OpenMode.ForRead, false);
                    ResultBuffer resbuf = ent.XData;
                    if (resbuf == null)
                        continue;
                    writer.WriteStartElement("resbuf");
                    TypedValue[] tvs = resbuf.AsArray();
                    foreach (TypedValue tv in tvs)
                    {
                        writer.WriteStartElement("xdata");
                        writer.WriteAttributeString("code", tv.TypeCode.ToString());
                        writer.WriteAttributeString("value", tv.Value.ToString());
                        writer.WriteEndElement();
                    }
                    writer.WriteEndElement();
                }
                tr.Commit();
            }
            writer.WriteEndElement();
            writer.WriteEndDocument();
            writer.Flush();
            writer.Close();
            XmlDocument xmlDoc = new XmlDocument();
            xmlDoc.Load(filename);
            foreach (XmlNode xdatas in xmlDoc.ChildNodes[1].ChildNodes)
            {
                ResultBuffer resbuf = new ResultBuffer();
                foreach (XmlNode data in xdatas.ChildNodes)
                {
                    XmlAttributeCollection atts = data.Attributes;
                    short code = Convert.ToInt16(atts["code"].Value);
                    resbuf.Add(new TypedValue(
                        code,
                        GetValue(code, atts["value"].Value)));
                }
            }
            DateTime t1 = DateTime.Now;
            TimeSpan ts = t1 - t0;
            ed.WriteMessage("\nEllapsed milliseconds: " + ts.TotalMilliseconds.ToString());
        }

        private object GetValue(short code, string p)
        {
            switch (code)
            {
                case 1010:
                    return StringToPoint(p);
                case 1040:
                    return Convert.ToDouble(p);
                case 1070:
                    return Convert.ToInt32(p);
                default:
                    return p;
            }
        }

        private Point3d StringToPoint(string p)
        {
            string[] strs = p.Trim(new char[] { '(', ')' }).Split(new char[] { ',' });
            double[] coords = new double[3];
            for (int i = 0; i < 3; i++)
            {
                coords[i] = Convert.ToDouble(strs[i]);
            }
            return new Point3d(coords);
        }
    }
}
Quote
Commande: test
Ellapsed milliseconds: 7515.625
Commande:
TEST
Ellapsed milliseconds: 6765.625
Commande:
TEST
Ellapsed milliseconds: 7046.875
Commande:
TEST
Ellapsed milliseconds: 7296.875

I try making Serializable classes too but i can't get it work :|
Speaking English as a French Frog

gile

  • Water Moccasin
  • Posts: 2233
  • Marseille, France
Re: -+{ Challenge }+- Serialize Xdata
« Reply #17 on: January 22, 2010, 04:58:28 PM »
I tried to optimize the upper routine but don't win so much.

Code: [Select]
using System;
using System.Text;
using System.Xml;
using System.Collections.Generic;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.Runtime;
using acadApp = Autodesk.AutoCAD.ApplicationServices.Application;

namespace SerializeChallenge
{
    public class Class1
    {
        [CommandMethod("gileCs")]
        public void Test()
        {
            DateTime t0 = DateTime.Now;
            Document doc = acadApp.DocumentManager.MdiActiveDocument;
            Database db = doc.Database;
            Editor ed = doc.Editor;
            string filename = "C:\\SerializeChallenge.xml";
            XmlTextWriter writer = new XmlTextWriter(filename, Encoding.UTF8);
            writer.Formatting = Formatting.Indented;
            writer.WriteStartDocument();
            writer.WriteStartElement("SerializeChallenge");
            int cnt = 0;
            using (Transaction tr = db.TransactionManager.StartTransaction())
            {
                BlockTable bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead);
                BlockTableRecord btr =
                    (BlockTableRecord)tr.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForRead);
                foreach (ObjectId id in btr)
                {
                    Entity ent = (Entity)tr.GetObject(id, OpenMode.ForRead, false);
                    ResultBuffer resbuf = ent.XData;
                    if (resbuf == null)
                        continue;
                    writer.WriteStartElement("resbuf");
                    TypedValue[] tvs = resbuf.AsArray();
                    foreach (TypedValue tv in tvs)
                    {
                        writer.WriteStartElement("xdata");
                        writer.WriteAttributeString("code", tv.TypeCode.ToString());
                        writer.WriteAttributeString("value", tv.Value.ToString());
                        writer.WriteEndElement();
                    }
                    writer.WriteEndElement();
                    cnt++;
                }
                tr.Commit();
            }
            writer.WriteEndElement();
            writer.WriteEndDocument();
            writer.Flush();
            writer.Close();
            XmlDocument xmlDoc = new XmlDocument();
            xmlDoc.Load(filename);
            List<ResultBuffer> lst = new List<ResultBuffer>(cnt);
            foreach (XmlNode xdatas in xmlDoc.ChildNodes[1].ChildNodes)
            {
                ResultBuffer resbuf = new ResultBuffer();
                foreach (XmlNode data in xdatas.ChildNodes)
                {
                    XmlAttributeCollection atts = data.Attributes;
                    short code = Convert.ToInt16(atts["code"].Value);
                    resbuf.Add(new TypedValue(
                        code,
                        GetValue(code, atts["value"].Value)));
                }
                lst.Add(resbuf);
            }
            DateTime t1 = DateTime.Now;
            TimeSpan ts = t1 - t0;
            ed.WriteMessage("\nEllapsed milliseconds: " + ts.TotalMilliseconds.ToString());
        }

        private object GetValue(short code, string p)
        {
            switch (code)
            {
                case 1010:
                    return StringToPoint(p);
                case 1040:
                    return Convert.ToDouble(p);
                case 1070:
                    return Convert.ToInt32(p);
                default:
                    return p;
            }
        }

        private Point3d StringToPoint(string p)
        {
            int pos0 = 1;
            int pos1 = p.IndexOf(',');
            double x = Convert.ToDouble(p.Substring(1, pos1 - pos0));
            pos0 = pos1 + 1;
            pos1 = p.IndexOf(',', pos0);
            double y = Convert.ToDouble(p.Substring(pos0, pos1 - pos0));
            pos0 = pos1 + 1;
            pos1 = p.IndexOf(')', pos0);
            double z = Convert.ToDouble(p.Substring(pos0, pos1 - pos0));
            return new Point3d(x, y, z);
        }
    }
}

I wrote a little one in LISP, it's nearly as fast...

Code: [Select]
(defun c:gileLsp (/ t0 t1 n ss file line lst)
  (vl-load-com)
  (setq t0 (getvar 'millisecs))
  (if (setq ss (ssget "_X" '((-3 ("MYXDATA")))))
    (progn
      (setq n 0
            file (open "C:\\SerializeChallenge.txt" "w")
            )
      (while (setq ent (ssname ss n))
        (write-line (vl-prin1-to-string (assoc -3 (entget ent '("MYXDATA")))) file)
        (setq n (1+ n))
      )
      (close file)
      (setq file (open "C:\\SerializeChallenge.txt" "r"))
      (while (setq line (read-line file))
        (setq lst (cons (read line) lst))
      )
      (reverse lst)
      (close file)
    )
  )
  (setq t1 (getvar 'millisecs))
  (princ (strcat "\n" (itoa n) " objects collected in " (itoa (- t1 t0))" milliseconds"))
  (princ)
)

I thaught my routine was slow, there're not very fast, but it seems to be my computer which is slower than yours...

Quote
Commande: gileCs
Ellapsed milliseconds: 6562.5
Commande: gileCs
Ellapsed milliseconds: 6593.75
Commande: gileCs
Ellapsed milliseconds: 6421.875

Commande: GILELSP
100000 objects collected in 8672 milliseconds
Commande: GILELSP
100000 objects collected in 8703 milliseconds
Commande: GILELSP
100000 objects collected in 8672 milliseconds

Commande: KDUB_DOIT
 100000 Objects Collected in : 14890 Milliseconds.
Commande: KDUB_DOIT
 100000 Objects Collected in : 15110 Milliseconds.
Commande: KDUB_DOIT
 100000 Objects Collected in : 15047 Milliseconds.
« Last Edit: January 22, 2010, 05:04:16 PM by gile »
Speaking English as a French Frog

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: -+{ Challenge }+- Serialize Xdata
« Reply #18 on: January 22, 2010, 06:46:42 PM »
gile

re : (defun c:gileLsp .......

Yes, using a linear approach with minimum variables and writing to the open file as each point is captured
is a lot faster than the modular approach I used. 

Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

--> Donate to theSwamp<--

It's Alive!

  • BricsCAD
  • Needs a day job
  • Posts: 6956
  • AKA Daniel
Re: -+{ Challenge }+- Serialize Xdata
« Reply #19 on: January 22, 2010, 07:44:41 PM »
HuH! I expected .NET to be much faster  :-o  :-o  :-o

Code: [Select]
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.Runtime;
using AcAp = Autodesk.AutoCAD.ApplicationServices;

[assembly: CommandClass(typeof(NetSerialize.Commands))]

namespace NetSerialize
{

  public class Commands
  {

    [Serializable]
    public class pnt3d
    {
      double x, y, z;
      public pnt3d(Point3d p)
      {
        x = p.X;
        y = p.Y;
        y = p.Z;
      }
      public double Z
      {
        get { return z; }
        set { z = value; }
      }
      public double Y
      {
        get { return y; }
        set { y = value; }
      }
      public double X
      {
        get { return x; }
        set { x = value; }
      }
    }

    [CommandMethod("doit")]
    static public void doit()
    {
      Stopwatch stopWatch = new Stopwatch();
      stopWatch.Start();

      Database db = HostApplicationServices.WorkingDatabase;
      string filename = "C:\\SerializeChallenge.dat";

      List<KeyValuePair<int, Object>>
          kvList = new List<KeyValuePair<int, object>>();

      using (Transaction tr = db.TransactionManager.StartTransaction())
      {
        BlockTable bt = (BlockTable)
          tr.GetObject(db.BlockTableId, OpenMode.ForRead);
        BlockTableRecord btr =(BlockTableRecord)
          tr.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForRead);

        foreach (ObjectId id in btr)
        {
          Entity ent = (Entity)tr.GetObject(id, OpenMode.ForRead, false);
          ResultBuffer resbuf = ent.XData;
          if (resbuf == null)
            continue;

          foreach (TypedValue item in resbuf)
          {
            if((int)item.TypeCode == 1010)
            {
              pnt3d p = new pnt3d((Point3d)item.Value);
              kvList.Add(new KeyValuePair<int, object>
                     ((int)item.TypeCode, p));
            }
            else
            {
              kvList.Add(new KeyValuePair<int, object>
                     ((int)item.TypeCode, item.Value));
            }
          }

        }
        tr.Commit();
      }
      dome(kvList, filename);
      stopWatch.Stop();
      TimeSpan ts = stopWatch.Elapsed;

      AcAp.Application.DocumentManager.
         MdiActiveDocument.Editor.WriteMessage
          ("\n{0} Milliseconds", ts.TotalMilliseconds);
    }

    [CommandMethod("undoit")]
    static public void undoit()
    {
      Stopwatch stopWatch = new Stopwatch();
      stopWatch.Start();

      string filename = "C:\\SerializeChallenge.dat";
      List<KeyValuePair<int, Object>> list = undome(filename);

      stopWatch.Stop();
      TimeSpan ts = stopWatch.Elapsed;

      AcAp.Application.DocumentManager.
         MdiActiveDocument.Editor.WriteMessage
           ("\n{0} Milliseconds", ts.TotalMilliseconds);
    }

    static public void dome(List<KeyValuePair<int, Object>> kvList,
                            string filename)
    {
      Stream stream = new FileStream(filename, FileMode.Create);
      try
      {
        IFormatter formatter = new BinaryFormatter();
        formatter.Serialize(stream, kvList);
      }
      catch (System.Exception ex)
      {
        AcAp.Application.DocumentManager.
          MdiActiveDocument.Editor.
            WriteMessage("crash {0}",ex.Message);
      }
      finally
      {
        stream.Close();
      }
    }


    static public List<KeyValuePair<int, Object>> undome(string filename)
    {
      List<KeyValuePair<int, Object>> kvList = null;
      Stream stream = null;
      try
      {
        stream = new FileStream(filename, FileMode.Open);
        IFormatter formatter = new BinaryFormatter();
        kvList =(List<KeyValuePair<int, Object>>)
                            formatter.Deserialize(stream);
      }
      catch (System.Exception ex)
      {
        AcAp.Application.DocumentManager.
          MdiActiveDocument.Editor.
           WriteMessage("crash {0}", ex.Message);
      }
      finally
      {
        stream.Close();
      }
      return kvList;
    }
  }
}
« Last Edit: January 22, 2010, 07:49:02 PM by Daniel »

It's Alive!

  • BricsCAD
  • Needs a day job
  • Posts: 6956
  • AKA Daniel
Re: -+{ Challenge }+- Serialize Xdata
« Reply #20 on: January 22, 2010, 09:33:13 PM »
A little more work for the C++ version, it's a tad faster  :evil:

CTypedValue.h
Code: [Select]
class CTypedValue : public CObject
{
public:
  union __declspec(novtable) Value
  {
    inline Value(){ this->setNull(); }
    inline void setNull(){memset(this,0,sizeof(Value));}
    unsigned char vChar;
    unsigned char vHandle[8];
    short         vShort;
    long          vLong;
    long          vEname[2];
    __int64       vInt64;
    double        vDouble;
    double        vPoint2d[2];
    double        vPoint3d[3];
    unsigned char vCharArray[24];
  } _value;

  CString vString;
  short _dfxType;

protected:
  DECLARE_SERIAL(CTypedValue)

public:
  enum ValueType {TVNull, TVChar, TVShort, TVLong, TVString, TVInt64,
                  TVEName,TVDouble, TVPoint2d, TVPoint3d, TVByteArray,
                  TVLispSym,TVHandle}_valueType;

public:
  CTypedValue( void );
  CTypedValue( const resbuf *src );
  CTypedValue( const CTypedValue& src );
  virtual ~CTypedValue( void );
  CTypedValue& operator=( const CTypedValue& src );

  bool operator == ( const CTypedValue& src ) const;
  bool operator != ( const CTypedValue& src ) const;
  bool Equals( const CTypedValue& src ) const;

  virtual void Serialize( CArchive &ar );
  resbuf* ToResbuf( void ) const;
};

CTypedValue.cpp
Code: [Select]
#include "StdAfx.h"
#include "TypedValue.h"


IMPLEMENT_SERIAL( CTypedValue, CObject, VERSIONABLE_SCHEMA|1)

CTypedValue::CTypedValue(void)
: _value(), _valueType(TVNull) , _dfxType(0){}

CTypedValue::CTypedValue( const resbuf *buf )
: _value(), _valueType(TVNull) , _dfxType(buf->restype)
{
  if(buf != NULL)
  {
    if(buf->restype > 5000)
    {
      switch (buf->restype)
      {
      case RTSTR:{
          _valueType = TVString;
          vString = buf->resval.rstring;
          break;
        }
      case RTSHORT:{
          _valueType = TVShort;
          _value.vShort = buf->resval.rint;
          break;
        }
      case RTLONG:{
          _valueType = TVLong;
          _value.vLong = buf->resval.rlong;
        }
      case RTREAL:{
          _valueType = TVDouble;
          _value.vDouble= buf->resval.rreal;
          break;
        }
      case RTENAME:{
          _valueType = TVEName;
          memcpy( _value.vEname,buf->resval.rlname,sizeof(_value.vEname));
          break;
        }
      case RTPOINT:{
          _valueType = TVPoint2d;
          memcpy( _value.vPoint3d,buf->resval.rpoint,sizeof(_value.vPoint3d));
          break;
        }
      case RT3DPOINT:{
          _valueType = TVPoint3d;
          memcpy( _value.vPoint3d,buf->resval.rpoint,sizeof(_value.vPoint3d));
          break;
        }
      default:{
          _valueType = TVLispSym;
        }
      }
    }
    else if(buf->restype < 5000)
    {
      short type = acdbGroupCodeToType(buf->restype);
      switch (type)
      {
      case kDwgText:{
          _valueType = TVString;
          vString = buf->resval.rstring;
          break;
        }
      case kDwgInt8:{
          _valueType = TVChar;
          _value.vShort = buf->resval.rint;
          break;
        }
      case kDwgInt16:{
          _valueType = TVShort;
          _value.vShort = buf->resval.rint;
          break;
        }
      case AcDb::kDwgInt32:{
          _valueType = TVLong;
          _value.vLong = buf->resval.rlong;
          break;
        }
      case AcDb::kDwgReal:{
          _valueType = TVDouble;
          _value.vDouble= buf->resval.rreal;
          break;
        }
      case kDwgHandle:{
          _valueType = TVHandle;
          memcpy(_value.vHandle, buf->resval.ihandle, sizeof(_value.vHandle));
          break;
        }
      case kDwgHardOwnershipId:
      case kDwgSoftOwnershipId:
      case kDwgHardPointerId:
      case kDwgSoftPointerId:{
          _valueType = TVEName;
           memcpy( _value.vEname,buf->resval.rlname,sizeof(_value.vEname));
          break;
        }
      case kDwg3Real:{
          _valueType = TVPoint3d;
          memcpy( _value.vPoint3d,buf->resval.rpoint,sizeof(_value.vPoint3d));
          break;
        }
      }
    }
  }
}

CTypedValue::CTypedValue( const CTypedValue& src )
: _value(), _valueType(TVNull) ,  _dfxType(0){}

CTypedValue::~CTypedValue(void)
{
  _value.setNull();
}

CTypedValue& CTypedValue::operator=( const CTypedValue& src )
{
  if(this != &src)
  {
    memcpy(&_value,&src._value,sizeof(src._value));
    _valueType = src._valueType;
    _dfxType = src._dfxType;
    if(_valueType == TVString)
    {
      this->vString =  src.vString;
    }
  }
  return *this;
}

bool CTypedValue::operator==( const CTypedValue& src ) const
{
  return this->Equals(src);
}

bool CTypedValue::operator!=( const CTypedValue& src ) const
{
  return !this->Equals(src);
}

bool CTypedValue::Equals( const CTypedValue& src ) const
{
  if(_valueType == TVString && src._valueType == TVString)
  {
    return this->vString.Compare(src.vString) == 0;
  }
  else if (memcmp(&_value, &src._value, sizeof(CTypedValue::Value)) == 0)
  {
    return true;
  }
  return false;
}

void CTypedValue::Serialize( CArchive &ar )
{
  CObject::Serialize( ar );

  if (ar.IsStoring())
  {
    for(size_t i = 0 ; i < sizeof(_value) ; i++)
    {
      ar << _value.vCharArray[i];
    }
    ar << vString;
    ar << (int)_valueType;
    ar << _dfxType;
  }
  else
  {
    for(size_t i = 0 ; i < sizeof(_value) ; i++)
    {
      ar >> _value.vCharArray[i];
    }
    ar >> vString;
    ar >> (int&)_valueType;
    ar >> _dfxType;;
  }
}

resbuf* CTypedValue::ToResbuf( void ) const
{
  resbuf *pBuf = NULL;
  if(_valueType == TVString)
  {
    pBuf = acutBuildList(_dfxType,vString,0);
  }
  else
  {
    pBuf = acutNewRb(_dfxType);//24 bytes
    memcmp(&pBuf->resval,&_value,sizeof(pBuf->resval.rpoint));
  }
  return pBuf;
}

CTypedValueArray.h
Code: [Select]
#pragma once
#include "afxtempl.h"
#include "TypedValue.h"

typedef  CArray<CTypedValue,CTypedValue&> Base_CTypedValueArray;


class CTypedValueArray : public Base_CTypedValueArray
{
public:
  CTypedValueArray(void);
  void AppendResbuf(const resbuf *pRb);
  virtual ~CTypedValueArray(void);
  virtual void Serialize(CArchive& ar);
  void SerializeElements (CArchive& ar, CTypedValue* pCTypedValue, INT_PTR nCount);
  resbuf* ToRbChain(void) const;
};

CTypedValueArray.cpp
Code: [Select]
#include "StdAfx.h"
#include "TypedValueArray.h"

CTypedValueArray::CTypedValueArray( void ) : Base_CTypedValueArray(){}

CTypedValueArray::~CTypedValueArray( void ){}

void CTypedValueArray::AppendResbuf( const resbuf *pRb )
{
  for(const resbuf* tmp = pRb;tmp!=NULL;tmp = tmp->rbnext)
  {
    this->Add(CTypedValue(tmp));
  }
}

void CTypedValueArray::Serialize( CArchive& ar )
{
  ASSERT_VALID(this);

  CObject::Serialize(ar);
  if (ar.IsStoring())
  {
    ar.WriteCount(m_nSize);
  }
  else
  {
    DWORD_PTR nOldSize = ar.ReadCount();
    SetSize(nOldSize, -1);
  }
  SerializeElements(ar, m_pData, m_nSize);
}

void CTypedValueArray::SerializeElements( CArchive& ar, CTypedValue* pCTypedValue, INT_PTR nCount )
{
  ENSURE(nCount == 0 || pCTypedValue != NULL);
  ASSERT(nCount == 0 || AfxIsValidAddress(pCTypedValue, (size_t)nCount * sizeof(CTypedValue)));

  for (INT_PTR i = 0; i < nCount; i++, pCTypedValue++)
    pCTypedValue->Serialize(ar);
}

resbuf* CTypedValueArray::ToRbChain( void ) const
{
  if(this->GetCount() == 0)
    return NULL;

  resbuf* pHead = this->GetAt(0).ToResbuf();
  resbuf* pTail = pHead;
  for(size_t i=1;i<this->GetCount();i++)
  {
   pTail = pTail->rbnext = this->GetAt(i).ToResbuf();
  }
  return pHead;
}


arx
Code: [Select]
static void ArxSerialize_doit(void)
  {
    LARGE_INTEGER freq,start,end; 
    QueryPerformanceFrequency(&freq);
    QueryPerformanceCounter(&start);

    CTypedValueArray arr;
    resbuf *pRb = acutNewRb(RTVOID);
    size_t len = GetAllXdata(pRb);

    arr.SetSize(len);
    fillarray(arr,pRb->rbnext);
    acutRelRb(pRb);

    CFile fHandles;
    fHandles.Open(_T("c:\\xdata.dat"),
      CFile::modeCreate | CFile::modeWrite |  CFile::typeBinary );
    CArchive ar(&fHandles, CArchive::store);
    arr.Serialize(ar);
    ar.Close();
    fHandles.Close();

    acutPrintf(_T("\nSerialized Elements %ld"),arr.GetCount());
    QueryPerformanceCounter( &end );
    acutPrintf(_T("\n%g"),(double)
      (end.QuadPart-start.QuadPart)/freq.QuadPart );
  }


  static void ArxSerialize_undoit(void)
  {
    LARGE_INTEGER freq,start,end; 
    QueryPerformanceFrequency(&freq);
    QueryPerformanceCounter(&start);

    CTypedValueArray arr;
    CFile fHandles;
    fHandles.Open(_T("c:\\xdata.dat"),  CFile::modeRead |  CFile::typeBinary);
    CArchive ar(&fHandles, CArchive::load);
    arr.Serialize(ar);
    ar.Close();
    fHandles.Close();

    acutPrintf(_T("\nDeserialized Elements %ld"),arr.GetCount());
    QueryPerformanceCounter( &end );
    acutPrintf(_T("\n%g"),(double)
      (end.QuadPart-start.QuadPart)/freq.QuadPart );
  }

  static size_t GetAllXdata( resbuf* pRb )
  {
    size_t cnt= 0;
    resbuf *pTail = pRb;
    AcDbDatabase *pDb = acdbHostApplicationServices()->workingDatabase();
    AcDbBlockTableRecordPointer pCurBtr(pDb->currentSpaceId(),AcDb::kForRead);
    if(pCurBtr.openStatus() == Acad::eOk)
    {
      AcDbBlockTableRecordIterator *pIter = NULL;
      if(pCurBtr->newIterator(pIter) == Acad::eOk)
      {
        AcDbObjectId id;
        for(pIter->start();!pIter->done();pIter->step())
        {
          pIter->getEntityId(id);
          AcDbEntityPointer pEnt(id,AcDb::kForRead);
          if(pEnt.openStatus() == eOk)
          {
            for(resbuf* tmp=pEnt->xData(_T("myxdata"));tmp!=NULL;tmp=tmp->rbnext)
            {
              pTail = pTail->rbnext = tmp;
              cnt++;
            }
          }
        }
      }
      delete pIter;
    }
    return cnt;
  }

  static void fillarray(CTypedValueArray &arr,const resbuf *pRb)
  {
    CTypedValue* pPt = (CTypedValue*) arr.GetData();
    for(const resbuf* tmp = pRb;tmp!=NULL;tmp = tmp->rbnext)
    {
      *pPt = CTypedValue(tmp);
      pPt++;
    }
  }
} ;


Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: -+{ Challenge }+- Serialize Xdata
« Reply #21 on: January 22, 2010, 09:39:57 PM »
A little more work for the C++ version, it's a tad faster  :evil:


 :-D

You had to make the point count 500,000 instead of 100,000 just to get a time reading, yes ?  :wink:
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

--> Donate to theSwamp<--

It's Alive!

  • BricsCAD
  • Needs a day job
  • Posts: 6956
  • AKA Daniel
Re: -+{ Challenge }+- Serialize Xdata
« Reply #22 on: January 22, 2010, 10:04:25 PM »
oops sorry, that number is the number of elements in my array, just to test what went out, was what I got back in. 100,000 * (1appname + 4xdata elements).
I thought my .NET version would be closer in performance, I must have done something wrong.  :|
Lisp performed impressively

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: -+{ Challenge }+- Serialize Xdata
« Reply #23 on: January 22, 2010, 10:07:29 PM »

Lisp performed impressively


Generally does  : ) , ... pity it has been treated like a second class citizen.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

--> Donate to theSwamp<--

gile

  • Water Moccasin
  • Posts: 2233
  • Marseille, France
Re: -+{ Challenge }+- Serialize Xdata
« Reply #24 on: January 23, 2010, 02:46:11 AM »
Hi,

My second C# routine (using serialized classes) is quite closed to Daniel's one.

On my computer, they both crashes the same way on deserialization (can't find the assembly):
Quote
Commande: test2
Erreur: Impossible de trouver l'assembly 'SerializeChallenge, Version=1.0.0.0,
Culture=neutral, PublicKeyToken=null'.
Ellapsed milliseconds: 7843.75

Commande: doit
5922.0574 Milliseconds

Commande: undoit
crash Impossible de trouver l'assembly 'SerializeChallenge, Version=1.0.0.0,
Culture=neutral, PublicKeyToken=null'.
11925.9626 Milliseconds

Any idea ?

Code: [Select]
using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.Runtime;
using acadApp = Autodesk.AutoCAD.ApplicationServices.Application;

namespace SerializeChallenge
{
    public class Class2
    {
        [CommandMethod("Test2")]
        public void Test2()
        {
            DateTime t0 = DateTime.Now;
            Document doc = acadApp.DocumentManager.MdiActiveDocument;
            Database db = doc.Database;
            Editor ed = doc.Editor;
            string filename = "C:\\SerializeChallenge.dat";
            List<SerializableResultBuffer> lst = new List<SerializableResultBuffer>();
            using (Transaction tr = db.TransactionManager.StartTransaction())
            {
                BlockTable bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead);
                BlockTableRecord btr =
                    (BlockTableRecord)tr.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForRead);
                foreach (ObjectId id in btr)
                {
                    Entity ent = (Entity)tr.GetObject(id, OpenMode.ForRead, false);
                    ResultBuffer resbuf = ent.XData;
                    if (resbuf == null)
                        continue;
                    lst.Add(new SerializableResultBuffer(resbuf));
                }
                tr.Commit();
            }
            FileStream fs = new FileStream(filename, FileMode.OpenOrCreate, FileAccess.Write);
            try
            {
            BinaryFormatter formatter = new BinaryFormatter();
                formatter.Serialize(fs, lst);
            }
            catch (System.Exception ex)
            {
                ed.WriteMessage("\nErreur: " + ex.Message);
            }
            finally
            {
                fs.Close();
            }

            fs = new FileStream(filename, FileMode.Open, FileAccess.Read);
            try
            {
                BinaryFormatter formatter = new BinaryFormatter();
                lst = (List<SerializableResultBuffer>)formatter.Deserialize(fs);
            }
            catch (System.Exception ex)
            {
                ed.WriteMessage("\nErreur: " + ex.Message);
            }
            finally
            {
                fs.Close();
            }
            foreach (SerializableResultBuffer srb in lst)
            {
                ResultBuffer resbuf = new ResultBuffer();
                foreach (SerializableTypedValue stv in srb.STypedValues)
                {
                    int code = stv.Code;
                    if (code == 1010)
                    {
                        SerializablePoint3d spt = (SerializablePoint3d)stv.Value;
                        resbuf.Add(new TypedValue(code, new Point3d(spt.X, spt.Y, spt.Z)));
                    }
                    else
                        resbuf.Add(new TypedValue(code, stv.Value));
                }
            }
            DateTime t1 = DateTime.Now;
            TimeSpan ts = t1 - t0;
            ed.WriteMessage("\nEllapsed milliseconds: " + ts.TotalMilliseconds.ToString());
        }
    }

    [Serializable]
    public class SerializableResultBuffer
    {
        private List<SerializableTypedValue> stv = new List<SerializableTypedValue>();

        public SerializableResultBuffer(ResultBuffer resbuf)
        {
            TypedValue[] tvs = resbuf.AsArray();
            foreach (TypedValue tv in tvs)
            {
                stv.Add(new SerializableTypedValue(tv));
            }
        }

        public List<SerializableTypedValue> STypedValues
        {
            get { return stv; }
        }
    }

    [Serializable]
    public class SerializableTypedValue
    {
        private int code;
        private object value;

        public SerializableTypedValue(TypedValue tv)
        {
            code = (int)tv.TypeCode;
            value = (code == 1010) ?
                new SerializablePoint3d((Point3d)tv.Value) :
                tv.Value;
        }

        public int Code
        {
            get { return code; }
        }

        public object Value
        {
            get { return value; }
        }
    }

    [Serializable]
    public class SerializablePoint3d
    {
        private double x;
        private double y;
        private double z;

        public SerializablePoint3d(Point3d pt)
        {
            x = pt.X;
            y = pt.Y;
            z = pt.Z;
        }

        public double X
        {
            get { return x; }
        }

        public double Y
        {
            get { return y; }
        }

        public double Z
        {
            get { return z; }
        }
    }
}
Speaking English as a French Frog

It's Alive!

  • BricsCAD
  • Needs a day job
  • Posts: 6956
  • AKA Daniel
Re: -+{ Challenge }+- Serialize Xdata
« Reply #25 on: January 23, 2010, 02:53:03 AM »
Nice work! I needed to netload the DLL from the AutoCAD folder to avoid the error, I think it's some security measure.

gile

  • Water Moccasin
  • Posts: 2233
  • Marseille, France
Re: -+{ Challenge }+- Serialize Xdata
« Reply #26 on: January 23, 2010, 03:30:40 AM »
Quote
Nice work!
Thanks !
I'm proud, it was the first time I used serialization classes and methods.
I thaught I was wrong because of this error. Thanks to fix it.

Anyway this seems to be a slower way than using a XML file. Re-building a ResusultBuffer from a Serializable object looks time expansive.
Speaking English as a French Frog

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: -+{ Challenge }+- Serialize Xdata
« Reply #27 on: January 23, 2010, 10:00:35 PM »

How fast can you doit?


about 3 months I think :)


after spending half an hour reviewing the C++ code
I'll change that to

"about 13 months"
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

--> Donate to theSwamp<--

It's Alive!

  • BricsCAD
  • Needs a day job
  • Posts: 6956
  • AKA Daniel
Re: -+{ Challenge }+- Serialize Xdata
« Reply #28 on: January 23, 2010, 10:17:56 PM »
Nah it's not so bad using CArchive, have a look at this basic 'Serializable' class

Code: [Select]
// derive from
class CNamedHandle: public CObject
{
private:
  CString m_name;
  AcDbHandle m_handle;

protected:
  DECLARE_SERIAL(CNamedHandle)//<------------ need this

public:
  CNamedHandle( void );
  CNamedHandle( const CNamedHandle &src );
  CNamedHandle( const CString &dwgName,const AcDbHandle &handle );
  virtual ~CNamedHandle( void );

  CNamedHandle& operator=( const CNamedHandle& rhs );
  bool operator==( const CNamedHandle& rhs ) const;
  bool operator!=( const CNamedHandle& rhs ) const;

  virtual bool    Equals( const CNamedHandle& rhs ) const;
  virtual void    Serialize( CArchive &ar );//<------------ need this
  virtual CString ToString( void ) const;
  AcDbHandle      getHandle( void ) const;
  void            setHandle(const AcDbHandle &val);
  CString         getDwgName( void ) const;
  void            setDwgName(const CString &val);

  __declspec( property(get=getHandle,put=setHandle) )AcDbHandle Handle;
  __declspec( property(get=getDwgName,put=setDwgName) )CString DwgName;
};

Code: [Select]
#include "StdAfx.h"
#include "NamedHandle.h"

//***** need this ********//
IMPLEMENT_SERIAL( CNamedHandle, CObject, VERSIONABLE_SCHEMA|1)

CNamedHandle::CNamedHandle(void)
: m_name(),m_handle(){}

CNamedHandle::CNamedHandle( const CNamedHandle &src )
: m_name(),m_handle(){}

CNamedHandle::CNamedHandle( const CString &dwgName, const AcDbHandle &handle )
: m_name(dwgName),m_handle(handle){}

CNamedHandle::~CNamedHandle(void){}

CNamedHandle& CNamedHandle::operator=( const CNamedHandle& rhs )
{
  if(this != &rhs)
  {
    m_name = rhs.m_name;
    m_handle = rhs.m_handle;
  }
  return *this;
}

bool CNamedHandle::operator==( const CNamedHandle& rhs ) const
{
  return Equals(rhs);
}

bool CNamedHandle::operator!=( const CNamedHandle& rhs ) const
{
  return !Equals(rhs);
}

bool CNamedHandle::Equals( const CNamedHandle& rhs ) const
{
  return (this->m_name ==  rhs.m_name &&
    this->m_handle ==  rhs.m_handle);
}


void CNamedHandle::Serialize( CArchive &ar ) // <------------ Need this
{
  CObject::Serialize( ar );

  // data out
  if (ar.IsStoring())
  {
    ar << m_name;
    ar << (__int64)m_handle;
  }
  //data in
  else
  {
    ar >> m_name;
    ar >> (__int64&)m_handle;
  }
}

CString CNamedHandle::ToString( void )const
{
  CString str;
  str.Format(_T("(%s, %I64d)"),m_name,(__int64)m_handle);
  return str;
}

AcDbHandle CNamedHandle::getHandle( void ) const
{
  return m_handle;
}

void CNamedHandle::setHandle( const AcDbHandle &val )
{
  m_handle = val;
}

CString CNamedHandle::getDwgName( void ) const
{
  return m_name;
}

void CNamedHandle::setDwgName( const CString &val )
{
  m_name = val;
}

then I just need to call CNamedHandle::Serialize done !

It's Alive!

  • BricsCAD
  • Needs a day job
  • Posts: 6956
  • AKA Daniel
Re: -+{ Challenge }+- Serialize Xdata
« Reply #29 on: January 23, 2010, 10:24:43 PM »
you can then build a Seralizable CArray for your object.

Code: [Select]
#pragma once
#include "afxtempl.h"
#include "NamedHandle.h"

typedef CArray <CNamedHandle, CNamedHandle&> Base_CNamedHandleArray;

class CNamedHandleArray : public Base_CNamedHandleArray
{
public:
  CNamedHandleArray(void);
  virtual ~CNamedHandleArray(void);

public:
  // we can override Serialize
  virtual void Serialize(CArchive& ar);
  void SerializeElements (CArchive& ar, CNamedHandle* pCNamedHandle, INT_PTR nCount);
};

Code: [Select]
#include "StdAfx.h"
#include "NamedHandleArray.h"

CNamedHandleArray::CNamedHandleArray(void)
: Base_CNamedHandleArray(){}

CNamedHandleArray::~CNamedHandleArray(void){}

void CNamedHandleArray::Serialize( CArchive& ar )
{
  ASSERT_VALID(this);

  CObject::Serialize(ar);
  if (ar.IsStoring())
  {
    ar.WriteCount(m_nSize);
  }
  else
  {
    DWORD_PTR nOldSize = ar.ReadCount();
    SetSize(nOldSize, -1);
  }
  SerializeElements(ar, m_pData, m_nSize);
}

//serialize each element
void CNamedHandleArray::SerializeElements( CArchive& ar,
                                           CNamedHandle* pCNamedHandle,
                                           INT_PTR nCount )
{
  for (INT_PTR i = 0; i < nCount; i++, pCNamedHandle++)
  {
    pCNamedHandle->Serialize(ar);
  }
}


then call CNamedHandleArray::Serialize  :laugh:

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: -+{ Challenge }+- Serialize Xdata
« Reply #30 on: January 23, 2010, 10:32:56 PM »
Thanks Dan, I'll work through it eventually :)

The time difference astounds me  !!  .... 8 seconds vs 0.7 seconds.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

--> Donate to theSwamp<--

pkohut

  • Guest
Re: -+{ Challenge }+- Serialize Xdata
« Reply #31 on: February 07, 2010, 08:20:28 PM »
Test results of supplied drawing (500,000 points), 'doit' middle 5 test results from  10 samples.

Only changes was to move the switch statement logic in CTypedValue::CTypedValue( const resbuf *buf )
to a class that holds a jump table of functions.  The class is called like
Code: [Select]
   short type = acdbGroupCodeToType(buf->restype);
   blaze1::op(buf, _value, _valueType, vString);
Because the compiler generated indirect calls through the jump table the speed boost I was looking for didn't
really happen.  Would need to restructor more of the code and try to keep parameters in functions to
3 or less, and have a jmp instead of a call.

Code: [Select]
                 Paul            Dan
              0.677111       0.690452
              0.678350       0.691959
              0.679616       0.695678
              0.680110       0.698469
              0.680415       0.699986

Average       0.679120       0.695309

Finally, Dan's runtime he posted of 0.53? for his i7 machine is what I get when I don't archive the data.

It's Alive!

  • BricsCAD
  • Needs a day job
  • Posts: 6956
  • AKA Daniel
Re: -+{ Challenge }+- Serialize Xdata
« Reply #32 on: February 07, 2010, 09:12:14 PM »
I played with  acdbGroupCodeToType too, I created a switch with all the codes including  ones > 5000, but it made little difference.

I'm still amazed at how fast CArchive is compared to serializing with .NET    :-o


It's Alive!

  • BricsCAD
  • Needs a day job
  • Posts: 6956
  • AKA Daniel
Re: -+{ Challenge }+- Serialize Xdata
« Reply #33 on: February 07, 2010, 09:16:35 PM »
I'm still pondering what kind of serialization I want to use, it seems most like some sort of XML format....  :|

pkohut

  • Guest
Re: -+{ Challenge }+- Serialize Xdata
« Reply #34 on: February 07, 2010, 09:36:14 PM »
Funny, I was just looking at Boost Fusion earlier as a possible XML solution.
Got as far as reading the preface and quick start pages.

http://www.boost.org/doc/libs/1_42_0/libs/fusion/doc/html/fusion/quick_start.html