[Spice-commits] 6 commits - common/canvas_base.c common/gdi_canvas.c common/gl_canvas.c python_modules/demarshal.py python_modules/marshal.py python_modules/ptypes.py server/red_parse_qxl.c server/red_worker.c spice1.proto spice.proto

Alexander Larsson alexl at kemper.freedesktop.org
Mon Jul 5 11:47:21 PDT 2010


 common/canvas_base.c        |   21 ++---
 common/gdi_canvas.c         |   13 +--
 common/gl_canvas.c          |   12 +--
 python_modules/demarshal.py |  173 +++++++++++++++++++++++++-------------------
 python_modules/marshal.py   |    6 -
 python_modules/ptypes.py    |   15 ++-
 server/red_parse_qxl.c      |    9 +-
 server/red_worker.c         |    7 -
 spice.proto                 |    2 
 spice1.proto                |    4 -
 10 files changed, 145 insertions(+), 117 deletions(-)

New commits:
commit f39d64f40bca094396d5002dcfcd38eaa281c9af
Author: Alexander Larsson <alexl at redhat.com>
Date:   Mon Jul 5 20:45:13 2010 +0200

    Convert SpicePath.segments to a pointer array

diff --git a/common/canvas_base.c b/common/canvas_base.c
index 53d13f2..a0429a6 100644
--- a/common/canvas_base.c
+++ b/common/canvas_base.c
@@ -3062,7 +3062,6 @@ static void canvas_draw_stroke(SpiceCanvas *spice_canvas, SpiceRect *bbox,
         stroke_fill_spans,
         stroke_fill_rects
     };
-    SpicePathSeg *seg;
     StrokeLines lines;
     unsigned int i;
     int dashed;
@@ -3165,24 +3164,22 @@ static void canvas_draw_stroke(SpiceCanvas *spice_canvas, SpiceRect *bbox,
         CANVAS_ERROR("invalid brush type");
     }
 
