text:
/// <summary>
/// Xcode PBX support library.  This is from the Unity open source.
/// https://bitbucket.org/Unity-Technologies/xcodeapi/overview
/// </summary>
///
/// The MIT License (MIT)

/// Copyright (c) 2014 Unity Technologies
///
/// Permission is hereby granted, free of charge, to any person obtaining a copy
/// of this software and associated documentation files (the "Software"), to deal
/// in the Software without restriction, including without limitation the rights
/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
/// copies of the Software, and to permit persons to whom the Software is
/// furnished to do so, subject to the following conditions:
///
/// The above copyright notice and this permission notice shall be included in
/// all copies or substantial portions of the Software.
///
/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
/// THE SOFTWARE.
///
#if !UNITY_5
namespace GooglePlayGames.xcode
{

	using System.Collections.Generic;
	using System.Text;
	using System.Text.RegularExpressions;
	using System.IO;
	using System;
	//using UnityEditor.iOS.Xcode.PBX;
	using PBXBuildFileSection           = KnownSectionBase<PBXBuildFile>;
	using PBXFileReferenceSection       = KnownSectionBase<PBXFileReference>;
	using PBXGroupSection               = KnownSectionBase<PBXGroup>;
	using PBXContainerItemProxySection  = KnownSectionBase<PBXContainerItemProxy>;
	using PBXReferenceProxySection      = KnownSectionBase<PBXReferenceProxy>;
	using PBXSourcesBuildPhaseSection   = KnownSectionBase<PBXSourcesBuildPhase>;
	using PBXFrameworksBuildPhaseSection= KnownSectionBase<PBXFrameworksBuildPhase>;
	using PBXResourcesBuildPhaseSection = KnownSectionBase<PBXResourcesBuildPhase>;
	using PBXCopyFilesBuildPhaseSection = KnownSectionBase<PBXCopyFilesBuildPhase>;
	using PBXShellScriptBuildPhaseSection = KnownSectionBase<PBXShellScriptBuildPhase>;
	using PBXVariantGroupSection        = KnownSectionBase<PBXVariantGroup>;
	using PBXNativeTargetSection        = KnownSectionBase<PBXNativeTarget>;
	using PBXTargetDependencySection    = KnownSectionBase<PBXTargetDependency>;
	using XCBuildConfigurationSection   = KnownSectionBase<XCBuildConfiguration>;
	using XCConfigurationListSection    = KnownSectionBase<XCConfigurationList>;
	using UnknownSection                = KnownSectionBase<PBXObject>;

	// Determines the tree the given path is relative to
	public enum PBXSourceTree
	{
		Absolute,   // The path is absolute
		Source,     // The path is relative to the source folder
		Group,      // The path is relative to the folder it's in. This enum is used only internally,
		// do not use it as function parameter
		Build,      // The path is relative to the build products folder
		Developer,  // The path is relative to the developer folder
		Sdk         // The path is relative to the sdk folder
	};

	public class PBXProject
	{
		private Dictionary<string, SectionBase> m_Section = null;
		private PBXElementDict m_RootElements = null;
		private PBXElementDict m_UnknownObjects = null;
		private string m_ObjectVersion = null;
		private List<string> m_SectionOrder = null;

		private Dictionary<string, UnknownSection> m_UnknownSections;
		private PBXBuildFileSection buildFiles = null; // use BuildFiles* methods instead of manipulating directly
		private PBXFileReferenceSection fileRefs = null; // use FileRefs* methods instead of manipulating directly
		private PBXGroupSection groups = null; // use Groups* methods instead of manipulating directly
		private PBXContainerItemProxySection containerItems = null;
		private PBXReferenceProxySection references = null;
		private PBXSourcesBuildPhaseSection sources = null;
		private PBXFrameworksBuildPhaseSection frameworks = null;
		private PBXResourcesBuildPhaseSection resources = null;
		private PBXCopyFilesBuildPhaseSection copyFiles = null;
		private PBXShellScriptBuildPhaseSection shellScripts = null;
		private PBXNativeTargetSection nativeTargets = null;
		private PBXTargetDependencySection targetDependencies = null;
		private PBXVariantGroupSection variantGroups = null;
		private XCBuildConfigurationSection buildConfigs = null;
		private XCConfigurationListSection configs = null;
		private PBXProjectSection project = null;

		// FIXME: create a separate PBXObject tree to represent these relationships

		// A build file can be represented only once in all *BuildPhaseSection sections, thus
		// we can simplify the cache by not caring about the file extension
		private Dictionary<string, Dictionary<string, PBXBuildFile>> m_FileGuidToBuildFileMap = null;
		private Dictionary<string, PBXFileReference> m_ProjectPathToFileRefMap = null;
		private Dictionary<string, string> m_FileRefGuidToProjectPathMap = null;
		private Dictionary<PBXSourceTree, Dictionary<string, PBXFileReference>> m_RealPathToFileRefMap = null;
		private Dictionary<string, PBXGroup> m_ProjectPathToGroupMap = null;
		private Dictionary<string, string> m_GroupGuidToProjectPathMap = null;
		private Dictionary<string, PBXGroup> m_GuidToParentGroupMap = null;

		// targetGuid is the guid of the target that contains the section that contains the buildFile
		void BuildFilesAdd(string targetGuid, PBXBuildFile buildFile)
		{
			if (!m_FileGuidToBuildFileMap.ContainsKey(targetGuid))
				m_FileGuidToBuildFileMap[targetGuid] = new Dictionary<string, PBXBuildFile>();
			m_FileGuidToBuildFileMap[targetGuid][buildFile.fileRef] = buildFile;
			buildFiles.AddEntry(buildFile);
		}

		void BuildFilesRemove(string targetGuid, string fileGuid)
		{
			var buildFile = BuildFilesGetForSourceFile(targetGuid, fileGuid);
			if (buildFile != null)
			{
				m_FileGuidToBuildFileMap[targetGuid].Remove(buildFile.fileRef);
				buildFiles.RemoveEntry(buildFile.guid);
			}
		}

		PBXBuildFile BuildFilesGetForSourceFile(string targetGuid, string fileGuid)
		{
			if (!m_FileGuidToBuildFileMap.ContainsKey(targetGuid))
				return null;
			if (!m_FileGuidToBuildFileMap[targetGuid].ContainsKey(fileGuid))
				return null;
			return m_FileGuidToBuildFileMap[targetGuid][fileGuid];
		}

		void FileRefsAdd(string realPath, string projectPath, PBXGroup parent, PBXFileReference fileRef)
		{
			fileRefs.AddEntry(fileRef);
			m_ProjectPathToFileRefMap.Add(projectPath, fileRef);
			m_FileRefGuidToProjectPathMap.Add(fileRef.guid, projectPath);
			m_RealPathToFileRefMap[fileRef.tree].Add(realPath, fileRef); // FIXME
			m_GuidToParentGroupMap.Add(fileRef.guid, parent);
		}

		PBXFileReference FileRefsGet(string guid)
		{
			return fileRefs[guid];
		}

		PBXFileReference FileRefsGetByRealPath(string path, PBXSourceTree sourceTree)
		{
			if (m_RealPathToFileRefMap[sourceTree].ContainsKey(path))
				return m_RealPathToFileRefMap[sourceTree][path];
			return null;
		}

		PBXFileReference FileRefsGetByProjectPath(string path)
		{
			if (m_ProjectPathToFileRefMap.ContainsKey(path))
				return m_ProjectPathToFileRefMap[path];
			return null;
		}

		void FileRefsRemove(string guid)
		{
			PBXFileReference fileRef = fileRefs[guid];
			fileRefs.RemoveEntry(guid);
			m_ProjectPathToFileRefMap.Remove(m_FileRefGuidToProjectPathMap[guid]);
			m_FileRefGuidToProjectPathMap.Remove(guid);
			foreach (var tree in FileTypeUtils.AllAbsoluteSourceTrees())
				m_RealPathToFileRefMap[tree].Remove(fileRef.path);
			m_GuidToParentGroupMap.Remove(guid);
		}

		PBXGroup GroupsGet(string guid)
		{
			return groups[guid];
		}

		PBXGroup GroupsGetByChild(string childGuid)
		{
			return m_GuidToParentGroupMap[childGuid];
		}

		PBXGroup GroupsGetMainGroup()
		{
			return groups[project.project.mainGroup];
		}

		/// Returns the source group identified by sourceGroup. If sourceGroup is empty or null,
		/// root group is returned. If no group is found, null is returned.
		PBXGroup GroupsGetByProjectPath(string sourceGroup)
		{
			if (m_ProjectPathToGroupMap.ContainsKey(sourceGroup))
				return m_ProjectPathToGroupMap[sourceGroup];
			return null;
		}

		void GroupsAdd(string projectPath, PBXGroup parent, PBXGroup gr)
		{
			m_ProjectPathToGroupMap.Add(projectPath, gr);
			m_GroupGuidToProjectPathMap.Add(gr.guid, projectPath);
			m_GuidToParentGroupMap.Add(gr.guid, parent);
			groups.AddEntry(gr);
		}

		void GroupsRemove(string guid)
		{
			m_ProjectPathToGroupMap.Remove(m_GroupGuidToProjectPathMap[guid]);
			m_GroupGuidToProjectPathMap.Remove(guid);
			m_GuidToParentGroupMap.Remove(guid);
			groups.RemoveEntry(guid);
		}

		void RefreshBuildFilesMapForBuildFileGuidList(Dictionary<string, PBXBuildFile> mapForTarget,
		                                              FileGUIDListBase list)
		{
			foreach (string guid in list.files)
			{
				var buildFile = buildFiles[guid];
				mapForTarget[buildFile.fileRef] = buildFile;
			}
		}

		void RefreshMapsForGroupChildren(string projectPath, string realPath, PBXSourceTree realPathTree, PBXGroup parent)
		{
			var children = new List<string>(parent.children);
			foreach (string guid in children)
			{
				PBXFileReference fileRef = fileRefs[guid];
				string pPath;
				string rPath;
				PBXSourceTree rTree;

				if (fileRef != null)
				{
					pPath = Utils.CombinePaths(projectPath, fileRef.name);
					Utils.CombinePaths(realPath, realPathTree, fileRef.path, fileRef.tree, out rPath, out rTree);

					if (!m_ProjectPathToFileRefMap.ContainsKey(pPath))
					{
						m_ProjectPathToFileRefMap.Add(pPath, fileRef);
					}
					if (!m_FileRefGuidToProjectPathMap.ContainsKey(fileRef.guid))
					{
						m_FileRefGuidToProjectPathMap.Add(fileRef.guid, pPath);
					}
					if (!m_RealPathToFileRefMap[rTree].ContainsKey(rPath))
					{
						m_RealPathToFileRefMap[rTree].Add(rPath, fileRef);
					}
					if (!m_GuidToParentGroupMap.ContainsKey(guid))
					{
						m_GuidToParentGroupMap.Add(guid, parent);
					}
					continue;
				}

				PBXGroup gr = groups[guid];
				if (gr != null)
				{
					pPath = Utils.CombinePaths(projectPath, gr.name);
					Utils.CombinePaths(realPath, realPathTree, gr.path, gr.tree, out rPath, out rTree);

					if (!m_ProjectPathToGroupMap.ContainsKey(pPath))
					{
						m_ProjectPathToGroupMap.Add(pPath, gr);
					}
					if (!m_GroupGuidToProjectPathMap.ContainsKey(gr.guid))
					{
						m_GroupGuidToProjectPathMap.Add(gr.guid, pPath);
					}
					if (!m_GuidToParentGroupMap.ContainsKey(guid))
					{
						m_GuidToParentGroupMap.Add(guid, parent);
					}

					RefreshMapsForGroupChildren(pPath, rPath, rTree, gr);
				}
			}
		}

		void RefreshAuxMaps()
		{
			foreach (var targetEntry in nativeTargets.GetEntries())
			{
				var map = new Dictionary<string, PBXBuildFile>();
				foreach (string phaseGuid in targetEntry.Value.phases)
				{
					if (frameworks.HasEntry(phaseGuid))
						RefreshBuildFilesMapForBuildFileGuidList(map, frameworks[phaseGuid]);
					if (resources.HasEntry(phaseGuid))
						RefreshBuildFilesMapForBuildFileGuidList(map, resources[phaseGuid]);
					if (sources.HasEntry(phaseGuid))
						RefreshBuildFilesMapForBuildFileGuidList(map, sources[phaseGuid]);
					if (copyFiles.HasEntry(phaseGuid))
						RefreshBuildFilesMapForBuildFileGuidList(map, copyFiles[phaseGuid]);
				}
				m_FileGuidToBuildFileMap[targetEntry.Key] = map;
			}
			RefreshMapsForGroupChildren("", "", PBXSourceTree.Source, GroupsGetMainGroup());
		}

