/* * Copyright 2013 (c) Anna Schumaker. */ #include #include #include static int track_less_than(const void *a, const void *b, void *data) { struct track *lhs = (struct track *)a; struct track *rhs = (struct track *)b; GSList *cur = (GSList *)data; int res, field; while (cur) { field = GPOINTER_TO_INT(cur->data); if (field > 0) res = track_compare(lhs, rhs, field); else res = track_compare(rhs, lhs, abs(field)); if (res == 0) { cur = g_slist_next(cur); continue; } break; }; return res; } static inline void *__queue_init(struct queue *queue, void *data) { if (queue->q_ops) return queue->q_ops->qop_init(queue, data); return NULL; } static inline void __queue_deinit(struct queue *queue) { if (queue->q_ops) queue->q_ops->qop_deinit(queue); } static inline unsigned int __queue_added(struct queue *queue, struct track *track, unsigned int pos) { queue->q_length += track->tr_length; if (queue->q_ops) queue->q_ops->qop_added(queue, pos); return pos; } static inline unsigned int __queue_add_head(struct queue *queue, struct track *track) { g_queue_push_head(&queue->q_tracks, track); return __queue_added(queue, track, 0); } static inline unsigned int __queue_add_tail(struct queue *queue, struct track *track) { g_queue_push_tail(&queue->q_tracks, track); return __queue_added(queue, track, queue_size(queue) - 1); } static inline unsigned int __queue_add_sorted(struct queue *queue, struct track *track) { struct queue_iter it; queue_for_each(queue, &it) { if (track_less_than(queue_iter_val(&it), track, queue->q_sort) > 0) { g_queue_insert_before(&queue->q_tracks, it.it_iter, track); return __queue_added(queue, track, it.it_pos); } } return __queue_add_tail(queue, track); } static inline void __queue_clear(struct queue *queue, unsigned int n) { queue->q_length = 0; if (queue->q_ops) queue->q_ops->qop_cleared(queue, n); } void queue_init(struct queue *queue, const struct queue_ops *ops, void *data) { queue->q_length = 0; queue->q_sort = NULL; queue->q_ops = ops; g_queue_init(&queue->q_tracks); queue_iter_init(queue, &queue->q_cur); queue->q_private = __queue_init(queue, data); } void queue_deinit(struct queue *queue) { queue_clear(queue); __queue_deinit(queue); g_slist_free(queue->q_sort); queue->q_sort = NULL; } unsigned int queue_add(struct queue *queue, struct track *track) { if (queue->q_sort) return __queue_add_sorted(queue, track); return __queue_add_tail(queue, track); } unsigned int queue_add_front(struct queue *queue, struct track *track) { return __queue_add_head(queue, track); } void queue_clear(struct queue *queue) { unsigned int n = queue_size(queue); g_queue_clear(&queue->q_tracks); __queue_clear(queue, n); } bool queue_has(struct queue *queue, struct track *track) { struct queue_iter it; queue_for_each(queue, &it) { if (queue_iter_val(&it) == track) return true; } return false; }