[880] in BarnOwl Developers

home help back first fref pref prev next nref lref last post

[D-O-H] r869 - branches/barnowl_sqlite/owl

daemon@ATHENA.MIT.EDU (nelhage@MIT.EDU)
Thu Oct 29 18:10:42 2009

Resent-From: nelhage@mit.edu
Resent-To: barnowl-dev-mtg@charon.mit.edu
To: dirty-owl-hackers@mit.edu
From: nelhage@MIT.EDU
Reply-to: dirty-owl-hackers@MIT.EDU
Date: Mon, 14 Jan 2008 05:04:34 -0500 (EST)

Author: nelhage
Date: 2008-01-14 05:04:33 -0500 (Mon, 14 Jan 2008)
New Revision: 869

Added:
   branches/barnowl_sqlite/owl/owl_perl.h
Modified:
   branches/barnowl_sqlite/owl/Makefile.in
   branches/barnowl_sqlite/owl/global.c
   branches/barnowl_sqlite/owl/mainwin.c
   branches/barnowl_sqlite/owl/message.c
   branches/barnowl_sqlite/owl/messagelist.c
   branches/barnowl_sqlite/owl/owl.c
   branches/barnowl_sqlite/owl/owl.h
   branches/barnowl_sqlite/owl/perlconfig.c
   branches/barnowl_sqlite/owl/perlwrap.pm
Log:
First pass at moving the messagelist into C land. This is not very
tested or stable yet.


Modified: branches/barnowl_sqlite/owl/Makefile.in
===================================================================
--- branches/barnowl_sqlite/owl/Makefile.in	2008-01-14 07:46:51 UTC (rev 868)
+++ branches/barnowl_sqlite/owl/Makefile.in	2008-01-14 10:04:33 UTC (rev 869)
@@ -44,7 +44,7 @@
 AUTOGEN=$(GEN_C) $(GEN_H)
 #AUTOGEN=$(GEN_C)
 
-HEADERS=$(GEN_H) owl.h config.h test.h
+HEADERS=$(GEN_H) owl.h owl_perl.h config.h test.h
 
 %.o: %.c $(HEADERS)
 	$(CC) -c $(CFLAGS) $< -o $@

Modified: branches/barnowl_sqlite/owl/global.c
===================================================================
--- branches/barnowl_sqlite/owl/global.c	2008-01-14 07:46:51 UTC (rev 868)
+++ branches/barnowl_sqlite/owl/global.c	2008-01-14 10:04:33 UTC (rev 869)
@@ -92,7 +92,6 @@
   owl_global_set_confdir(g, cd);
   owl_free(cd);
 
-  owl_messagelist_create(&(g->msglist));
   owl_mainwin_init(&(g->mw));
   owl_popwin_init(&(g->pw));
 
@@ -211,7 +210,7 @@
 /* msglist */
 
 owl_messagelist *owl_global_get_msglist(owl_global *g) {
-  return(&(g->msglist));
+  return g->msglist;
 }
 
 /* keyhandler */