		void Clear()
		{
			buildFiles = new PBXBuildFileSection("PBXBuildFile");
			fileRefs = new PBXFileReferenceSection("PBXFileReference");
			groups = new PBXGroupSection("PBXGroup");
			containerItems = new PBXContainerItemProxySection("PBXContainerItemProxy");
			references = new PBXReferenceProxySection("PBXReferenceProxy");
			sources = new PBXSourcesBuildPhaseSection("PBXSourcesBuildPhase");
			frameworks = new PBXFrameworksBuildPhaseSection("PBXFrameworksBuildPhase");
			resources = new PBXResourcesBuildPhaseSection("PBXResourcesBuildPhase");
			copyFiles = new PBXCopyFilesBuildPhaseSection("PBXCopyFilesBuildPhase");
			shellScripts = new PBXShellScriptBuildPhaseSection("PBXShellScriptBuildPhase");
			nativeTargets = new PBXNativeTargetSection("PBXNativeTarget");
			targetDependencies = new PBXTargetDependencySection("PBXTargetDependency");
			variantGroups = new PBXVariantGroupSection("PBXVariantGroup");
			buildConfigs = new XCBuildConfigurationSection("XCBuildConfiguration");
			configs = new XCConfigurationListSection("XCConfigurationList");
			project = new PBXProjectSection();
			m_UnknownSections = new Dictionary<string, UnknownSection>();

			m_Section = new Dictionary<string, SectionBase>
			{
				{ "PBXBuildFile", buildFiles },
				{ "PBXFileReference", fileRefs },
				{ "PBXGroup", groups },
				{ "PBXContainerItemProxy", containerItems },
				{ "PBXReferenceProxy", references },
				{ "PBXSourcesBuildPhase", sources },
				{ "PBXFrameworksBuildPhase", frameworks },
				{ "PBXResourcesBuildPhase", resources },
				{ "PBXCopyFilesBuildPhase", copyFiles },
				{ "PBXShellScriptBuildPhase", shellScripts },
				{ "PBXNativeTarget", nativeTargets },
				{ "PBXTargetDependency", targetDependencies },
				{ "PBXVariantGroup", variantGroups },
				{ "XCBuildConfiguration", buildConfigs },
				{ "XCConfigurationList", configs },
				{ "PBXProject", project },
			};
			m_RootElements = new PBXElementDict();
			m_UnknownObjects = new PBXElementDict();
			m_ObjectVersion = null;
			m_SectionOrder = new List<string>{
				"PBXBuildFile", "PBXContainerItemProxy", "PBXCopyFilesBuildPhase", "PBXFileReference",
				"PBXFrameworksBuildPhase", "PBXGroup", "PBXNativeTarget", "PBXProject", "PBXReferenceProxy",
				"PBXResourcesBuildPhase", "PBXShellScriptBuildPhase", "PBXSourcesBuildPhase", "PBXTargetDependency",
				"PBXVariantGroup", "XCBuildConfiguration", "XCConfigurationList"
			};
			m_FileGuidToBuildFileMap = new Dictionary<string, Dictionary<string, PBXBuildFile>>();
			m_ProjectPathToFileRefMap = new Dictionary<string, PBXFileReference>();
			m_FileRefGuidToProjectPathMap = new Dictionary<string, string>();
			m_RealPathToFileRefMap = new Dictionary<PBXSourceTree, Dictionary<string, PBXFileReference>>();
			foreach (var tree in FileTypeUtils.AllAbsoluteSourceTrees())
				m_RealPathToFileRefMap.Add(tree, new Dictionary<string, PBXFileReference>());
			m_ProjectPathToGroupMap = new Dictionary<string, PBXGroup>();
			m_GroupGuidToProjectPathMap = new Dictionary<string, string>();
			m_GuidToParentGroupMap = new Dictionary<string, PBXGroup>();
		}

		public static string GetPBXProjectPath(string buildPath)
		{
			return Utils.CombinePaths(buildPath, "Unity-iPhone/project.pbxproj");
		}

		public static string GetUnityTargetName()
		{
			return "Unity-iPhone";
		}

		public static string GetUnityTestTargetName()
		{
			return "Unity-iPhone Tests";
		}

		/// Returns a guid identifying native target with name @a name
		public string TargetGuidByName(string name)
		{
			foreach (var entry in nativeTargets.GetEntries())
				if (entry.Value.name == name)
					return entry.Key;
			return null;
		}

		internal string ProjectGuid()
		{
			return project.project.guid;
		}

		private FileGUIDListBase BuildSection(PBXNativeTarget target, string path)
		{
			string ext = Path.GetExtension(path);
			var phase = FileTypeUtils.GetFileType(ext);
			switch (phase) {
			case PBXFileType.Framework:
				foreach (var guid in target.phases)
					if (frameworks.HasEntry(guid))
						return frameworks[guid];
				break;
			case PBXFileType.Resource:
				foreach (var guid in target.phases)
					if (resources.HasEntry(guid))
						return resources[guid];
				break;
			case PBXFileType.Source:
				foreach (var guid in target.phases)
					if (sources.HasEntry(guid))
						return sources[guid];
				break;
			case PBXFileType.CopyFile:
				foreach (var guid in target.phases)
					if (copyFiles.HasEntry(guid))
						return copyFiles[guid];
				break;
			}
			return null;
		}

		public static bool IsKnownExtension(string ext)
		{
			return FileTypeUtils.IsKnownExtension(ext);
		}

		public static bool IsBuildable(string ext)
		{
			return FileTypeUtils.IsBuildable(ext);
		}

		// The same file can be referred to by more than one project path.
		private string AddFileImpl(string path, string projectPath, PBXSourceTree tree)
		{
			path = Utils.FixSlashesInPath(path);
			projectPath = Utils.FixSlashesInPath(projectPath);

			string ext = Path.GetExtension(path);
			if (ext != Path.GetExtension(projectPath))
				throw new Exception("Project and real path extensions do not match");

			string guid = FindFileGuidByProjectPath(projectPath);
			if (guid == null)
				guid = FindFileGuidByRealPath(path);
			if (guid == null)
			{
				PBXFileReference fileRef = PBXFileReference.CreateFromFile(path, Utils.GetFilenameFromPath(projectPath), tree);
				PBXGroup parent = CreateSourceGroup(Utils.GetDirectoryFromPath(projectPath));
				parent.children.AddGUID(fileRef.guid);
				FileRefsAdd(path, projectPath, parent, fileRef);
				guid = fileRef.guid;
			}
			return guid;
		}

		// The extension of the files identified by path and projectPath must be the same.
		public string AddFile(string path, string projectPath)
		{
			return AddFileImpl(path, projectPath, PBXSourceTree.Source);
		}

		// sourceTree must not be PBXSourceTree.Group
		public string AddFile(string path, string projectPath, PBXSourceTree sourceTree)
		{
			if (sourceTree == PBXSourceTree.Group)
				throw new Exception("sourceTree must not be PBXSourceTree.Group");
			return AddFileImpl(path, projectPath, sourceTree);
		}

		private void AddBuildFileImpl(string targetGuid, string fileGuid, bool weak, string compileFlags)
		{
			PBXNativeTarget target = nativeTargets[targetGuid];
			string ext = Path.GetExtension(fileRefs[fileGuid].path);
			if (FileTypeUtils.IsBuildable(ext) &&
			    BuildFilesGetForSourceFile(targetGuid, fileGuid) == null)
			{
				PBXBuildFile buildFile = PBXBuildFile.CreateFromFile(fileGuid, weak, compileFlags);
				BuildFilesAdd(targetGuid, buildFile);
				BuildSection(target, ext).files.AddGUID(buildFile.guid);
			}
		}

		public void AddFileToBuild(string targetGuid, string fileGuid)
		{
			AddBuildFileImpl(targetGuid, fileGuid, false, null);
		}

		public void AddFileToBuildWithFlags(string targetGuid, string fileGuid, string compileFlags)
		{
			AddBuildFileImpl(targetGuid, fileGuid, false, compileFlags);
		}

		// returns null on error
		// FIXME: at the moment returns all flags as the first element of the array
		public List<string> GetCompileFlagsForFile(string targetGuid, string fileGuid)
		{
			var buildFile = BuildFilesGetForSourceFile(targetGuid, fileGuid);
			if (buildFile == null)
				return null;
			if (buildFile.compileFlags == null)
				return new List<string>();
			return new List<string>{buildFile.compileFlags};
		}

		public void SetCompileFlagsForFile(string targetGuid, string fileGuid, List<string> compileFlags)
		{
			var buildFile = BuildFilesGetForSourceFile(targetGuid, fileGuid);
			if (buildFile == null)
				return;
			buildFile.compileFlags = string.Join(" ", compileFlags.ToArray());
		}

		public bool ContainsFileByRealPath(string path)
		{
			return FindFileGuidByRealPath(path) != null;
		}

		// sourceTree must not be PBXSourceTree.Group
		public bool ContainsFileByRealPath(string path, PBXSourceTree sourceTree)
		{
			if (sourceTree == PBXSourceTree.Group)
				throw new Exception("sourceTree must not be PBXSourceTree.Group");
			return FindFileGuidByRealPath(path, sourceTree) != null;
		}

		public bool ContainsFileByProjectPath(string path)
		{
			return FindFileGuidByProjectPath(path) != null;
		}

		public bool HasFramework(string framework)
		{
			return ContainsFileByRealPath("System/Library/Frameworks/"+framework);
		}

		/// The framework must be specified with the '.framework' extension
		public void AddFrameworkToProject(string targetGuid, string framework, bool weak)
		{
			string fileGuid = AddFile("System/Library/Frameworks/"+framework, "Frameworks/"+framework, PBXSourceTree.Sdk);
			AddBuildFileImpl(targetGuid, fileGuid, weak, null);
		}

		/// The framework must be specified with the '.framework' extension
		// FIXME: targetGuid is ignored at the moment
		public void RemoveFrameworkFromProject(string targetGuid, string framework)
		{
			string fileGuid = FindFileGuidByRealPath("System/Library/Frameworks/"+framework);
			if (fileGuid != null)
				RemoveFile(fileGuid);
		}

		// sourceTree must not be PBXSourceTree.Group
		public string FindFileGuidByRealPath(string path, PBXSourceTree sourceTree)
		{
			if (sourceTree == PBXSourceTree.Group)
				throw new Exception("sourceTree must not be PBXSourceTree.Group");
			path = Utils.FixSlashesInPath(path);
			var fileRef = FileRefsGetByRealPath(path, sourceTree);
			if (fileRef != null)
				return fileRef.guid;
			return null;
		}

		public string FindFileGuidByRealPath(string path)
		{
			path = Utils.FixSlashesInPath(path);

			foreach (var tree in FileTypeUtils.AllAbsoluteSourceTrees())
			{
				string res = FindFileGuidByRealPath(path, tree);
				if (res != null)
					return res;
			}
			return null;
		}

		public string FindFileGuidByProjectPath(string path)
		{
			path = Utils.FixSlashesInPath(path);
			var fileRef = FileRefsGetByProjectPath(path);
			if (fileRef != null)
				return fileRef.guid;
			return null;
		}

		public void RemoveFileFromBuild(string targetGuid, string fileGuid)
		{
			var buildFile = BuildFilesGetForSourceFile(targetGuid, fileGuid);
			if (buildFile == null)
				return;
			BuildFilesRemove(targetGuid, fileGuid);

			string buildGuid = buildFile.guid;
			if (buildGuid != null)
			{
				foreach (var section in sources.GetEntries())
					section.Value.files.RemoveGUID(buildGuid);
				foreach (var section in resources.GetEntries())
					section.Value.files.RemoveGUID(buildGuid);
				foreach (var section in copyFiles.GetEntries())
					section.Value.files.RemoveGUID(buildGuid);
				foreach (var section in frameworks.GetEntries())
					section.Value.files.RemoveGUID(buildGuid);
			}
		}

		public void RemoveFile(string fileGuid)
		{
			if (fileGuid == null)
				return;

			// remove from parent
			PBXGroup parent = GroupsGetByChild(fileGuid);
			if (parent != null)
				parent.children.RemoveGUID(fileGuid);
			RemoveGroupIfEmpty(parent);

			// remove actual file
			foreach (var target in nativeTargets.GetEntries())
				RemoveFileFromBuild(target.Value.guid, fileGuid);
			FileRefsRemove(fileGuid);
		}

		void RemoveGroupIfEmpty(PBXGroup gr)
		{
			if (gr.children.Count == 0 && gr != GroupsGetMainGroup())
			{
				// remove from parent
				PBXGroup parent = GroupsGetByChild(gr.guid);
				parent.children.RemoveGUID(gr.guid);
				RemoveGroupIfEmpty(parent);

				// remove actual group
				GroupsRemove(gr.guid);
			}
		}

