// // NSData+RSParser.m // RSParser // // Created by Brent Simmons on 6/24/17. // Copyright © 2017 Ranchero Software, LLC. All rights reserved. // #import /* TODO: find real-world cases where the isProbably* cases fail when they should succeed, and add them to tests.*/ static BOOL bytesAreProbablyHTML(const char *bytes, NSUInteger numberOfBytes); static BOOL bytesAreProbablyXML(const char *bytes, NSUInteger numberOfBytes); static BOOL bytesStartWithStringIgnoringWhitespace(const char *string, const char *bytes, NSUInteger numberOfBytes); static BOOL didFindString(const char *string, const char *bytes, NSUInteger numberOfBytes); static BOOL bytesStartWithRSS(const char *bytes, NSUInteger numberOfBytes); @implementation NSData (RSParser) - (BOOL)isProbablyHTML { return bytesAreProbablyHTML(self.bytes, self.length); } - (BOOL)isProbablyXML { return bytesAreProbablyXML(self.bytes, self.length); } - (BOOL)isProbablyJSON { return bytesStartWithStringIgnoringWhitespace("{", self.bytes, self.length); } - (BOOL)isProbablyJSONFeed { if (![self isProbablyJSON]) { return NO; } return didFindString("://jsonfeed.org/version/", self.bytes, self.length); } - (BOOL)isProbablyRSSInJSON { if (![self isProbablyJSON]) { return NO; } const char *bytes = self.bytes; NSUInteger length = self.length; return didFindString("rss", bytes, length) && didFindString("channel", bytes, length) && didFindString("item", bytes, length); } - (BOOL)isProbablyRSS { if (bytesStartWithRSS(self.bytes, self.length)) { // Macworld’s RSS feed does not start with xml header. return YES; } if (![self isProbablyXML]) { return NO; } if (didFindString(" tag, but it should be parsed anyway. It does have some other distinct RSS markers we can find. return (didFindString("", self.bytes, self.length) && didFindString("", self.bytes, self.length)); } - (BOOL)isProbablyAtom { if (![self isProbablyXML]) { return NO; } return didFindString("