[Xfce4-commits] <glib-objc:no-foundation-dep> WIP: string stuff

Brian J. Tarricone noreply at xfce.org
Sun Nov 22 04:02:20 CET 2009


Updating branch refs/heads/no-foundation-dep
         to 77118dd5d7cfd682cef9ae5c7ff0a2a1fcc39c7a (commit)
       from d5c7bec9bec6f9b8eade690b3c08d67211def16d (commit)

commit 77118dd5d7cfd682cef9ae5c7ff0a2a1fcc39c7a
Author: Brian J. Tarricone <brian at tarricone.org>
Date:   Tue Aug 11 03:36:44 2009 -0700

    WIP: string stuff

 configure.ac.in                                  |   37 +++
 glib-objc/{GOCIterable.h => GOCConstantString.h} |   25 +-
 glib-objc/GOCString.h                            |  103 +++++++
 glib-objc/GOCString.m                            |  311 ++++++++++++++++++++++
 gobject-objc/GOCObject.m                         |   44 ++--
 5 files changed, 486 insertions(+), 34 deletions(-)

diff --git a/configure.ac.in b/configure.ac.in
index 72e3819..99e36eb 100644
--- a/configure.ac.in
+++ b/configure.ac.in
@@ -134,6 +134,40 @@ AC_MSG_CHECKING([the type signature of enums])
 GOC_ARGTYPE_ENUM='e'
 AC_MSG_RESULT([$GOC_ARGTYPE_ENUM])
 