Modified: branches/barnowl_sqlite/owl/mainwin.c
===================================================================
--- branches/barnowl_sqlite/owl/mainwin.c	2008-01-14 07:46:51 UTC (rev 868)
+++ branches/barnowl_sqlite/owl/mainwin.c	2008-01-14 10:04:33 UTC (rev 869)
@@ -113,7 +113,7 @@
     getyx(recwin, y, x);
     wattrset(recwin, A_NORMAL);
     if (owl_global_get_rightshift(&g)==0) {   /* this lame and should be fixed */
-      if (m==owl_view_get_element(v, curmsg)) {
+      if (owl_message_get_id(m)==owl_message_get_id(owl_view_get_element(v, curmsg))) {
 	wmove(recwin, savey, 0);
 	wattron(recwin, A_BOLD);	
 	if (owl_global_get_curmsg_vert_offset(&g)>0) {

Modified: branches/barnowl_sqlite/owl/message.c
===================================================================
--- branches/barnowl_sqlite/owl/message.c	2008-01-14 07:46:51 UTC (rev 868)
+++ branches/barnowl_sqlite/owl/message.c	2008-01-14 10:04:33 UTC (rev 869)
@@ -17,34 +17,7 @@
 static owl_fmtext_cache * fmtext_cache_next = fmtext_cache;
 
 owl_message *owl_message_new() {
-  dSP;
-  SV *msg;
-  int count;
-
-  ENTER;
-  SAVETMPS;
-
-  PUSHMARK(SP);
-  XPUSHs(sv_2mortal(newSVpv("BarnOwl::Message", 0)));
-  PUTBACK;
-
-  count = call_method("new", G_SCALAR|G_EVAL);
-
-  SPAGAIN;
-
-  if (SvTRUE(ERRSV)) {
-    printf("Ooops: %s\n", SvPV_nolen(ERRSV));
-    exit(-1);
-  }
-
-  msg = POPs;
-  SvREFCNT_inc(msg);
-
-  PUTBACK;
-  FREETMPS;
-  LEAVE;
-
-  return (owl_message*)msg;
+  return (owl_message*)owl_perl_new("BarnOwl::Message");
 }
 
 void owl_message_init(owl_message *m)

Modified: branches/barnowl_sqlite/owl/messagelist.c
===================================================================
--- branches/barnowl_sqlite/owl/messagelist.c	2008-01-14 07:46:51 UTC (rev 868)
+++ branches/barnowl_sqlite/owl/messagelist.c	2008-01-14 10:04:33 UTC (rev 869)
@@ -1,97 +1,94 @@
+#define OWL_PERL
 #include "owl.h"
-#include <stdlib.h>
-#include <string.h>
 
 static const char fileIdent[] = "$Id$";
 
-int owl_messagelist_create(owl_messagelist *ml)
-{
-  owl_list_create(&(ml->list));
-  return(0);
+owl_messagelist * owl_messagelist_new() {
+  return (owl_messagelist*)owl_perl_new("BarnOwl::MessageList");
 }
 
 int owl_messagelist_get_size(owl_messagelist *ml)
 {
-  return(owl_list_get_size(&(ml->list)));
+  int size;
+  OWL_PERL_CALL_METHOD(ml, "get_size",
+                       , // No arguments
+                       // Error message
+                       "Error in get_size: %s",
+                       // Errors are fatal
+                       1,
+                       // Success code
+                       size = POPi;
+                       );
+  return size;
 }
 
 void owl_messagelist_start_iterate(owl_messagelist *ml) {
-  ml->iterator = 0;
+  OWL_PERL_CALL_METHOD(ml, "start_iterate",
+                       , // No arguments
+                       // Error
+                       "Error in start_iterate: %s",
+                       1, //Fatal errors
+                       OWL_PERL_VOID_CALL
+                       );
 }
 
 owl_message *owl_messagelist_iterate_next(owl_messagelist *ml) {
-  owl_message *m = NULL;
-  if(ml->iterator >= 0 && ml->iterator < owl_list_get_size(&(ml->list))) {
-    m = owl_list_get_element(&(ml->list), ml->iterator);
-    ml->iterator++;
-  }
-  return m;
+  SV *msg;
+  OWL_PERL_CALL_METHOD(ml, "iterate_next",
+                       , // No arguments
+                       // Error
+                       "Error in iterate_next: %s",
+                       1, //Fatal errors
+                       msg = POPs;
+                       if(SvROK(msg)) SvREFCNT_inc(msg);
+                       );
+  if(SvROK(msg)) return msg;
+  return NULL;
 }
 
 owl_message *owl_messagelist_get_by_id(owl_messagelist *ml, int target_id)
 {
-  /* return the message with id == 'id'.  If it doesn't exist return NULL. */
-  int first, last, mid, msg_id;
-  owl_message *m;
-
-  first = 0;
-  last = owl_list_get_size(&(ml->list)) - 1;
-  while (first <= last) {
-    mid = (first + last) / 2;
-    m = owl_list_get_element(&(ml->list), mid);
-    msg_id = owl_message_get_id(m);
-    if (msg_id == target_id) {
-      return(m);
-    } else if (msg_id < target_id) {
-      first = mid + 1;
-    } else {
-      last = mid - 1;
-    }
-  }
-  return(NULL);
+  SV *msg;
+  OWL_PERL_CALL_METHOD(ml, "get_by_id",
+                       mXPUSHi(target_id); ,
+                       // Error
+                       "Error in get_by_id: %s",
+                       1, //Fatal errors
+                       msg = POPs;
+                       SvREFCNT_inc(msg);
+                       );
+  return msg;
 }
 
-int owl_messagelist_append_element(owl_messagelist *ml, void *element)
+void owl_messagelist_append_element(owl_messagelist *ml, void *element)
 {
-  return(owl_list_append_element(&(ml->list), element));
+  OWL_PERL_CALL_METHOD(ml, "add_message",
+                       XPUSHs((SV*)element); ,
+                       // Error
+                       "Error in add_message: %s",
+                       1, // Fatal
+                       OWL_PERL_VOID_CALL
+                       );
 }
 
-int owl_messagelist_expunge(owl_messagelist *ml)
+void owl_messagelist_expunge(owl_messagelist *ml)
 {
-  /* expunge deleted messages */
-  int i, j;
-  owl_list newlist;
-  owl_message *m;
-
-  owl_list_create(&newlist);
-  /*create a new list without messages marked as deleted */
-  j=owl_list_get_size(&(ml->list));
-  for (i=0; i<j; i++) {
-    m=owl_list_get_element(&(ml->list), i);
-    if (owl_message_is_delete(m)) {
-      owl_message_free(m);
-    } else {
-      owl_list_append_element(&newlist, m);
-    }
-  }
-
-  /* free the old list */
-  owl_list_free_simple(&(ml->list));
-
-  /* copy the new list to the old list */
-  memcpy(&(ml->list), &newlist, sizeof(owl_list));
-
-  return(0);
+  OWL_PERL_CALL_METHOD(ml, "expunge",
+                       , // No args
+                       // Error
+                       "Error in expunge: %s",
+                       1, // Fatal
+                       OWL_PERL_VOID_CALL
+                       );
 }
 
 void owl_messagelist_invalidate_formats(owl_messagelist *ml)
 {
-  int i, j;
   owl_message *m;
 
-  j=owl_list_get_size(&(ml->list));
-  for (i=0; i<j; i++) {
-    m=owl_list_get_element(&(ml->list), i);
+  owl_messagelist_iterate_next(ml);
+
+  while((m = owl_messagelist_iterate_next(ml)) != NULL) {
     owl_message_invalidate_format(m);
   }
 }

Modified: branches/barnowl_sqlite/owl/owl.c
===================================================================
--- branches/barnowl_sqlite/owl/owl.c	2008-01-14 07:46:51 UTC (rev 868)
+++ branches/barnowl_sqlite/owl/owl.c	2008-01-14 10:04:33 UTC (rev 869)
@@ -247,6 +247,9 @@
     exit(1);
   }
 
+  /* Now that we have perl, we can initialize the msssage list*/
+  g.msglist = owl_messagelist_new();
+
   /* setup the built-in styles */
   owl_function_debugmsg("startup: creating built-in styles");
 

Modified: branches/barnowl_sqlite/owl/owl.h
===================================================================
--- branches/barnowl_sqlite/owl/owl.h	2008-01-14 07:46:51 UTC (rev 868)
+++ branches/barnowl_sqlite/owl/owl.h	2008-01-14 10:04:33 UTC (rev 869)
@@ -67,6 +67,7 @@
 /* aim.h defines bool */
 #define HAS_BOOL
 #include <perl.h>
+#include "owl_perl.h"
 #undef logout
 #include "XSUB.h"
 #else
@@ -403,10 +404,7 @@
   int rfd;  
 } owl_popexec;
 
-typedef struct _owl_messagelist {
-  owl_list list;
-  int iterator;
-} owl_messagelist;
+typedef SV owl_messagelist;
 
 typedef struct _owl_regex {
   int negate;
@@ -556,7 +554,7 @@
   int curmsg, topmsg;
   int curmsg_vert_offset;
   owl_view current_view;
-  owl_messagelist msglist;
+  owl_messagelist *msglist;
   WINDOW *recwin, *sepwin, *msgwin, *typwin;
   int needrefresh;
   int rightshift;

Added: branches/barnowl_sqlite/owl/owl_perl.h
===================================================================
--- branches/barnowl_sqlite/owl/owl_perl.h	                        (rev 0)
+++ branches/barnowl_sqlite/owl/owl_perl.h	2008-01-14 10:04:33 UTC (rev 869)
@@ -0,0 +1,55 @@
+#ifndef INC_OWL_PERL_H
+#define INC_OWL_PERL_H
+
+#define OWL_PERL_VOID_CALL (void)POPs;
+
+/*
+ * This macro defines a convenience wrapper around the boilerplate of
+ * calling a method on a perl object (SV*) from C.
+ *
+ * Arguments are
+ * * obj    - the SV* to call the method on
+ * * meth   - a char* method name
+ * * args   - a code block responsible for pushing args (other than the object)
+ * * err    - a string with a %s format specifier to log in case of error
+ * * fatalp - if true, perl errors terminate barnowl
+ * * ret    - a code block executed if the call succeeded
+ *
+ * See also: `perldoc perlcall', `perldoc perlapi'
+ */
+#define OWL_PERL_CALL_METHOD(obj, meth, args, err, fatalp, ret) { \
+    int count; \
+    dSP; \
+    ENTER; \
+    SAVETMPS; \
+    PUSHMARK(SP); \
+    XPUSHs(obj); \
+    {args} \
+    PUTBACK; \
+    \
+    count = call_method(meth, G_SCALAR|G_EVAL); \
+    \
+    SPAGAIN; \
+    \
+    if(count != 1) { \
+      fprintf(stderr, "perl returned wrong count: %d\n", count); \
+      abort();                                                   \
+    } \
+    if (SvTRUE(ERRSV)) { \
+      if(fatalp) { \
+        printf(err, SvPV_nolen(ERRSV)); \
+        exit(-1); \
+      } else { \
+        owl_function_error(err, SvPV_nolen(ERRSV)); \
+        (void)POPs; \
+        sv_setsv(ERRSV, &PL_sv_undef); \
+      } \
+    } else { \
+      ret; \
+    } \
+    PUTBACK; \
+    FREETMPS; \
+    LEAVE; \
+}
+
+#endif //INC_PERL_PERL_H

Modified: branches/barnowl_sqlite/owl/perlconfig.c
===================================================================
--- branches/barnowl_sqlite/owl/perlconfig.c	2008-01-14 07:46:51 UTC (rev 868)
+++ branches/barnowl_sqlite/owl/perlconfig.c	2008-01-14 10:04:33 UTC (rev 869)
@@ -397,3 +397,17 @@
   }
   return;
 }
+
+SV * owl_perl_new(char *class)
+{
+  SV *obj;
+  OWL_PERL_CALL_METHOD(sv_2mortal(newSVpv(class, 0)), "new",
+                       // No args
+                       ,
+                       "Error in perl: %s\n",
+                       1,
+                       obj = POPs;
+                       SvREFCNT_inc(obj);
+                       );
+  return obj;
+}

Modified: branches/barnowl_sqlite/owl/perlwrap.pm
===================================================================
--- branches/barnowl_sqlite/owl/perlwrap.pm	2008-01-14 07:46:51 UTC (rev 868)
+++ branches/barnowl_sqlite/owl/perlwrap.pm	2008-01-14 10:04:33 UTC (rev 869)
@@ -288,6 +288,57 @@
 #####################################################################
 #####################################################################
 
+package BarnOwl::MessageList;
+
+sub new {
+    my $class = shift;
+    my $self = {messages => {}};
+    return bless $self, $class;
+}
+
+sub get_size {
+    my $self = shift;
+    return scalar keys %{$self->{messages}};
+}
+
+sub start_iterate {
+    my $self = shift;
+    $self->{keys} = [sort {$a <=> $b} keys %{$self->{messages}}];
+    $self->{iterator} = 0;
+}
+
+sub iterate_next {
+    my $self = shift;
+    if($self->{iterator} >= scalar @{$self->{keys}}) {
+        return undef;
+    }
+    return $self->get_by_id($self->{keys}->[$self->{iterator}++]);
+}
+
+sub get_by_id {
+    my $self = shift;
+    my $id = shift;
+    return $self->{messages}{$id};
+}
+
+sub add_message {
+    my $self = shift;
+    my $m = shift;
+    $self->{messages}->{$m->id} = $m;
+}
+
+sub expunge {
+    my $self = shift;
+    for my $message (values %{$self->{messages}}) {
+        if($message->is_deleted) {
+            delete $self->{messages}->{$message->id};
+        }
+    }
+}
+
+#####################################################################
+#####################################################################
+
 package BarnOwl::Message;
 use POSIX qw(ctime);
 


home help back first fref pref prev next nref lref last post