|  | // Copyright 2016 The Chromium Authors. All rights reserved. | 
|  | // Use of this source code is governed by a BSD-style license that can be | 
|  | // found in the LICENSE file. | 
|  |  | 
|  | #include "base/mac/objc_release_properties.h" | 
|  |  | 
|  | #include <memory> | 
|  |  | 
|  | #include <objc/runtime.h> | 
|  |  | 
|  | #include "base/logging.h" | 
|  | #include "base/memory/free_deleter.h" | 
|  |  | 
|  | namespace { | 
|  |  | 
|  | bool IsRetained(objc_property_t property) { | 
|  | // The format of the string returned by property_getAttributes is documented | 
|  | // at | 
|  | // http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtPropertyIntrospection.html#//apple_ref/doc/uid/TP40008048-CH101-SW6 | 
|  | const char* attribute = property_getAttributes(property); | 
|  | while (attribute[0]) { | 
|  | switch (attribute[0]) { | 
|  | case 'C':  // copy | 
|  | case '&':  // retain | 
|  | return true; | 
|  | } | 
|  | do { | 
|  | attribute++; | 
|  | } while (attribute[0] && attribute[-1] != ','); | 
|  | } | 
|  | return false; | 
|  | } | 
|  |  | 
|  | id ValueOf(id obj, objc_property_t property) { | 
|  | std::unique_ptr<char, base::FreeDeleter> ivar_name( | 
|  | property_copyAttributeValue(property, "V"));  // instance variable name | 
|  | if (!ivar_name) | 
|  | return nil; | 
|  | id ivar_value = nil; | 
|  | Ivar ivar = object_getInstanceVariable(obj, &*ivar_name, | 
|  | reinterpret_cast<void**>(&ivar_value)); | 
|  | DCHECK(ivar); | 
|  | return ivar_value; | 
|  | } | 
|  |  | 
|  | }  // namespace | 
|  |  | 
|  | namespace base { | 
|  | namespace mac { | 
|  | namespace details { | 
|  |  | 
|  | void ReleaseProperties(id self, Class cls) { | 
|  | unsigned int property_count; | 
|  | std::unique_ptr<objc_property_t[], base::FreeDeleter> properties( | 
|  | class_copyPropertyList(cls, &property_count)); | 
|  | for (size_t i = 0; i < property_count; ++i) { | 
|  | objc_property_t property = properties[i]; | 
|  | if (!IsRetained(property)) | 
|  | continue; | 
|  | [ValueOf(self, property) release]; | 
|  | } | 
|  | } | 
|  |  | 
|  | }  // namespace details | 
|  | }  // namespace mac | 
|  | }  // namespace base |