+dnl figure out if we can use our own constant string class
+AC_MSG_CHECKING([if $CC supports -fconstant-string-class])
+saved_CPPFLAGS="$CPPFLAGS"
+CPPFLAGS="$CPPFLAGS -fconstant-string-class=TestConstantString"
+AC_LANG_PUSH([Objective C])
+AC_RUN_IFELSE(
+[AC_LANG_PROGRAM(
+  [
+    #import <objc/Object.h>
+
+    @interface TestConstantString : Object
+    {
+        const char *c_string;
+        unsigned int length;
+    }
+    @end
+  ],
+  [
+    TestConstantString *conststr = @"this is a test";
+  ])],
+  [
+    GOC_CONSTANT_STRING_CLASS=GOCConstantString
+    GOC_CONSTANT_STRING_PCFILE_CFLAGS="-fconstant-string-class=$GOC_CONSTANT_STRING_CLASS"
+    AC_MSG_RESULT([yes])
+  ],
+  [
+    GOC_CONSTANT_STRING_CLASS=NXConstantString
+    GOC_CONSTANT_STRING_CPPFLAGS="-DGOCConstantString=NXConstantString"
+    AC_MSG_RESULT([no])
+  ])
+CPPFLAGS="$saved_CPPFLAGS $GOC_CONSTANT_STRING_CPPFLAGS"
+AC_SUBST(GOC_CONSTANT_STRING_PCFILE_CFLAGS)
+AC_SUBST(GOC_CONSTANT_STRING_CLASS)
+
 dnl check for debugging support
 AC_ARG_ENABLE([debug],
               [AC_HELP_STRING([--enable-debug=[full|yes|no]],
@@ -176,6 +210,8 @@ AC_CONFIG_COMMANDS([glib-objc-config.h],
 #define __GOC_ARGTYPE_FLAGS        "$argtype_flags"
 #define __GOC_ARGTYPE_ENUM         "$argtype_enum"
 
+#define GOC_CONSTANT_STRING_CLASS  $const_str_class
+
 #endif  /* __GLIB_OBJC_CONFIG_H__ */
 __EOF
     if cmp -s $outfile glib-objc-config.h; then
@@ -189,6 +225,7 @@ __EOF
     argtype_bool=$GOC_ARGTYPE_BOOL
     argtype_flags=$GOC_ARGTYPE_FLAGS
     argtype_enum=$GOC_ARGTYPE_ENUM
+    const_str_class=$GOC_CONSTANT_STRING_CLASS
 ])
 
 AC_OUTPUT([
diff --git a/glib-objc/GOCIterable.h b/glib-objc/GOCConstantString.h
similarity index 79%
copy from glib-objc/GOCIterable.h
copy to glib-objc/GOCConstantString.h
index 5e15e9e..3e3d977 100644
--- a/glib-objc/GOCIterable.h
+++ b/glib-objc/GOCConstantString.h
@@ -17,20 +17,19 @@
  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
  */
 
-#ifndef __GOC_ITERABLE_H__
-#define __GOC_ITERABLE_H__
+#ifndef __GOC_CONSTANT_STRING__
+#define __GOC_CONSTANT_STRING__
 
- at protocol GOCIter
+ at interface GOCConstantString
+{
+    Class isa;
+    char *c_string;
+    unsigned int length;
+}
 
-- (id <GOCObject>)next;
+- (const char *)cString;
+- (unsigned int)length;
 
- at end
+ at endif
 
- at protocol GOCIterable
-
-- (id <GOCIter>)getIter;
-
- at end
-
-
-#endif  /* __GOC_ITERABLE_H__ */
+#endif
diff --git a/glib-objc/GOCString.h b/glib-objc/GOCString.h
new file mode 100644
index 0000000..fcdff60
--- /dev/null
+++ b/glib-objc/GOCString.h
@@ -0,0 +1,103 @@
+/*
+ *  glib-objc - objective-c bindings for glib/gobject
+ *
+ *  Copyright (c) 2009 Brian Tarricone <brian at tarricone.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU Lesser General Public License as published
+ *  by the Free Software Foundation; version 2 of the License ONLY.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU Library General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+#ifndef __GOC_STRING_H__
+#define __GOC_STRING_H__
+
+
+#include <glib.h>
+#import <glib-objc/GOCObjectBase.h>
+
+typedef struct _GOCStringPriv  GOCStringPriv;
+
+ at interface GOCString : GOCObjectBase <GOCComparable>
+{
+  @private
+    GOCStringPriv *gspriv;
+}
+
++ (id)stringWithCString:(const char *)cString
+               encoding:(const char *)encoding;
++ (id)stringWithUTF8String:(const char *)utf8String;
++ (id)stringWithFormat:(const char *)format,...;
++ (id)stringWithString:(GOCString *)aString;
+
+/* this is the designated initializer */
+- (id)initWithCString:(const char *)cString
+             encoding:(const char *)encoding;
+- (id)initWithUTF8String:(const char *)utf8String;
+- (id)initWithFormat:(const char *)format,...;
+- (id)initWithString:(GOCString *)aString;
+
+- (id)initWithBytes:(const char *)byteString
+             length:(int)length
+           encoding:(const char *)encoding;
+- (id)initWithBytes:(const char *)byteString
+             length:(int)length
+           encoding:(const char *)encoding
+      takeOwnership:(BOOL)takeOwnership;
+
+/* length in characters */
+- (unsigned int)length;
+
+- (gunichar)characterAtIndex:(int)pos;
+/* returns utf8 representation of the character.  buffer must be at least
+ * four bytes long (no checking is done).  returns NO if char doesn't exist */
+- (BOOL)characterAtIndex:(int)pos
+                inBuffer:(char *)buffer;
+
+- (const char *)cStringUsingEncoding:(const char *)encoding;
+- (const char *)UTF8String;
+
+- (GOCString *)substringfromIndex:(int)pos
+                         ofLength:(unsigned int)length;
+
+/* modifies the string */
+- (void)appendString:(GOCString *)aString;
+- (void)appendCString:(const char *)cString
+             encoding:(const char *)encoding;
+- (void)appendUTF8String:(const char *)utf8String;
+- (void)appendFormat:(const char *)format,...;
+
+- (void)insertString:(GOCString *)aString
+             atIndex:(int)pos;
+- (void)insertCString:(const char *)cString
+              atIndex:(int)pos;
+- (void)insertUTF8String:(const char *)utf8String;
+- (void)insertFormat:(const char *)format,...;
+
+- (void)makeLower;
+- (void)makeUpper;
+
+/* returns new autounref'd strings */
+- (GOCString *)stringAsLower;
+- (GOCString *)stringAsUpper;
+
+- (BOOL)hasPrefix:(GOCString *)aString;
+- (BOOL)hasSuffix:(GOCString *)aString;
+
+/* attempts to convert the string to a numeric value */
+- (BOOL)boolValue;
+- (int)intValue;
+- (long long)int64Value;
+- (double)doubleValue;
+
+ at end
+
+#endif  /* __GOC_STRING_H__ */
diff --git a/glib-objc/GOCString.m b/glib-objc/GOCString.m
new file mode 100644
index 0000000..ae1a597
--- /dev/null
+++ b/glib-objc/GOCString.m
@@ -0,0 +1,311 @@
+/*
+ *  glib-objc - objective-c bindings for glib/gobject
+ *
+ *  Copyright (c) 2009 Brian Tarricone <brian at tarricone.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU Lesser General Public License as published
+ *  by the Free Software Foundation; version 2 of the License ONLY.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU Library General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#import "GOString.h"
+
+struct _GOCStringPriv
+{
+    GString *gstr;
+    unsigned int length_chars;
+    GCache *encoded_strings;
+};
+
+ at implementation GOCString : GOCObjectBase <GOCComparable>
+
+- (id)_initWithFormat:(const char *)format
+             encoding:(const char *)encoding
+           andArgList:(va_list)var_args;
+{
+    char *new_string = NULL;
+
+    /* TODO: do stuff */
+
+    return [self initWithBytes:new_string
+                        length:strlen(new_string)
+                      encoding:encoding
+                 takeOwnership:YES];
+}            
+
++ (id)stringWithCString:(const char *)cString
+               encoding:(const char *)encoding
+{
+    return [[[GOCString alloc] initWithCString:cString encoding:encoding] autounref];    
+}
+
++ (id)stringWithUTF8String:(const char *)utf8String
+{
+    return [GOCString stringWithCString:utf8String encoding:"UTF-8"];
+}
+
++ (id)stringWithFormat:(const char *)format,...
+{
+    va_list var_args;
+    id ret;
+
+    va_start(var_args, format);
+    ret = [[[GOCString alloc] _initWithFormat:format
+                                     encoding:"UTF-8"
+                                   andArgList:var_args];
+    va_end(var_args);
+
+    return ret;
+}
+
++ (id)stringWithString:(GOCString *)aString
+{
+    return [self stringWithUTF8String:[aString UTF8String]];
+}
+
+/* this is the designated initializer */
+- (id)initWithCString:(const char *)cString
+             encoding:(const char *)encoding
+{
+    if(!cString)
+        return [self init];
+    return [self initWithBytes:cString
+                        length:strlen(cString)
+                      encoding:encoding
+                 takeOwnership:NO];
+}
+
+- (id)initWithUTF8String:(const char *)utf8String
+{
+    if(!tf8String)
+        return [self init];
+    return [self initWithBytes:utf8String
+                        length:strlen(utf8String)
+                      encoding:"UTF-8"
+                 takeOwnership:NO];
+}
+
+- (id)initWithFormat:(const char *)format,...
+{
+    va_list var_args;
+    id ret;
+
+    va_start(var_args, format);
+    ret = [[[GOCString alloc] _initWithFormat:format
+                                     encoding:"UTF-8"
+                                   andArgList:var_args];
+    va_end(var_args);
+
+    return ret;
+}
+
+- (id)initWithFormat:(const char *)format
+            encoding:(const char *)encoding
+           arguments:...
+{
+    va_list var_args;
+    id ret;
+
+    va_start(var_args, encoding);
+    ret = [[[GOCString alloc] _initWithFormat:format
+                                     encoding:encoding
+                                   andArgList:var_args];
+    va_end(var_args);
+
+    return ret;
+}
+
+- (id)initWithString:(GOCString *)aString
+{
+    return [self initWithUTF8String:[aString UTF8String]];
+}
+
+- (id)initWithBytes:(const char *)byteString
+             length:(int)length
+           encoding:(const char *)encoding
+{
+    return [self initWithBytes:byteString
+                        length:length
+                      encoding:encoding
+                 takeOwnership:NO];
+}
+
+- (id)initWithBytes:(const char *)byteString
+             length:(int)length
+           encoding:(const char *)encoding
+      takeOwnership:(BOOL)takeOwnership;
+{
+    self = [super init];
+    if(self) {
+        gspriv = g_slice_new0(GOCStringPriv);
+        
+        if(takeOwnership) {
+            /* this is probably evil and broken */
+            gspriv->gstr = g_slice_new0(GString);
+            gspriv->gstr->str = (char *)byteString;
+            gspriv->allocated_len = length + 1;
+            gspriv->len = length;
+        } else
+            gspriv->gstr = g_string_new_len(byteString, length);
+
+        gspriv->length_chars = g_utf8_strlen(gspriv->gstr->str);
+
+        /* FIXME: need to pass struct { GString, encoding } to new func */
+        gspriv->encoded_strings = g_cache_new((GCacheNewFunc)cached_string_new,
+                                              (GCacheDestroyFunc)g_free,
+                                              (GCacheDupFunc)g_strdup,
+                                              (GCacheDestroyFunc)g_free,
+                                              g_str_hash, g_str_hash,
+                                              g_str_equal);
+    }
+    return self;
+}
+
+/* length in characters */
+- (unsigned int)length
+{
+    return gspriv->length_chars;
+}
+
+- (gunichar)characterAtIndex:(int)pos;
+/* returns utf8 representation of the character.  buffer must be at least
+ * four bytes long (no checking is done).  returns NO if char doesn't exist */
+- (BOOL)characterAtIndex:(int)pos
+                inBuffer:(char *)buffer;
+
+- (const char *)cStringUsingEncoding:(const char *)encoding
+{
+    gchar *new_str = NULL;
+    gsize bread = 0, bwritten = 0;
+    GError **error = NULL;
+
+    new_str = g_hash_table_lookup(gspriv->cached_encodings, encoding);
+    if(new_str)
+        return new_str;
+
+    new_str = g_convert(gspriv->gstr->str, gspriv->gstr->len, encoding,
+                        "UTF-8", &bread, &bwritten, &error);
+    if(error) {
+        g_warning("Unable to convert string to %s: %s", encoding, error->message);
+        if(new_str)
+            g_free(new_str);
+        g_error_free(error);
+        return NULL;
+    }
+
+    if(new_str)
+        g_hash_table_replace(gspriv->cached_encodings, g_strdup(encoding), new_str);
+
+    return new_str;
+}
+
+- (const char *)UTF8String
+{
+    return gspriv->gstr->str;  //[self cStringUsingEncoding:"UTF-8"];
+}
+
+- (GOCString *)substringfromIndex:(int)pos
+                         ofLength:(unsigned int)length
+{
+
+}
+
+- (void)appendString:(GOCString *)aString
+{
+
+    g_hash_table_remove_all(gspriv->cached_encodings);
+}
+
+- (void)appendCString:(const char *)cString
+             encoding:(const char *)encoding
+{
+
+    g_hash_table_remove_all(gspriv->cached_encodings);
+}
+- (void)appendUTF8String:(const char *)utf8String
+{
+
+    g_hash_table_remove_all(gspriv->cached_encodings);
+}
+
+- (void)appendFormat:(const char *)format,...
+{
+
+    g_hash_table_remove_all(gspriv->cached_encodings);
+}
+
+- (void)insertString:(GOCString *)aString
+             atIndex:(int)pos
+{
+
+    g_hash_table_remove_all(gspriv->cached_encodings);
+}
+
+- (void)insertCString:(const char *)cString
+              atIndex:(int)pos
+{
+
+    g_hash_table_remove_all(gspriv->cached_encodings);
+}
+
+- (void)insertUTF8String:(const char *)utf8String
+{
+
+    g_hash_table_remove_all(gspriv->cached_encodings);
+}
+
+- (void)insertFormat:(const char *)format,...
+{
+
+    g_hash_table_remove_all(gspriv->cached_encodings);
+}
+
+- (void)makeLower
+{
+
+    g_hash_table_remove_all(gspriv->cached_encodings);
+}
+
+- (void)makeUpper
+{
+
+    g_hash_table_remove_all(gspriv->cached_encodings);
+}
+
+/* returns new autounref'd strings */
+- (GOCString *)stringAsLower;
+- (GOCString *)stringAsUpper;
+
+- (BOOL)hasPrefix:(GOCString *)aString;
+- (BOOL)hasSuffix:(GOCString *)aString;
+
+/* attempts to convert the string to a numeric value */
+- (BOOL)boolValue;
+- (int)intValue;
+- (long long)int64Value;
+- (double)doubleValue;
+
+- (void)free
+{
+    g_hash_table_destroy(gspriv->cached_encodings);
+    g_string_free(gspriv->gstr, TRUE);
+
+    g_slice_free(GOCStringPriv, gspriv);
+
+    [super free];
+}
+
+ at end
diff --git a/gobject-objc/GOCObject.m b/gobject-objc/GOCObject.m
index 1d7d61d..1cd3deb 100644
--- a/gobject-objc/GOCObject.m
+++ b/gobject-objc/GOCObject.m
@@ -26,6 +26,7 @@
 #import "GOCObject.h"
 #import "GOCValue.h"
 #import "GOCBoxedValue.h"
+#import "GOCClosure.h"
 #include "gobject-objc-private.h"
 #include "goc-private.h"
 
@@ -45,7 +46,8 @@ typedef struct
     guint signal_id;
     GQuark detail;
     BOOL after;
-    NSInvocation *invocation;  /* FIXME: no-ns */
+
+    GOCClosure *closure;
 } ObjCClosure;
 
 typedef struct
@@ -178,41 +180,41 @@ gobject_objc_marshal_signal(GClosure *closure,
 {
     GOCAutoreleasePool *pool = [[GOCAutoreleasePool alloc] init];
     ObjCClosure *occlosure = (ObjCClosure *)closure;
-    NSInvocation *invoc = occlosure->invocation;  /* FIXME: no-ns */
-    id param;
+    GOCClosure *gclo = occlosure->closure;
+    GOCValue **argv;
+    GOCValue *retval;
     int i;
     gboolean clear_target = FALSE;
+
+    argv = g_new0(GOCValue *, n_param_values + 1);
     
     for(i = 0; i < n_param_values; ++i) {
-        param = _gobject_objc_nsobject_from_gvalue(&param_values[i]);  /* FIXME: no-ns */
-        if(!param) {
+        argv[i] = _gobject_objc_gocvalue_from_gvalue(&param_values[i]);
+        if(!argv[i]) {
             g_critical("%s: couldn't marshal value of type \"%s\"", PACKAGE,
                        G_VALUE_TYPE_NAME(&param_values[i]));
         }
-        
-        [invoc setArgument:param atIndex:i+2];  /* FIXME: no-ns */
     }
 
-    if(![invoc target]) {
+    /* FIXME: this needs rethinking -- why do we want 'self' in the arglist at all? */
+    if(![gclo target]) {
         /* this is to handle class closures */
         id target = nil;
-        [invoc getArgument:&target atIndex:2];  /* FIXME: no-ns */
-        [invoc setTarget:target];  /* FIXME: no-ns */
+        [gclo setTarget:argv[0]];
         clear_target = TRUE;
     }
-    
-    [invoc invoke];  /* FIXME: no-ns */
+
+    retval = [gclo invokeWithInvocationHint:invocation_hint andArgV:argv];
     
     if(G_VALUE_TYPE(return_value)) {
-        id ret = nil;
-        [invoc getReturnValue:(void *)&ret];  /* FIXME: no-ns */
-        _gobject_objc_gvalue_from_nsobject(return_value, ret, FALSE);  /* FIXME: no-ns */
+        /* FIXME: i don't recall what the bool value is supposed to do */
+        _gobject_objc_gvalue_from_gocvalue(return_value, ret, FALSE);
     }
 
     if(clear_target)
-        [invoc setTarget:nil];  /* FIXME: no-ns */
+        [gclo setTarget:nil];
     
-    [pool unref];  /* FIXME: no-ns */
+    [pool unref];
 }
 
 static gboolean
@@ -242,7 +244,7 @@ gobject_objc_accumulate_signal(GSignalInvocationHint *ihint,
     _gobject_objc_gvalue_from_nsobject(return_accu, returnAccu, FALSE);  /* FIXME: no-ns */
     [invoc getReturnValue:&ret];  /* FIXME: no-ns */
 
-    [pool unref];  /* FIXME: no-ns */
+    [pool unref];
 
     return ret;
 }
@@ -252,7 +254,7 @@ objc_closure_finalize(gpointer data,
                       GClosure *closure)
 {
     ObjCClosure *occlosure = (ObjCClosure *)closure;
-    [occlosure->invocation release];
+    [occlosure->closure unref];
 }
 
 static void
@@ -273,7 +275,7 @@ gobject_objc_gobject_set_property(GObject *obj,
         return;
     }
 
-    nsobject = _gobject_objc_nsobject_from_gvalue(value);
+    nsobject = _gobject_objc_nsobject_from_gvalue(value);  /* FIXME: no-ns */
 
     pool = [[GOCAutoreleasePool alloc] init];
     [objCObj performSelector:@selector(handleSetProperty:toValue:)
@@ -305,7 +307,7 @@ gobject_objc_gobject_get_property(GObject *obj,
                              withObject:[NSString stringWithUTF8String:g_param_spec_get_name(pspec)]];
     [pool unref];
 
-    _gobject_objc_gvalue_from_nsobject(value, nsobject, NO);
+    _gobject_objc_gvalue_from_nsobject(value, nsobject, NO);  /* FIXME: no-ns */
 }
 
 



More information about the Xfce4-commits mailing list