Hi,
I've made a small change in OrderedCollection in growBy:shift:
I use the primitive VMpr_OrderedCollection_replaceFromToWithStartingAt.
I guess it should be possible to tweak again a bit the behavior:
In addLast or addFirst if we have any free rooms but first is <= 1 or
last >= n we could move instead of allocating a new collection.
Gwen
>From f9c742d176e8f5c43d49acc5f2fb239ba8e871a3 Mon Sep 17 00:00:00 2001
From: Gwenael Casaccio <[email protected]>
Date: Fri, 24 Jun 2011 08:11:59 +0200
Subject: [PATCH] OrderedCollection
---
kernel/OrderColl.st | 11 ++++--
libgst/prims.def | 64 ++++++++++++++++++++++++++++++++++++++++
snprintfv/snprintfv/filament.h | 4 +-
snprintfv/snprintfv/printf.h | 8 ++--
snprintfv/snprintfv/stream.h | 4 +-
5 files changed, 79 insertions(+), 12 deletions(-)
diff --git a/kernel/OrderColl.st b/kernel/OrderColl.st
index 7d15dd4..0adfddc 100644
--- a/kernel/OrderColl.st
+++ b/kernel/OrderColl.st
@@ -508,13 +508,16 @@ on content (such as add:after:)'>
<category: 'private methods'>
| newOrderedCollection |
newOrderedCollection := self copyEmpty: self basicSize + delta.
- firstIndex to: lastIndex
- do:
- [:index |
- newOrderedCollection basicAt: index + shiftCount put: (self basicAt: index)].
+ newOrderedCollection primReplaceFrom: firstIndex + shiftCount to: lastIndex + shiftCount with: self startingAt: firstIndex.
newOrderedCollection firstIndex: firstIndex + shiftCount
lastIndex: lastIndex + shiftCount.
self become: newOrderedCollection
]
+
+ primReplaceFrom: aFromInteger to: aToInteger with: anOrderedCollection startingAt: aStartInteger [
+ <category: 'private methods'>
+
+ <primitive: VMpr_OrderedCollection_replaceFromToWithStartingAt>
+ ]
]
diff --git a/libgst/prims.def b/libgst/prims.def
index 5eff664..dbed9c8 100644
--- a/libgst/prims.def
+++ b/libgst/prims.def
@@ -3303,6 +3303,70 @@ primitive VMpr_ArrayedCollection_replaceFromToWithStartingAt [succeed,fail]
UNPOP (4);
PRIM_FAILED;
}
+
+/* OrderedCollection primReplaceFrom:to:with:startingAt:*/
+primitive VMpr_OrderedCollection_replaceFromToWithStartingAt [succeed,fail]
+{
+ OOP srcIndexOOP, srcOOP, dstEndIndexOOP, dstStartIndexOOP, dstOOP;
+ int dstEndIndex, dstStartIndex, srcIndex, dstLen, srcLen, dstRangeLen;
+ gst_uchar *dstBase, *srcBase;
+ _gst_primitives_executed++;
+
+ srcIndexOOP = POP_OOP ();
+ srcOOP = POP_OOP ();
+ dstEndIndexOOP = POP_OOP ();
+ dstStartIndexOOP = POP_OOP ();
+ dstOOP = STACKTOP ();
+ if COMMON (IS_INT (srcIndexOOP) && IS_INT (dstStartIndexOOP)
+ && IS_INT (dstEndIndexOOP) && !IS_INT (srcOOP))
+ {
+ intptr_t srcSpec = OOP_INSTANCE_SPEC (srcOOP);
+ intptr_t dstSpec = OOP_INSTANCE_SPEC (dstOOP);
+ int srcOffset = srcSpec >> ISP_NUMFIXEDFIELDS;
+ int dstOffset = dstSpec >> ISP_NUMFIXEDFIELDS;
+ int size;
+
+ /* Check compatibility. */
+ size = _gst_log2_sizes[srcSpec & ISP_SHAPE];
+ if (size != _gst_log2_sizes[dstSpec & ISP_SHAPE])
+ goto bad;
+ if (((srcSpec & ISP_INDEXEDVARS) == GST_ISP_POINTER)
+ != ((dstSpec & ISP_INDEXEDVARS) == GST_ISP_POINTER))
+ goto bad;
+
+ /* dstEnd is inclusive: (1 to: 1) has length 1 */
+ dstEndIndex = TO_INT (dstEndIndexOOP);
+ dstStartIndex = TO_INT (dstStartIndexOOP);
+ srcIndex = TO_INT (srcIndexOOP);
+ dstOOP = STACKTOP ();
+ dstLen = NUM_INDEXABLE_FIELDS (dstOOP);
+ srcLen = NUM_INDEXABLE_FIELDS (srcOOP);
+ dstRangeLen = dstEndIndex - dstStartIndex + 1;
+
+ if UNCOMMON (dstRangeLen < 0
+ || dstEndIndex > dstLen || dstStartIndex <= 0
+ || srcIndex + dstRangeLen - 1 > srcLen
+ || (srcIndex <= 0 && dstRangeLen > 0))
+ goto bad;
+
+ /* don't do it unless there's something to copy */
+ if COMMON (dstRangeLen > 0)
+ {
+ /* do the copy */
+ dstBase = (gst_uchar *) &(OOP_TO_OBJ (dstOOP)->data[dstOffset]);
+ srcBase = (gst_uchar *) &(OOP_TO_OBJ (srcOOP)->data[srcOffset]);
+ dstStartIndex = (dstStartIndex - 1) << size;
+ srcIndex = (srcIndex - 1) << size;
+ dstRangeLen <<= size;
+ memmove (&dstBase[dstStartIndex], &srcBase[srcIndex], dstRangeLen);
+ }
+ PRIM_SUCCEEDED;
+ }
+
+ bad:
+ UNPOP (4);
+ PRIM_FAILED;
+}
/* Object == */
diff --git a/snprintfv/snprintfv/filament.h b/snprintfv/snprintfv/filament.h
index 4a91eb6..8a7ce6c 100644
--- a/snprintfv/snprintfv/filament.h
+++ b/snprintfv/snprintfv/filament.h
@@ -1,4 +1,4 @@
-#line 1 "../../../snprintfv/snprintfv/filament.in"
+#line 1 "./filament.in"
/* -*- Mode: C -*- */
/* filament.h --- a bit like a string but different =)O|
@@ -118,7 +118,7 @@ extern char * fildelete (Filament *fil);
extern void _fil_extend (Filament *fil, size_t len, boolean copy);
-#line 61 "../../../snprintfv/snprintfv/filament.in"
+#line 61 "./filament.in"
/* Save the overhead of a function call in the great majority of cases. */
#define fil_maybe_extend(fil, len, copy) \
diff --git a/snprintfv/snprintfv/printf.h b/snprintfv/snprintfv/printf.h
index 49a2e9f..1437dd5 100644
--- a/snprintfv/snprintfv/printf.h
+++ b/snprintfv/snprintfv/printf.h
@@ -1,4 +1,4 @@
-#line 1 "../../../snprintfv/snprintfv/printf.in"
+#line 1 "./printf.in"
/* -*- Mode: C -*- */
/* printf.in --- printf clone for argv arrays
@@ -266,7 +266,7 @@ enum
} \
} SNV_STMT_END
-#line 269 "../../../snprintfv/snprintfv/printf.in"
+#line 269 "./printf.in"
/**
* printf_generic_info:
* @pinfo: the current state information for the format
@@ -302,7 +302,7 @@ extern int printf_generic_info (struct printf_info *const pinfo, size_t n, int *
extern int printf_generic (STREAM *stream, struct printf_info *const pinfo, union printf_arg const *args);
-#line 270 "../../../snprintfv/snprintfv/printf.in"
+#line 270 "./printf.in"
/**
* register_printf_function:
* @spec: the character which will trigger @func, cast to an unsigned int.
@@ -789,7 +789,7 @@ extern int snv_vasprintf (char **result, const char *format, va_list ap);
extern int snv_asprintfv (char **result, const char *format, snv_constpointer const args[]);
-#line 271 "../../../snprintfv/snprintfv/printf.in"
+#line 271 "./printf.in"
/* If you don't want to use snprintfv functions for *all* of your string
formatting API, then define COMPILING_SNPRINTFV_C and use the snv_
diff --git a/snprintfv/snprintfv/stream.h b/snprintfv/snprintfv/stream.h
index 496bd33..0bebce1 100644
--- a/snprintfv/snprintfv/stream.h
+++ b/snprintfv/snprintfv/stream.h
@@ -1,4 +1,4 @@
-#line 1 "../../../snprintfv/snprintfv/stream.in"
+#line 1 "./stream.in"
/* -*- Mode: C -*- */
/* stream.h --- customizable stream routines
@@ -180,7 +180,7 @@ extern int stream_puts (char *s, STREAM *stream);
extern int stream_get (STREAM *stream);
-#line 88 "../../../snprintfv/snprintfv/stream.in"
+#line 88 "./stream.in"
#ifdef __cplusplus
#if 0
/* This brace is so that emacs can still indent properly: */
--
1.7.4.1
_______________________________________________
help-smalltalk mailing list
[email protected]
https://lists.gnu.org/mailman/listinfo/help-smalltalk