-    seg = (SpicePathSeg*)stroke->path->segments;
-
     stroke_lines_init(&lines);
 
     for (i = 0; i < stroke->path->num_segments; i++) {
-        uint32_t flags = seg->flags;
-        SpicePointFix* point = seg->points;
-        SpicePointFix* end_point = point + seg->count;
-        ASSERT(point < end_point);
-        seg = (SpicePathSeg*)end_point;
+        SpicePathSeg *seg = stroke->path->segments[i];
+        SpicePointFix* point, *end_point;
+
+        point = seg->points;
+        end_point = point + seg->count;
 
-        if (flags & SPICE_PATH_BEGIN) {
+        if (seg->flags & SPICE_PATH_BEGIN) {
             stroke_lines_draw(&lines, (lineGC *)&gc, dashed);
             stroke_lines_append_fix(&lines, point);
             point++;
         }
 
-        if (flags & SPICE_PATH_BEZIER) {
+        if (seg->flags & SPICE_PATH_BEZIER) {
             ASSERT((point - end_point) % 3 == 0);
             for (; point + 2 < end_point; point += 3) {
                 stroke_lines_append_bezier(&lines,
@@ -3196,8 +3193,8 @@ static void canvas_draw_stroke(SpiceCanvas *spice_canvas, SpiceRect *bbox,
                 stroke_lines_append_fix(&lines, point);
             }
         }
-        if (flags & SPICE_PATH_END) {
-            if (flags & SPICE_PATH_CLOSE) {
+        if (seg->flags & SPICE_PATH_END) {
+            if (seg->flags & SPICE_PATH_CLOSE) {
                 stroke_lines_append(&lines,
                                     lines.points[0].x, lines.points[0].y);
             }
diff --git a/common/gdi_canvas.c b/common/gdi_canvas.c
index e348994..9c52002 100644
--- a/common/gdi_canvas.c
+++ b/common/gdi_canvas.c
@@ -310,17 +310,14 @@ uint32_t raster_ops[] = {
 
 static void set_path(GdiCanvas *canvas, SpicePath *s)
 {
-    SpicePathSeg* seg = (SpicePathSeg*)s->segments;
     unsigned int i;
 
     for (i = 0; i < s->num_segments; i++) {
-        uint32_t flags = seg->flags;
+        SpicePathSeg* seg = s->segments[0];
         SpicePointFix* point = seg->points;
         SpicePointFix* end_point = point + seg->count;
-        ASSERT(point < end_point);
-        seg = (SpicePathSeg*)end_point;
 
-        if (flags & SPICE_PATH_BEGIN) {
+        if (seg->flags & SPICE_PATH_BEGIN) {
             BeginPath(canvas->dc);
             if (!MoveToEx(canvas->dc, (int)fix_to_double(point->x), (int)fix_to_double(point->y),
                           NULL)) {
@@ -330,7 +327,7 @@ static void set_path(GdiCanvas *canvas, SpicePath *s)
             point++;
         }
 
-        if (flags & SPICE_PATH_BEZIER) {
+        if (seg->flags & SPICE_PATH_BEZIER) {
             ASSERT((point - end_point) % 3 == 0);
             for (; point + 2 < end_point; point += 3) {
                 POINT points[3];
@@ -355,9 +352,9 @@ static void set_path(GdiCanvas *canvas, SpicePath *s)
             }
         }
 
-        if (flags & SPICE_PATH_END) {
+        if (seg->flags & SPICE_PATH_END) {
 
-            if (flags & SPICE_PATH_CLOSE) {
+            if (seg->flags & SPICE_PATH_CLOSE) {
                 if (!CloseFigure(canvas->dc)) {
                     CANVAS_ERROR("CloseFigure failed");
                 }
diff --git a/common/gl_canvas.c b/common/gl_canvas.c
index 3e02a25..f0e10dd 100644
--- a/common/gl_canvas.c
+++ b/common/gl_canvas.c
@@ -115,20 +115,18 @@ static GLCPath get_path(GLCanvas *canvas, SpicePath *s)
 {
     GLCPath path = glc_path_create(canvas->glc);
     int i;
-    SpicePathSeg* seg = (SpicePathSeg*)s->segments;
 
     for (i = 0; i < s->num_segments; i++) {
-        uint32_t flags = seg->flags;
+        SpicePathSeg* seg = s->segments[i];
         SpicePointFix* point = seg->points;
         SpicePointFix* end_point = point + seg->count;
-        seg = (SpicePathSeg*)end_point;
 
-        if (flags & SPICE_PATH_BEGIN) {
+        if (seg->flags & SPICE_PATH_BEGIN) {
             glc_path_move_to(path, fix_to_double(point->x), fix_to_double(point->y));
             point++;
         }
 
-        if (flags & SPICE_PATH_BEZIER) {
+        if (seg->flags & SPICE_PATH_BEZIER) {
             ASSERT((point - end_point) % 3 == 0);
             for (; point + 2 < end_point; point += 3) {
                 glc_path_curve_to(path,
@@ -141,8 +139,8 @@ static GLCPath get_path(GLCanvas *canvas, SpicePath *s)
                 glc_path_line_to(path, fix_to_double(point->x), fix_to_double(point->y));
             }
         }
-        if (flags & SPICE_PATH_END) {
-            if (flags & SPICE_PATH_CLOSE) {
+        if (seg->flags & SPICE_PATH_END) {
+            if (seg->flags & SPICE_PATH_CLOSE) {
                 glc_path_close(path);
             }
         }
diff --git a/python_modules/demarshal.py b/python_modules/demarshal.py
index 606b926..bd7660d 100644
--- a/python_modules/demarshal.py
+++ b/python_modules/demarshal.py
@@ -47,13 +47,16 @@ def write_parser_helpers(writer):
             swap = "SPICE_BYTESWAP%d" % size
             if size == 8:
                 writer.macro("read_%s" % type, "ptr", "(*((%s_t *)(ptr)))" % type)
+                writer.macro("write_%s" % type, "ptr, val", "*(%s_t *)(ptr) = val" % (type))
             else:
                 writer.macro("read_%s" % type, "ptr", "((%s_t)%s(*((%s_t *)(ptr)))" % (type, swap, utype))
+                writer.macro("write_%s" % type, "ptr, val", "*(%s_t *)(ptr) = %s((%s_t)val)" % (utype, swap, utype))
     writer.writeln("#else")
     for size in [8, 16, 32, 64]:
         for sign in ["", "u"]:
             type = "%sint%d" % (sign, size)
             writer.macro("read_%s" % type, "ptr", "(*((%s_t *)(ptr)))" % type)
+            writer.macro("write_%s" % type, "ptr, val", "(*((%s_t *)(ptr))) = val" % type)
     writer.writeln("#endif")
 
     for size in [8, 16, 32, 64]:
@@ -96,6 +99,15 @@ def write_read_primitive(writer, start, container, name, scope):
     writer.assign(var, "read_%s(pos)" % (m.member_type.primitive_type()))
     return var
 
+def write_write_primitive(writer, start, container, name, val):
+    m = container.lookup_member(name)
+    assert(m.is_primitive())
+    writer.assign("pos", start + " + " + container.get_nw_offset(m, "", "__nw_size"))
+
+    var = "%s__value" % (name)
+    writer.statement("write_%s(pos, %s)" % (m.member_type.primitive_type(), val))
+    return var
+
 def write_read_primitive_item(writer, item, scope):
     assert(item.type.is_primitive())
     writer.assign("pos", item.get_position())
@@ -280,6 +292,9 @@ def write_validate_array_item(writer, container, item, scope, parent_scope, star
     element_type = array.element_type
     if array.is_bytes_length():
         nelements = "%s__nbytes" %(item.prefix)
+        real_nelements = "%s__nelements" %(item.prefix)
+        if not parent_scope.variable_defined(real_nelements):
+            parent_scope.variable_def("uint32_t", real_nelements)
     else:
         nelements = "%s__nelements" %(item.prefix)
     if not parent_scope.variable_defined(nelements):
@@ -315,6 +330,7 @@ def write_validate_array_item(writer, container, item, scope, parent_scope, star
         is_byte_size = True
         v = write_read_primitive(writer, start, container, array.size[1], scope)
         writer.assign(nelements, v)
+        writer.assign(real_nelements, 0)
     elif array.is_cstring_length():
         writer.todo("cstring array size type not handled yet")
     else:
@@ -389,6 +405,8 @@ def write_validate_array_item(writer, container, item, scope, parent_scope, star
 
     with writer.index(no_block = is_byte_size) as index:
         with writer.while_loop("%s < %s" % (start2, start2_end) ) if is_byte_size else writer.for_loop(index, nelements) as scope:
+            if is_byte_size:
+                writer.increment(real_nelements, 1)
             write_validate_item(writer, container, element_item, scope, parent_scope, start2,
                                 want_element_nw_size, want_mem_size, want_extra_size)
 
@@ -405,6 +423,7 @@ def write_validate_array_item(writer, container, item, scope, parent_scope, star
             writer.increment(start2, start_increment)
     if is_byte_size:
         writer.error_check("%s != %s" % (start2, start2_end))
+        write_write_primitive(writer, start, container, array.size[1], real_nelements)
 
 def write_validate_struct_item(writer, container, item, scope, parent_scope, start,
                                want_nw_size, want_mem_size, want_extra_size):
@@ -613,11 +632,9 @@ class SubDemarshallingDestination(DemarshallingDestination):
     def get_ref(self, member):
         return self.parent_dest.get_ref(self.member) + "." + member
 
-def read_array_len(writer, prefix, array, dest, scope, handles_bytes = False):
-    if array.is_bytes_length():
-        nelements = "%s__nbytes" % prefix
-    else:
-        nelements = "%s__nelements" % prefix
+# Note: during parsing, byte_size types have been converted to count during validation
+def read_array_len(writer, prefix, array, dest, scope):
+    nelements = "%s__nelements" % prefix
     if dest.is_toplevel():
         return nelements # Already there for toplevel, need not recalculate
     element_type = array.element_type
@@ -645,9 +662,7 @@ def read_array_len(writer, prefix, array, dest, scope, handles_bytes = False):
         else:
             writer.assign(nelements, "((%s * %s + 7) / 8 ) * %s" % (bpp, width_v, rows_v))
     elif array.is_bytes_length():
-        if not handles_bytes:
-            raise NotImplementedError("handling of bytes() not supported here yet")
-        writer.assign(nelements, array.size[1])
+        writer.assign(nelements, dest.get_ref(array.size[2]))
     else:
         raise NotImplementedError("TODO array size type not handled yet")
     return nelements
@@ -758,24 +773,16 @@ def write_array_parser(writer, nelements, array, dest, scope):
         writer.increment("in", nelements)
         writer.increment("end", nelements)
     else:
-        if is_byte_size:
-            real_nelements = nelements[:-len("nbytes")] + "nelements"
-            scope.variable_def("uint8_t *", "array_end")
-            scope.variable_def("uint32_t", real_nelements)
-            writer.assign("array_end", "end + %s" % nelements)
-            writer.assign(real_nelements, 0)
         if array.has_attr("ptr_array"):
             scope.variable_def("void **", "ptr_array")
             scope.variable_def("int", "ptr_array_index")
             writer.assign("ptr_array_index", 0)
             writer.assign("ptr_array", "(void **)end")
             writer.increment("end", "sizeof(void *) * %s" % nelements)
-        with writer.index(no_block = is_byte_size) as index:
-            with writer.while_loop("end < array_end") if is_byte_size else writer.for_loop(index, nelements) as array_scope:
+        with writer.index() as index:
+            with writer.for_loop(index, nelements) as array_scope:
                 if array.has_attr("ptr_array"):
                     writer.statement("ptr_array[ptr_array_index++] = end")
-                if is_byte_size:
-                    writer.increment(real_nelements, 1)
                 if element_type.is_primitive():
                     writer.statement("*(%s *)end = consume_%s(&in)" % (element_type.c_type(), element_type.primitive_type()))
                     writer.increment("end", element_type.sizeof())
@@ -786,8 +793,6 @@ def write_array_parser(writer, nelements, array, dest, scope):
                 if array.has_attr("ptr_array"):
                     writer.comment("Align ptr_array element to 4 bytes").newline()
                     writer.assign("end", "(uint8_t *)SPICE_ALIGN((size_t)end, 4)")
-        if is_byte_size:
-            writer.assign(dest.get_ref(array.size[2]), real_nelements)
 
 def write_parse_pointer(writer, t, at_end, dest, member_name, scope):
     as_c_ptr = t.has_attr("c_ptr")
@@ -831,14 +836,14 @@ def write_member_parser(writer, container, member, dest, scope):
             writer.increment("end", t.sizeof())
         else:
             if member.has_attr("bytes_count"):
-                scope.variable_def("uint32_t", member.name);
-                dest_var = member.name
+                print member.attributes["bytes_count"]
+                dest_var = dest.get_ref(member.attributes["bytes_count"][0])
             else:
                 dest_var = dest.get_ref(member.name)
             writer.assign(dest_var, "consume_%s(&in)" % (t.primitive_type()))
         #TODO validate e.g. flags and enums
     elif t.is_array():
-        nelements = read_array_len(writer, member.name, t, dest, scope, handles_bytes = True)
+        nelements = read_array_len(writer, member.name, t, dest, scope)
         if member.has_attr("as_ptr") and t.element_type.is_fixed_nw_size():
             writer.comment("use array as pointer").newline()
             writer.assign(dest.get_ref(member.name), "(%s *)in" % t.element_type.c_type())
diff --git a/server/red_parse_qxl.c b/server/red_parse_qxl.c
index d38cad7..56f17dc 100644
--- a/server/red_parse_qxl.c
+++ b/server/red_parse_qxl.c
@@ -153,7 +153,7 @@ static SpicePath *red_get_path(RedMemSlotInfo *slots, int group_id,
     bool free_data;
     QXLPath *qxl;
     SpicePath *red;
-    size_t size, mem_size, mem_size2, dsize;
+    size_t size, mem_size, mem_size2, dsize, segment_size;
     int n_segments;
     int i;
     uint32_t count;
@@ -173,7 +173,8 @@ static SpicePath *red_get_path(RedMemSlotInfo *slots, int group_id,
     while (start < end) {
         n_segments++;
         count = start->count;
-        mem_size += sizeof(SpicePathSeg) + count * sizeof(SpicePointFix);
+        segment_size = sizeof(SpicePathSeg) + count * sizeof(SpicePointFix);
+        mem_size += sizeof(SpicePathSeg *) + SPICE_ALIGN(segment_size, 4);
         start = (QXLPathSeg*)(&start->points[count]);
     }
 
@@ -182,11 +183,11 @@ static SpicePath *red_get_path(RedMemSlotInfo *slots, int group_id,
 
     start = (QXLPathSeg*)data;
     end = (QXLPathSeg*)(data + size);
-    seg = (SpicePathSeg*)red->segments;
+    seg = (SpicePathSeg*)&red->segments[n_segments];
     n_segments = 0;
     mem_size2 = sizeof(*red);
     while (start < end) {
-        n_segments++;
+        red->segments[n_segments++] = seg;
         count = start->count;
 
         /* Protect against overflow in size calculations before
diff --git a/server/red_worker.c b/server/red_worker.c
index ff0a049..255a46e 100644
--- a/server/red_worker.c
+++ b/server/red_worker.c
@@ -2296,9 +2296,10 @@ static int is_equal_path(RedWorker *worker, SpicePath *path1, SpicePath *path2)
     if (path1->num_segments != path2->num_segments)
         return FALSE;
 
-    seg1 = (SpicePathSeg*)&path1->segments[0];
-    seg2 = (SpicePathSeg*)&path2->segments[0];
     for (i = 0; i < path1->num_segments; i++) {
+        seg1 = path1->segments[i];
+        seg2 = path2->segments[i];
+
         if (seg1->flags != seg2->flags ||
             seg1->count != seg2->count) {
             return FALSE;
@@ -2309,8 +2310,6 @@ static int is_equal_path(RedWorker *worker, SpicePath *path1, SpicePath *path2)
                 return FALSE;
             }
         }
-        seg1 = (SpicePathSeg*)(&seg1->points[seg1->count]);
-        seg2 = (SpicePathSeg*)(&seg2->points[seg2->count]);
     }
 
     return TRUE;
diff --git a/spice.proto b/spice.proto
index 8df1238..e437630 100644
--- a/spice.proto
+++ b/spice.proto
@@ -393,7 +393,7 @@ struct PathSegment {
 
 struct Path {
     uint32 num_segments;
-    PathSegment segments[num_segments] @end;
+    PathSegment segments[num_segments] @ptr_array;
 };
 
 struct Clip {
diff --git a/spice1.proto b/spice1.proto
index 982f666..b49371a 100644
--- a/spice1.proto
+++ b/spice1.proto
@@ -374,8 +374,8 @@ struct PathSegment {
 }  @ctype(SpicePathSeg);
 
 struct Path {
-    uint32 segments_size @bytes_count;
-    PathSegment segments[bytes(segments_size, num_segments)] @end;
+    uint32 segments_size @bytes_count(num_segments);
+    PathSegment segments[bytes(segments_size, num_segments)] @ptr_array;
 };
 
 struct Clip {
commit 6dcf43912e752b8c61199017718ccfb067b45576
Author: Alexander Larsson <alexl at redhat.com>
Date:   Mon Jul 5 13:13:39 2010 +0200

    Handle extra size for switch and array the right way
    
    Even for is_extra_size() we should calculate the mem_size for
    arrays, its just that the parent type (in this case switch) should
    request mem_size if the type is_extra_size.

diff --git a/python_modules/demarshal.py b/python_modules/demarshal.py
index cf6fefd..606b926 100644
--- a/python_modules/demarshal.py
+++ b/python_modules/demarshal.py
@@ -150,13 +150,19 @@ def write_validate_switch_member(writer, container, switch_member, scope, parent
         with writer.if_block(check, not first, False) as if_scope:
             item.type = c.member.member_type
             item.subprefix = item.prefix + "_" + m.name
-            sub_want_extra_size = want_extra_size
-            if sub_want_extra_size and not m.contains_extra_size() and not m.is_extra_size():
-                writer.assign(item.extra_size(), 0)
-                sub_want_extra_size = False
+
+            all_as_extra_size = m.is_extra_size() and want_extra_size
+            if not want_mem_size and all_as_extra_size and not scope.variable_defined(item.mem_size()):
+                scope.variable_def("uint32_t", item.mem_size())
+
+            sub_want_mem_size = want_mem_size or all_as_extra_size
+            sub_want_extra_size = want_extra_size and not all_as_extra_size
 
             write_validate_item(writer, container, item, if_scope, scope, start,
-                                want_nw_size, want_mem_size, sub_want_extra_size)
+                                want_nw_size, sub_want_mem_size, sub_want_extra_size)
+
+            if all_as_extra_size:
+                writer.assign(item.extra_size(), item.mem_size())
 
         first = False
 
@@ -341,7 +347,7 @@ def write_validate_array_item(writer, container, item, scope, parent_scope, star
             writer.assign(mem_size, "%s * %s" % (element_type.sizeof(), nelements))
         want_mem_size = False
 
-    if not element_type.contains_extra_size() and not array.is_extra_size() and want_extra_size:
+    if not element_type.contains_extra_size() and want_extra_size:
         writer.assign(extra_size, 0)
         want_extra_size = False
 
@@ -361,21 +367,14 @@ def write_validate_array_item(writer, container, item, scope, parent_scope, star
     element_extra_size = element_item.extra_size()
     scope.variable_def("uint32_t", element_nw_size)
     scope.variable_def("uint32_t", element_mem_size)
-    want_is_extra_size = False
-    want_element_mem_size = want_mem_size
     if want_extra_size:
-        if array.is_extra_size():
-            want_is_extra_size = True
-            want_extra_size = False
-            want_element_mem_size = True
-        else:
-            scope.variable_def("uint32_t", element_extra_size)
+        scope.variable_def("uint32_t", element_extra_size)
 
     if want_nw_size:
         writer.assign(nw_size, 0)
     if want_mem_size:
         writer.assign(mem_size, 0)
-    if want_extra_size or want_is_extra_size:
+    if want_extra_size:
         writer.assign(extra_size, 0)
 
     want_element_nw_size = want_nw_size
@@ -391,19 +390,16 @@ def write_validate_array_item(writer, container, item, scope, parent_scope, star
     with writer.index(no_block = is_byte_size) as index:
         with writer.while_loop("%s < %s" % (start2, start2_end) ) if is_byte_size else writer.for_loop(index, nelements) as scope:
             write_validate_item(writer, container, element_item, scope, parent_scope, start2,
-                                want_element_nw_size, want_element_mem_size, want_extra_size)
+                                want_element_nw_size, want_mem_size, want_extra_size)
 
             if want_nw_size:
                 writer.increment(nw_size, element_nw_size)
             if want_mem_size:
-                if not array.is_extra_size():
-                    writer.increment(mem_size, element_mem_size)
-            if want_is_extra_size:
                 if array.has_attr("ptr_array"):
-                    writer.increment(extra_size, "sizeof(void *) + SPICE_ALIGN(%s, 4)" % element_mem_size)
+                    writer.increment(mem_size, "sizeof(void *) + SPICE_ALIGN(%s, 4)" % element_mem_size)
                 else:
-                    writer.increment(extra_size, "%s + %s" % (element_mem_size, element_extra_size))
-            elif want_extra_size:
+                    writer.increment(mem_size, element_mem_size)
+            if want_extra_size:
                 writer.increment(extra_size, element_extra_size)
 
             writer.increment(start2, start_increment)
@@ -426,7 +422,8 @@ def write_validate_primitive_item(writer, container, item, scope, parent_scope,
     if want_mem_size:
         mem_size = item.mem_size()
         writer.assign(mem_size, item.type.sizeof())
-    assert not want_extra_size
+    if want_extra_size:
+        writer.assign(item.extra_size(), 0)
 
 def write_validate_item(writer, container, item, scope, parent_scope, start,
                         want_nw_size, want_mem_size, want_extra_size):
commit b8524fc33861cbb7000631ccc647af109b0399ef
Author: Alexander Larsson <alexl at redhat.com>
Date:   Mon Jul 5 13:13:09 2010 +0200

    marshaller: Add some docs describing the types of sizes

diff --git a/python_modules/demarshal.py b/python_modules/demarshal.py
index 5709567..cf6fefd 100644
--- a/python_modules/demarshal.py
+++ b/python_modules/demarshal.py
@@ -1,6 +1,35 @@
 import ptypes
 import codegen
 
+# The handling of sizes is somewhat complex, as there are several types of size:
+# * nw_size
+#   This is the network size, i.e. the number of bytes on the network
+#
+# * mem_size
+#   The total amount of memory used for the representation of something inside
+#   spice. This is generally sizeof(C struct), but can be larger if for instance
+#   the type has a variable size array at the end or has a pointer in it that
+#   points to another data chunk (which will be allocated after the main
+#   data chunk). This is essentially how much memory you need to allocate to
+#   contain the data type.
+#
+# * extra_size
+#   This is the size of anything that is not part of the containing structure.
+#   For instance, a primitive (say uint32_t) member has no extra size, because
+#   when allocating its part of the sizeof(MessageStructType) struct. However
+#   a variable array can be places at the end of a structure (@end) and its
+#   size is then extra_size. Note that this extra_size is included in the
+#   mem_size of the enclosing struct, and even if you request the mem_size
+#   of the array itself. However, extra_size is typically not requested
+#   when the full mem_size is also requested.
+#
+#   extra sizes come in two flavours. contains_extra_size means that the item
+#   has a normal presence in the parent container, but has some additional
+#   extra_size it references. For instance via a pointer somewhere in it.
+#   There is also is_extra_size(). This indicates that the whole elements
+#   "normal" mem size should be considered extra size for the container, so
+#   when computing the parent mem_size you should add the mem_size of this
+#   part as extra_size
 
 def write_parser_helpers(writer):
     if writer.is_generated("helper", "demarshaller"):
commit d161994f46af7c77e428f11fea84eb34fc097449
Author: Alexander Larsson <alexl at redhat.com>
Date:   Mon Jul 5 12:13:45 2010 +0200

    marshaller: Make @nonnull a propagated attribute
    
    This cleans up some stuff

diff --git a/python_modules/demarshal.py b/python_modules/demarshal.py
index 5a8f8ff..5709567 100644
--- a/python_modules/demarshal.py
+++ b/python_modules/demarshal.py
@@ -82,7 +82,6 @@ class ItemInfo:
         self.prefix = prefix
         self.subprefix = prefix
         self.position = position
-        self.non_null = False
         self.member = None
 
     def nw_size(self):
@@ -103,7 +102,6 @@ class MemberItemInfo(ItemInfo):
             self.type = member.member_type
         self.prefix = member.name
         self.subprefix = member.name
-        self.non_null = member.has_attr("nonnull")
         self.position = "(%s + %s)" % (start, container.get_nw_offset(member, "", "__nw_size"))
         self.member = member
 
@@ -123,7 +121,6 @@ def write_validate_switch_member(writer, container, switch_member, scope, parent
         with writer.if_block(check, not first, False) as if_scope:
             item.type = c.member.member_type
             item.subprefix = item.prefix + "_" + m.name
-            item.non_null = c.member.has_attr("nonnull")
             sub_want_extra_size = want_extra_size
             if sub_want_extra_size and not m.contains_extra_size() and not m.is_extra_size():
                 writer.assign(item.extra_size(), 0)
@@ -192,7 +189,7 @@ def write_validate_pointer_item(writer, container, item, scope, parent_scope, st
         target_type = item.type.target_type
 
         v = write_read_primitive_item(writer, item, scope)
-        if item.non_null:
+        if item.type.has_attr("nonnull"):
             writer.error_check("%s == 0" % v)
 
         # pointer target is struct, or array of primitives
diff --git a/python_modules/marshal.py b/python_modules/marshal.py
index f151d94..df0c3b3 100644
--- a/python_modules/marshal.py
+++ b/python_modules/marshal.py
@@ -235,7 +235,7 @@ def write_pointer_marshaller(writer, member, src):
     submarshaller = "spice_marshaller_get_ptr_submarshaller(m, %d)" % (1 if member.get_fixed_nw_size() == 8 else 0)
     if member.has_attr("marshall"):
         writer.assign("m2", submarshaller)
-        if member.has_attr("nonnull"):
+        if t.has_attr("nonnull"):
             writer.statement("%s(m2, %s)" % (ptr_func, src.get_ref(member.name)))
         else:
             with writer.if_block("%s != NULL" % src.get_ref(member.name)) as block:
diff --git a/python_modules/ptypes.py b/python_modules/ptypes.py
index 2c0dd88..31ae79d 100644
--- a/python_modules/ptypes.py
+++ b/python_modules/ptypes.py
@@ -60,7 +60,7 @@ class FixedSize:
 # only to attributes that affect pointer or array attributes, as these
 # are member local types, unlike e.g. a Struct that may be used by
 # other members
-propagated_attributes=["ptr_array", "c_ptr"]
+propagated_attributes=["ptr_array", "c_ptr", "nonnull"]
 
 class Type:
     def __init__(self):
commit d7164a0669b0f8c6531b1728f4fbda32647942ba
Author: Alexander Larsson <alexl at redhat.com>
Date:   Mon Jul 5 12:09:08 2010 +0200

    marshaller: Make @c_ptr a propagated attribute
    
    This simplifies some code

diff --git a/python_modules/demarshal.py b/python_modules/demarshal.py
index 5391e53..5a8f8ff 100644
--- a/python_modules/demarshal.py
+++ b/python_modules/demarshal.py
@@ -657,7 +657,7 @@ def write_switch_parser(writer, container, switch, dest, scope):
             if t.is_struct():
                 write_container_parser(writer, t, dest2)
             elif t.is_pointer():
-                write_parse_pointer(writer, t, False, m.has_attr("c_ptr"), dest2, m.name, block)
+                write_parse_pointer(writer, t, False, dest2, m.name, block)
             elif t.is_primitive():
                 if m.has_attr("zero"):
                     writer.statement("consume_%s(&in)" % (t.primitive_type()))
@@ -766,21 +766,22 @@ def write_array_parser(writer, nelements, array, dest, scope):
         if is_byte_size:
             writer.assign(dest.get_ref(array.size[2]), real_nelements)
 
-def write_parse_pointer(writer, t, at_end, as_c_ptr, dest, member_name, scope):
-        target_type = t.target_type
-        writer.assign("ptr_info[n_ptr].offset", "consume_%s(&in)" % t.primitive_type())
-        writer.assign("ptr_info[n_ptr].parse", write_parse_ptr_function(writer, target_type))
-        if at_end:
-            writer.assign("ptr_info[n_ptr].dest", "end")
-            writer.increment("end", "sizeof(void *)" if as_c_ptr else "sizeof(SPICE_ADDRESS)");
-        else:
-            writer.assign("ptr_info[n_ptr].dest", "&%s" % dest.get_ref(member_name))
-        writer.assign("ptr_info[n_ptr].is_ptr", "1" if as_c_ptr else "0")
-        if target_type.is_array():
-            nelements = read_array_len(writer, member_name, target_type, dest, scope)
-            writer.assign("ptr_info[n_ptr].nelements", nelements)
+def write_parse_pointer(writer, t, at_end, dest, member_name, scope):
+    as_c_ptr = t.has_attr("c_ptr")
+    target_type = t.target_type
+    writer.assign("ptr_info[n_ptr].offset", "consume_%s(&in)" % t.primitive_type())
+    writer.assign("ptr_info[n_ptr].parse", write_parse_ptr_function(writer, target_type))
+    if at_end:
+        writer.assign("ptr_info[n_ptr].dest", "end")
+        writer.increment("end", "sizeof(void *)" if as_c_ptr else "sizeof(SPICE_ADDRESS)");
+    else:
+        writer.assign("ptr_info[n_ptr].dest", "&%s" % dest.get_ref(member_name))
+    writer.assign("ptr_info[n_ptr].is_ptr", "1" if as_c_ptr else "0")
+    if target_type.is_array():
+        nelements = read_array_len(writer, member_name, target_type, dest, scope)
+        writer.assign("ptr_info[n_ptr].nelements", nelements)
 
-        writer.statement("n_ptr++")
+    writer.statement("n_ptr++")
 
 def write_member_parser(writer, container, member, dest, scope):
     if member.has_attr("virtual"):
@@ -798,7 +799,7 @@ def write_member_parser(writer, container, member, dest, scope):
             writer.comment("Reuse data from network message").newline()
             writer.assign(dest.get_ref(member.name), "(size_t)(message_start + consume_%s(&in))" % t.primitive_type())
         else:
-            write_parse_pointer(writer, t, member.has_end_attr(), member.has_attr("c_ptr"), dest, member.name, scope)
+            write_parse_pointer(writer, t, member.has_end_attr(), dest, member.name, scope)
     elif t.is_primitive():
         if member.has_attr("zero"):
             writer.statement("consume_%s(&in)" % t.primitive_type())
diff --git a/python_modules/ptypes.py b/python_modules/ptypes.py
index cc74b72..2c0dd88 100644
--- a/python_modules/ptypes.py
+++ b/python_modules/ptypes.py
@@ -60,7 +60,7 @@ class FixedSize:
 # only to attributes that affect pointer or array attributes, as these
 # are member local types, unlike e.g. a Struct that may be used by
 # other members
-propagated_attributes=["ptr_array"]
+propagated_attributes=["ptr_array", "c_ptr"]
 
 class Type:
     def __init__(self):
commit 4a60f1822a356e4e1e2d7ecd2d18f4e3fce48f85
Author: Alexander Larsson <alexl at redhat.com>
Date:   Mon Jul 5 12:03:34 2010 +0200

    marshaller: Add generic way to handle propagating attributes
    
    Also switches @ptr_array to use this

diff --git a/python_modules/demarshal.py b/python_modules/demarshal.py
index 4d3e79b..5391e53 100644
--- a/python_modules/demarshal.py
+++ b/python_modules/demarshal.py
@@ -309,7 +309,7 @@ def write_validate_array_item(writer, container, item, scope, parent_scope, star
 
     if element_type.is_fixed_sizeof() and want_mem_size and not is_byte_size:
         # TODO: Overflow check the multiplication
-        if array.ptr_array:
+        if array.has_attr("ptr_array"):
             writer.assign(mem_size, "sizeof(void *) + SPICE_ALIGN(%s * %s, 4)" % (element_type.sizeof(), nelements))
         else:
             writer.assign(mem_size, "%s * %s" % (element_type.sizeof(), nelements))
@@ -373,7 +373,7 @@ def write_validate_array_item(writer, container, item, scope, parent_scope, star
                 if not array.is_extra_size():
                     writer.increment(mem_size, element_mem_size)
             if want_is_extra_size:
-                if array.ptr_array:
+                if array.has_attr("ptr_array"):
                     writer.increment(extra_size, "sizeof(void *) + SPICE_ALIGN(%s, 4)" % element_mem_size)
                 else:
                     writer.increment(extra_size, "%s + %s" % (element_mem_size, element_extra_size))
@@ -741,7 +741,7 @@ def write_array_parser(writer, nelements, array, dest, scope):
             scope.variable_def("uint32_t", real_nelements)
             writer.assign("array_end", "end + %s" % nelements)
             writer.assign(real_nelements, 0)
-        if array.ptr_array:
+        if array.has_attr("ptr_array"):
             scope.variable_def("void **", "ptr_array")
             scope.variable_def("int", "ptr_array_index")
             writer.assign("ptr_array_index", 0)
@@ -749,7 +749,7 @@ def write_array_parser(writer, nelements, array, dest, scope):
             writer.increment("end", "sizeof(void *) * %s" % nelements)
         with writer.index(no_block = is_byte_size) as index:
             with writer.while_loop("end < array_end") if is_byte_size else writer.for_loop(index, nelements) as array_scope:
-                if array.ptr_array:
+                if array.has_attr("ptr_array"):
                     writer.statement("ptr_array[ptr_array_index++] = end")
                 if is_byte_size:
                     writer.increment(real_nelements, 1)
@@ -760,7 +760,7 @@ def write_array_parser(writer, nelements, array, dest, scope):
                     dest2 = dest.child_at_end(writer, element_type)
                     dest2.reuse_scope = array_scope
                     write_container_parser(writer, element_type, dest2)
-                if array.ptr_array:
+                if array.has_attr("ptr_array"):
                     writer.comment("Align ptr_array element to 4 bytes").newline()
                     writer.assign("end", "(uint8_t *)SPICE_ALIGN((size_t)end, 4)")
         if is_byte_size:
diff --git a/python_modules/marshal.py b/python_modules/marshal.py
index 95413fc..f151d94 100644
--- a/python_modules/marshal.py
+++ b/python_modules/marshal.py
@@ -186,13 +186,13 @@ def write_array_marshaller(writer, at_end, member, array, container_src, scope):
     element = "%s__element" % member.name
 
     if not scope.variable_defined(element):
-        if array.ptr_array:
+        if array.has_attr("ptr_array"):
             stars = " **"
         else:
             stars = " *"
         scope.variable_def(element_type.c_type() + stars, element)
     element_array = element
-    if array.ptr_array:
+    if array.has_attr("ptr_array"):
         element = "*" + element
 
     if not at_end:
diff --git a/python_modules/ptypes.py b/python_modules/ptypes.py
index 055034e..cc74b72 100644
--- a/python_modules/ptypes.py
+++ b/python_modules/ptypes.py
@@ -55,6 +55,13 @@ class FixedSize:
                 s = s + " + ((minor >= %d)?%d:0)" % (i, self.vals[i])
         return s
 
+# Some attribute are propagated from member to the type as they really
+# are part of the type definition, rather than the member. This applies
+# only to attributes that affect pointer or array attributes, as these
+# are member local types, unlike e.g. a Struct that may be used by
+# other members
+propagated_attributes=["ptr_array"]
+
 class Type:
     def __init__(self):
         self.attributes = {}
@@ -353,7 +360,6 @@ class ArrayType(Type):
 
         self.element_type = element_type
         self.size = size
-        self.ptr_array = False
 
     def __str__(self):
         if self.size == None:
@@ -416,7 +422,7 @@ class ArrayType(Type):
         raise Exception, "Pointer names in arrays not supported"
 
     def is_extra_size(self):
-        return self.ptr_array
+        return self.has_attr("ptr_array")
 
     def contains_extra_size(self):
         return self.element_type.contains_extra_size()
@@ -516,8 +522,9 @@ class Member(Containee):
         self.member_type.register()
         if self.has_attr("ptr32") and self.member_type.is_pointer():
             self.member_type.set_ptr_size(4)
-        if self.has_attr("ptr_array") and self.member_type.is_array():
-            self.member_type.ptr_array = True
+        for i in propagated_attributes:
+            if self.has_attr(i):
+                self.member_type.attributes[i] = self.attributes[i]
         return self
 
     def is_primitive(self):


More information about the Spice-commits mailing list