		private void RemoveGroupChildrenRecursive(PBXGroup parent)
		{
			List<string> children = new List<string>(parent.children);
			parent.children.Clear();
			foreach (string guid in children)
			{
				PBXFileReference file = fileRefs[guid];
				if (file != null)
				{
					foreach (var target in nativeTargets.GetEntries())
						RemoveFileFromBuild(target.Value.guid, guid);
					FileRefsRemove(guid);
					continue;
				}

				PBXGroup gr = groups[guid];
				if (gr != null)
				{
					RemoveGroupChildrenRecursive(gr);
					GroupsRemove(gr.guid);
					continue;
				}
			}
		}

		internal void RemoveFilesByProjectPathRecursive(string projectPath)
		{
			projectPath = Utils.FixSlashesInPath(projectPath);
			PBXGroup gr = GroupsGetByProjectPath(projectPath);
			if (gr == null)
				return;
			RemoveGroupChildrenRecursive(gr);
			RemoveGroupIfEmpty(gr);
		}

		// Returns null on error
		internal List<string> GetGroupChildrenFiles(string projectPath)
		{
			projectPath = Utils.FixSlashesInPath(projectPath);
			PBXGroup gr = GroupsGetByProjectPath(projectPath);
			if (gr == null)
				return null;
			var res = new List<string>();
			foreach (var guid in gr.children)
			{
				res.Add(FileRefsGet(guid).name);
			}
			return res;
		}

		private PBXGroup GetPBXGroupChildByName(PBXGroup group, string name)
		{
			foreach (string guid in group.children)
			{
				var gr = groups[guid];
				if (gr != null && gr.name == name)
					return gr;
			}
			return null;
		}

		/// Creates source group identified by sourceGroup, if needed, and returns it.
		/// If sourceGroup is empty or null, root group is returned
		private PBXGroup CreateSourceGroup(string sourceGroup)
		{
			sourceGroup = Utils.FixSlashesInPath(sourceGroup);

			if (sourceGroup == null || sourceGroup == "")
				return GroupsGetMainGroup();

			PBXGroup gr = GroupsGetByProjectPath(sourceGroup);
			if (gr != null)
				return gr;

			// the group does not exist -- create new
			gr = GroupsGetMainGroup();

			string[] elements = sourceGroup.Trim('/').Split('/');
			string projectPath = null;
			foreach (string pathEl in elements)
			{
				if (projectPath == null)
					projectPath = pathEl;
				else
					projectPath += "/" + pathEl;

				PBXGroup child = GetPBXGroupChildByName(gr, pathEl);
				if (child != null)
					gr = child;
				else
				{
					PBXGroup newGroup = PBXGroup.Create(pathEl, pathEl, PBXSourceTree.Group);
					gr.children.AddGUID(newGroup.guid);
					GroupsAdd(projectPath, gr, newGroup);
					gr = newGroup;
				}
			}
			return gr;
		}

		// sourceTree must not be PBXSourceTree.Group
		public void AddExternalProjectDependency(string path, string projectPath, PBXSourceTree sourceTree)
		{
			if (sourceTree == PBXSourceTree.Group)
				throw new Exception("sourceTree must not be PBXSourceTree.Group");
			path = Utils.FixSlashesInPath(path);
			projectPath = Utils.FixSlashesInPath(projectPath);

			// note: we are duplicating products group for the project reference. Otherwise Xcode crashes.
			PBXGroup productGroup = PBXGroup.CreateRelative("Products");
			groups.AddEntry(productGroup); // don't use GroupsAdd here

			PBXFileReference fileRef = PBXFileReference.CreateFromFile(path, Path.GetFileName(projectPath),
			                                                           sourceTree);
			FileRefsAdd(path, projectPath, null, fileRef);
			CreateSourceGroup(Utils.GetDirectoryFromPath(projectPath)).children.AddGUID(fileRef.guid);

			project.project.AddReference(productGroup.guid, fileRef.guid);
		}

		/** This function must be called only after the project the library is in has
            been added as a dependency via AddExternalProjectDependency. projectPath must be
            the same as the 'path' parameter passed to the AddExternalProjectDependency.
            remoteFileGuid must be the guid of the referenced file as specified in
            PBXFileReference section of the external project

            TODO: what. is remoteInfo entry in PBXContainerItemProxy? Is in referenced project name or
            referenced library name without extension?
        */
		public void AddExternalLibraryDependency(string targetGuid, string filename, string remoteFileGuid, string projectPath,
		                                         string remoteInfo)
		{
			PBXNativeTarget target = nativeTargets[targetGuid];
			filename = Utils.FixSlashesInPath(filename);
			projectPath = Utils.FixSlashesInPath(projectPath);

			// find the products group to put the new library in
			string projectGuid = FindFileGuidByRealPath(projectPath);
			if (projectGuid == null)
				throw new Exception("No such project");

			string productsGroupGuid = null;
			foreach (var proj in project.project.projectReferences)
			{
				if (proj.projectRef == projectGuid)
				{
					productsGroupGuid = proj.group;
					break;
				}
			}

			if (productsGroupGuid == null)
				throw new Exception("Malformed project: no project in project references");

			PBXGroup productGroup = groups[productsGroupGuid];

			// verify file extension
			string ext = Path.GetExtension(filename);
			if (!FileTypeUtils.IsBuildable(ext))
				throw new Exception("Wrong file extension");

			// create ContainerItemProxy object
			var container = PBXContainerItemProxy.Create(projectGuid, "2", remoteFileGuid, remoteInfo);
			containerItems.AddEntry(container);

			// create a reference and build file for the library
			string typeName = FileTypeUtils.GetTypeName(ext);

			var libRef = PBXReferenceProxy.Create(filename, typeName, container.guid, "BUILT_PRODUCTS_DIR");
			references.AddEntry(libRef);
			PBXBuildFile libBuildFile = PBXBuildFile.CreateFromFile(libRef.guid, false, null);
			BuildFilesAdd(targetGuid, libBuildFile);
			BuildSection(target, ext).files.AddGUID(libBuildFile.guid);

			// add to products folder
			productGroup.children.AddGUID(libRef.guid);
		}

		private void SetDefaultAppExtensionReleaseBuildFlags(XCBuildConfiguration config, string infoPlistPath)
		{
			config.AddProperty("ALWAYS_SEARCH_USER_PATHS", "NO");
			config.AddProperty("CLANG_CXX_LANGUAGE_STANDARD", "gnu++0x");
			config.AddProperty("CLANG_CXX_LIBRARY", "libc++");
			config.AddProperty("CLANG_ENABLE_MODULES", "YES");
			config.AddProperty("CLANG_ENABLE_OBJC_ARC", "YES");
			config.AddProperty("CLANG_WARN_BOOL_CONVERSION", "YES");
			config.AddProperty("CLANG_WARN_CONSTANT_CONVERSION", "YES");
			config.AddProperty("CLANG_WARN_DIRECT_OBJC_ISA_USAGE", "YES_ERROR");
			config.AddProperty("CLANG_WARN_EMPTY_BODY", "YES");
			config.AddProperty("CLANG_WARN_ENUM_CONVERSION", "YES");
			config.AddProperty("CLANG_WARN_INT_CONVERSION", "YES");
			config.AddProperty("CLANG_WARN_OBJC_ROOT_CLASS", "YES_ERROR");
			config.AddProperty("CLANG_WARN_UNREACHABLE_CODE", "YES");
			config.AddProperty("CLANG_WARN__DUPLICATE_METHOD_MATCH", "YES");
			config.AddProperty("COPY_PHASE_STRIP", "YES");
			config.AddProperty("ENABLE_NS_ASSERTIONS", "NO");
			config.AddProperty("ENABLE_STRICT_OBJC_MSGSEND", "YES");
			config.AddProperty("GCC_C_LANGUAGE_STANDARD", "gnu99");
			config.AddProperty("GCC_WARN_64_TO_32_BIT_CONVERSION", "YES");
			config.AddProperty("GCC_WARN_ABOUT_RETURN_TYPE", "YES_ERROR");
			config.AddProperty("GCC_WARN_UNDECLARED_SELECTOR", "YES");
			config.AddProperty("GCC_WARN_UNINITIALIZED_AUTOS", "YES_AGGRESSIVE");
			config.AddProperty("GCC_WARN_UNUSED_FUNCTION", "YES");
			config.AddProperty("INFOPLIST_FILE", infoPlistPath);
			config.AddProperty("IPHONEOS_DEPLOYMENT_TARGET", "8.0");
			config.AddProperty("LD_RUNPATH_SEARCH_PATHS", "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks");
			config.AddProperty("MTL_ENABLE_DEBUG_INFO", "NO");
			config.AddProperty("PRODUCT_NAME", "$(TARGET_NAME)");
			config.AddProperty("SKIP_INSTALL", "YES");
			config.AddProperty("VALIDATE_PRODUCT", "YES");
		}

		private void SetDefaultAppExtensionDebugBuildFlags(XCBuildConfiguration config, string infoPlistPath)
		{
			config.AddProperty("ALWAYS_SEARCH_USER_PATHS", "NO");
			config.AddProperty("CLANG_CXX_LANGUAGE_STANDARD", "gnu++0x");
			config.AddProperty("CLANG_CXX_LIBRARY", "libc++");
			config.AddProperty("CLANG_ENABLE_MODULES", "YES");
			config.AddProperty("CLANG_ENABLE_OBJC_ARC", "YES");
			config.AddProperty("CLANG_WARN_BOOL_CONVERSION", "YES");
			config.AddProperty("CLANG_WARN_CONSTANT_CONVERSION", "YES");
			config.AddProperty("CLANG_WARN_DIRECT_OBJC_ISA_USAGE", "YES_ERROR");
			config.AddProperty("CLANG_WARN_EMPTY_BODY", "YES");
			config.AddProperty("CLANG_WARN_ENUM_CONVERSION", "YES");
			config.AddProperty("CLANG_WARN_INT_CONVERSION", "YES");
			config.AddProperty("CLANG_WARN_OBJC_ROOT_CLASS", "YES_ERROR");
			config.AddProperty("CLANG_WARN_UNREACHABLE_CODE", "YES");
			config.AddProperty("CLANG_WARN__DUPLICATE_METHOD_MATCH", "YES");
			config.AddProperty("COPY_PHASE_STRIP", "NO");
			config.AddProperty("ENABLE_STRICT_OBJC_MSGSEND", "YES");
			config.AddProperty("GCC_C_LANGUAGE_STANDARD", "gnu99");
			config.AddProperty("GCC_DYNAMIC_NO_PIC", "NO");
			config.AddProperty("GCC_OPTIMIZATION_LEVEL", "0");
			config.AddProperty("GCC_PREPROCESSOR_DEFINITIONS", "DEBUG=1");
			config.AddProperty("GCC_PREPROCESSOR_DEFINITIONS", "$(inherited)");
			config.AddProperty("GCC_SYMBOLS_PRIVATE_EXTERN", "NO");
			config.AddProperty("GCC_WARN_64_TO_32_BIT_CONVERSION", "YES");
			config.AddProperty("GCC_WARN_ABOUT_RETURN_TYPE", "YES_ERROR");
			config.AddProperty("GCC_WARN_UNDECLARED_SELECTOR", "YES");
			config.AddProperty("GCC_WARN_UNINITIALIZED_AUTOS", "YES_AGGRESSIVE");
			config.AddProperty("GCC_WARN_UNUSED_FUNCTION", "YES");
			config.AddProperty("INFOPLIST_FILE", infoPlistPath);
			config.AddProperty("IPHONEOS_DEPLOYMENT_TARGET", "8.0");
			config.AddProperty("LD_RUNPATH_SEARCH_PATHS", "$(inherited)");
			config.AddProperty("LD_RUNPATH_SEARCH_PATHS", "@executable_path/Frameworks");
			config.AddProperty("LD_RUNPATH_SEARCH_PATHS", "@executable_path/../../Frameworks");
			config.AddProperty("MTL_ENABLE_DEBUG_INFO", "YES");
			config.AddProperty("ONLY_ACTIVE_ARCH", "YES");
			config.AddProperty("PRODUCT_NAME", "$(TARGET_NAME)");
			config.AddProperty("SKIP_INSTALL", "YES");
		}

