-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Implement a new CalendarKit based on libical
- Loading branch information
Showing
20 changed files
with
824 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
/* CalendarKit - An ObjC wrapper around libical | ||
* Copyright (C) 2024 Hugo Melder | ||
* | ||
* SPDX-License-Identifier: MIT | ||
*/ | ||
|
||
#import <CalendarKit/ICALComponent.h> | ||
#import <CalendarKit/ICALError.h> | ||
#import <CalendarKit/ICALProperty.h> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
/* CalendarKit - An ObjC wrapper around libical | ||
* Copyright (C) 2024 Hugo Melder | ||
* | ||
* SPDX-License-Identifier: MIT | ||
*/ | ||
|
||
#import <Foundation/NSData.h> | ||
#import <Foundation/NSEnumerator.h> | ||
#import <Foundation/NSError.h> | ||
#import <Foundation/NSObjCRuntime.h> | ||
#import <Foundation/NSObject.h> | ||
#import <Foundation/NSString.h> | ||
|
||
// Class reference to avoid cyclic dependency | ||
@class ICALProperty; | ||
|
||
NS_ASSUME_NONNULL_BEGIN | ||
|
||
typedef NS_ENUM(NSUInteger, ICALComponentKind) { | ||
ICALComponentKindPlaceholder, | ||
/// Used to select all components | ||
ICALComponentKindAny, | ||
ICALComponentKindXROOT, | ||
/// MIME attached data, returned by parser | ||
ICALComponentKindXATTACH, | ||
ICALComponentKindVEVENT, | ||
ICALComponentKindVTODO, | ||
ICALComponentKindVJOURNAL, | ||
ICALComponentKindVCALENDAR, | ||
ICALComponentKindVAGENDA, | ||
ICALComponentKindVFREEBUSY, | ||
ICALComponentKindVALARM, | ||
ICALComponentKindXAUDIOALARM, | ||
ICALComponentKindXDISPLAYALARM, | ||
ICALComponentKindXEMAILALARM, | ||
ICALComponentKindXPROCEDUREALARM, | ||
ICALComponentKindVTIMEZONE, | ||
ICALComponentKindXSTANDARD, | ||
ICALComponentKindXDAYLIGHT, | ||
ICALComponentKindX, | ||
ICALComponentKindVSCHEDULE, | ||
ICALComponentKindVQUERY, | ||
ICALComponentKindVREPLY, | ||
ICALComponentKindVCAR, | ||
ICALComponentKindVCOMMAND, | ||
ICALComponentKindXLICINVALID, | ||
ICALComponentKindXLICMIMEPART, | ||
ICALComponentKindVAVAILABILITY, | ||
ICALComponentKindXAVAILABLE, | ||
ICALComponentKindVPOLL, | ||
ICALComponentKindVVOTER, | ||
ICALComponentKindXVOTE, | ||
ICALComponentKindVPATCH, | ||
ICALComponentKindXPATCH | ||
}; | ||
|
||
@interface ICALComponent : NSObject <NSCopying> { | ||
void *_handle; | ||
ICALComponent *_Nullable _root; | ||
} | ||
|
||
+ (instancetype)componentWithData:(NSData *)data error:(NSError **)error; | ||
|
||
- (instancetype)initWithData:(NSData *)data error:(NSError **)error; | ||
|
||
- (ICALComponentKind)kind; | ||
|
||
- (NSString *_Nullable)uid; | ||
|
||
- (NSString *_Nullable)summary; | ||
|
||
- (id)copyWithZone:(NSZone *)zone; | ||
|
||
- (NSInteger)numberOfChildren; | ||
- (NSInteger)numberOfProperties; | ||
|
||
- (void)enumerateComponentsUsingBlock:(void (^)(ICALComponent *component, BOOL *stop))block; | ||
- (void)enumeratePropertiesUsingBlock:(void (^)(ICALProperty *property, BOOL *stop))block; | ||
|
||
@end | ||
|
||
NS_ASSUME_NONNULL_END |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
/* CalendarKit - An ObjC wrapper around libical | ||
* Copyright (C) 2024 Hugo Melder | ||
* | ||
* SPDX-License-Identifier: MIT | ||
*/ | ||
|
||
#import <Foundation/NSDictionary.h> | ||
#import <Foundation/NSError.h> | ||
#import <Foundation/NSObjCRuntime.h> | ||
#import <Foundation/NSString.h> | ||
|
||
NS_ASSUME_NONNULL_BEGIN | ||
|
||
extern NSString *const ICALErrorDomain; | ||
|
||
#define ICAL_FAST_ERROR(err, errorCode, description, ...) \ | ||
do { \ | ||
if (err) { \ | ||
NSString *message = [NSString stringWithFormat:description, ##__VA_ARGS__]; \ | ||
*err = [NSError errorWithDomain:ICALErrorDomain \ | ||
code:errorCode \ | ||
userInfo:@{NSLocalizedDescriptionKey : message}]; \ | ||
} \ | ||
} while (0) | ||
|
||
typedef NS_ENUM(NSUInteger, ICALError) { | ||
ICALErrorNone = 0, | ||
ICALErrorBadArgument, | ||
ICALErrorConstruction, | ||
ICALErrorAllocation, | ||
ICALErrorMalformedData, | ||
ICALErrorParse, | ||
ICALErrorInternal, | ||
ICALErrorFile, | ||
ICALErrorUsage, | ||
ICALUnimplementedError, | ||
ICALUnknownError | ||
}; | ||
|
||
NS_ASSUME_NONNULL_END |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
/* CalendarKit - An ObjC wrapper around libical | ||
* Copyright (C) 2024 Hugo Melder | ||
* | ||
* SPDX-License-Identifier: MIT | ||
*/ | ||
|
||
#import <Foundation/NSObjCRuntime.h> | ||
#import <Foundation/NSObject.h> | ||
#import <Foundation/NSString.h> | ||
|
||
NS_ASSUME_NONNULL_BEGIN | ||
|
||
@interface ICALParameter : NSObject { | ||
void *_handle; | ||
} | ||
|
||
- (NSString *_Nullable)ianaName; | ||
- (NSString *_Nullable)ianaValue; | ||
- (NSString *)icalString; | ||
|
||
@end | ||
|
||
NS_ASSUME_NONNULL_END |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
/* CalendarKit - An ObjC wrapper around libical | ||
* Copyright (C) 2024 Hugo Melder | ||
* | ||
* SPDX-License-Identifier: MIT | ||
*/ | ||
|
||
#import <Foundation/NSObjCRuntime.h> | ||
#import <Foundation/NSObject.h> | ||
#import <Foundation/NSString.h> | ||
|
||
#import <CalendarKit/ICALComponent.h> | ||
#import <CalendarKit/ICALParameter.h> | ||
|
||
NS_ASSUME_NONNULL_BEGIN | ||
|
||
@interface ICALProperty : NSObject { | ||
// Strong reference to owner | ||
ICALComponent *_owner; | ||
// underlying libical handle. Lifetime tied to owner. | ||
void *_handle; | ||
} | ||
|
||
- (NSString *)name; | ||
- (NSString *)value; | ||
|
||
- (NSInteger)numberOfParameters; | ||
- (void)enumerateParametersUsingBlock:(void (^)(ICALParameter *parameter, BOOL *stop))block; | ||
|
||
@end | ||
|
||
NS_ASSUME_NONNULL_END |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
/* CalendarKit - An ObjC wrapper around libical | ||
* Copyright (C) 2024 Hugo Melder | ||
* | ||
* SPDX-License-Identifier: MIT | ||
*/ | ||
|
||
#import "CalendarKit/ICALComponent.h" | ||
#import <libical/icalcomponent.h> | ||
|
||
@interface ICALComponent (Private) | ||
|
||
- (instancetype)initWithHandle:(icalcomponent *)handle; | ||
- (instancetype)initWithHandle:(icalcomponent *)handle root:(ICALComponent *)root; | ||
|
||
- (icalcomponent *)handle; | ||
|
||
@end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,145 @@ | ||
/* CalendarKit - An ObjC wrapper around libical | ||
* Copyright (C) 2024 Hugo Melder | ||
* | ||
* SPDX-License-Identifier: MIT | ||
*/ | ||
|
||
#include "libical/ical.h" | ||
#import <assert.h> | ||
#import <libical/icalcomponent.h> | ||
#import <libical/icalenums.h> | ||
#import <libical/icalerror.h> | ||
#import <libical/icalparser.h> | ||
|
||
#import <Foundation/NSException.h> | ||
|
||
#import "CalendarKit/ICALComponent.h" | ||
#import "CalendarKit/ICALError.h" | ||
|
||
#import "ICALComponent+Private.h" | ||
#import "ICALProperty+Private.h" | ||
|
||
// Make sure that ICALComponentKind is in sync with icalcomponent_kind | ||
// so that we can just cast it. | ||
static_assert(ICAL_XPATCH_COMPONENT == ICALComponentKindXPATCH, | ||
"icalcomponent_kind enumeration is not in sync!"); | ||
|
||
@implementation ICALComponent (Private) | ||
|
||
- (instancetype)initWithHandle:(icalcomponent *)handle { | ||
self = [super init]; | ||
if (self) { | ||
_handle = handle; | ||
} | ||
|
||
return self; | ||
} | ||
- (instancetype)initWithHandle:(icalcomponent *)handle root:(ICALComponent *)root { | ||
self = [super init]; | ||
if (self) { | ||
_handle = handle; | ||
_root = root; | ||
} | ||
|
||
return self; | ||
} | ||
|
||
- (icalcomponent *)handle { | ||
return _handle; | ||
} | ||
|
||
@end | ||
|
||
@implementation ICALComponent | ||
|
||
+ (instancetype)componentWithData:(NSData *)data error:(NSError **)error { | ||
return [[ICALComponent alloc] initWithData:data error:error]; | ||
} | ||
|
||
- (instancetype)initWithData:(NSData *)data error:(NSError **)error { | ||
NSAssert(data, @"Data is valid"); | ||
|
||
NSString *string = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; | ||
|
||
icalcomponent *parsed = icalparser_parse_string([string UTF8String]); | ||
// Some error occured during parsing | ||
if (!parsed) { | ||
if (error) { | ||
ICALError errorCode = (ICALError) icalerrno; | ||
NSString *message = [NSString stringWithUTF8String:icalerror_strerror(icalerrno)]; | ||
*error = [NSError errorWithDomain:ICALErrorDomain | ||
code:errorCode | ||
userInfo:@{NSLocalizedDescriptionKey : message}]; | ||
} | ||
icalerror_clear_errno(); | ||
return nil; | ||
} | ||
|
||
return [self initWithHandle:parsed]; | ||
} | ||
|
||
- (ICALComponentKind)kind { | ||
return (ICALComponentKind) icalcomponent_isa(_handle); | ||
} | ||
|
||
- (NSString *_Nullable)uid { | ||
const char *uid = icalcomponent_get_uid(_handle); | ||
if (!uid) { | ||
return nil; | ||
} | ||
|
||
return [NSString stringWithUTF8String:uid]; | ||
} | ||
|
||
- (NSString *_Nullable)summary { | ||
const char *summary = icalcomponent_get_summary(_handle); | ||
if (!summary) { | ||
return nil; | ||
} | ||
|
||
return [NSString stringWithUTF8String:summary]; | ||
} | ||
|
||
- (NSInteger)numberOfChildren { | ||
return icalcomponent_count_components(_handle, ICAL_ANY_COMPONENT); | ||
} | ||
|
||
- (NSInteger)numberOfProperties { | ||
return icalcomponent_count_properties(_handle, ICAL_ANY_PROPERTY); | ||
} | ||
|
||
- (void)enumerateComponentsUsingBlock:(void (^)(ICALComponent *component, BOOL *stop))block { | ||
icalcompiter iter = icalcomponent_begin_component(_handle, ICAL_ANY_COMPONENT); | ||
|
||
BOOL stop = NO; | ||
|
||
for (; icalcompiter_deref(&iter) != 0 && stop == NO; icalcompiter_next(&iter)) { | ||
ICALComponent *cur = [[ICALComponent alloc] initWithHandle:icalcompiter_deref(&iter) | ||
root:self]; | ||
block(cur, &stop); | ||
} | ||
} | ||
|
||
- (void)enumeratePropertiesUsingBlock:(void (^)(ICALProperty *property, BOOL *stop))block { | ||
icalproperty *cur = icalcomponent_get_first_property(_handle, ICAL_ANY_PROPERTY); | ||
|
||
BOOL stop = NO; | ||
while (cur != 0 && stop == NO) { | ||
ICALProperty *obj = [[ICALProperty alloc] initWithHandle:cur owner:self]; | ||
block(obj, &stop); | ||
cur = icalcomponent_get_next_property(_handle, ICAL_ANY_PROPERTY); | ||
} | ||
} | ||
|
||
- (id)copyWithZone:(NSZone *)zone { | ||
icalcomponent *cloned = icalcomponent_new_clone(_handle); | ||
return [[ICALComponent alloc] initWithHandle:cloned]; | ||
} | ||
|
||
- (void)dealloc { | ||
if (!_root) { | ||
icalcomponent_free(_handle); | ||
} | ||
} | ||
|
||
@end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
/* CalendarKit - An ObjC wrapper around libical | ||
* Copyright (C) 2024 Hugo Melder | ||
* | ||
* SPDX-License-Identifier: MIT | ||
*/ | ||
|
||
#import "CalendarKit/ICALError.h" | ||
|
||
NSString *const ICALErrorDomain = @"ICALErrorDomain"; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
/* CalendarKit - An ObjC wrapper around libical | ||
* Copyright (C) 2024 Hugo Melder | ||
* | ||
* SPDX-License-Identifier: MIT | ||
*/ | ||
|
||
#import <libical/icalparameter.h> | ||
|
||
#import <CalendarKit/ICALParameter.h> | ||
|
||
NS_ASSUME_NONNULL_BEGIN | ||
|
||
@interface ICALParameter (Private) | ||
|
||
/** | ||
* Clone the underlying icalparameter and return an initialised ICALParameter | ||
* instance. | ||
*/ | ||
- (instancetype)initWithHandle:(icalparameter *)handle; | ||
|
||
@end | ||
|
||
NS_ASSUME_NONNULL_END |
Oops, something went wrong.