[vlc-commits] epg: do ordered inserts and optimize merging

Francois Cartegnie git at videolan.org
Sat Feb 13 15:44:06 CET 2016


vlc | branch: master | Francois Cartegnie <fcvlcdev at free.fr> | Fri Feb 12 20:30:06 2016 +0100| [d9db85c3b8e48e74f393ba83577cc0873e85e1b9] | committer: Francois Cartegnie

epg: do ordered inserts and optimize merging

allows updating existing entries through merge

> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=d9db85c3b8e48e74f393ba83577cc0873e85e1b9
---

 src/misc/epg.c |  141 ++++++++++++++++++++++++++++++++++++++++++++------------
 1 file changed, 111 insertions(+), 30 deletions(-)

diff --git a/src/misc/epg.c b/src/misc/epg.c
index 522d366..2541a5a 100644
--- a/src/misc/epg.c
+++ b/src/misc/epg.c
@@ -87,7 +87,58 @@ void vlc_epg_AddEvent( vlc_epg_t *p_epg, int64_t i_start, int i_duration,
     vlc_epg_event_t *p_evt = vlc_epg_Event_New( i_start, i_duration,
                                                 psz_name, psz_short_description,
                                                 psz_description, i_rating );
-    if( likely(p_evt) )
+    if( unlikely(!p_evt) )
+        return;
+
+    int i_pos = -1;
+
+    /* Insertions are supposed in sequential order first */
+    if( p_epg->i_event )
+    {
+        if( p_epg->pp_event[0]->i_start > i_start )
+        {
+            i_pos = 0;
+        }
+        else if ( p_epg->pp_event[p_epg->i_event - 1]->i_start >= i_start )
+        {
+            /* Do bisect search lower start time entry */
+            int i_lower = 0;
+            int i_upper = p_epg->i_event - 1;
+
+            while( i_lower < i_upper )
+            {
+                int i_split = ( (size_t)i_lower + i_upper ) / 2;
+                vlc_epg_event_t *p_cur = p_epg->pp_event[i_split];
+
+                if( p_cur->i_start < i_start )
+                {
+                    i_lower = i_split + 1;
+                }
+                else if ( p_cur->i_start >= i_start )
+                {
+                    i_upper = i_split;
+                }
+            }
+            i_pos = i_lower;
+        }
+    }
+
+    if( i_pos != -1 )
+    {
+        if( p_epg->pp_event[i_pos]->i_start == i_start )/* There can be only one event at same time */
+        {
+            vlc_epg_Event_Delete( p_epg->pp_event[i_pos] );
+            if( p_epg->p_current == p_epg->pp_event[i_pos] )
+                p_epg->p_current = p_evt;
+            p_epg->pp_event[i_pos] = p_evt;
+            return;
+        }
+        else
+        {
+            TAB_INSERT( p_epg->i_event, p_epg->pp_event, p_evt, i_pos );
+        }
+    }
+    else
         TAB_APPEND( p_epg->i_event, p_epg->pp_event, p_evt );
 }
 
@@ -122,46 +173,76 @@ void vlc_epg_SetCurrent( vlc_epg_t *p_epg, int64_t i_start )
     }
 }
 