		// Returns the guid of the new target
		internal string AddAppExtension(string mainTarget, string name, string infoPlistPath)
		{
			string ext = ".appex";
			string fullName = name + ext;
			var productFileRef = PBXFileReference.CreateFromFile("Products/" + fullName, "Products/" + fullName,
			                                                     PBXSourceTree.Group);
			var releaseBuildConfig = XCBuildConfiguration.Create("Release");
			buildConfigs.AddEntry(releaseBuildConfig);
			SetDefaultAppExtensionReleaseBuildFlags(releaseBuildConfig, infoPlistPath);

			var debugBuildConfig = XCBuildConfiguration.Create("Debug");
			buildConfigs.AddEntry(debugBuildConfig);
			SetDefaultAppExtensionDebugBuildFlags(debugBuildConfig, infoPlistPath);

			var buildConfigList = XCConfigurationList.Create();
			configs.AddEntry(buildConfigList);
			buildConfigList.buildConfigs.AddGUID(releaseBuildConfig.guid);
			buildConfigList.buildConfigs.AddGUID(debugBuildConfig.guid);

			var newTarget = PBXNativeTarget.Create(name, productFileRef.guid, "com.apple.product-type.app-extension", buildConfigList.guid);
			nativeTargets.AddEntry(newTarget);
			project.project.targets.Add(newTarget.guid);

			var sourcesBuildPhase = PBXSourcesBuildPhase.Create();
			sources.AddEntry(sourcesBuildPhase);
			newTarget.phases.AddGUID(sourcesBuildPhase.guid);

			var resourcesBuildPhase = PBXResourcesBuildPhase.Create();
			resources.AddEntry(resourcesBuildPhase);
			newTarget.phases.AddGUID(resourcesBuildPhase.guid);

			var frameworksBuildPhase = PBXFrameworksBuildPhase.Create();
			frameworks.AddEntry(frameworksBuildPhase);
			newTarget.phases.AddGUID(frameworksBuildPhase.guid);

			var copyFilesBuildPhase = PBXCopyFilesBuildPhase.Create("Embed App Extensions", "13");
			copyFiles.AddEntry(copyFilesBuildPhase);
			nativeTargets[mainTarget].phases.AddGUID(copyFilesBuildPhase.guid);

			var containerProxy = PBXContainerItemProxy.Create(project.project.guid, "1", newTarget.guid, name);
			containerItems.AddEntry(containerProxy);

			var targetDependency = PBXTargetDependency.Create(newTarget.guid, containerProxy.guid);
			targetDependencies.AddEntry(targetDependency);

			nativeTargets[mainTarget].dependencies.AddGUID(targetDependency.guid);

			AddFile(fullName, "Products/" + fullName, PBXSourceTree.Build);
			var buildAppCopy = PBXBuildFile.CreateFromFile(FindFileGuidByProjectPath("Products/" + fullName), false, "");
			BuildFilesAdd(mainTarget, buildAppCopy);
			copyFilesBuildPhase.files.AddGUID(buildAppCopy.guid);

			AddFile(infoPlistPath, name + "/Supporting Files/Info.plist", PBXSourceTree.Group);

			return newTarget.guid;
		}

		public string BuildConfigByName(string targetGuid, string name)
		{
			PBXNativeTarget target = nativeTargets[targetGuid];
			foreach (string guid in configs[target.buildConfigList].buildConfigs)
			{
				var buildConfig = buildConfigs[guid];
				if (buildConfig != null && buildConfig.name == name)
					return buildConfig.guid;
			}
			return null;
		}

		string GetConfigListForTarget(string targetGuid)
		{
			if (targetGuid == project.project.guid)
				return project.project.buildConfigList;
			else
				return nativeTargets[targetGuid].buildConfigList;
		}

		// Adds an item to a build property that contains a value list. Duplicate build properties
		// are ignored. Values for name "LIBRARY_SEARCH_PATHS" are quoted if they contain spaces.
		// targetGuid may refer to PBXProject object
		public void AddBuildProperty(string targetGuid, string name, string value)
		{
			foreach (string guid in configs[GetConfigListForTarget(targetGuid)].buildConfigs)
				AddBuildPropertyForConfig(guid, name, value);
		}

		public void AddBuildProperty(string[] targetGuids, string name, string value)
		{
			foreach (string t in targetGuids)
				AddBuildProperty(t, name, value);
		}
		public void AddBuildPropertyForConfig(string configGuid, string name, string value)
		{
			buildConfigs[configGuid].AddProperty(name, value);
		}

		public void AddBuildPropertyForConfig(string[] configGuids, string name, string value)
		{
			foreach (string guid in configGuids)
				AddBuildPropertyForConfig(guid, name, value);
		}
		// targetGuid may refer to PBXProject object
		public void SetBuildProperty(string targetGuid, string name, string value)
		{
			foreach (string guid in configs[GetConfigListForTarget(targetGuid)].buildConfigs)
				SetBuildPropertyForConfig(guid, name, value);
		}
		public void SetBuildProperty(string[] targetGuids, string name, string value)
		{
			foreach (string t in targetGuids)
				SetBuildProperty(t, name, value);
		}
		public void SetBuildPropertyForConfig(string configGuid, string name, string value)
		{
			buildConfigs[configGuid].SetProperty(name, value);
		}
		public void SetBuildPropertyForConfig(string[] configGuids, string name, string value)
		{
			foreach (string guid in configGuids)
				SetBuildPropertyForConfig(guid, name, value);
		}

		internal void RemoveBuildProperty(string targetGuid, string name)
		{
			foreach (string guid in configs[GetConfigListForTarget(targetGuid)].buildConfigs)
				RemoveBuildPropertyForConfig(guid, name);
		}
		internal void RemoveBuildProperty(string[] targetGuids, string name)
		{
			foreach (string t in targetGuids)
				RemoveBuildProperty(t, name);
		}
		internal void RemoveBuildPropertyForConfig(string configGuid, string name)
		{
			buildConfigs[configGuid].RemoveProperty(name);
		}
		internal void RemoveBuildPropertyForConfig(string[] configGuids, string name)
		{
			foreach (string guid in configGuids)
				RemoveBuildPropertyForConfig(guid, name);
		}

		/// Interprets the value of the given property as a set of space-delimited strings, then
		/// removes strings equal to items to removeValues and adds strings in addValues.
		public void UpdateBuildProperty(string targetGuid, string name, string[] addValues, string[] removeValues)
		{
			foreach (string guid in configs[GetConfigListForTarget(targetGuid)].buildConfigs)
				UpdateBuildPropertyForConfig(guid, name, addValues, removeValues);
		}
		public void UpdateBuildProperty(string[] targetGuids, string name, string[] addValues, string[] removeValues)
		{
			foreach (string t in targetGuids)
				UpdateBuildProperty(t, name, addValues, removeValues);
		}
		public void UpdateBuildPropertyForConfig(string configGuid, string name, string[] addValues, string[] removeValues)
		{
			var config = buildConfigs[configGuid];
			if (config != null)
			{
				if (removeValues != null)
					foreach (var v in removeValues)
						config.RemovePropertyValue(name, v);
				if (addValues != null)
					foreach (var v in addValues)
						config.AddProperty(name, v);
			}
		}
		public void UpdateBuildPropertyForConfig(string[] configGuids, string name, string[] addValues, string[] removeValues)
		{
			foreach (string guid in configGuids)
				UpdateBuildProperty(guid, name, addValues, removeValues);
		}

		private void BuildCommentMapForBuildFiles(GUIDToCommentMap comments, List<string> guids, string sectName)
		{
			foreach (var guid in guids)
			{
				var buildFile = buildFiles[guid];
				if (buildFile != null)
				{
					var fileRef = fileRefs[buildFile.fileRef];
					if (fileRef != null)
						comments.Add(guid, String.Format("{0} in {1}", fileRef.name, sectName));
					else
					{
						var reference = references[buildFile.fileRef];
						if (reference != null)
							comments.Add(guid, String.Format("{0} in {1}", reference.path, sectName));
					}
				}
			}
		}

		private GUIDToCommentMap BuildCommentMap()
		{
			GUIDToCommentMap comments = new GUIDToCommentMap();

			// buildFiles are handled below
			// filerefs are handled below
			foreach (var e in groups.GetObjects())
				comments.Add(e.guid, e.name);
			foreach (var e in containerItems.GetObjects())
				comments.Add(e.guid, "PBXContainerItemProxy");
			foreach (var e in references.GetObjects())
				comments.Add(e.guid, e.path);
			foreach (var e in sources.GetObjects())
			{
				comments.Add(e.guid, "Sources");
				BuildCommentMapForBuildFiles(comments, e.files, "Sources");
			}
			foreach (var e in resources.GetObjects())
			{
				comments.Add(e.guid, "Resources");
				BuildCommentMapForBuildFiles(comments, e.files, "Resources");
			}
			foreach (var e in frameworks.GetObjects())
			{
				comments.Add(e.guid, "Frameworks");
				BuildCommentMapForBuildFiles(comments, e.files, "Frameworks");
			}
			foreach (var e in copyFiles.GetObjects())
			{
				string sectName = e.name;
				if (sectName == null)
					sectName = "CopyFiles";
				comments.Add(e.guid, sectName);
				BuildCommentMapForBuildFiles(comments, e.files, sectName);
			}
			foreach (var e in shellScripts.GetObjects())
				comments.Add(e.guid, "ShellScript");
			foreach (var e in targetDependencies.GetObjects())
				comments.Add(e.guid, "PBXTargetDependency");
			foreach (var e in nativeTargets.GetObjects())
			{
				comments.Add(e.guid, e.name);
				comments.Add(e.buildConfigList, String.Format("Build configuration list for PBXNativeTarget \"{0}\"", e.name));
			}
			foreach (var e in variantGroups.GetObjects())
				comments.Add(e.guid, e.name);
			foreach (var e in buildConfigs.GetObjects())
				comments.Add(e.guid, e.name);
			foreach (var e in project.GetObjects())
			{
				comments.Add(e.guid, "Project object");
				comments.Add(e.buildConfigList, "Build configuration list for PBXProject \"Unity-iPhone\""); // FIXME: project name is hardcoded
			}
			foreach (var e in fileRefs.GetObjects())
				comments.Add(e.guid, e.name);
			if (m_RootElements.Contains("rootObject") && m_RootElements["rootObject"] is PBXElementString)
				comments.Add(m_RootElements["rootObject"].AsString(), "Project object");

			return comments;
		}

		public void ReadFromFile(string path)
		{
			ReadFromString(File.ReadAllText(path));
		}

		public void ReadFromString(string src)
		{
			TextReader sr = new StringReader(src);
			ReadFromStream(sr);
		}

		private static PBXElementDict ParseContent(string content)
		{
			TokenList tokens = Lexer.Tokenize(content);
			var parser = new Parser(tokens);
			TreeAST ast = parser.ParseTree();
			return Serializer.ParseTreeAST(ast, tokens, content);
		}

		public void ReadFromStream(TextReader sr)
		{
			Clear();
			m_RootElements = ParseContent(sr.ReadToEnd());

			if (!m_RootElements.Contains("objects"))
				throw new Exception("Invalid PBX project file: no objects element");

			var objects = m_RootElements["objects"].AsDict();
			m_RootElements.Remove("objects");
			m_RootElements.SetString("objects", "OBJMARKER");

			if (m_RootElements.Contains("objectVersion"))
			{
				m_ObjectVersion = m_RootElements["objectVersion"].AsString();
				m_RootElements.Remove("objectVersion");
			}

			var allGuids = new List<string>();
			string prevSectionName = null;
			foreach (var kv in objects.values)
			{
				allGuids.Add(kv.Key);
				var el = kv.Value;

				if (!(el is PBXElementDict) || !el.AsDict().Contains("isa"))
				{
					m_UnknownObjects.values.Add(kv.Key, el);
					continue;
				}
				var dict = el.AsDict();
				var sectionName = dict["isa"].AsString();

				if (m_Section.ContainsKey(sectionName))
				{
					var section = m_Section[sectionName];
					section.AddObject(kv.Key, dict);
				}
				else
				{
					UnknownSection section;
					if (m_UnknownSections.ContainsKey(sectionName))
						section = m_UnknownSections[sectionName];
					else
					{
						section = new UnknownSection(sectionName);
						m_UnknownSections.Add(sectionName, section);
					}
					section.AddObject(kv.Key, dict);

					// update section order
					if (!m_SectionOrder.Contains(sectionName))
					{
						int pos = 0;
						if (prevSectionName != null)
						{
							// this never fails, because we already added any previous unknown sections
							// to m_SectionOrder
							pos = m_SectionOrder.FindIndex(x => x == prevSectionName);
							pos += 1;
						}
						m_SectionOrder.Insert(pos, sectionName);
					}
				}
				prevSectionName = sectionName;
			}
			RepairStructure(allGuids);
			RefreshAuxMaps();
		}

		public void WriteToFile(string path)
		{
			File.WriteAllText(path, WriteToString());
		}

		public void WriteToStream(TextWriter sw)
		{
			sw.Write(WriteToString());
		}

