Branch 'kolab/integration/4.13.0' - kcalcore/icalformat.cpp kcalcore/icalformat.h kcalcore/icalformat_p.cpp kcalcore/icalformat_p.h
Christian Mollekopf
mollekopf at kolabsys.com
Wed Sep 24 21:49:38 CEST 2014
kcalcore/icalformat.cpp | 33 +++++++++++++++++++++++++++++++++
kcalcore/icalformat.h | 17 +++++++++++++++++
kcalcore/icalformat_p.cpp | 24 ++++++++++++++++++++++++
kcalcore/icalformat_p.h | 2 ++
4 files changed, 76 insertions(+)
New commits:
commit e773b80ef526b01466ac070536b693e2d66c3e23
Author: Christian Mollekopf <chrigi_1 at fastmail.fm>
Date: Wed Sep 24 21:42:39 2014 +0200
ICalFormat: Introduce incidence parsing that ignores timezoneinformation.
This is orders of magnitudes faster when used in the akonadi serializer,
and uses a lot less memory (from 500mb to 100 for 10k events).
diff --git a/kcalcore/icalformat.cpp b/kcalcore/icalformat.cpp
index 362710d..27bec95 100644
--- a/kcalcore/icalformat.cpp
+++ b/kcalcore/icalformat.cpp
@@ -145,6 +145,39 @@ bool ICalFormat::fromString(const Calendar::Ptr &cal, const QString &string,
return fromRawString(cal, string.toUtf8(), deleted, notebook);
}
+Incidence::Ptr ICalFormat::readIncidence( const QByteArray &string, ICalTimeZones *tzlist )
+{
+ icalcomponent *calendar;
+
+ // Let's defend const correctness until the very gates of hell^Wlibical
+ calendar = icalcomponent_new_from_string(const_cast<char*>((const char *)string));
+ if (!calendar) {
+ kError() << "parse error ; string is empty?" << string.isEmpty();
+ setException(new Exception(Exception::ParseErrorIcal));
+ return Incidence::Ptr();
+ }
+
+ Incidence::Ptr incidence;
+ if (icalcomponent_isa(calendar) == ICAL_VCALENDAR_COMPONENT) {
+ incidence = d->mImpl->readOneIncidence(calendar, tzlist);
+ } else if (icalcomponent_isa(calendar) == ICAL_XROOT_COMPONENT) {
+ icalcomponent *comp = icalcomponent_get_first_component(calendar, ICAL_VCALENDAR_COMPONENT);
+ if (comp) {
+ incidence = d->mImpl->readOneIncidence(comp, tzlist);
+ }
+ }
+
+ if (!incidence) {
+ kDebug() << "No VCALENDAR component found";
+ setException(new Exception(Exception::NoCalendar));
+ }
+
+ icalcomponent_free(calendar);
+ icalmemory_free_ring();
+
+ return incidence;
+}
+
bool ICalFormat::fromRawString(const Calendar::Ptr &cal, const QByteArray &string,
bool deleted, const QString ¬ebook)
{
diff --git a/kcalcore/icalformat.h b/kcalcore/icalformat.h
index 534f134..358362b 100644
--- a/kcalcore/icalformat.h
+++ b/kcalcore/icalformat.h
@@ -100,6 +100,23 @@ public:
Incidence::Ptr fromString(const QString &string);
/**
+ Parses a string, returning the first iCal component as an Incidence, ignored timezone information.
+
+ This function is significantly faster than fromString by avoiding the overhead of parsing timezone information.
+ Timezones are instead solely interpreted by using system-timezones.
+
+ @param string is a utf8 QByteArray containing the data to be parsed.
+ @param tzlist is a collection of timezones used for the parsed date-times.
+ This collection may be empty or pre-populated. If it is empty, it is populated
+ automatically from the systemtimezones and thus acts as a cache. The tzlist may be 0
+ if the timezone should be read everytime from the system.
+
+ @return non-zero pointer if the parsing was successful; 0 otherwise.
+ @see fromString(const QString &), fromRawString()
+ */
+ Incidence::Ptr readIncidence(const QByteArray &string, ICalTimeZones *tzlist);
+
+ /**
Parses a string and fills a RecurrenceRule object with the information.
@param rule is a pointer to a RecurrenceRule object.
diff --git a/kcalcore/icalformat_p.cpp b/kcalcore/icalformat_p.cpp
index b1d119c..0f54e39 100644
--- a/kcalcore/icalformat_p.cpp
+++ b/kcalcore/icalformat_p.cpp
@@ -2656,6 +2656,29 @@ icalcomponent *ICalFormatImpl::createCalendarComponent(const Calendar::Ptr &cal)
return calendar;
}
+Incidence::Ptr ICalFormatImpl::readOneIncidence(icalcomponent *calendar, ICalTimeZones *tzlist)
+{
+ if (!calendar) {
+ kWarning() << "Populate called with empty calendar";
+ return Incidence::Ptr();
+ }
+ icalcomponent *c;
+ c = icalcomponent_get_first_component(calendar, ICAL_VEVENT_COMPONENT);
+ if (c) {
+ return readEvent(c, tzlist);
+ }
+ c = icalcomponent_get_first_component(calendar, ICAL_VTODO_COMPONENT);
+ if (c) {
+ return readTodo(c, tzlist);
+ }
+ c = icalcomponent_get_first_component(calendar, ICAL_VJOURNAL_COMPONENT);
+ if (c) {
+ return readJournal(c, tzlist);
+ }
+ kWarning() << "Found no incidence";
+ return Incidence::Ptr();
+}
+
// take a raw vcalendar (i.e. from a file on disk, clipboard, etc. etc.
// and break it down from its tree-like format into the dictionary format
// that is used internally in the ICalFormatImpl.
@@ -2736,6 +2759,7 @@ bool ICalFormatImpl::populate(const Calendar::Ptr &cal, icalcomponent *calendar,
}
// Populate the calendar's time zone collection with all VTIMEZONE components
+ // FIXME: HUUUUUGE memory consumption
ICalTimeZones *tzlist = cal->timeZones();
ICalTimeZoneSource tzs;
tzs.parse(calendar, *tzlist);
diff --git a/kcalcore/icalformat_p.h b/kcalcore/icalformat_p.h
index ccc03ec..dfb5047 100644
--- a/kcalcore/icalformat_p.h
+++ b/kcalcore/icalformat_p.h
@@ -108,6 +108,8 @@ public:
bool populate(const Calendar::Ptr &calendar, icalcomponent *fs,
bool deleted = false, const QString ¬ebook = QString());
+ Incidence::Ptr readOneIncidence(icalcomponent *calendar, ICalTimeZones *tzlist);
+
icalcomponent *writeIncidence(const IncidenceBase::Ptr &incidence,
iTIPMethod method = iTIPRequest,
ICalTimeZones *tzList = 0,
More information about the commits
mailing list