/** Permit handling JSON as plists, and writing Objective-C literals. Copyright (C) 2020 Free Software Foundation, Inc. Written by: Mingye Wang Created: feb 2020 This file is part of the GNUstep Objective-C Library. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111 USA. */ #import "NSPropertyList+PLUtil.h" #import "GNUstepBase/GSObjCRuntime.h" #import "Foundation/NSData.h" #import "Foundation/NSUserDefaults.h" #import "Foundation/NSJSONSerialization.h" static IMP originalRead = 0; static IMP originalWrite = 0; @implementation NSPropertyListSerialization (PLUtilAdditions) + (NSData *)_pdataFromPropertyList:(id)aPropertyList format:(NSPropertyListFormat)aFormat errorDescription:(NSString **)anErrorString { NSError * myError = nil; NSData * dest; NSDictionary *loc; loc = [[NSUserDefaults standardUserDefaults] dictionaryRepresentation]; switch (aFormat) { case NSPropertyListJSONFormat: dest = [NSJSONSerialization dataWithJSONObject:aPropertyList options:loc != nil ? NSJSONWritingPrettyPrinted : 0 error:&myError]; if (myError != nil && anErrorString != NULL) { *anErrorString = [myError description]; } return dest; case NSPropertyListObjectiveCFormat: case NSPropertyListSwiftFormat: *anErrorString = @"Not implemented"; return nil; default: return (*originalWrite)(self, _cmd, aPropertyList, aFormat, anErrorString); } } + (id)_ppropertyListWithData:(NSData *)data options:(NSPropertyListReadOptions)anOption format:(NSPropertyListFormat *)aFormat error:(out NSError **)error; { NSError * myError = nil; NSPropertyListFormat format; NSJSONReadingOptions jsonOptions = NSJSONReadingAllowFragments; id prop = (*originalRead)(self, _cmd, data, anOption, &format, &myError); if (prop == nil) if (format == NSPropertyListOpenStepFormat || format == NSPropertyListGNUstepFormat) // rescue as json when we know it is not anything else { switch (anOption) { case NSPropertyListMutableContainersAndLeaves: jsonOptions |= NSJSONReadingMutableLeaves; /* FALLTHROUGH */ case NSPropertyListMutableContainers: jsonOptions |= NSJSONReadingMutableContainers; } format = NSPropertyListJSONFormat; prop = [NSJSONSerialization JSONObjectWithData:data options:jsonOptions error:&myError]; } if (error != NULL) *error = myError; if (*aFormat != NULL) *aFormat = format; return prop; } + (void)load { Method replacementRead; Method replacementWrite; replacementRead = class_getClassMethod(self, @selector (_ppropertyListWithData:options:format:error:)); replacementWrite = class_getClassMethod(self, @selector (_pdataFromPropertyList:format:errorDescription:)); originalRead = class_replaceMethod(object_getClass(self), @selector(propertyListWithData:options:format:error:), method_getImplementation(replacementRead), method_getTypeEncoding(replacementRead)); originalWrite = class_replaceMethod(object_getClass(self), @selector(dataFromPropertyList: format:errorDescription:), method_getImplementation(replacementWrite), method_getTypeEncoding(replacementWrite)); } @end