		public string WriteToString()
		{
			var commentMap = BuildCommentMap();
			var emptyChecker = new PropertyCommentChecker();
			var emptyCommentMap = new GUIDToCommentMap();

			// since we need to add custom comments, the serialization is much more complex
			StringBuilder objectsSb = new StringBuilder();
			if (m_ObjectVersion != null) // objectVersion comes right before objects
				objectsSb.AppendFormat("objectVersion = {0};\n\t", m_ObjectVersion);
			objectsSb.Append("objects = {");
			foreach (string sectionName in m_SectionOrder)
			{
				if (m_Section.ContainsKey(sectionName))
					m_Section[sectionName].WriteSection(objectsSb, commentMap);
				else if (m_UnknownSections.ContainsKey(sectionName))
					m_UnknownSections[sectionName].WriteSection(objectsSb, commentMap);
			}
			foreach (var kv in m_UnknownObjects.values)
				Serializer.WriteDictKeyValue(objectsSb, kv.Key, kv.Value, 2, false, emptyChecker, emptyCommentMap);
			objectsSb.Append("\n\t};");

			StringBuilder contentSb = new StringBuilder();
			contentSb.Append("// !$*UTF8*$!\n");
			Serializer.WriteDict(contentSb, m_RootElements, 0, false,
			                     new PropertyCommentChecker(new string[]{"rootObject/*"}), commentMap);
			contentSb.Append("\n");
			string content = contentSb.ToString();

			content = content.Replace("objects = OBJMARKER;", objectsSb.ToString());
			return content;
		}

		// This method walks the project structure and removes invalid entries.
		void RepairStructure(List<string> allGuids)
		{
			var guidSet = new Dictionary<string, bool>(); // emulate HashSet on .Net 2.0
			foreach (var guid in allGuids)
				guidSet.Add(guid, false);

			while (RepairStructureImpl(guidSet) == true)
				;
		}

		/* Iterates the given guid list and removes all guids that are not in allGuids dictionary.
        */
		static void RemoveMissingGuidsFromGuidList(GUIDList guidList, Dictionary<string, bool> allGuids)
		{
			List<string> guidsToRemove = null;
			foreach (var guid in guidList)
			{
				if (!allGuids.ContainsKey(guid))
				{
					if (guidsToRemove == null)
						guidsToRemove = new List<string>();
					guidsToRemove.Add(guid);
				}
			}
			if (guidsToRemove != null)
			{
				foreach (var guid in guidsToRemove)
					guidList.RemoveGUID(guid);
			}
		}

		/*  Removes objects from the given @a section for which @a checker returns true.
            Also removes the guids of the removed elements from allGuids dictionary.
            Returns true if any objects were removed.
        */
		static bool RemoveObjectsFromSection<T>(KnownSectionBase<T> section,
		                                        Dictionary<string, bool> allGuids,
		                                        Func<T, bool> checker) where T : PBXObject, new()
		{
			List<string> guidsToRemove = null;
			foreach (var kv in section.GetEntries())
			{
				if (checker(kv.Value))
				{
					if (guidsToRemove == null)
						guidsToRemove = new List<string>();
					guidsToRemove.Add(kv.Key);
				}
			}
			if (guidsToRemove != null)
			{
				foreach (var guid in guidsToRemove)
				{
					section.RemoveEntry(guid);
					allGuids.Remove(guid);
				}
				return true;
			}
			return false;
		}

		// Returns true if changes were done and one should call RepairStructureImpl again
		bool RepairStructureImpl(Dictionary<string, bool> allGuids)
		{
			bool changed = false;

			// PBXBuildFile
			changed |= RemoveObjectsFromSection(buildFiles, allGuids,
			                                    o => (o.fileRef == null || !allGuids.ContainsKey(o.fileRef)));
			// PBXFileReference / fileRefs not cleaned

			// PBXGroup
			changed |= RemoveObjectsFromSection(groups, allGuids, o => o.children == null);
			foreach (var o in groups.GetObjects())
				RemoveMissingGuidsFromGuidList(o.children, allGuids);

			// PBXContainerItem / containerItems not cleaned
			// PBXReferenceProxy / references not cleaned

			// PBXSourcesBuildPhase
			changed |= RemoveObjectsFromSection(sources, allGuids, o => o.files == null);
			foreach (var o in sources.GetObjects())
				RemoveMissingGuidsFromGuidList(o.files, allGuids);
			// PBXFrameworksBuildPhase
			changed |= RemoveObjectsFromSection(frameworks, allGuids, o => o.files == null);
			foreach (var o in frameworks.GetObjects())
				RemoveMissingGuidsFromGuidList(o.files, allGuids);
			// PBXResourcesBuildPhase
			changed |= RemoveObjectsFromSection(resources, allGuids, o => o.files == null);
			foreach (var o in resources.GetObjects())
				RemoveMissingGuidsFromGuidList(o.files, allGuids);
			// PBXCopyFilesBuildPhase
			changed |= RemoveObjectsFromSection(copyFiles, allGuids, o => o.files == null);
			foreach (var o in copyFiles.GetObjects())
				RemoveMissingGuidsFromGuidList(o.files, allGuids);
			// PBXShellScriptsBuildPhase
			changed |= RemoveObjectsFromSection(shellScripts, allGuids, o => o.files == null);
			foreach (var o in shellScripts.GetObjects())
				RemoveMissingGuidsFromGuidList(o.files, allGuids);

			// PBXNativeTarget
			changed |= RemoveObjectsFromSection(nativeTargets, allGuids, o => o.phases == null);
			foreach (var o in nativeTargets.GetObjects())
				RemoveMissingGuidsFromGuidList(o.phases, allGuids);

			// PBXTargetDependency / targetDependencies not cleaned

			// PBXVariantGroup
			changed |= RemoveObjectsFromSection(variantGroups, allGuids, o => o.children == null);
			foreach (var o in variantGroups.GetObjects())
				RemoveMissingGuidsFromGuidList(o.children, allGuids);

			// XCBuildConfiguration / buildConfigs not cleaned

			// XCConfigurationList
			changed |= RemoveObjectsFromSection(configs, allGuids, o => o.buildConfigs == null);
			foreach (var o in configs.GetObjects())
				RemoveMissingGuidsFromGuidList(o.buildConfigs, allGuids);

			// PBXProject project not cleaned
			return changed;
		}
	}

}
#endif


text:
package page

import (
	"fmt"
	"os"
	"path"
	"path/filepath"
	"regexp"
	"strconv"
	"strings"
	"time"

	"github.com/pkg/errors"

	"github.com/gohugoio/hugo/helpers"
)

// PermalinkExpander holds permalin mappings per section.
type PermalinkExpander struct {
	// knownPermalinkAttributes maps :tags in a permalink specification to a
	// function which, given a page and the tag, returns the resulting string
	// to be used to replace that tag.
	knownPermalinkAttributes map[string]pageToPermaAttribute

	expanders map[string]func(Page) (string, error)

	ps *helpers.PathSpec
}

// Time for checking date formats. Every field is different than the
// Go reference time for date formatting. This ensures that formatting this date
// with a Go time format always has a different output than the format itself.
var referenceTime = time.Date(2019, time.November, 9, 23, 1, 42, 1, time.UTC)

// Return the callback for the given permalink attribute and a boolean indicating if the attribute is valid or not.
func (p PermalinkExpander) callback(attr string) (pageToPermaAttribute, bool) {
	if callback, ok := p.knownPermalinkAttributes[attr]; ok {
		return callback, true
	}

	if strings.HasPrefix(attr, "sections[") {
		fn := p.toSliceFunc(strings.TrimPrefix(attr, "sections"))
		return func(p Page, s string) (string, error) {
			return path.Join(fn(p.CurrentSection().SectionsEntries())...), nil
		}, true
	}

	// Make sure this comes after all the other checks.
	if referenceTime.Format(attr) != attr {
		return p.pageToPermalinkDate, true
	}

	return nil, false
}

// NewPermalinkExpander creates a new PermalinkExpander configured by the given
// PathSpec.
func NewPermalinkExpander(ps *helpers.PathSpec) (PermalinkExpander, error) {
	p := PermalinkExpander{ps: ps}

	p.knownPermalinkAttributes = map[string]pageToPermaAttribute{
		"year":        p.pageToPermalinkDate,
		"month":       p.pageToPermalinkDate,
		"monthname":   p.pageToPermalinkDate,
		"day":         p.pageToPermalinkDate,
		"weekday":     p.pageToPermalinkDate,
		"weekdayname": p.pageToPermalinkDate,
		"yearday":     p.pageToPermalinkDate,
		"section":     p.pageToPermalinkSection,
		"sections":    p.pageToPermalinkSections,
		"title":       p.pageToPermalinkTitle,
		"slug":        p.pageToPermalinkSlugElseTitle,
		"filename":    p.pageToPermalinkFilename,
	}

	patterns := ps.Cfg.GetStringMapString("permalinks")
	if patterns == nil {
		return p, nil
	}

	e, err := p.parse(patterns)
	if err != nil {
		return p, err
	}

	p.expanders = e

	return p, nil
}

// Expand expands the path in p according to the rules defined for the given key.
// If no rules are found for the given key, an empty string is returned.
func (l PermalinkExpander) Expand(key string, p Page) (string, error) {
	expand, found := l.expanders[key]

	if !found {
		return "", nil
	}

	return expand(p)
}

func (l PermalinkExpander) parse(patterns map[string]string) (map[string]func(Page) (string, error), error) {
	expanders := make(map[string]func(Page) (string, error))

	// Allow " " and / to represent the root section.
	const sectionCutSet = " /" + string(os.PathSeparator)

	for k, pattern := range patterns {
		k = strings.Trim(k, sectionCutSet)

		if !l.validate(pattern) {
			return nil, &permalinkExpandError{pattern: pattern, err: errPermalinkIllFormed}
		}

		pattern := pattern
		matches := attributeRegexp.FindAllStringSubmatch(pattern, -1)

		callbacks := make([]pageToPermaAttribute, len(matches))
		replacements := make([]string, len(matches))
		for i, m := range matches {
			replacement := m[0]
			attr := replacement[1:]
			replacements[i] = replacement
			callback, ok := l.callback(attr)

			if !ok {
				return nil, &permalinkExpandError{pattern: pattern, err: errPermalinkAttributeUnknown}
			}

			callbacks[i] = callback
		}

		expanders[k] = func(p Page) (string, error) {
			if matches == nil {
				return pattern, nil
			}

			newField := pattern

			for i, replacement := range replacements {
				attr := replacement[1:]
				callback := callbacks[i]
				newAttr, err := callback(p, attr)
				if err != nil {
					return "", &permalinkExpandError{pattern: pattern, err: err}
				}

				newField = strings.Replace(newField, replacement, newAttr, 1)

			}

			return newField, nil
		}

	}

	return expanders, nil
}

// pageToPermaAttribute is the type of a function which, given a page and a tag
// can return a string to go in that position in the page (or an error)
type pageToPermaAttribute func(Page, string) (string, error)

var attributeRegexp = regexp.MustCompile(`:\w+(\[.+\])?`)

// validate determines if a PathPattern is well-formed
func (l PermalinkExpander) validate(pp string) bool {
	fragments := strings.Split(pp[1:], "/")
	bail := false
	for i := range fragments {
		if bail {
			return false
		}
		if len(fragments[i]) == 0 {
			bail = true
			continue
		}

		matches := attributeRegexp.FindAllStringSubmatch(fragments[i], -1)
		if matches == nil {
			continue
		}

		for _, match := range matches {
			k := match[0][1:]
			if _, ok := l.callback(k); !ok {
				return false
			}
		}
	}
	return true
}

type permalinkExpandError struct {
	pattern string
	err     error
}

func (pee *permalinkExpandError) Error() string {
	return fmt.Sprintf("error expanding %q: %s", pee.pattern, pee.err)
}

var (
	errPermalinkIllFormed        = errors.New("permalink ill-formed")
	errPermalinkAttributeUnknown = errors.New("permalink attribute not recognised")
)

func (l PermalinkExpander) pageToPermalinkDate(p Page, dateField string) (string, error) {
	// a Page contains a Node which provides a field Date, time.Time
	switch dateField {
	case "year":
		return strconv.Itoa(p.Date().Year()), nil
	case "month":
		return fmt.Sprintf("%02d", int(p.Date().Month())), nil
	case "monthname":
		return p.Date().Month().String(), nil
	case "day":
		return fmt.Sprintf("%02d", p.Date().Day()), nil
	case "weekday":
		return strconv.Itoa(int(p.Date().Weekday())), nil
	case "weekdayname":
		return p.Date().Weekday().String(), nil
	case "yearday":
		return strconv.Itoa(p.Date().YearDay()), nil
	}

	return p.Date().Format(dateField), nil
}

// pageToPermalinkTitle returns the URL-safe form of the title
func (l PermalinkExpander) pageToPermalinkTitle(p Page, _ string) (string, error) {
	return l.ps.URLize(p.Title()), nil
}

// pageToPermalinkFilename returns the URL-safe form of the filename
func (l PermalinkExpander) pageToPermalinkFilename(p Page, _ string) (string, error) {
	name := p.File().TranslationBaseName()
	if name == "index" {
		// Page bundles; the directory name will hopefully have a better name.
		dir := strings.TrimSuffix(p.File().Dir(), helpers.FilePathSeparator)
		_, name = filepath.Split(dir)
	}

	return l.ps.URLize(name), nil
}

