diff options
author | Robin Rosenberg <robin.rosenberg@dewire.com> | 2012-04-02 17:59:34 -0400 |
---|---|---|
committer | Gerrit Code Review @ Eclipse.org <gerrit@eclipse.org> | 2012-04-02 17:59:34 -0400 |
commit | 86db05602fc8f42fd171df177fb9f4394a1b8ae5 (patch) | |
tree | 1c747acb7d4cdc13f0a27e6c8cbeae2ae2e491d1 | |
parent | 159533c4cf06f10ce1c86bd7e3d51a1eadaa0fc9 (diff) | |
parent | c0b1443926b001db2620b65103e4526b955a0897 (diff) | |
download | jgit-86db05602fc8f42fd171df177fb9f4394a1b8ae5.tar.gz jgit-86db05602fc8f42fd171df177fb9f4394a1b8ae5.zip |
Merge "Index config section and subsection names in one pass"
3 files changed, 137 insertions, 149 deletions
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/ConfigTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/ConfigTest.java index b9f62177cc..c764928771 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/ConfigTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/ConfigTest.java @@ -414,9 +414,9 @@ public class ConfigTest { names.contains("repositoryformatversion")); Iterator<String> itr = names.iterator(); - assertEquals("repositoryFormatVersion", itr.next()); assertEquals("filemode", itr.next()); assertEquals("logAllRefUpdates", itr.next()); + assertEquals("repositoryFormatVersion", itr.next()); assertFalse(itr.hasNext()); } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/Config.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/Config.java index 58a03bf8bf..1619b589c4 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/Config.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/Config.java @@ -52,14 +52,9 @@ package org.eclipse.jgit.lib; import java.text.MessageFormat; -import java.util.AbstractSet; import java.util.ArrayList; import java.util.Collections; -import java.util.Iterator; -import java.util.LinkedHashMap; -import java.util.LinkedHashSet; import java.util.List; -import java.util.Map; import java.util.Set; import java.util.concurrent.atomic.AtomicReference; @@ -479,17 +474,22 @@ public class Config { * section to search for. * @return set of all subsections of specified section within this * configuration and its base configuration; may be empty if no - * subsection exists. + * subsection exists. The set's iterator returns sections in the + * order they are declared by the configuration starting from this + * instance and progressing through the base. */ public Set<String> getSubsections(final String section) { - return get(new SubsectionNames(section)); + return getState().getSubsections(section); } /** - * @return the sections defined in this {@link Config} + * @return the sections defined in this {@link Config}. The set's iterator + * returns sections in the order they are declared by the + * configuration starting from this instance and progressing through + * the base. */ public Set<String> getSections() { - return get(new SectionNames()); + return getState().getSections(); } /** @@ -509,7 +509,7 @@ public class Config { * @return the list of names defined for this subsection */ public Set<String> getNames(String section, String subsection) { - return get(new NamesInSection(section, subsection)); + return getState().getNames(section, subsection); } /** @@ -1243,144 +1243,6 @@ public class Config { T parse(Config cfg); } - private static class SubsectionNames implements SectionParser<Set<String>> { - private final String section; - - SubsectionNames(final String sectionName) { - section = sectionName; - } - - public int hashCode() { - return section.hashCode(); - } - - public boolean equals(Object other) { - if (other instanceof SubsectionNames) { - return section.equals(((SubsectionNames) other).section); - } - return false; - } - - public Set<String> parse(Config cfg) { - final Set<String> result = new LinkedHashSet<String>(); - while (cfg != null) { - for (final ConfigLine e : cfg.state.get().entryList) { - if (e.subsection != null && e.name == null - && StringUtils.equalsIgnoreCase(section, e.section)) - result.add(e.subsection); - } - cfg = cfg.baseConfig; - } - return Collections.unmodifiableSet(result); - } - } - - private static class NamesInSection implements SectionParser<Set<String>> { - private final String section; - - private final String subsection; - - NamesInSection(final String sectionName, final String subSectionName) { - section = sectionName; - subsection = subSectionName; - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + section.hashCode(); - result = prime * result - + ((subsection == null) ? 0 : subsection.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - NamesInSection other = (NamesInSection) obj; - if (!section.equals(other.section)) - return false; - if (subsection == null) { - if (other.subsection != null) - return false; - } else if (!subsection.equals(other.subsection)) - return false; - return true; - } - - public Set<String> parse(Config cfg) { - final Map<String, String> m = new LinkedHashMap<String, String>(); - while (cfg != null) { - for (final ConfigLine e : cfg.state.get().entryList) { - if (e.name == null) - continue; - if (!StringUtils.equalsIgnoreCase(section, e.section)) - continue; - if ((subsection == null && e.subsection == null) - || (subsection != null && subsection - .equals(e.subsection))) { - String lc = StringUtils.toLowerCase(e.name); - if (!m.containsKey(lc)) - m.put(lc, e.name); - } - } - cfg = cfg.baseConfig; - } - return new CaseFoldingSet(m); - } - } - - private static class SectionNames implements SectionParser<Set<String>> { - public Set<String> parse(Config cfg) { - final Map<String, String> m = new LinkedHashMap<String, String>(); - while (cfg != null) { - for (final ConfigLine e : cfg.state.get().entryList) { - if (e.section != null) { - String lc = StringUtils.toLowerCase(e.section); - if (!m.containsKey(lc)) - m.put(lc, e.section); - } - } - cfg = cfg.baseConfig; - } - return new CaseFoldingSet(m); - } - } - - private static class CaseFoldingSet extends AbstractSet<String> { - private final Map<String, String> names; - - CaseFoldingSet(Map<String, String> names) { - this.names = Collections.unmodifiableMap(names); - } - - @Override - public boolean contains(Object needle) { - if (!(needle instanceof String)) - return false; - - String n = (String) needle; - return names.containsKey(n) - || names.containsKey(StringUtils.toLowerCase(n)); - } - - @Override - public Iterator<String> iterator() { - return names.values().iterator(); - } - - @Override - public int size() { - return names.size(); - } - } - private static class StringReader { private final char[] buf; diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/ConfigSnapshot.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/ConfigSnapshot.java index 5527267b86..cc5fe25e52 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/ConfigSnapshot.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/ConfigSnapshot.java @@ -52,19 +52,29 @@ package org.eclipse.jgit.lib; import static org.eclipse.jgit.util.StringUtils.compareIgnoreCase; import static org.eclipse.jgit.util.StringUtils.compareWithCase; +import static org.eclipse.jgit.util.StringUtils.toLowerCase; +import java.util.AbstractSet; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; +import java.util.HashMap; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.LinkedHashSet; import java.util.List; import java.util.Map; +import java.util.Set; import java.util.concurrent.ConcurrentHashMap; +import org.eclipse.jgit.util.StringUtils; + class ConfigSnapshot { final List<ConfigLine> entryList; final Map<Object, Object> cache; final ConfigSnapshot baseState; volatile List<ConfigLine> sorted; + volatile SectionNames names; ConfigSnapshot(List<ConfigLine> entries, ConfigSnapshot base) { entryList = entries; @@ -72,6 +82,40 @@ class ConfigSnapshot { baseState = base; } + Set<String> getSections() { + return names().sections; + } + + Set<String> getSubsections(String section) { + Map<String, Set<String>> m = names().subsections; + Set<String> r = m.get(section); + if (r == null) + r = m.get(toLowerCase(section)); + if (r == null) + return Collections.emptySet(); + return Collections.unmodifiableSet(r); + } + + Set<String> getNames(String section, String subsection) { + List<ConfigLine> s = sorted(); + int idx = find(s, section, subsection, ""); + if (idx < 0) + idx = -(idx + 1); + + Map<String, String> m = new LinkedHashMap<String, String>(); + while (idx < s.size()) { + ConfigLine e = s.get(idx++); + if (!e.match(section, subsection)) + break; + if (e.name == null) + continue; + String l = toLowerCase(e.name); + if (!m.containsKey(l)) + m.put(l, e.name); + } + return new CaseFoldingSet(m); + } + String[] get(String section, String subsection, String name) { List<ConfigLine> s = sorted(); int idx = find(s, section, subsection, name); @@ -167,4 +211,86 @@ class ConfigSnapshot { b.section, b.subsection, b.name); } } + + private SectionNames names() { + SectionNames n = names; + if (n == null) + names = n = new SectionNames(this); + return n; + } + + private static class SectionNames { + final CaseFoldingSet sections; + final Map<String, Set<String>> subsections; + + SectionNames(ConfigSnapshot cfg) { + Map<String, String> sec = new LinkedHashMap<String, String>(); + Map<String, Set<String>> sub = new HashMap<String, Set<String>>(); + while (cfg != null) { + for (ConfigLine e : cfg.entryList) { + if (e.section == null) + continue; + + String l1 = toLowerCase(e.section); + if (!sec.containsKey(l1)) + sec.put(l1, e.section); + + if (e.subsection == null) + continue; + + Set<String> m = sub.get(l1); + if (m == null) { + m = new LinkedHashSet<String>(); + sub.put(l1, m); + } + m.add(e.subsection); + } + cfg = cfg.baseState; + } + + sections = new CaseFoldingSet(sec); + subsections = sub; + } + } + + private static class CaseFoldingSet extends AbstractSet<String> { + private final Map<String, String> names; + + CaseFoldingSet(Map<String, String> names) { + this.names = names; + } + + @Override + public boolean contains(Object needle) { + if (needle instanceof String) { + String n = (String) needle; + return names.containsKey(n) + || names.containsKey(StringUtils.toLowerCase(n)); + } + return false; + } + + @Override + public Iterator<String> iterator() { + final Iterator<String> i = names.values().iterator(); + return new Iterator<String>() { + public boolean hasNext() { + return i.hasNext(); + } + + public String next() { + return i.next(); + } + + public void remove() { + throw new UnsupportedOperationException(); + } + }; + } + + @Override + public int size() { + return names.size(); + } + } } |