Make progress on getting RSParser.framework to build.
This commit is contained in:
parent
6f0e4a9da6
commit
1ad4474b29
|
@ -16,7 +16,7 @@ public struct FeedParser {
|
|||
|
||||
static let minNumberOfBytesRequired = 128
|
||||
|
||||
public static func feedType(parserData: ParserData) -> FeedType {
|
||||
public static func feedType(_ parserData: ParserData) -> FeedType {
|
||||
|
||||
// Can call with partial data — while still downloading, for instance.
|
||||
// If there’s not enough data, return .unknown. Ask again when there’s more data.
|
||||
|
@ -26,38 +26,40 @@ public struct FeedParser {
|
|||
return .unknown
|
||||
}
|
||||
|
||||
if parserData.data.isProbablyJSONFeed() {
|
||||
let nsdata = parserData.data as NSData
|
||||
if nsdata.isProbablyJSONFeed() {
|
||||
return .jsonFeed
|
||||
}
|
||||
if parserData.data.isProbablyRSSInJSON() {
|
||||
if nsdata.isProbablyRSSInJSON() {
|
||||
return .rssInJSON
|
||||
}
|
||||
|
||||
if parserData.data.isProbablyHTML() {
|
||||
if nsdata.isProbablyHTML() {
|
||||
return .notAFeed
|
||||
}
|
||||
|
||||
if parserData.data.isProbablyRSS() {
|
||||
if nsdata.isProbablyRSS() {
|
||||
return .rss
|
||||
}
|
||||
if parserData.data.isProbablyAtom() {
|
||||
if nsdata.isProbablyAtom() {
|
||||
return .atom
|
||||
}
|
||||
|
||||
return .notAFeed
|
||||
}
|
||||
|
||||
public static func parseFeed(parserData: ParserData) -> ParsedFeed? {
|
||||
public static func parseFeed(_ parserData: ParserData) throws -> ParsedFeed? {
|
||||
|
||||
do {
|
||||
let type = feedType(parserData)
|
||||
|
||||
switch type {
|
||||
|
||||
case .jsonFeed:
|
||||
return JSONFeedParser.parse(parserData)
|
||||
return try JSONFeedParser.parse(parserData)
|
||||
|
||||
case .rssInJSON:
|
||||
return RSSInJSONFeedParser.parse(parserData)
|
||||
return try RSSInJSONParser.parse(parserData)
|
||||
|
||||
case .rss:
|
||||
return RSSParser.parse(parserData)
|
||||
|
@ -69,4 +71,6 @@ public struct FeedParser {
|
|||
return nil
|
||||
}
|
||||
}
|
||||
catch { throw error }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@ public struct FeedParserError: Error {
|
|||
case jsonFeedVersionNotFound
|
||||
case jsonFeedItemsNotFound
|
||||
case jsonFeedTitleNotFound
|
||||
case invalidJSON
|
||||
}
|
||||
|
||||
public let errorType: FeedParserErrorType
|
||||
|
|
|
@ -12,10 +12,12 @@ import Foundation
|
|||
|
||||
public struct JSONFeedParser {
|
||||
|
||||
public static func parse(parserData: ParserData) throws -> ParsedFeed? {
|
||||
public static func parse(_ parserData: ParserData) throws -> ParsedFeed? {
|
||||
|
||||
do {
|
||||
let parsedObject = try JSONSerialization.jsonObject(with: parserData.data)
|
||||
guard let parsedObject = try JSONSerialization.jsonObject(with: parserData.data) as? JSONDictionary else {
|
||||
throw FeedParserError(.invalidJSON)
|
||||
}
|
||||
|
||||
guard let version = parsedObject["version"] as? String, version.hasPrefix("https://jsonfeed.org/version/") else {
|
||||
throw FeedParserError(.jsonFeedVersionNotFound)
|
||||
|
@ -27,13 +29,13 @@ public struct JSONFeedParser {
|
|||
throw FeedParserError(.jsonFeedTitleNotFound)
|
||||
}
|
||||
|
||||
let authors = parseAuthors(parsedObject)
|
||||
let homePageURL = parsedObject["home_page_url"] as? String
|
||||
let feedURL = parsedObject["feed_url"] ?? parserData.url
|
||||
let feedURL = parsedObject["feed_url"] as? String ?? parserData.url
|
||||
let feedDescription = parsedObject["description"] as? String
|
||||
let nextURL = parsedObject["next_url"] as? String
|
||||
let iconURL = parsedObject["icon_url"] as? String
|
||||
let faviconURL = parsedObject["favicon_url"] as? String
|
||||
let authors = parseAuthors(parsedObject)
|
||||
let expired = parsedObject["expired"] as? Bool ?? false
|
||||
let hubs = parseHubs(parsedObject)
|
||||
|
||||
|
@ -48,15 +50,15 @@ public struct JSONFeedParser {
|
|||
|
||||
private extension JSONFeedParser {
|
||||
|
||||
func parseAuthors(_ dictionary: JSONDictionary) -> [ParsedAuthor]? {
|
||||
static func parseAuthors(_ dictionary: JSONDictionary) -> [ParsedAuthor]? {
|
||||
|
||||
guard let authorDictionary = dictionary["author"] as? JSONDictionary else {
|
||||
return nil
|
||||
}
|
||||
|
||||
let name = authorDictionary["name"]
|
||||
let url = authorDictionary["url"]
|
||||
let avatar = authorDictionary["avatar"]
|
||||
let name = authorDictionary["name"] as? String
|
||||
let url = authorDictionary["url"] as? String
|
||||
let avatar = authorDictionary["avatar"] as? String
|
||||
if name == nil && url == nil && avatar == nil {
|
||||
return nil
|
||||
}
|
||||
|
@ -64,14 +66,14 @@ private extension JSONFeedParser {
|
|||
return [parsedAuthor]
|
||||
}
|
||||
|
||||
func parseHubs(_ dictionary: JSONDictionary) -> [ParsedHub]? {
|
||||
static func parseHubs(_ dictionary: JSONDictionary) -> [ParsedHub]? {
|
||||
|
||||
guard let hubsArray = dictionary["hubs"] as? JSONArray else {
|
||||
return nil
|
||||
}
|
||||
|
||||
let hubs = hubsArray.flatMap { (oneHubDictionary) -> ParsedHub? in
|
||||
guard let oneHubURL = oneHubDictionary["url"], let oneHubType = oneHubDictionary["type"] else {
|
||||
guard let oneHubURL = oneHubDictionary["url"] as? String, let oneHubType = oneHubDictionary["type"] as? String else {
|
||||
return nil
|
||||
}
|
||||
return ParsedHub(type: oneHubType, url: oneHubURL)
|
||||
|
@ -79,14 +81,14 @@ private extension JSONFeedParser {
|
|||
return hubs.isEmpty ? nil : hubs
|
||||
}
|
||||
|
||||
func parseItems(_ itemsArray: JSONArray) -> [ParsedItem] {
|
||||
static func parseItems(_ itemsArray: JSONArray) -> [ParsedItem] {
|
||||
|
||||
return itemsArray.flatMap { (oneItemDictionary) -> ParsedItem? in
|
||||
return parseItem(oneItemDictionary)
|
||||
}
|
||||
}
|
||||
|
||||
func parseItem(_ itemDictionary: JSONDictionary) -> ParsedItem? {
|
||||
static func parseItem(_ itemDictionary: JSONDictionary) -> ParsedItem? {
|
||||
|
||||
guard let uniqueID = parseUniqueID(itemDictionary) else {
|
||||
return nil
|
||||
|
@ -105,8 +107,8 @@ private extension JSONFeedParser {
|
|||
let imageURL = itemDictionary["image"] as? String
|
||||
let bannerImageURL = itemDictionary["banner_image"] as? String
|
||||
|
||||
let datePublished = parseDate(itemDictionary["date_published"])
|
||||
let dateModified = parseDate(itemDictionary["date_modified"])
|
||||
let datePublished = parseDate(itemDictionary["date_published"] as? String)
|
||||
let dateModified = parseDate(itemDictionary["date_modified"] as? String)
|
||||
|
||||
let authors = parseAuthors(itemDictionary)
|
||||
let tags = itemDictionary["tags"] as? [String]
|
||||
|
@ -115,7 +117,7 @@ private extension JSONFeedParser {
|
|||
return ParsedItem(uniqueID: uniqueID, url: url, externalURL: externalURL, title: title, contentHTML: contentHTML, contentText: contentText, summary: summary, imageURL: imageURL, bannerImageURL: bannerImageURL, datePublished: datePublished, dateModified: dateModified, authors: authors, tags: tags, attachments: attachments)
|
||||
}
|
||||
|
||||
func parseUniqueID(_ itemDictionary: JSONDictionary) -> String? {
|
||||
static func parseUniqueID(_ itemDictionary: JSONDictionary) -> String? {
|
||||
|
||||
if let uniqueID = itemDictionary["id"] as? String {
|
||||
return uniqueID // Spec says it must be a string
|
||||
|
@ -130,7 +132,7 @@ private extension JSONFeedParser {
|
|||
return nil
|
||||
}
|
||||
|
||||
func parseDate(_ dateString: String?) -> Date? {
|
||||
static func parseDate(_ dateString: String?) -> Date? {
|
||||
|
||||
guard let dateString = dateString, !dateString.isEmpty else {
|
||||
return nil
|
||||
|
@ -138,7 +140,7 @@ private extension JSONFeedParser {
|
|||
return RSDateWithString(dateString)
|
||||
}
|
||||
|
||||
func parseAttachments(_ itemDictionary: JSONDictionary) -> [ParsedAttachment]? {
|
||||
static func parseAttachments(_ itemDictionary: JSONDictionary) -> [ParsedAttachment]? {
|
||||
|
||||
guard let attachmentsArray = itemDictionary["attachments"] as? JSONArray else {
|
||||
return nil
|
||||
|
@ -148,7 +150,7 @@ private extension JSONFeedParser {
|
|||
}
|
||||
}
|
||||
|
||||
func parseAttachment(_ attachmentObject: JSONDictionary) -> ParsedAttachment? {
|
||||
static func parseAttachment(_ attachmentObject: JSONDictionary) -> ParsedAttachment? {
|
||||
|
||||
guard let url = attachmentObject["url"] as? String else {
|
||||
return nil
|
||||
|
|
|
@ -13,10 +13,12 @@ import Foundation
|
|||
|
||||
public struct RSSInJSONParser {
|
||||
|
||||
public static func parse(parserData: ParserData) throws -> ParsedFeed? {
|
||||
public static func parse(_ parserData: ParserData) throws -> ParsedFeed? {
|
||||
|
||||
do {
|
||||
let parsedObject = try JSONSerialization.jsonObject(with: parserData.data)
|
||||
guard let parsedObject = try JSONSerialization.jsonObject(with: parserData.data) as? JSONDictionary else {
|
||||
throw FeedParserError(.invalidJSON)
|
||||
}
|
||||
|
||||
guard let channelObject = parsedObject["channel"] as? JSONDictionary else {
|
||||
throw FeedParserError(.rssChannelNotFound)
|
||||
|
@ -32,7 +34,7 @@ public struct RSSInJSONParser {
|
|||
itemsObject = channelObject["items"] as? JSONArray
|
||||
}
|
||||
if itemsObject == nil {
|
||||
itemsObject == parsedObject["items"] as? JSONArray
|
||||
itemsObject = parsedObject["items"] as? JSONArray
|
||||
}
|
||||
if itemsObject == nil {
|
||||
throw FeedParserError(.rssItemsNotFound)
|
||||
|
@ -43,7 +45,7 @@ public struct RSSInJSONParser {
|
|||
let feedURL = parserData.url
|
||||
let feedDescription = channelObject["description"] as? String
|
||||
|
||||
let items = parseItems(itemsObject)
|
||||
let items = parseItems(itemsObject!)
|
||||
|
||||
return ParsedFeed(type: .rssInJSON, title: title, homePageURL: homePageURL, feedURL: feedURL, feedDescription: feedDescription, nextURL: nil, iconURL: nil, faviconURL: nil, authors: nil, expired: false, hubs: nil, items: items)
|
||||
|
||||
|
@ -56,19 +58,19 @@ private extension RSSInJSONParser {
|
|||
|
||||
static func parseItems(_ itemsObject: JSONArray) -> [ParsedItem] {
|
||||
|
||||
return itemsObject.flatMap{ (oneItemDictionary) -> ParsedItem in
|
||||
return itemsObject.flatMap{ (oneItemDictionary) -> ParsedItem? in
|
||||
|
||||
return parsedItemWithDictionary(oneItemDictionary)
|
||||
}
|
||||
}
|
||||
|
||||
static func parsedItemWithDictionary(_ JSONDictionary: itemDictionary) -> ParsedItem? {
|
||||
static func parsedItemWithDictionary(_ itemDictionary: JSONDictionary) -> ParsedItem? {
|
||||
|
||||
let externalURL = itemDictionary["link"] as? String
|
||||
let title = itemDictionary["title"] as? String
|
||||
|
||||
var contentHTML = itemDictionary["description"] as? String
|
||||
var contentText = nil
|
||||
var contentText: String? = nil
|
||||
if contentHTML != nil && !(contentHTML!.contains("<")) {
|
||||
contentText = contentHTML
|
||||
contentHTML = nil
|
||||
|
@ -77,9 +79,9 @@ private extension RSSInJSONParser {
|
|||
return nil
|
||||
}
|
||||
|
||||
var datePublished: Date = nil
|
||||
var datePublished: Date? = nil
|
||||
if let datePublishedString = itemDictionary["pubDate"] as? String {
|
||||
datePublished = RSDateWithString(datePublishedString as NSString)
|
||||
datePublished = RSDateWithString(datePublishedString)
|
||||
}
|
||||
|
||||
let authors = parseAuthors(itemDictionary)
|
||||
|
@ -112,14 +114,14 @@ private extension RSSInJSONParser {
|
|||
}
|
||||
if s.isEmpty {
|
||||
// Sheesh. Tough case.
|
||||
if contentHTML != nil {
|
||||
s = contentHTML
|
||||
if let _ = contentHTML {
|
||||
s = contentHTML!
|
||||
}
|
||||
if contentText != nil {
|
||||
s = contentText
|
||||
if let _ = contentText {
|
||||
s = contentText!
|
||||
}
|
||||
}
|
||||
uniqueID = (s as NSString).rsxml_md5HashString()
|
||||
uniqueID = (s as NSString).rsparser_md5Hash()
|
||||
}
|
||||
|
||||
return ParsedItem(uniqueID: uniqueID, url: nil, externalURL: externalURL, title: title, contentHTML: contentHTML, contentText: contentText, summary: nil, imageURL: nil, bannerImageURL: nil, datePublished: datePublished, dateModified: nil, authors: authors, tags: tags, attachments: attachments)
|
||||
|
@ -137,11 +139,14 @@ private extension RSSInJSONParser {
|
|||
static func parseTags(_ itemDictionary: JSONDictionary) -> [String]? {
|
||||
|
||||
if let categoryObject = itemDictionary["category"] as? JSONDictionary {
|
||||
return categoryObject["#value"]
|
||||
if let oneTag = categoryObject["#value"] as? String {
|
||||
return [oneTag]
|
||||
}
|
||||
return nil
|
||||
}
|
||||
else if let categoryArray = itemDictionary["category"] as? JSONArray {
|
||||
return categoryArray.flatMap{ (categoryObject) in
|
||||
return categoryObject["#value"]
|
||||
return categoryObject["#value"] as? String
|
||||
}
|
||||
}
|
||||
return nil
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
//
|
||||
// RSAtomParser.h
|
||||
// RSXML
|
||||
// RSParser
|
||||
//
|
||||
// Created by Brent Simmons on 1/15/15.
|
||||
// Copyright (c) 2015 Ranchero Software LLC. All rights reserved.
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
//
|
||||
// RSAtomParser.m
|
||||
// RSXML
|
||||
// RSParser
|
||||
//
|
||||
// Created by Brent Simmons on 1/15/15.
|
||||
// Copyright (c) 2015 Ranchero Software LLC. All rights reserved.
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
//
|
||||
// RSFeedParser.h
|
||||
// RSXML
|
||||
// RSParser
|
||||
//
|
||||
// Created by Brent Simmons on 1/4/15.
|
||||
// Copyright (c) 2015 Ranchero Software LLC. All rights reserved.
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
//
|
||||
// FeedParser.m
|
||||
// RSXML
|
||||
// RSParser
|
||||
//
|
||||
// Created by Brent Simmons on 1/4/15.
|
||||
// Copyright (c) 2015 Ranchero Software LLC. All rights reserved.
|
||||
|
|
|
@ -56,16 +56,16 @@
|
|||
datePublishedTimeStampString = [NSString stringWithFormat:@"%.0f", self.datePublished.timeIntervalSince1970];
|
||||
}
|
||||
|
||||
if (!RSXMLStringIsEmpty(self.guid)) {
|
||||
if (!RSParserStringIsEmpty(self.guid)) {
|
||||
[s appendString:self.guid];
|
||||
}
|
||||
|
||||
else if (!RSXMLStringIsEmpty(self.link) && self.datePublished != nil) {
|
||||
else if (!RSParserStringIsEmpty(self.link) && self.datePublished != nil) {
|
||||
[s appendString:self.link];
|
||||
[s appendString:datePublishedTimeStampString];
|
||||
}
|
||||
|
||||
else if (!RSXMLStringIsEmpty(self.title) && self.datePublished != nil) {
|
||||
else if (!RSParserStringIsEmpty(self.title) && self.datePublished != nil) {
|
||||
[s appendString:self.title];
|
||||
[s appendString:datePublishedTimeStampString];
|
||||
}
|
||||
|
@ -74,19 +74,19 @@
|
|||
[s appendString:datePublishedTimeStampString];
|
||||
}
|
||||
|
||||
else if (!RSXMLStringIsEmpty(self.link)) {
|
||||
else if (!RSParserStringIsEmpty(self.link)) {
|
||||
[s appendString:self.link];
|
||||
}
|
||||
|
||||
else if (!RSXMLStringIsEmpty(self.title)) {
|
||||
else if (!RSParserStringIsEmpty(self.title)) {
|
||||
[s appendString:self.title];
|
||||
}
|
||||
|
||||
else if (!RSXMLStringIsEmpty(self.body)) {
|
||||
else if (!RSParserStringIsEmpty(self.body)) {
|
||||
[s appendString:self.body];
|
||||
}
|
||||
|
||||
NSAssert(!RSXMLStringIsEmpty(self.feedURL), nil);
|
||||
NSAssert(!RSParserStringIsEmpty(self.feedURL), nil);
|
||||
[s appendString:self.feedURL];
|
||||
|
||||
return [s rsxml_md5HashString];
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
//
|
||||
// RSRSSParser.h
|
||||
// RSXML
|
||||
// RSParser
|
||||
//
|
||||
// Created by Brent Simmons on 1/6/15.
|
||||
// Copyright (c) 2015 Ranchero Software LLC. All rights reserved.
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
//
|
||||
// RSRSSParser.m
|
||||
// RSXML
|
||||
// RSParser
|
||||
//
|
||||
// Created by Brent Simmons on 1/6/15.
|
||||
// Copyright (c) 2015 Ranchero Software LLC. All rights reserved.
|
||||
|
@ -256,7 +256,7 @@ static const NSInteger kTrueLength = 5;
|
|||
|
||||
self.currentArticle.guid = self.parser.currentStringWithTrimmedWhitespace;
|
||||
|
||||
NSString *isPermaLinkValue = [self.currentAttributes rsxml_objectForCaseInsensitiveKey:@"ispermalink"];
|
||||
NSString *isPermaLinkValue = [self.currentAttributes rsparser_objectForCaseInsensitiveKey:@"ispermalink"];
|
||||
if (!isPermaLinkValue || ![isPermaLinkValue isEqualToString:@"false"]) {
|
||||
self.currentArticle.permalink = [self urlString:self.currentArticle.guid];
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
//
|
||||
// RSHTMLLinkParser.h
|
||||
// RSXML
|
||||
// RSParser
|
||||
//
|
||||
// Created by Brent Simmons on 8/7/16.
|
||||
// Copyright © 2016 Ranchero Software, LLC. All rights reserved.
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
//
|
||||
// RSHTMLLinkParser.m
|
||||
// RSXML
|
||||
// RSParser
|
||||
//
|
||||
// Created by Brent Simmons on 8/7/16.
|
||||
// Copyright © 2016 Ranchero Software, LLC. All rights reserved.
|
||||
|
@ -88,7 +88,7 @@ static NSString *kHrefKey = @"href";
|
|||
|
||||
- (NSString *)urlStringFromDictionary:(NSDictionary *)d {
|
||||
|
||||
NSString *href = [d rsxml_objectForCaseInsensitiveKey:kHrefKey];
|
||||
NSString *href = [d rsparser_objectForCaseInsensitiveKey:kHrefKey];
|
||||
if (!href) {
|
||||
return nil;
|
||||
}
|
||||
|
@ -102,7 +102,7 @@ static NSString *kTitleKey = @"title";
|
|||
|
||||
- (NSString *)titleFromDictionary:(NSDictionary *)d {
|
||||
|
||||
return [d rsxml_objectForCaseInsensitiveKey:kTitleKey];
|
||||
return [d rsparser_objectForCaseInsensitiveKey:kTitleKey];
|
||||
}
|
||||
|
||||
|
||||
|
@ -127,7 +127,7 @@ static const NSInteger kAnchorLength = 2;
|
|||
[self.links addObject:link];
|
||||
|
||||
NSDictionary *d = [SAXParser attributesDictionary:attributes];
|
||||
if (!RSXMLIsEmpty(d)) {
|
||||
if (!RSParser_IsEmpty(d)) {
|
||||
[self handleLinkAttributes:d];
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
//
|
||||
// RSHTMLMetadata.h
|
||||
// RSXML
|
||||
// RSParser
|
||||
//
|
||||
// Created by Brent Simmons on 3/6/16.
|
||||
// Copyright © 2016 Ranchero Software, LLC. All rights reserved.
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
//
|
||||
// RSHTMLMetadata.m
|
||||
// RSXML
|
||||
// RSParser
|
||||
//
|
||||
// Created by Brent Simmons on 3/6/16.
|
||||
// Copyright © 2016 Ranchero Software, LLC. All rights reserved.
|
||||
|
@ -114,12 +114,12 @@ static NSString *kTypeKey = @"type";
|
|||
continue;
|
||||
}
|
||||
|
||||
NSString *oneType = [oneDictionary rsxml_objectForCaseInsensitiveKey:kTypeKey];
|
||||
NSString *oneType = [oneDictionary rsparser_objectForCaseInsensitiveKey:kTypeKey];
|
||||
if (!typeIsFeedType(oneType)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (RSXMLStringIsEmpty(urlStringFromDictionary(oneDictionary))) {
|
||||
if (RSParserStringIsEmpty(urlStringFromDictionary(oneDictionary))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -142,18 +142,18 @@ static NSString *kTypeKey = @"type";
|
|||
|
||||
static NSString *relValue(NSDictionary *d) {
|
||||
|
||||
return [d rsxml_objectForCaseInsensitiveKey:kRelKey];
|
||||
return [d rsparser_objectForCaseInsensitiveKey:kRelKey];
|
||||
}
|
||||
|
||||
|
||||
static NSString *urlStringFromDictionary(NSDictionary *d) {
|
||||
|
||||
NSString *urlString = [d rsxml_objectForCaseInsensitiveKey:kHrefKey];
|
||||
NSString *urlString = [d rsparser_objectForCaseInsensitiveKey:kHrefKey];
|
||||
if (urlString) {
|
||||
return urlString;
|
||||
}
|
||||
|
||||
return [d rsxml_objectForCaseInsensitiveKey:kSrcKey];
|
||||
return [d rsparser_objectForCaseInsensitiveKey:kSrcKey];
|
||||
}
|
||||
|
||||
|
||||
|
@ -172,7 +172,7 @@ static NSString *absoluteURLStringWithRelativeURLString(NSString *relativeURLStr
|
|||
static NSString *absoluteURLStringWithDictionary(NSDictionary *d, NSString *baseURLString) {
|
||||
|
||||
NSString *urlString = urlStringFromDictionary(d);
|
||||
if (RSXMLStringIsEmpty(urlString)) {
|
||||
if (RSParserStringIsEmpty(urlString)) {
|
||||
return nil;
|
||||
}
|
||||
return absoluteURLStringWithRelativeURLString(urlString, baseURLString);
|
||||
|
@ -213,8 +213,8 @@ static BOOL typeIsFeedType(NSString *type) {
|
|||
}
|
||||
|
||||
_urlString = absoluteURLStringWithDictionary(d, baseURLString);
|
||||
_sizes = [d rsxml_objectForCaseInsensitiveKey:kSizesKey];
|
||||
_rel = [d rsxml_objectForCaseInsensitiveKey:kRelKey];
|
||||
_sizes = [d rsparser_objectForCaseInsensitiveKey:kSizesKey];
|
||||
_rel = [d rsparser_objectForCaseInsensitiveKey:kRelKey];
|
||||
|
||||
return self;
|
||||
}
|
||||
|
@ -234,8 +234,8 @@ static BOOL typeIsFeedType(NSString *type) {
|
|||
}
|
||||
|
||||
_urlString = absoluteURLStringWithDictionary(d, baseURLString);
|
||||
_title = [d rsxml_objectForCaseInsensitiveKey:kTitleKey];
|
||||
_type = [d rsxml_objectForCaseInsensitiveKey:kTypeKey];
|
||||
_title = [d rsparser_objectForCaseInsensitiveKey:kTitleKey];
|
||||
_type = [d rsparser_objectForCaseInsensitiveKey:kTypeKey];
|
||||
|
||||
return self;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
//
|
||||
// RSHTMLMetadataParser.h
|
||||
// RSXML
|
||||
// RSParser
|
||||
//
|
||||
// Created by Brent Simmons on 3/6/16.
|
||||
// Copyright © 2016 Ranchero Software, LLC. All rights reserved.
|
||||
|
|
|
@ -76,21 +76,21 @@ static NSString *kRelKey = @"rel";
|
|||
|
||||
- (NSString *)linkForDictionary:(NSDictionary *)d {
|
||||
|
||||
NSString *link = [d rsxml_objectForCaseInsensitiveKey:kHrefKey];
|
||||
NSString *link = [d rsparser_objectForCaseInsensitiveKey:kHrefKey];
|
||||
if (link) {
|
||||
return link;
|
||||
}
|
||||
|
||||
return [d rsxml_objectForCaseInsensitiveKey:kSrcKey];
|
||||
return [d rsparser_objectForCaseInsensitiveKey:kSrcKey];
|
||||
}
|
||||
|
||||
|
||||
- (void)handleLinkAttributes:(NSDictionary *)d {
|
||||
|
||||
if (RSXMLStringIsEmpty([d rsxml_objectForCaseInsensitiveKey:kRelKey])) {
|
||||
if (RSParserStringIsEmpty([d rsparser_objectForCaseInsensitiveKey:kRelKey])) {
|
||||
return;
|
||||
}
|
||||
if (RSXMLStringIsEmpty([self linkForDictionary:d])) {
|
||||
if (RSParserStringIsEmpty([self linkForDictionary:d])) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -121,7 +121,7 @@ static const NSInteger kLinkLength = 5;
|
|||
}
|
||||
|
||||
NSDictionary *d = [SAXParser attributesDictionary:attributes];
|
||||
if (!RSXMLIsEmpty(d)) {
|
||||
if (!RSParser_IsEmpty(d)) {
|
||||
[self handleLinkAttributes:d];
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
//
|
||||
// RSSAXHTMLParser.h
|
||||
// RSXML
|
||||
// RSParser
|
||||
//
|
||||
// Created by Brent Simmons on 3/6/16.
|
||||
// Copyright © 2016 Ranchero Software, LLC. All rights reserved.
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
//
|
||||
// RSSAXHTMLParser.m
|
||||
// RSXML
|
||||
// RSParser
|
||||
//
|
||||
// Created by Brent Simmons on 3/6/16.
|
||||
// Copyright © 2016 Ranchero Software, LLC. All rights reserved.
|
||||
|
@ -150,7 +150,7 @@ static xmlSAXHandler saxHandlerStruct;
|
|||
- (NSString *)currentString {
|
||||
|
||||
NSData *d = self.currentCharacters;
|
||||
if (RSXMLIsEmpty(d)) {
|
||||
if (RSParserObjectIsEmpty(d)) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
|
|
|
@ -23,43 +23,43 @@ NSString *OPMLXMLURLKey = @"xmlUrl";
|
|||
|
||||
- (NSString *)opml_text {
|
||||
|
||||
return [self rsxml_objectForCaseInsensitiveKey:OPMLTextKey];
|
||||
return [self rsparser_objectForCaseInsensitiveKey:OPMLTextKey];
|
||||
}
|
||||
|
||||
|
||||
- (NSString *)opml_title {
|
||||
|
||||
return [self rsxml_objectForCaseInsensitiveKey:OPMLTitleKey];
|
||||
return [self rsparser_objectForCaseInsensitiveKey:OPMLTitleKey];
|
||||
}
|
||||
|
||||
|
||||
- (NSString *)opml_description {
|
||||
|
||||
return [self rsxml_objectForCaseInsensitiveKey:OPMLDescriptionKey];
|
||||
return [self rsparser_objectForCaseInsensitiveKey:OPMLDescriptionKey];
|
||||
}
|
||||
|
||||
|
||||
- (NSString *)opml_type {
|
||||
|
||||
return [self rsxml_objectForCaseInsensitiveKey:OPMLTypeKey];
|
||||
return [self rsparser_objectForCaseInsensitiveKey:OPMLTypeKey];
|
||||
}
|
||||
|
||||
|
||||
- (NSString *)opml_version {
|
||||
|
||||
return [self rsxml_objectForCaseInsensitiveKey:OPMLVersionKey];
|
||||
return [self rsparser_objectForCaseInsensitiveKey:OPMLVersionKey];
|
||||
}
|
||||
|
||||
|
||||
- (NSString *)opml_htmlUrl {
|
||||
|
||||
return [self rsxml_objectForCaseInsensitiveKey:OPMLHMTLURLKey];
|
||||
return [self rsparser_objectForCaseInsensitiveKey:OPMLHMTLURLKey];
|
||||
}
|
||||
|
||||
|
||||
- (NSString *)opml_xmlUrl {
|
||||
|
||||
return [self rsxml_objectForCaseInsensitiveKey:OPMLXMLURLKey];
|
||||
return [self rsparser_objectForCaseInsensitiveKey:OPMLXMLURLKey];
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -14,28 +14,28 @@
|
|||
|
||||
- (instancetype)initWithTitle:(NSString *)title feedDescription:(NSString *)feedDescription homePageURL:(NSString *)homePageURL feedURL:(NSString *)feedURL {
|
||||
|
||||
NSParameterAssert(!RSXMLIsEmpty(feedURL));
|
||||
NSParameterAssert(!RSParserStringIsEmpty(feedURL));
|
||||
|
||||
self = [super init];
|
||||
if (!self) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
if (RSXMLIsEmpty(title)) {
|
||||
if (RSParserStringIsEmpty(title)) {
|
||||
_title = nil;
|
||||
}
|
||||
else {
|
||||
_title = title;
|
||||
}
|
||||
|
||||
if (RSXMLIsEmpty(feedDescription)) {
|
||||
if (RSParserStringIsEmpty(feedDescription)) {
|
||||
_feedDescription = nil;
|
||||
}
|
||||
else {
|
||||
_feedDescription = feedDescription;
|
||||
}
|
||||
|
||||
if (RSXMLIsEmpty(homePageURL)) {
|
||||
if (RSParserStringIsEmpty(homePageURL)) {
|
||||
_homePageURL = nil;
|
||||
}
|
||||
else {
|
||||
|
|
|
@ -55,7 +55,7 @@
|
|||
}
|
||||
|
||||
NSString *feedURL = self.attributes.opml_xmlUrl;
|
||||
if (RSXMLIsEmpty(feedURL)) {
|
||||
if (RSParserObjectIsEmpty(feedURL)) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
|
|
|
@ -9,7 +9,8 @@
|
|||
@import Foundation;
|
||||
|
||||
#import <RSParser/NSData+RSParser.h>
|
||||
#import <RSParser/RSParser.h>
|
||||
#import <RSParser/RSDateParser.h>
|
||||
#import <RSParser/NSString+RSParser.h>
|
||||
|
||||
//#import <RSXML/RSSAXParser.h>
|
||||
//#import <RSXML/RSXMLData.h>
|
||||
|
|
|
@ -28,12 +28,12 @@
|
|||
84469D0C1EFA307E004A6B28 /* RSHTMLMetadataParser.m in Sources */ = {isa = PBXBuildFile; fileRef = 84469D041EFA307E004A6B28 /* RSHTMLMetadataParser.m */; };
|
||||
84469D0D1EFA307E004A6B28 /* RSSAXHTMLParser.h in Headers */ = {isa = PBXBuildFile; fileRef = 84469D051EFA307E004A6B28 /* RSSAXHTMLParser.h */; };
|
||||
84469D0E1EFA307E004A6B28 /* RSSAXHTMLParser.m in Sources */ = {isa = PBXBuildFile; fileRef = 84469D061EFA307E004A6B28 /* RSSAXHTMLParser.m */; };
|
||||
84469D161EFA30A2004A6B28 /* NSString+RSXML.h in Headers */ = {isa = PBXBuildFile; fileRef = 84469D101EFA30A2004A6B28 /* NSString+RSXML.h */; };
|
||||
84469D171EFA30A2004A6B28 /* NSString+RSXML.m in Sources */ = {isa = PBXBuildFile; fileRef = 84469D111EFA30A2004A6B28 /* NSString+RSXML.m */; };
|
||||
84469D181EFA30A2004A6B28 /* RSDateParser.h in Headers */ = {isa = PBXBuildFile; fileRef = 84469D121EFA30A2004A6B28 /* RSDateParser.h */; };
|
||||
84469D161EFA30A2004A6B28 /* NSString+RSParser.h in Headers */ = {isa = PBXBuildFile; fileRef = 84469D101EFA30A2004A6B28 /* NSString+RSParser.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
84469D171EFA30A2004A6B28 /* NSString+RSParser.m in Sources */ = {isa = PBXBuildFile; fileRef = 84469D111EFA30A2004A6B28 /* NSString+RSParser.m */; };
|
||||
84469D181EFA30A2004A6B28 /* RSDateParser.h in Headers */ = {isa = PBXBuildFile; fileRef = 84469D121EFA30A2004A6B28 /* RSDateParser.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
84469D191EFA30A2004A6B28 /* RSDateParser.m in Sources */ = {isa = PBXBuildFile; fileRef = 84469D131EFA30A2004A6B28 /* RSDateParser.m */; };
|
||||
84469D1A1EFA30A2004A6B28 /* RSXMLInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = 84469D141EFA30A2004A6B28 /* RSXMLInternal.h */; };
|
||||
84469D1B1EFA30A2004A6B28 /* RSXMLInternal.m in Sources */ = {isa = PBXBuildFile; fileRef = 84469D151EFA30A2004A6B28 /* RSXMLInternal.m */; };
|
||||
84469D1A1EFA30A2004A6B28 /* RSParserInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = 84469D141EFA30A2004A6B28 /* RSParserInternal.h */; };
|
||||
84469D1B1EFA30A2004A6B28 /* RSParserInternal.m in Sources */ = {isa = PBXBuildFile; fileRef = 84469D151EFA30A2004A6B28 /* RSParserInternal.m */; };
|
||||
84469D271EFA3134004A6B28 /* RSAtomParser.h in Headers */ = {isa = PBXBuildFile; fileRef = 84469D1D1EFA3134004A6B28 /* RSAtomParser.h */; };
|
||||
84469D281EFA3134004A6B28 /* RSAtomParser.m in Sources */ = {isa = PBXBuildFile; fileRef = 84469D1E1EFA3134004A6B28 /* RSAtomParser.m */; };
|
||||
84469D291EFA3134004A6B28 /* RSFeedParser.h in Headers */ = {isa = PBXBuildFile; fileRef = 84469D1F1EFA3134004A6B28 /* RSFeedParser.h */; };
|
||||
|
@ -45,7 +45,7 @@
|
|||
84469D2F1EFA3134004A6B28 /* RSRSSParser.h in Headers */ = {isa = PBXBuildFile; fileRef = 84469D251EFA3134004A6B28 /* RSRSSParser.h */; };
|
||||
84469D301EFA3134004A6B28 /* RSRSSParser.m in Sources */ = {isa = PBXBuildFile; fileRef = 84469D261EFA3134004A6B28 /* RSRSSParser.m */; };
|
||||
84469D321EFA31CF004A6B28 /* FeedParser.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84469D311EFA31CF004A6B28 /* FeedParser.swift */; };
|
||||
84469D351EFF1190004A6B28 /* NSData+RSParser.h in Headers */ = {isa = PBXBuildFile; fileRef = 84469D331EFF1190004A6B28 /* NSData+RSParser.h */; };
|
||||
84469D351EFF1190004A6B28 /* NSData+RSParser.h in Headers */ = {isa = PBXBuildFile; fileRef = 84469D331EFF1190004A6B28 /* NSData+RSParser.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
84469D361EFF1190004A6B28 /* NSData+RSParser.m in Sources */ = {isa = PBXBuildFile; fileRef = 84469D341EFF1190004A6B28 /* NSData+RSParser.m */; };
|
||||
84469D381EFF2645004A6B28 /* RSSInJSONParser.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84469D371EFF2645004A6B28 /* RSSInJSONParser.swift */; };
|
||||
84469D401EFF29A9004A6B28 /* FeedParserError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84469D3F1EFF29A9004A6B28 /* FeedParserError.swift */; };
|
||||
|
@ -94,12 +94,12 @@
|
|||
84469D041EFA307E004A6B28 /* RSHTMLMetadataParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RSHTMLMetadataParser.m; sourceTree = "<group>"; };
|
||||
84469D051EFA307E004A6B28 /* RSSAXHTMLParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RSSAXHTMLParser.h; sourceTree = "<group>"; };
|
||||
84469D061EFA307E004A6B28 /* RSSAXHTMLParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RSSAXHTMLParser.m; sourceTree = "<group>"; };
|
||||
84469D101EFA30A2004A6B28 /* NSString+RSXML.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSString+RSXML.h"; sourceTree = "<group>"; };
|
||||
84469D111EFA30A2004A6B28 /* NSString+RSXML.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSString+RSXML.m"; sourceTree = "<group>"; };
|
||||
84469D121EFA30A2004A6B28 /* RSDateParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RSDateParser.h; sourceTree = "<group>"; };
|
||||
84469D131EFA30A2004A6B28 /* RSDateParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RSDateParser.m; sourceTree = "<group>"; };
|
||||
84469D141EFA30A2004A6B28 /* RSXMLInternal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RSXMLInternal.h; sourceTree = "<group>"; };
|
||||
84469D151EFA30A2004A6B28 /* RSXMLInternal.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RSXMLInternal.m; sourceTree = "<group>"; };
|
||||
84469D101EFA30A2004A6B28 /* NSString+RSParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSString+RSParser.h"; sourceTree = "<group>"; };
|
||||
84469D111EFA30A2004A6B28 /* NSString+RSParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSString+RSParser.m"; sourceTree = "<group>"; };
|
||||
84469D121EFA30A2004A6B28 /* RSDateParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RSDateParser.h; path = Utilities/RSDateParser.h; sourceTree = "<group>"; };
|
||||
84469D131EFA30A2004A6B28 /* RSDateParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = RSDateParser.m; path = Utilities/RSDateParser.m; sourceTree = "<group>"; };
|
||||
84469D141EFA30A2004A6B28 /* RSParserInternal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RSParserInternal.h; sourceTree = "<group>"; };
|
||||
84469D151EFA30A2004A6B28 /* RSParserInternal.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RSParserInternal.m; sourceTree = "<group>"; };
|
||||
84469D1D1EFA3134004A6B28 /* RSAtomParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RSAtomParser.h; sourceTree = "<group>"; };
|
||||
84469D1E1EFA3134004A6B28 /* RSAtomParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RSAtomParser.m; sourceTree = "<group>"; };
|
||||
84469D1F1EFA3134004A6B28 /* RSFeedParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RSFeedParser.h; sourceTree = "<group>"; };
|
||||
|
@ -150,6 +150,15 @@
|
|||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
84285AA61F004879002E8708 /* Dates */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
84469D121EFA30A2004A6B28 /* RSDateParser.h */,
|
||||
84469D131EFA30A2004A6B28 /* RSDateParser.m */,
|
||||
);
|
||||
name = Dates;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
84469CE31EFA2FB0004A6B28 /* Feeds */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
|
@ -213,12 +222,10 @@
|
|||
children = (
|
||||
84469D331EFF1190004A6B28 /* NSData+RSParser.h */,
|
||||
84469D341EFF1190004A6B28 /* NSData+RSParser.m */,
|
||||
84469D101EFA30A2004A6B28 /* NSString+RSXML.h */,
|
||||
84469D111EFA30A2004A6B28 /* NSString+RSXML.m */,
|
||||
84469D121EFA30A2004A6B28 /* RSDateParser.h */,
|
||||
84469D131EFA30A2004A6B28 /* RSDateParser.m */,
|
||||
84469D141EFA30A2004A6B28 /* RSXMLInternal.h */,
|
||||
84469D151EFA30A2004A6B28 /* RSXMLInternal.m */,
|
||||
84469D101EFA30A2004A6B28 /* NSString+RSParser.h */,
|
||||
84469D111EFA30A2004A6B28 /* NSString+RSParser.m */,
|
||||
84469D141EFA30A2004A6B28 /* RSParserInternal.h */,
|
||||
84469D151EFA30A2004A6B28 /* RSParserInternal.m */,
|
||||
);
|
||||
path = Utilities;
|
||||
sourceTree = "<group>";
|
||||
|
@ -257,6 +264,7 @@
|
|||
84D81BDA1EFA28E700652332 /* RSParser.h */,
|
||||
84469CE11EFA2F3E004A6B28 /* ParserData.swift */,
|
||||
84469CE31EFA2FB0004A6B28 /* Feeds */,
|
||||
84285AA61F004879002E8708 /* Dates */,
|
||||
84469CE41EFA3000004A6B28 /* OPML */,
|
||||
84469CFE1EFA307E004A6B28 /* HTML */,
|
||||
84469CF91EFA3069004A6B28 /* SAX */,
|
||||
|
@ -298,7 +306,7 @@
|
|||
84469CF51EFA3000004A6B28 /* RSOPMLItem.h in Headers */,
|
||||
84469D2D1EFA3134004A6B28 /* RSParsedFeed.h in Headers */,
|
||||
84469D181EFA30A2004A6B28 /* RSDateParser.h in Headers */,
|
||||
84469D1A1EFA30A2004A6B28 /* RSXMLInternal.h in Headers */,
|
||||
84469D1A1EFA30A2004A6B28 /* RSParserInternal.h in Headers */,
|
||||
84469D351EFF1190004A6B28 /* NSData+RSParser.h in Headers */,
|
||||
84D81BDC1EFA28E700652332 /* RSParser.h in Headers */,
|
||||
84469D0B1EFA307E004A6B28 /* RSHTMLMetadataParser.h in Headers */,
|
||||
|
@ -311,7 +319,7 @@
|
|||
84469CF31EFA3000004A6B28 /* RSOPMLFeedSpecifier.h in Headers */,
|
||||
84469CF11EFA3000004A6B28 /* RSOPMLDocument.h in Headers */,
|
||||
84469D091EFA307E004A6B28 /* RSHTMLMetadata.h in Headers */,
|
||||
84469D161EFA30A2004A6B28 /* NSString+RSXML.h in Headers */,
|
||||
84469D161EFA30A2004A6B28 /* NSString+RSParser.h in Headers */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
@ -414,7 +422,7 @@
|
|||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
84469D081EFA307E004A6B28 /* RSHTMLLinkParser.m in Sources */,
|
||||
84469D1B1EFA30A2004A6B28 /* RSXMLInternal.m in Sources */,
|
||||
84469D1B1EFA30A2004A6B28 /* RSParserInternal.m in Sources */,
|
||||
84D81BE21EFA2D0900652332 /* ParsedAuthor.swift in Sources */,
|
||||
84469D0E1EFA307E004A6B28 /* RSSAXHTMLParser.m in Sources */,
|
||||
84469CF41EFA3000004A6B28 /* RSOPMLFeedSpecifier.m in Sources */,
|
||||
|
@ -431,7 +439,7 @@
|
|||
84469D421EFF2B2D004A6B28 /* JSONTypes.swift in Sources */,
|
||||
84469D0C1EFA307E004A6B28 /* RSHTMLMetadataParser.m in Sources */,
|
||||
84469D0A1EFA307E004A6B28 /* RSHTMLMetadata.m in Sources */,
|
||||
84469D171EFA30A2004A6B28 /* NSString+RSXML.m in Sources */,
|
||||
84469D171EFA30A2004A6B28 /* NSString+RSParser.m in Sources */,
|
||||
84469D2C1EFA3134004A6B28 /* RSParsedArticle.m in Sources */,
|
||||
84469D2E1EFA3134004A6B28 /* RSParsedFeed.m in Sources */,
|
||||
84469CF81EFA3000004A6B28 /* RSOPMLParser.m in Sources */,
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
//
|
||||
// RSSAXParser.h
|
||||
// RSXML
|
||||
// RSParser
|
||||
//
|
||||
// Created by Brent Simmons on 3/25/15.
|
||||
// Copyright (c) 2015 Ranchero Software, LLC. All rights reserved.
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
//
|
||||
// RSSAXParser.m
|
||||
// RSXML
|
||||
// RSParser
|
||||
//
|
||||
// Created by Brent Simmons on 3/25/15.
|
||||
// Copyright (c) 2015 Ranchero Software, LLC. All rights reserved.
|
||||
|
@ -152,7 +152,7 @@ static xmlSAXHandler saxHandlerStruct;
|
|||
- (NSString *)currentString {
|
||||
|
||||
NSData *d = self.currentCharacters;
|
||||
if (RSXMLIsEmpty(d)) {
|
||||
if (RSParserObjectIsEmpty(d)) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
|
|
|
@ -15,6 +15,11 @@
|
|||
- (BOOL)isProbablyXML;
|
||||
- (BOOL)isProbablyJSON;
|
||||
|
||||
- (BOOL)isProbablyJSONFeed;
|
||||
- (BOOL)isProbablyRSSInJSON;
|
||||
- (BOOL)isProbablyRSS;
|
||||
- (BOOL)isProbablyAtom;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
|
|
|
@ -39,7 +39,7 @@ static BOOL bytesStartWithStringIgnoringWhitespace(const char *string, const cha
|
|||
return didFindString("https://jsonfeed.org/version/", self.bytes, self.length);
|
||||
}
|
||||
|
||||
- (BOOL)isProbablyRSSInJSONFeed {
|
||||
- (BOOL)isProbablyRSSInJSON {
|
||||
|
||||
if (![self isProbablyJSON]) {
|
||||
return NO;
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
//
|
||||
// NSString+RSParser.h
|
||||
// RSParser
|
||||
//
|
||||
// Created by Brent Simmons on 9/25/15.
|
||||
// Copyright © 2015 Ranchero Software, LLC. All rights reserved.
|
||||
//
|
||||
|
||||
@import Foundation;
|
||||
|
||||
@interface NSString (RSParser)
|
||||
|
||||
- (NSString *)rsparser_stringByDecodingHTMLEntities;
|
||||
|
||||
- (NSString *)rsparser_md5Hash;
|
||||
|
||||
@end
|
||||
|
|
@ -1,24 +1,24 @@
|
|||
//
|
||||
// NSString+RSXML.m
|
||||
// RSXML
|
||||
// NSString+RSParser.m
|
||||
// RSParser
|
||||
//
|
||||
// Created by Brent Simmons on 9/25/15.
|
||||
// Copyright © 2015 Ranchero Software, LLC. All rights reserved.
|
||||
//
|
||||
|
||||
#import "NSString+RSXML.h"
|
||||
#import "NSString+RSParser.h"
|
||||
|
||||
|
||||
@interface NSScanner (RSXML)
|
||||
@interface NSScanner (RSParser)
|
||||
|
||||
- (BOOL)rs_scanEntityValue:(NSString * _Nullable * _Nullable)decodedEntity;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@implementation NSString (RSXML)
|
||||
@implementation NSString (RSParser)
|
||||
|
||||
- (NSString *)rs_stringByDecodingHTMLEntities {
|
||||
- (NSString *)rsparser_stringByDecodingHTMLEntities {
|
||||
|
||||
@autoreleasepool {
|
||||
|
||||
|
@ -60,7 +60,7 @@
|
|||
|
||||
|
||||
static NSDictionary *RSEntitiesDictionary(void);
|
||||
static NSString *RSXMLStringWithValue(unichar value);
|
||||
static NSString *RSParserStringWithValue(unichar value);
|
||||
|
||||
- (NSString * _Nullable)rs_stringByDecodingEntity {
|
||||
|
||||
|
@ -87,7 +87,7 @@ static NSString *RSXMLStringWithValue(unichar value);
|
|||
scanner.charactersToBeSkipped = [NSCharacterSet characterSetWithCharactersInString:@"#x"];
|
||||
unsigned int hexValue = 0;
|
||||
if ([scanner scanHexInt:&hexValue]) {
|
||||
return RSXMLStringWithValue((unichar)hexValue);
|
||||
return RSParserStringWithValue((unichar)hexValue);
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
@ -98,15 +98,33 @@ static NSString *RSXMLStringWithValue(unichar value);
|
|||
if (value < 1) {
|
||||
return nil;
|
||||
}
|
||||
return RSXMLStringWithValue((unichar)value);
|
||||
return RSParserStringWithValue((unichar)value);
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (NSData *)_rsparser_md5HashData {
|
||||
|
||||
NSData *data = [self dataUsingEncoding:NSUTF8StringEncoding];
|
||||
unsigned char hash[CC_MD5_DIGEST_LENGTH];
|
||||
CC_MD5(data.bytes, (CC_LONG)data.length, hash);
|
||||
|
||||
return [NSData dataWithBytes:(const void *)hash length:CC_MD5_DIGEST_LENGTH];
|
||||
}
|
||||
|
||||
- (NSString *)rsparser_md5Hash {
|
||||
|
||||
NSData *md5Data = [self _rsparser_md5HashData];
|
||||
const Byte *bytes = md5Data.bytes;
|
||||
return [NSString stringWithFormat:@"%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5], bytes[6], bytes[7], bytes[8], bytes[9], bytes[10], bytes[11], bytes[12], bytes[13], bytes[14], bytes[15]];
|
||||
}
|
||||
|
||||
|
||||
|
||||
@end
|
||||
|
||||
@implementation NSScanner (RSXML)
|
||||
@implementation NSScanner (RSParser)
|
||||
|
||||
- (BOOL)rs_scanEntityValue:(NSString * _Nullable * _Nullable)decodedEntity {
|
||||
|
||||
|
@ -144,7 +162,7 @@ static NSString *RSXMLStringWithValue(unichar value);
|
|||
|
||||
@end
|
||||
|
||||
static NSString *RSXMLStringWithValue(unichar value) {
|
||||
static NSString *RSParserStringWithValue(unichar value) {
|
||||
|
||||
return [[NSString alloc] initWithFormat:@"%C", value];
|
||||
}
|
||||
|
@ -169,7 +187,7 @@ static NSDictionary *RSEntitiesDictionary(void) {
|
|||
@"#150": @"-",
|
||||
@"#151": @"—",
|
||||
@"#153": @"™",
|
||||
@"#160": RSXMLStringWithValue(160),
|
||||
@"#160": RSParserStringWithValue(160),
|
||||
@"#161": @"¡",
|
||||
@"#162": @"¢",
|
||||
@"#163": @"£",
|
||||
|
@ -277,7 +295,7 @@ static NSDictionary *RSEntitiesDictionary(void) {
|
|||
@"#8220": @"“",
|
||||
@"#8221": @"”",
|
||||
@"#8230": @"…",
|
||||
@"#8617": RSXMLStringWithValue(8617),
|
||||
@"#8617": RSParserStringWithValue(8617),
|
||||
@"AElig": @"Æ",
|
||||
@"Aacute": @"Á",
|
||||
@"Acirc": @"Â",
|
||||
|
@ -394,14 +412,14 @@ static NSDictionary *RSEntitiesDictionary(void) {
|
|||
@"yen": @"¥",
|
||||
@"yuml": @"ÿ",
|
||||
@"infin": @"∞",
|
||||
@"nbsp": RSXMLStringWithValue(160),
|
||||
@"#x21A9": RSXMLStringWithValue(8617),
|
||||
@"#xFE0E": RSXMLStringWithValue(65038),
|
||||
@"#x2019": RSXMLStringWithValue(8217),
|
||||
@"#x2026": RSXMLStringWithValue(8230),
|
||||
@"#x201C": RSXMLStringWithValue(8220),
|
||||
@"#x201D": RSXMLStringWithValue(8221),
|
||||
@"#x2014": RSXMLStringWithValue(8212)};
|
||||
@"nbsp": RSParserStringWithValue(160),
|
||||
@"#x21A9": RSParserStringWithValue(8617),
|
||||
@"#xFE0E": RSParserStringWithValue(65038),
|
||||
@"#x2019": RSParserStringWithValue(8217),
|
||||
@"#x2026": RSParserStringWithValue(8230),
|
||||
@"#x201C": RSParserStringWithValue(8220),
|
||||
@"#x201D": RSParserStringWithValue(8221),
|
||||
@"#x2014": RSParserStringWithValue(8212)};
|
||||
});
|
||||
|
||||
return entitiesDictionary;
|
|
@ -1,16 +0,0 @@
|
|||
//
|
||||
// NSString+RSXML.h
|
||||
// RSXML
|
||||
//
|
||||
// Created by Brent Simmons on 9/25/15.
|
||||
// Copyright © 2015 Ranchero Software, LLC. All rights reserved.
|
||||
//
|
||||
|
||||
@import Foundation;
|
||||
|
||||
@interface NSString (RSXML)
|
||||
|
||||
- (NSString *)rs_stringByDecodingHTMLEntities;
|
||||
|
||||
@end
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
//
|
||||
// RSDateParser.h
|
||||
// RSXML
|
||||
// RSParser
|
||||
//
|
||||
// Created by Brent Simmons on 3/25/15.
|
||||
// Copyright (c) 2015 Ranchero Software, LLC. All rights reserved.
|
||||
|
@ -9,17 +9,14 @@
|
|||
@import Foundation;
|
||||
|
||||
|
||||
/*Common web dates -- RFC 822 and 8601 -- are handled here:
|
||||
the formats you find in JSON and XML feeds.
|
||||
|
||||
Any of these may return nil. They may also return garbage, given bad input.*/
|
||||
|
||||
// Common web dates -- RFC 822 and 8601 -- are handled here: the formats you find in JSON and XML feeds.
|
||||
// These may return nil. They may also return garbage, given bad input.
|
||||
|
||||
NSDate *RSDateWithString(NSString *dateString);
|
||||
|
||||
/*If you're using a SAX parser, you have the bytes and don't need to convert to a string first.
|
||||
It's faster and uses less memory.
|
||||
(Assumes bytes are UTF-8 or ASCII. If you're using the libxml SAX parser, this will work.)*/
|
||||
// If you're using a SAX parser, you have the bytes and don't need to convert to a string first.
|
||||
// It's faster and uses less memory.
|
||||
// (Assumes bytes are UTF-8 or ASCII. If you're using the libxml SAX parser, this will work.)
|
||||
|
||||
NSDate *RSDateWithBytes(const char *bytes, NSUInteger numberOfBytes);
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
//
|
||||
// RSDateParser.m
|
||||
// RSXML
|
||||
// RSParser
|
||||
//
|
||||
// Created by Brent Simmons on 3/25/15.
|
||||
// Copyright (c) 2015 Ranchero Software, LLC. All rights reserved.
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
//
|
||||
// RSParserInternal.h
|
||||
// RSParser
|
||||
//
|
||||
// Created by Brent Simmons on 12/26/16.
|
||||
// Copyright © 2016 Ranchero Software, LLC. All rights reserved.
|
||||
//
|
||||
|
||||
@import Foundation;
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
BOOL RSParser_IsEmpty(id _Nullable obj);
|
||||
BOOL RSParserStringIsEmpty(NSString * _Nullable s);
|
||||
|
||||
|
||||
@interface NSDictionary (RSParserInternal)
|
||||
|
||||
- (nullable id)rsparser_objectForCaseInsensitiveKey:(NSString *)key;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
|
@ -0,0 +1,60 @@
|
|||
//
|
||||
// RSXMLInternal.m
|
||||
// RSParser
|
||||
//
|
||||
// Created by Brent Simmons on 12/26/16.
|
||||
// Copyright © 2016 Ranchero Software, LLC. All rights reserved.
|
||||
//
|
||||
|
||||
#import <CommonCrypto/CommonDigest.h>
|
||||
#import "RSXMLInternal.h"
|
||||
|
||||
|
||||
static BOOL RSParserIsNil(id obj) {
|
||||
|
||||
return obj == nil || obj == [NSNull null];
|
||||
}
|
||||
|
||||
BOOL RSParserObjectIsEmpty(id obj) {
|
||||
|
||||
if (RSParserIsNil(obj)) {
|
||||
return YES;
|
||||
}
|
||||
|
||||
if ([obj respondsToSelector:@selector(count)]) {
|
||||
return [obj count] < 1;
|
||||
}
|
||||
|
||||
if ([obj respondsToSelector:@selector(length)]) {
|
||||
return [obj length] < 1;
|
||||
}
|
||||
|
||||
return NO; /*Shouldn't get here very often.*/
|
||||
}
|
||||
|
||||
BOOL RSParserStringIsEmpty(NSString *s) {
|
||||
|
||||
return RSParserIsNil(s) || s.length < 1;
|
||||
}
|
||||
|
||||
|
||||
@implementation NSDictionary (RSParserInternal)
|
||||
|
||||
- (nullable id)rsparser_objectForCaseInsensitiveKey:(NSString *)key {
|
||||
|
||||
id obj = self[key];
|
||||
if (obj) {
|
||||
return obj;
|
||||
}
|
||||
|
||||
for (NSString *oneKey in self.allKeys) {
|
||||
|
||||
if ([oneKey isKindOfClass:[NSString class]] && [key caseInsensitiveCompare:oneKey] == NSOrderedSame) {
|
||||
return self[oneKey];
|
||||
}
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
@end
|
|
@ -1,31 +0,0 @@
|
|||
//
|
||||
// RSXMLInternal.h
|
||||
// RSXML
|
||||
//
|
||||
// Created by Brent Simmons on 12/26/16.
|
||||
// Copyright © 2016 Ranchero Software, LLC. All rights reserved.
|
||||
//
|
||||
|
||||
@import Foundation;
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
BOOL RSXMLIsEmpty(id _Nullable obj);
|
||||
BOOL RSXMLStringIsEmpty(NSString * _Nullable s);
|
||||
|
||||
|
||||
@interface NSString (RSXMLInternal)
|
||||
|
||||
- (NSString *)rsxml_md5HashString;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@interface NSDictionary (RSXMLInternal)
|
||||
|
||||
- (nullable id)rsxml_objectForCaseInsensitiveKey:(NSString *)key;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
|
@ -1,83 +0,0 @@
|
|||
//
|
||||
// RSXMLInternal.m
|
||||
// RSXML
|
||||
//
|
||||
// Created by Brent Simmons on 12/26/16.
|
||||
// Copyright © 2016 Ranchero Software, LLC. All rights reserved.
|
||||
//
|
||||
|
||||
#import <CommonCrypto/CommonDigest.h>
|
||||
#import "RSXMLInternal.h"
|
||||
|
||||
|
||||
static BOOL RSXMLIsNil(id obj) {
|
||||
|
||||
return obj == nil || obj == [NSNull null];
|
||||
}
|
||||
|
||||
BOOL RSXMLIsEmpty(id obj) {
|
||||
|
||||
if (RSXMLIsNil(obj)) {
|
||||
return YES;
|
||||
}
|
||||
|
||||
if ([obj respondsToSelector:@selector(count)]) {
|
||||
return [obj count] < 1;
|
||||
}
|
||||
|
||||
if ([obj respondsToSelector:@selector(length)]) {
|
||||
return [obj length] < 1;
|
||||
}
|
||||
|
||||
return NO; /*Shouldn't get here very often.*/
|
||||
}
|
||||
|
||||
BOOL RSXMLStringIsEmpty(NSString *s) {
|
||||
|
||||
return RSXMLIsNil(s) || s.length < 1;
|
||||
}
|
||||
|
||||
|
||||
@implementation NSString (RSXMLInternal)
|
||||
|
||||
- (NSData *)rsxml_md5Hash {
|
||||
|
||||
NSData *data = [self dataUsingEncoding:NSUTF8StringEncoding];
|
||||
unsigned char hash[CC_MD5_DIGEST_LENGTH];
|
||||
CC_MD5(data.bytes, (CC_LONG)data.length, hash);
|
||||
|
||||
return [NSData dataWithBytes:(const void *)hash length:CC_MD5_DIGEST_LENGTH];
|
||||
}
|
||||
|
||||
- (NSString *)rsxml_md5HashString {
|
||||
|
||||
NSData *md5Data = [self rsxml_md5Hash];
|
||||
const Byte *bytes = md5Data.bytes;
|
||||
return [NSString stringWithFormat:@"%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5], bytes[6], bytes[7], bytes[8], bytes[9], bytes[10], bytes[11], bytes[12], bytes[13], bytes[14], bytes[15]];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@implementation NSDictionary (RSXMLInternal)
|
||||
|
||||
|
||||
- (nullable id)rsxml_objectForCaseInsensitiveKey:(NSString *)key {
|
||||
|
||||
id obj = self[key];
|
||||
if (obj) {
|
||||
return obj;
|
||||
}
|
||||
|
||||
for (NSString *oneKey in self.allKeys) {
|
||||
|
||||
if ([oneKey isKindOfClass:[NSString class]] && [key caseInsensitiveCompare:oneKey] == NSOrderedSame) {
|
||||
return self[oneKey];
|
||||
}
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
|
||||
@end
|
Loading…
Reference in New Issue