// if the page has a slug, return the slug, else return the title
func (l PermalinkExpander) pageToPermalinkSlugElseTitle(p Page, a string) (string, error) {
	if p.Slug() != "" {
		return l.ps.URLize(p.Slug()), nil
	}
	return l.pageToPermalinkTitle(p, a)
}

func (l PermalinkExpander) pageToPermalinkSection(p Page, _ string) (string, error) {
	return p.Section(), nil
}

func (l PermalinkExpander) pageToPermalinkSections(p Page, _ string) (string, error) {
	return p.CurrentSection().SectionsPath(), nil
}

var (
	nilSliceFunc = func(s []string) []string {
		return nil
	}
	allSliceFunc = func(s []string) []string {
		return s
	}
)

// toSliceFunc returns a slice func that slices s according to the cut spec.
// The cut spec must be on form [low:high] (one or both can be omitted),
// also allowing single slice indices (e.g. [2]) and the special [last] keyword
// giving the last element of the slice.
// The returned function will be lenient and not panic in out of bounds situation.
//
// The current use case for this is to use parts of the sections path in permalinks.
func (l PermalinkExpander) toSliceFunc(cut string) func(s []string) []string {
	cut = strings.ToLower(strings.TrimSpace(cut))
	if cut == "" {
		return allSliceFunc
	}

	if len(cut) < 3 || (cut[0] != '[' || cut[len(cut)-1] != ']') {
		return nilSliceFunc
	}

	toNFunc := func(s string, low bool) func(ss []string) int {
		if s == "" {
			if low {
				return func(ss []string) int {
					return 0
				}
			} else {
				return func(ss []string) int {
					return len(ss)
				}
			}
		}

		if s == "last" {
			return func(ss []string) int {
				return len(ss) - 1
			}
		}

		n, _ := strconv.Atoi(s)
		if n < 0 {
			n = 0
		}
		return func(ss []string) int {
			// Prevent out of bound situations. It would not make
			// much sense to panic here.
			if n > len(ss) {
				return len(ss)
			}
			return n
		}
	}

	opsStr := cut[1 : len(cut)-1]
	opts := strings.Split(opsStr, ":")

	if !strings.Contains(opsStr, ":") {
		toN := toNFunc(opts[0], true)
		return func(s []string) []string {
			if len(s) == 0 {
				return nil
			}
			v := s[toN(s)]
			if v == "" {
				return nil
			}
			return []string{v}
		}
	}

	toN1, toN2 := toNFunc(opts[0], true), toNFunc(opts[1], false)

	return func(s []string) []string {
		if len(s) == 0 {
			return nil
		}
		return s[toN1(s):toN2(s)]
	}

}

redpajama_set_name: RedPajamaGithub


text:
SYNONYM

#### According to
Index Fungorum

#### Published in
null

#### Original name
Mytilidion subcompressum P. Karst.

### Remarks
null


text:
layout: post
title: "liquidsoap fallbacks explained"
tags: [liquidsoap]
---

## Preventing Radio Castatrophy

![not what liquidsoap looks like](/assets/images/old_radio.gif)

In liquidsoap, the *last* thing you want is your users to hear silence. There
are many reasons this could happen, the DJ fell asleep/got drunk, there's a bad
file in the playlist that cannot be played, etc.

## The fallback function

In liquidsoap you can prevent disasters with fallbacks. If one source cannot be
played, liquidsoap will gracefully fall back to another source. Here's a typical
setup:

{% highlight ruby %}
backup_playlist = playlist("./playlist.txt",conservative=true,mode="normal",reload_mode="watch")
output.dummy(fallible=true,backup_playlist)

live_dj = input.harbor("live",port=9000)

on_fail = single("./technical_difficulties.wav")

source = fallback(track_sensitive=false,
                  [live_dj,backup_playlist,on_fail])
{% endhighlight %}

While some sources may be fallible, that's ok if that are arranged in a
cascading fallback, with the last source being unfallible. This way we can
guarantee something should always be playing.

{% include mailchimp.html %}


text:
/*
    jTable localization file for 'Portuguese - Brazilian' language.
    Authors: Renato Bigliazzi, Paulo Soriano
*/
(function ($) {

    $.extend(true, $.hik.jtable.prototype.options.messages, {
        serverCommunicationError: 'Erro durante comunicação com o servidor.',
        loadingMessage: 'Carregando registros...',
        noDataAvailable: 'Nenhum dado disponível!',
        addNewRecord: 'Adicionar novo registro',
        editRecord: 'Editar registro',
        areYouSure: 'Você tem certeza?',
        deleteConfirmation: 'Este registro será excluído. Você tem certeza?',
        save: 'Salvar',
        saving: 'Salvando...',
        cancel: 'Cancelar',
        deleteText: 'Excluir',
        deleting: 'Excluindo...',
        error: 'Erro',
        close: 'Fechar',
        cannotLoadOptionsFor: 'Não foi possível carregar opções para o campo {0}!',
        pagingInfo: 'Exibindo {0}-{1} de {2}',
        canNotDeletedRecords: 'Não foi possível excluir registro(s) {0} de {1}!',
        deleteProggress: 'Excluindo {0} de {1} registros, processando...',
        pageSizeChangeLabel: 'Linhas',
        gotoPageLabel: 'Ir para página'
    });

})(jQuery);


text:
require 'test_helper'
require 'surf/repository'

describe Surf::Repository do
  subject do
    Surf::Repository
      .dup
      .configuration do |config|
        config.mapping = mapping
        config.pull_request_class = FakeStore::InitializerTest
        config.webhook_storage = FakeStore::WebhookStorage.new
      end
  end

  let(:webhook) { Fixtures.webhook_registration }
  let(:mapping) { { pulls_url: %w[repository pulls_url], id: %w[repository id] } }

  it 'creates methods to allow use mapped keys' do
    assert_match %r[pulls{/number}], subject.new(webhook).pulls_url
  end

  context '#pull_request' do
    it 'creates pull request instance with self and id' do
      assert_equal :called, subject.new(webhook).pull_request(42).result
    end
  end

  context '.all' do
    it 'retreives all saved webhooks and wraps it to repo object' do
      assert_equal 1, subject.all.count
      assert_equal 27, subject.all.first.id
    end
  end

  context '.find' do
    it 'retrives passed webhook by id and wrap it to repo object' do
      assert_equal 27, subject.find(id: 42).id
    end
  end
end


text:
package com.matthiasj.verTrakTV.models;

/**
 * Created by Matthias on 16.08.16 at 12:57.
 */
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;

import javax.annotation.Generated;

@Generated("org.jsonschema2pojo")
public class Clearart {

    @SerializedName("full")
    @Expose
    private String full;

    /**
     *
     * @return
     * The full
     */
    public String getFull() {
        return full;
    }

    /**
     *
     * @param full
     * The full
     */
    public void setFull(String full) {
        this.full = full;
    }

}


text:
package net.md_5.bungee.scheduler;

import lombok.Data;
import net.md_5.bungee.api.ProxyServer;
import net.md_5.bungee.api.plugin.Plugin;
import net.md_5.bungee.api.scheduler.ScheduledTask;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.logging.Level;

@Data
public class BungeeTask implements Runnable, ScheduledTask
{

    private final BungeeScheduler sched;
    private final int id;
    private final Plugin owner;
    private final Runnable task;
    //
    private final long delay;
    private final long period;
    private final AtomicBoolean running = new AtomicBoolean( true );

    public BungeeTask(BungeeScheduler sched, int id, Plugin owner, Runnable task, long delay, long period, TimeUnit unit)
    {
        this.sched = sched;
        this.id = id;
        this.owner = owner;
        this.task = task;
        this.delay = unit.toMillis( delay );
        this.period = unit.toMillis( period );
    }

    @Override
    public void cancel()
    {
        running.set( false );
    }

    @Override
    public void run()
    {
        if ( delay > 0 )
        {
            try
            {
                Thread.sleep( delay );
            } catch ( InterruptedException ex )
            {
                Thread.currentThread().interrupt();
            }
        }

        while ( running.get() )
        {
            try
            {
                task.run();
            } catch ( Throwable t )
            {
                ProxyServer.getInstance().getLogger().log( Level.SEVERE, String.format( "Task %s encountered an exception", this ), t );
            }

            // If we have a period of 0 or less, only run once
            if ( period <= 0 )
            {
                break;
            }

            try
            {
                Thread.sleep( period );
            } catch ( InterruptedException ex )
            {
                Thread.currentThread().interrupt();
            }
        }

        sched.cancel( this );
    }
}


text:
<!DOCTYPE html>

<meta charset="utf-8">

<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<meta name="author" content="Active 9 LLC.">
<meta name="Description" content="Vinegar.JS" />
<title>Vinegar.JS</title>
<link href="css/reset.css" rel="stylesheet" type="text/css" media="screen" />
<link href="css/contact.css" rel="stylesheet" type="text/css" media="screen" />
<link href="css/styles.css" rel="stylesheet" type="text/css" media="screen" />
<link href="css/flexslider.css" rel="stylesheet" type="text/css" media="screen">
<link href="css/jquery.fancybox.css" rel="stylesheet" type="text/css" media="screen" />
<link href="css/retina-responsive.css" rel="stylesheet" type="text/css" media="screen" />

<link href="css/print.css" rel="stylesheet" type="text/css" media="print" />
<link href='http://fonts.googleapis.com/css?family=Open+Sans:400,300,300italic,700,600,800' rel='stylesheet' type='text/css' />

<{HEADER}>

  <{CONTENT}>

<{FOOTER}>


text:
#ifdef USE_TI_UIREFRESHCONTROL

#if defined (USE_TI_UIATTRIBUTEDSTRING) || defined (USE_TI_UIIOSATTRIBUTEDSTRING)
#import "TiUIAttributedStringProxy.h"
#endif
#import "TiUIRefreshControlProxy.h"
#import "TiUtils.h"

@implementation TiUIRefreshControlProxy

-(NSString*)apiName
{
    return @"Ti.UI.RefreshControl";
}

-(void) dealloc
{
    RELEASE_TO_NIL(_refreshControl);
    RELEASE_TO_NIL(_attributedString);
    RELEASE_TO_NIL(refreshTintColor);
    [super dealloc];
}

#pragma mark - Internal Use
-(UIRefreshControl*)control
{
    //Must be called on main thread
    if (_refreshControl == nil) {
        _refreshControl = [[UIRefreshControl alloc] init];
        [_refreshControl addTarget:self action:@selector(refreshStart) forControlEvents:UIControlEventValueChanged];
        [self refreshControl];
    }

    return _refreshControl;
}

-(void)refreshControl
{
    if (_refreshControl != nil) {
        [_refreshControl setAttributedTitle:_attributedString];
        [_refreshControl setTintColor:refreshTintColor];
    }
}

-(void)refreshStart
{
    if ([self _hasListeners:@"refreshstart"]) {
        [self fireEvent:@"refreshstart" withObject:nil propagate:NO reportSuccess:NO errorCode:0 message:nil];
    }
}

#pragma mark - Public API

-(void)setTitle:(id)args
{

#if defined (USE_TI_UIATTRIBUTEDSTRING) || defined (USE_TI_UIIOSATTRIBUTEDSTRING)
	ENSURE_SINGLE_ARG_OR_NIL(args, TiUIAttributedStringProxy);
	[self replaceValue:args forKey:@"title" notification:NO];
	RELEASE_TO_NIL(_attributedString);
	if (args != nil) {
		_attributedString = [[args attributedString] copy];
	}
	TiThreadPerformOnMainThread(^{
		[self refreshControl];
	}, NO);
#endif
}

-(void)setTintColor:(id)args
{
    ENSURE_SINGLE_ARG_OR_NIL(args, NSObject);
    [self replaceValue:args forKey:@"tintColor" notification:NO];
    RELEASE_TO_NIL(refreshTintColor);
    refreshTintColor = [[[TiUtils colorValue:args] color] retain];
    //Changing tintColor works on iOS6 but not on iOS7. iOS Bug?
    TiThreadPerformOnMainThread(^{
        [self refreshControl];
    }, NO);
}

-(void)beginRefreshing:(id)unused
{
    TiThreadPerformOnMainThread(^{
        [_refreshControl beginRefreshing];
    }, NO);
}

-(void)endRefreshing:(id)unused
{
    TiThreadPerformOnMainThread(^{
        [_refreshControl endRefreshing];
    }, NO);
}

@end
#endif


text:
<?php
/**
 * Created by PhpStorm.
 * User: afinogen
 * Date: 11.04.16
 * Time: 12:03
 */

namespace app\commands;

use app\models\UserGroupRule;
use yii\console\Controller;
use yii\helpers\Console;