-void vlc_epg_Merge( vlc_epg_t *p_dst, const vlc_epg_t *p_src )
+static void vlc_epg_Prune( vlc_epg_t *p_dst )
 {
-    int i;
+    /* Keep only 1 old event  */
+    if( p_dst->p_current )
+    {
+        while( p_dst->i_event > 1 && p_dst->pp_event[0] != p_dst->p_current && p_dst->pp_event[1] != p_dst->p_current )
+        {
+            vlc_epg_Event_Delete( p_dst->pp_event[0] );
+            TAB_ERASE( p_dst->i_event, p_dst->pp_event, 0 );
+        }
+    }
+}
+
+void vlc_epg_Merge( vlc_epg_t *p_dst_epg, const vlc_epg_t *p_src_epg )
+{
+    if( p_src_epg->i_event == 0 )
+        return;
 
-    /* Add new event */
-    for( i = 0; i < p_src->i_event; i++ )
+    int i_dst=0;
+    int i_src=0;
+    for( ; i_src < p_src_epg->i_event; i_src++ )
     {
-        vlc_epg_event_t *p_evt = p_src->pp_event[i];
-        bool b_add = true;
-        int j;
+        const bool b_current = ( p_src_epg->pp_event[i_src] == p_src_epg->p_current );
 
-        for( j = 0; j < p_dst->i_event; j++ )
+        vlc_epg_event_t *p_src = vlc_epg_Event_Duplicate( p_src_epg->pp_event[i_src] );
+        if( unlikely(!p_src) )
+            return;
+        const int64_t i_src_end = p_src->i_start + p_src->i_duration;
+
+        while( i_dst < p_dst_epg->i_event )
         {
-            if( p_dst->pp_event[j]->i_start == p_evt->i_start && p_dst->pp_event[j]->i_duration == p_evt->i_duration )
+            vlc_epg_event_t *p_dst = p_dst_epg->pp_event[i_dst];
+            const int64_t i_dst_end = p_dst->i_start + p_dst->i_duration;
+
+            /* appended is before current, no overlap */
+            if( p_dst->i_start >= i_src_end )
             {
-                b_add = false;
                 break;
             }
-            if( p_dst->pp_event[j]->i_start > p_evt->i_start )
-                break;
-        }
-        if( b_add )
-        {
-            vlc_epg_event_t *p_copy = vlc_epg_Event_Duplicate( p_evt );
-            if( likely(p_copy) )
-                TAB_INSERT( p_dst->i_event, p_dst->pp_event, p_copy, j );
+            /* overlap case: appended would contain current's start (or are identical) */
+            else if( ( p_dst->i_start >= p_src->i_start && p_dst->i_start < i_src_end ) ||
+            /* overlap case: appended would contain current's end */
+                    ( i_dst_end > p_src->i_start && i_dst_end <= i_src_end ) )
+            {
+                vlc_epg_Event_Delete( p_dst );
+                if( p_dst_epg->p_current )
+                    p_dst_epg->p_current = NULL;
+                TAB_ERASE( p_dst_epg->i_event, p_dst_epg->pp_event, i_dst );
+            }
+            else
+            {
+                i_dst++;
+            }
         }
+
+        TAB_INSERT( p_dst_epg->i_event, p_dst_epg->pp_event, p_src, i_dst );
+        if( b_current )
+            p_dst_epg->p_current = p_src;
     }
-    /* Update current */
-    if( p_src->p_current )
-        vlc_epg_SetCurrent( p_dst, p_src->p_current->i_start );
 
-    /* Keep only 1 old event  */
-    if( p_dst->p_current )
+    /* Remaining/trailing ones */
+    for( ; i_src < p_src_epg->i_event; i_src++ )
     {
-        while( p_dst->i_event > 1 && p_dst->pp_event[0] != p_dst->p_current && p_dst->pp_event[1] != p_dst->p_current )
-        {
-            vlc_epg_Event_Delete( p_dst->pp_event[0] );
-            TAB_REMOVE( p_dst->i_event, p_dst->pp_event, p_dst->pp_event[0] );
-        }
+        vlc_epg_event_t *p_src = vlc_epg_Event_Duplicate( p_src_epg->pp_event[i_src] );
+        if( unlikely(!p_src) )
+            return;
+        TAB_APPEND( p_dst_epg->i_event, p_dst_epg->pp_event, p_src );
+        if( p_src_epg->pp_event[i_src] == p_src_epg->p_current )
+            p_dst_epg->p_current = p_src;
     }
-}
 
+    vlc_epg_Prune( p_dst_epg );
+}



More information about the vlc-commits mailing list