OpenShot Audio Library | OpenShotAudio: juce_StringPool.cpp Source File

OpenShot Audio Library | OpenShotAudio 0.3.1

Loading...
Searching...
No Matches
juce_StringPool.cpp
1/*
2 ==============================================================================
3
4 This file is part of the JUCE library.
5 Copyright (c) 2017 - ROLI Ltd.
6
7 JUCE is an open source library subject to commercial or open-source
8 licensing.
9
10 The code included in this file is provided under the terms of the ISC license
11 http://www.isc.org/downloads/software-support-policy/isc-license. Permission
12 To use, copy, modify, and/or distribute this software for any purpose with or
13 without fee is hereby granted provided that the above copyright notice and
14 this permission notice appear in all copies.
15
16 JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
17 EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
18 DISCLAIMED.
19
20 ==============================================================================
21*/
22
23namespace juce
24{
25
26static const int minNumberOfStringsForGarbageCollection = 300;
27static const uint32 garbageCollectionInterval = 30000;
28
29
30StringPool::StringPool() noexcept : lastGarbageCollectionTime (0) {}
31StringPool::~StringPool() {}
32
33struct StartEndString
34{
35 StartEndString (String::CharPointerType s, String::CharPointerType e) noexcept : start (s), end (e) {}
36 operator String() const { return String (start, end); }
37
38 String::CharPointerType start, end;
39};
40
41static int compareStrings (const String& s1, const String& s2) noexcept { return s1.compare (s2); }
42static int compareStrings (CharPointer_UTF8 s1, const String& s2) noexcept { return s1.compare (s2.getCharPointer()); }
43
44static int compareStrings (const StartEndString& string1, const String& string2) noexcept
45{
46 String::CharPointerType s1 (string1.start), s2 (string2.getCharPointer());
47
48 for (;;)
49 {
50 const int c1 = s1 < string1.end ? (int) s1.getAndAdvance() : 0;
51 const int c2 = (int) s2.getAndAdvance();
52 const int diff = c1 - c2;
53
54 if (diff != 0) return diff < 0 ? -1 : 1;
55 if (c1 == 0) break;
56 }
57
58 return 0;
59}
60
61template <typename NewStringType>
62static String addPooledString (Array<String>& strings, const NewStringType& newString)
63{
64 int start = 0;
65 int end = strings.size();
66
67 while (start < end)
68 {
69 const String& startString = strings.getReference (start);
70 const int startComp = compareStrings (newString, startString);
71
72 if (startComp == 0)
73 return startString;
74
75 const int halfway = (start + end) / 2;
76
77 if (halfway == start)
78 {
79 if (startComp > 0)
80 ++start;
81
82 break;
83 }
84
85 const String& halfwayString = strings.getReference (halfway);
86 const int halfwayComp = compareStrings (newString, halfwayString);
87
88 if (halfwayComp == 0)
89 return halfwayString;
90
91 if (halfwayComp > 0)
92 start = halfway;
93 else
94 end = halfway;
95 }
96
97 strings.insert (start, newString);
98 return strings.getReference (start);
99}
100
101 String StringPool::getPooledString (const char* const newString)
102{
103 if (newString == nullptr || *newString == 0)
104 return {};
105
106 const ScopedLock sl (lock);
107 garbageCollectIfNeeded();
108 return addPooledString (strings, CharPointer_UTF8 (newString));
109}
110
111 String StringPool::getPooledString (String::CharPointerType start, String::CharPointerType end)
112{
113 if (start.isEmpty() || start == end)
114 return {};
115
116 const ScopedLock sl (lock);
117 garbageCollectIfNeeded();
118 return addPooledString (strings, StartEndString (start, end));
119}
120
121 String StringPool::getPooledString (StringRef newString)
122{
123 if (newString.isEmpty())
124 return {};
125
126 const ScopedLock sl (lock);
127 garbageCollectIfNeeded();
128 return addPooledString (strings, newString.text);
129}
130
131 String StringPool::getPooledString (const String& newString)
132{
133 if (newString.isEmpty())
134 return {};
135
136 const ScopedLock sl (lock);
137 garbageCollectIfNeeded();
138 return addPooledString (strings, newString);
139}
140
141void StringPool::garbageCollectIfNeeded()
142{
143 if (strings.size() > minNumberOfStringsForGarbageCollection
144 && Time::getApproximateMillisecondCounter() > lastGarbageCollectionTime + garbageCollectionInterval)
145 garbageCollect();
146}
147
148 void StringPool::garbageCollect()
149{
150 const ScopedLock sl (lock);
151
152 for (int i = strings.size(); --i >= 0;)
153 if (strings.getReference(i).getReferenceCount() == 1)
154 strings.remove (i);
155
156 lastGarbageCollectionTime = Time::getApproximateMillisecondCounter();
157}
158
159 StringPool& StringPool::getGlobalPool() noexcept
160{
161 static StringPool pool;
162 return pool;
163}
164
165} // namespace juce
juce::CharPointer_UTF8
Definition: juce_CharPointer_UTF8.h:35
juce::GenericScopedLock
Definition: juce_ScopedLock.h:55
juce::StringPool
Definition: juce_StringPool.h:40
juce::StringPool::getPooledString
String getPooledString(const String &original)
Definition: juce_StringPool.cpp:131
juce::StringPool::StringPool
StringPool() noexcept
Definition: juce_StringPool.cpp:30
juce::StringPool::getGlobalPool
static StringPool & getGlobalPool() noexcept
Definition: juce_StringPool.cpp:159
juce::StringPool::garbageCollect
void garbageCollect()
Definition: juce_StringPool.cpp:148
juce::StringPool::~StringPool
~StringPool()
Definition: juce_StringPool.cpp:31
juce::StringRef
Definition: juce_StringRef.h:62
juce::StringRef::text
String::CharPointerType text
Definition: juce_StringRef.h:130
juce::StringRef::isEmpty
bool isEmpty() const noexcept
Definition: juce_StringRef.h:101
juce::String
Definition: juce_String.h:39
juce::String::isEmpty
bool isEmpty() const noexcept
Definition: juce_String.h:296
juce::Time::getApproximateMillisecondCounter
static uint32 getApproximateMillisecondCounter() noexcept
Definition: juce_Time.cpp:246