/**
 * Class RbacController
 * @package app\commands
 */
class RbacController extends Controller
{
    /**
     * Создание ролей
     */
    public function actionInit()
    {
        Console::output('Add roles');

        $auth = \Yii::$app->authManager;
        $auth->removeAll();

        $userRule = new UserGroupRule();
        $auth->add($userRule);

        $user = $auth->createRole('user');
        $user->ruleName = $userRule->name;
        $auth->add($user);

        $admin = $auth->createRole('admin');
        $admin->ruleName = $userRule->name;
        $auth->add($admin);
        $auth->addChild($admin, $user);

        Console::output('ok');
    }
}


text:
/* Data structure to contain the action information.  */
struct __spawn_action
{
  enum
  {
    spawn_do_close,
    spawn_do_dup2,
    spawn_do_open
  } tag;

  union
  {
    struct
    {
      int fd;
    } close_action;
    struct
    {
      int fd;
      int newfd;
    } dup2_action;
    struct
    {
      int fd;
      const char *path;
      int oflag;
      mode_t mode;
    } open_action;
  } action;
};

#define SPAWN_XFLAGS_USE_PATH	0x1
#define SPAWN_XFLAGS_TRY_SHELL	0x2

extern int __posix_spawn_file_actions_realloc (posix_spawn_file_actions_t *
					       file_actions);

extern int __spawni (pid_t *pid, const char *path,
		     const posix_spawn_file_actions_t *file_actions,
		     const posix_spawnattr_t *attrp, char *const argv[],
		     char *const envp[], int xflags);


text:
/**
 * @module
 * @description
 * Entry point for all public APIs of the common package.
 */
export * from './location/index';
export {NgLocaleLocalization, NgLocalization} from './i18n/localization';
export {registerLocaleData} from './i18n/locale_data';
export {Plural, NumberFormatStyle, FormStyle, Time, TranslationWidth, FormatWidth, NumberSymbol, WeekDay, getCurrencySymbol, getLocaleDayPeriods, getLocaleDayNames, getLocaleMonthNames, getLocaleId, getLocaleEraNames, getLocaleWeekEndRange, getLocaleFirstDayOfWeek, getLocaleDateFormat, getLocaleDateTimeFormat, getLocaleExtraDayPeriodRules, getLocaleExtraDayPeriods, getLocalePluralCase, getLocaleTimeFormat, getLocaleNumberSymbol, getLocaleNumberFormat, getLocaleCurrencyName, getLocaleCurrencySymbol} from './i18n/locale_data_api';
export {parseCookieValue as ɵparseCookieValue} from './cookie';
export {CommonModule, DeprecatedI18NPipesModule} from './common_module';
export {NgClass, NgForOf, NgForOfContext, NgIf, NgIfContext, NgPlural, NgPluralCase, NgStyle, NgSwitch, NgSwitchCase, NgSwitchDefault, NgTemplateOutlet, NgComponentOutlet} from './directives/index';
export {DOCUMENT} from './dom_tokens';
export {AsyncPipe, DatePipe, I18nPluralPipe, I18nSelectPipe, JsonPipe, LowerCasePipe, CurrencyPipe, DecimalPipe, PercentPipe, SlicePipe, UpperCasePipe, TitleCasePipe} from './pipes/index';
export {DeprecatedDatePipe, DeprecatedCurrencyPipe, DeprecatedDecimalPipe, DeprecatedPercentPipe} from './pipes/deprecated/index';
export {PLATFORM_BROWSER_ID as ɵPLATFORM_BROWSER_ID, PLATFORM_SERVER_ID as ɵPLATFORM_SERVER_ID, PLATFORM_WORKER_APP_ID as ɵPLATFORM_WORKER_APP_ID, PLATFORM_WORKER_UI_ID as ɵPLATFORM_WORKER_UI_ID, isPlatformBrowser, isPlatformServer, isPlatformWorkerApp, isPlatformWorkerUi} from './platform_id';
export {VERSION} from './version';


text:
FROM centos:7.3.1611
MAINTAINER Craig Minihan <craig@ripcordsoftware.com>
USER root

# install basic tools
RUN yum install -y sudo curl wget unzip bzip2 xz pkgconfig rsync epel-release net-tools which telnet nano file which

# C++ tools
RUN yum install -y git gcc gcc-c++ make autoconf automake libtool doxygen valgrind ccache

# C++ libraries
RUN yum install -y zlib-devel boost-devel cppunit-devel

# other languages
RUN yum install -y ruby ruby-devel rubygems rubygem-bundler rubygem-rspec && \
    yum install -y java-1.8.0-openjdk-headless && \
    yum install -y nodejs npm && \
    yum install -y python python-pip python34 python34-pip && \
    yum install -y golang

# other language tools and libs
RUN yum install -y lcov && \
    pip install --upgrade pip && \
    pip install json_tools && \
    pip install u-msgpack-python

# build and install couchdb
RUN yum install -y erlang-asn1 erlang-erts erlang-eunit erlang-os_mon erlang-xmerl help2man libicu-devel js js-devel && \
    wget https://archive.apache.org/dist/couchdb/source/1.6.1/apache-couchdb-1.6.1.tar.gz && \
    tar xf apache-couchdb-1.6.1.tar.gz && \
    cd apache-couchdb-1.6.1 && \
    ./configure --prefix=/usr/local --enable-init --with-erlang=/usr/lib64/erlang/erts-5.10.4/include && \
    make -j4 && \
    make install && \
    useradd -d /var/lib/couchdb couchdb && \
    mkdir -p /usr/local/{lib,etc}/couchdb /usr/local/var/{lib,log,run}/couchdb /var/lib/couchdb && \
    chmod -R g+rw /usr/local/{lib,etc}/couchdb /usr/local/var/{lib,log,run}/couchdb && \
    chown -R couchdb:couchdb /usr/local/{lib,etc}/couchdb /usr/local/var/{lib,log,run}/couchdb

# update sudoers
RUN echo "jenkins ALL=NOPASSWD: ALL" >> /etc/sudoers


text:
class MainScene : public Scene {
public:
  MainScene();
  virtual void OnActivation() override;
  virtual void OnDeactivation() override;
  virtual void OnShown() override;
  virtual void OnHidden() override;

private:
  void CreateAnimation();
  int m_width_middle;
  int m_height_middle;
  void CreateLogo();
  void CreatePlayButton();
  void CreateQuitButton();

  void CreateMusic();
  //void CreateBackground();
  //void CreateGamemodes();

};

#endif


text: Web Translations API


text:
<?php

/**
 * @namespace
 */
namespace ZendTest\Feed\PubSubHubbub;
use Zend\Http;
use Zend\Feed\PubSubHubbub;

/**
 * @category   Zend
 * @package    Zend_Feed
 * @subpackage UnitTests
 * @group      Zend_Feed
 * @group      Zend_Feed_Subsubhubbub
 * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
 * @license    http://framework.zend.com/license/new-bsd     New BSD License
 */
class PublisherTest extends \PHPUnit_Framework_TestCase
{

    /**
     * @var \Zend\Feed\PubSubHubbub\Publisher
     */
    protected $_publisher = null;

    public function setUp()
    {
        $client = new Http\Client;
        PubSubHubbub\PubSubHubbub::setHttpClient($client);
        $this->_publisher = new PubSubHubbub\Publisher;
    }

    public function testAddsHubServerUrl()
    {
        $this->_publisher->addHubUrl('http://www.example.com/hub');
        $this->assertEquals(array('http://www.example.com/hub'), $this->_publisher->getHubUrls());
    }

    public function testAddsHubServerUrlsFromArray()
    {
        $this->_publisher->addHubUrls(array(
            'http://www.example.com/hub', 'http://www.example.com/hub2'
        ));
        $this->assertEquals(array(
            'http://www.example.com/hub', 'http://www.example.com/hub2'
        ), $this->_publisher->getHubUrls());
    }

    public function testAddsHubServerUrlsFromArrayUsingSetConfig()
    {
        $this->_publisher->setConfig(array('hubUrls' => array(
            'http://www.example.com/hub', 'http://www.example.com/hub2'
        )));
        $this->assertEquals(array(
            'http://www.example.com/hub', 'http://www.example.com/hub2'
        ), $this->_publisher->getHubUrls());
    }

    public function testRemovesHubServerUrl()
    {
        $this->_publisher->addHubUrls(array(
            'http://www.example.com/hub', 'http://www.example.com/hub2'
        ));
        $this->_publisher->removeHubUrl('http://www.example.com/hub');
        $this->assertEquals(array(
            1 => 'http://www.example.com/hub2'
        ), $this->_publisher->getHubUrls());
    }

    public function testRetrievesUniqueHubServerUrlsOnly()
    {
        $this->_publisher->addHubUrls(array(
            'http://www.example.com/hub', 'http://www.example.com/hub2',
            'http://www.example.com/hub'
        ));
        $this->assertEquals(array(
            'http://www.example.com/hub', 'http://www.example.com/hub2'
        ), $this->_publisher->getHubUrls());
    }

    public function testThrowsExceptionOnSettingEmptyHubServerUrl()
    {
        try {
            $this->_publisher->addHubUrl('');
            $this->fail('Should not fail as an Exception would be raised and caught');
        } catch (PubSubHubbub\Exception $e) {}
    }

    public function testThrowsExceptionOnSettingNonStringHubServerUrl()
    {
        try {
            $this->_publisher->addHubUrl(123);
            $this->fail('Should not fail as an Exception would be raised and caught');
        } catch (PubSubHubbub\Exception $e) {}
    }

    public function testThrowsExceptionOnSettingInvalidHubServerUrl()
    {
        try {
            $this->_publisher->addHubUrl('http://');
            $this->fail('Should not fail as an Exception would be raised and caught');
        } catch (PubSubHubbub\Exception $e) {}
    }

    public function testAddsUpdatedTopicUrl()
    {
        $this->_publisher->addUpdatedTopicUrl('http://www.example.com/topic');
        $this->assertEquals(array('http://www.example.com/topic'), $this->_publisher->getUpdatedTopicUrls());
    }

    public function testAddsUpdatedTopicUrlsFromArray()
    {
        $this->_publisher->addUpdatedTopicUrls(array(
            'http://www.example.com/topic', 'http://www.example.com/topic2'
        ));
        $this->assertEquals(array(
            'http://www.example.com/topic', 'http://www.example.com/topic2'
        ), $this->_publisher->getUpdatedTopicUrls());
    }

    public function testAddsUpdatedTopicUrlsFromArrayUsingSetConfig()
    {
        $this->_publisher->setConfig(array('updatedTopicUrls' => array(
            'http://www.example.com/topic', 'http://www.example.com/topic2'
        )));
        $this->assertEquals(array(
            'http://www.example.com/topic', 'http://www.example.com/topic2'
        ), $this->_publisher->getUpdatedTopicUrls());
    }

    public function testRemovesUpdatedTopicUrl()
    {
        $this->_publisher->addUpdatedTopicUrls(array(
            'http://www.example.com/topic', 'http://www.example.com/topic2'
        ));
        $this->_publisher->removeUpdatedTopicUrl('http://www.example.com/topic');
        $this->assertEquals(array(
            1 => 'http://www.example.com/topic2'
        ), $this->_publisher->getUpdatedTopicUrls());
    }

    public function testRetrievesUniqueUpdatedTopicUrlsOnly()
    {
        $this->_publisher->addUpdatedTopicUrls(array(
            'http://www.example.com/topic', 'http://www.example.com/topic2',
            'http://www.example.com/topic'
        ));
        $this->assertEquals(array(
            'http://www.example.com/topic', 'http://www.example.com/topic2'
        ), $this->_publisher->getUpdatedTopicUrls());
    }

    public function testThrowsExceptionOnSettingEmptyUpdatedTopicUrl()
    {
        try {
            $this->_publisher->addUpdatedTopicUrl('');
            $this->fail('Should not fail as an Exception would be raised and caught');
        } catch (PubSubHubbub\Exception $e) {}
    }

    public function testThrowsExceptionOnSettingNonStringUpdatedTopicUrl()
    {
        try {
            $this->_publisher->addUpdatedTopicUrl(123);
            $this->fail('Should not fail as an Exception would be raised and caught');
        } catch (PubSubHubbub\Exception $e) {}
    }

    public function testThrowsExceptionOnSettingInvalidUpdatedTopicUrl()
    {
        try {
            $this->_publisher->addUpdatedTopicUrl('http://');
            $this->fail('Should not fail as an Exception would be raised and caught');
        } catch (PubSubHubbub\Exception $e) {}
    }

    public function testAddsParameter()
    {
        $this->_publisher->setParameter('foo', 'bar');
        $this->assertEquals(array('foo'=>'bar'), $this->_publisher->getParameters());
    }

    public function testAddsParametersFromArray()
    {
        $this->_publisher->setParameters(array(
            'foo' => 'bar', 'boo' => 'baz'
        ));
        $this->assertEquals(array(
            'foo' => 'bar', 'boo' => 'baz'
        ), $this->_publisher->getParameters());
    }

    public function testAddsParametersFromArrayInSingleMethod()
    {
        $this->_publisher->setParameter(array(
            'foo' => 'bar', 'boo' => 'baz'
        ));
        $this->assertEquals(array(
            'foo' => 'bar', 'boo' => 'baz'
        ), $this->_publisher->getParameters());
    }

    public function testAddsParametersFromArrayUsingSetConfig()
    {
        $this->_publisher->setConfig(array('parameters' => array(
            'foo' => 'bar', 'boo' => 'baz'
        )));
        $this->assertEquals(array(
            'foo' => 'bar', 'boo' => 'baz'
        ), $this->_publisher->getParameters());
    }

    public function testRemovesParameter()
    {
        $this->_publisher->setParameters(array(
            'foo' => 'bar', 'boo' => 'baz'
        ));
        $this->_publisher->removeParameter('boo');
        $this->assertEquals(array(
            'foo' => 'bar'
        ), $this->_publisher->getParameters());
    }

    public function testRemovesParameterIfSetToNull()
    {
        $this->_publisher->setParameters(array(
            'foo' => 'bar', 'boo' => 'baz'
        ));
        $this->_publisher->setParameter('boo', null);
        $this->assertEquals(array(
            'foo' => 'bar'
        ), $this->_publisher->getParameters());
    }

    public function testNotifiesHubWithCorrectParameters()
    {
        PubSubHubbub\PubSubHubbub::setHttpClient(new ClientSuccess);
        $client = PubSubHubbub\PubSubHubbub::getHttpClient();
        $this->_publisher->addHubUrl('http://www.example.com/hub');
        $this->_publisher->addUpdatedTopicUrl('http://www.example.com/topic');
        $this->_publisher->setParameter('foo', 'bar');
        $this->_publisher->notifyAll();
        $this->assertEquals('hub.mode=publish&hub.url=http%3A%2F%2Fwww.example.com%2Ftopic&foo=bar', $client->getBody());
    }

    public function testNotifiesHubWithCorrectParametersAndMultipleTopics()
    {
        PubSubHubbub\PubSubHubbub::setHttpClient(new ClientSuccess);
        $client = PubSubHubbub\PubSubHubbub::getHttpClient();
        $this->_publisher->addHubUrl('http://www.example.com/hub');
        $this->_publisher->addUpdatedTopicUrl('http://www.example.com/topic');
        $this->_publisher->addUpdatedTopicUrl('http://www.example.com/topic2');
        $this->_publisher->notifyAll();
        $this->assertEquals('hub.mode=publish&hub.url=http%3A%2F%2Fwww.example.com%2Ftopic&hub.url=http%3A%2F%2Fwww.example.com%2Ftopic2', $client->getBody());
    }

    public function testNotifiesHubAndReportsSuccess()
    {
        PubSubHubbub\PubSubHubbub::setHttpClient(new ClientSuccess);
        $client = PubSubHubbub\PubSubHubbub::getHttpClient();
        $this->_publisher->addHubUrl('http://www.example.com/hub');
        $this->_publisher->addUpdatedTopicUrl('http://www.example.com/topic');
        $this->_publisher->setParameter('foo', 'bar');
        $this->_publisher->notifyAll();
        $this->assertTrue($this->_publisher->isSuccess());
    }

    public function testNotifiesHubAndReportsFail()
    {
        PubSubHubbub\PubSubHubbub::setHttpClient(new ClientFail);
        $client = PubSubHubbub\PubSubHubbub::getHttpClient();
        $this->_publisher->addHubUrl('http://www.example.com/hub');
        $this->_publisher->addUpdatedTopicUrl('http://www.example.com/topic');
        $this->_publisher->setParameter('foo', 'bar');
        $this->_publisher->notifyAll();
        $this->assertFalse($this->_publisher->isSuccess());
    }

}

// Some stubs for what Http_Client would be doing

class ClientSuccess extends Http\Client
{
    public function request($method = null) {
        $response = new ResponseSuccess;
        return $response;
    }
    public function getBody(){return $this->prepareBody();}
}
class ClientFail extends Http\Client
{
    public function request($method = null) {
        $response = new ResponseFail;
        return $response;
    }
    public function getBody(){return $this->prepareBody();}
}
class ResponseSuccess
{
    public function getStatus(){return 204;}
}
class ResponseFail
{
    public function getStatus(){return 404;}
}


text:
from __future__ import unicode_literals

from django.apps import AppConfig

class TemperatureConfig(AppConfig):
    name = 'temperature'


text:
@interface ChildAccountController () {
    long long _birthday;
}

@property (weak, nonatomic) IBOutlet UITextField *nameTextField;
@property (weak, nonatomic) IBOutlet UITextField *schoolTextField;
@property (weak, nonatomic) IBOutlet UIView *birthdayView;
@property (weak, nonatomic) IBOutlet UILabel *birthdayLabel;
@property (weak, nonatomic) IBOutlet UIView *privinceView;
@property (weak, nonatomic) IBOutlet UILabel *privinceLabel;
@property (weak, nonatomic) IBOutlet UIButton *childButton;
@property (strong, nonatomic) UIDatePicker *datePicker;
@property (strong, nonatomic) UIView *blurView;

@end

@implementation ChildAccountController

- (void)dealloc {
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view from its nib.

    self.title = @"创建孩子账号";
    self.childButton.layer.cornerRadius = 5.0;
    self.childButton.clipsToBounds = YES;
    [self addUITapGesture];
    [self addNotificationObserver];
}

#pragma mark -- 网络请求
- (void)createChildAccount {
    ApplyViewModel *model = [[ApplyViewModel alloc] init];
    weakify(self);
    model.returnBlock = ^(id response) {
        strongify(weakSelf);
        [weakSelf postNotificationCenter];
        [MBProgressHUD hideHUDForView:strongSelf.view];
        ChildSuccessController *successVC = [[ChildSuccessController alloc] init];
        successVC.account = response;
        [strongSelf.navigationController pushViewController:successVC animated:YES];
    };
    model.errorBlock = ^(id error) {
        strongify(weakSelf);
        [MBProgressHUD hideHUDForView:strongSelf.view];
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            [MBProgressHUD showError:error toView:strongSelf.view];
        });
    };
    [MBProgressHUD showMessage:@"" toView:self.view];
    [model createChildAccountWithName:self.nameTextField.text.trimString withBirthday:_birthday withPrivince:self.privinceLabel.text withColleage:self.schoolTextField.text.trimString];
}

- (void)addUITapGesture {
    UITapGestureRecognizer *birthdayTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapAction)];
    [self.birthdayView addGestureRecognizer:birthdayTap];

    UITapGestureRecognizer *privinceTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(privinceTapAction)];
    [self.privinceView addGestureRecognizer:privinceTap];
}

//选择地址的通知
- (void)addNotificationObserver {
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(selectAddress:) name:kFilterUserAddressNotification object:nil];
}

//创建孩子账号成功的通知
- (void)postNotificationCenter {
    [[NSNotificationCenter defaultCenter] postNotificationName:kCreateChildAccountNotification object:nil];
}

- (void)initBlurView {
    UIView *blurView = [[UIView alloc] initWithFrame:[UIScreen mainScreen].bounds];
    blurView.alpha = 0;
    blurView.backgroundColor = RGBAColor(0, 0, 0, 0.3);
    self.blurView = blurView;

    UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapBlurAction)];
    [blurView addGestureRecognizer:tap];

    [self.view.window addSubview:blurView];

    [blurView addSubview:self.datePicker];

    [UIView animateWithDuration:0.25 animations:^{
        blurView.alpha = 1;
        self.datePicker.alpha = 1;
        self.datePicker.y = [ApplicationStyle screenHeight] - [ApplicationStyle screenWidth] *3/5;
    }];
}

#pragma mark --
- (void)selectAddress:(NSNotification *)notification {
    NSDictionary *objects = (NSDictionary *)notification.object;
    NSString *result = objects[@"result"];
    self.privinceLabel.text = result;
}

- (void)tapBlurAction {
    [self hiderDataPickerView];
    NSDate *selectedDate = self.datePicker.date;
    NSString *dateStr = [NSObject getTimeWithFormat:@"M月dd日" andDate:selectedDate];
    _birthday = (long long)[selectedDate timeIntervalSince1970];

    self.birthdayLabel.text = dateStr;
}

- (void)tapAction {
    [self.view endEditing:YES];
    [self initBlurView];
}

- (void)privinceTapAction {
    AddressViewController *addressVC = [[AddressViewController alloc] init];
    addressVC.address = YES;
    [self.navigationController pushViewController:addressVC animated:YES];
}

- (void)hiderDataPickerView {
    [UIView animateWithDuration:0.25 animations:^{
        self.datePicker.y = [ApplicationStyle screenHeight];
        self.datePicker.alpha = 0;
        self.blurView.alpha = 0;
    } completion:^(BOOL finished) {
        [self.blurView removeFromSuperview];
        self.blurView = nil;
    }];
}

//判空处理
- (BOOL)handlerInputIsLegal {
    if (self.nameTextField.text.trimString.length == 0) {
        [MBProgressHUD showText:@"请输入孩子姓名"];
        return NO;
    } else if (self.schoolTextField.text.trimString.length == 0) {
        [MBProgressHUD showText:@"请输入孩子学校"];
        return NO;
    } else if (!self.birthdayLabel.text || self.birthdayLabel.text.length == 0 || !_birthday) {
        [MBProgressHUD showText:@"请选择孩子生日"];
        return NO;
    } else if (!self.privinceLabel.text || self.privinceLabel.text.length == 0) {
        [MBProgressHUD showText:@"请选择省市"];
        return NO;
    }
    return YES;
}

- (IBAction)buttonAction {
    if ([self handlerInputIsLegal]) {
        [self createChildAccount];
    }
}

- (UIDatePicker *)datePicker {
    if (!_datePicker) {
        _datePicker = [[UIDatePicker alloc] initWithFrame:CGRectMake(0, [ApplicationStyle screenHeight], [ApplicationStyle screenWidth], [ApplicationStyle screenWidth] *3/5)];
        _datePicker.backgroundColor = [UIColor whiteColor];
        _datePicker.timeZone = [NSTimeZone timeZoneForSecondsFromGMT:8];
        _datePicker.maximumDate = [NSDate date];
        _datePicker.datePickerMode = UIDatePickerModeDate;
        _datePicker.alpha = 0;
    }
    return _datePicker;
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

@end


text:
//  (C) Copyright Edward Diener 2011-2015
//  Use, modification and distribution are subject to the Boost Software License,
//  Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt).

#if !defined(BOOST_VMD_IS_NUMBER_HPP)
#define BOOST_VMD_IS_NUMBER_HPP

#include <boost/vmd/detail/setup.hpp>

#if BOOST_PP_VARIADICS

#include <boost/vmd/detail/is_number.hpp>

/*

  The succeeding comments in this file are in doxygen format.

*/

/** \file
*/

/** \def BOOST_VMD_IS_NUMBER(sequence)

    \brief Tests whether a sequence is a Boost PP number.

    The macro checks to see if a sequence is a Boost PP number.
    A Boost PP number is a value from 0 to 256.

    sequence = a possible number

    returns = 1 if the sequence is a Boost PP number,
              0 if it is not.

    If the input is not a VMD data type this macro could lead to
    a preprocessor error. This is because the macro
    uses preprocessor concatenation to determine if the input
    is a number once it is determined that the input does not
    start with parenthesis. If the data being concatenated would
    lead to an invalid preprocessor token the compiler can issue
    a preprocessor error.

*/

#define BOOST_VMD_IS_NUMBER(sequence) \
    BOOST_VMD_DETAIL_IS_NUMBER(sequence) \
/**/

#endif /* BOOST_PP_VARIADICS */
#endif /* BOOST_VMD_IS_NUMBER_HPP */


text:
package picard.util;

import java.io.File;
import java.io.InputStream;

public class CsvInputParser extends BasicInputParser {
    /**
     * Constructor
     *
     * @param stream  The input stream(s) to parse
     */
    public CsvInputParser(final boolean treatGroupedDelimitersAsOne, final InputStream... stream) {
        super(treatGroupedDelimitersAsOne, stream);
    }

    /**
     * Constructor
     *
     * @param file  The file(s) to parse
     */
    public CsvInputParser(final boolean treatGroupedDelimitersAsOne, final File... file) {
        super(treatGroupedDelimitersAsOne, file);
    }

    /**
     * Determines whether a given character is a delimiter
     *
     * @param b the character to evaluate
     * @return  true if b is a delimiter; otherwise false
     */
    @Override
    protected boolean isDelimiter(final byte b) {
        return b == ',';
    }

}