line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Tie::Google; |
2
|
|
|
|
|
|
|
|
3
|
|
|
|
|
|
|
# ---------------------------------------------------------------------- |
4
|
|
|
|
|
|
|
# $Id: Google.pm,v 1.3 2003/04/01 14:48:34 dlc Exp $ |
5
|
|
|
|
|
|
|
# ---------------------------------------------------------------------- |
6
|
|
|
|
|
|
|
# Apparently, a few people thought this would be a neat idea. |
7
|
|
|
|
|
|
|
# The initial email I recieved on the topic: |
8
|
|
|
|
|
|
|
# |
9
|
|
|
|
|
|
|
# From: Richard Soderberg |
10
|
|
|
|
|
|
|
# Date: Thu, 13 Feb 2003 10:42:07 -0500 |
11
|
|
|
|
|
|
|
# To: darren@cpan.org |
12
|
|
|
|
|
|
|
# Subject: Tie::Google? |
13
|
|
|
|
|
|
|
# |
14
|
|
|
|
|
|
|
# #perl found DBD::google recently. I thought I'd point out that there'd |
15
|
|
|
|
|
|
|
# also be a great market for Tie::Google. =) |
16
|
|
|
|
|
|
|
# |
17
|
|
|
|
|
|
|
# my @results; tie @results, 'Tie::Google', $KEY, $saerch_string; |
18
|
|
|
|
|
|
|
# do ... for my $result { grep { $_->{url} =~ /google.com/ } @results }; |
19
|
|
|
|
|
|
|
# |
20
|
|
|
|
|
|
|
# - R. |
21
|
|
|
|
|
|
|
# |
22
|
|
|
|
|
|
|
# To which I cavalierly responded with something ridiculous, like "OK". |
23
|
|
|
|
|
|
|
|
24
|
4
|
|
|
4
|
|
88434
|
use strict; |
|
4
|
|
|
|
|
10
|
|
|
4
|
|
|
|
|
176
|
|
25
|
4
|
|
|
4
|
|
21
|
use vars qw($VERSION $DEBUG $DEFAULT_BATCH_SIZE); |
|
4
|
|
|
|
|
7
|
|
|
4
|
|
|
|
|
324
|
|
26
|
|
|
|
|
|
|
|
27
|
4
|
|
|
4
|
|
22
|
use Carp qw(carp); |
|
4
|
|
|
|
|
13
|
|
|
4
|
|
|
|
|
348
|
|
28
|
4
|
|
|
4
|
|
10432
|
use Symbol qw(gensym); |
|
4
|
|
|
|
|
4295
|
|
|
4
|
|
|
|
|
289
|
|
29
|
4
|
|
|
4
|
|
7432
|
use Net::Google; |
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
30
|
|
|
|
|
|
|
|
31
|
|
|
|
|
|
|
# Offsets into the array-based object |
32
|
|
|
|
|
|
|
sub KEY() { 0 } # The user's API key |
33
|
|
|
|
|
|
|
sub TYPE() { 1 } # The tie type: SCALAR, ARRAY, HASH |
34
|
|
|
|
|
|
|
sub QUERY() { 2 } # The query terms |
35
|
|
|
|
|
|
|
sub OPTIONS() { 3 } # Options tied in |
36
|
|
|
|
|
|
|
sub DATA() { 4 } # Search results |
37
|
|
|
|
|
|
|
sub GOOGLE() { 5 } # Net::Google instance |
38
|
|
|
|
|
|
|
|
39
|
|
|
|
|
|
|
# Tie types that we support and have to differentiate between |
40
|
|
|
|
|
|
|
sub SCALAR() { 0 } |
41
|
|
|
|
|
|
|
sub ARRAY() { 1 } |
42
|
|
|
|
|
|
|
sub HASH() { 2 } |
43
|
|
|
|
|
|
|
|
44
|
|
|
|
|
|
|
$VERSION = 0.03; |
45
|
|
|
|
|
|
|
$DEFAULT_BATCH_SIZE = 10 unless defined $DEFAULT_BATCH_SIZE; |
46
|
|
|
|
|
|
|
$DEBUG = 0 unless defined $DEBUG; |
47
|
|
|
|
|
|
|
|
48
|
|
|
|
|
|
|
# tie constructors |
49
|
|
|
|
|
|
|
sub TIESCALAR { return shift->new(SCALAR, @_) } |
50
|
|
|
|
|
|
|
sub TIEARRAY { return shift->new(ARRAY, @_) } |
51
|
|
|
|
|
|
|
sub TIEHASH { return shift->new(HASH, @_) } |
52
|
|
|
|
|
|
|
|
53
|
|
|
|
|
|
|
# ---------------------------------------------------------------------- |
54
|
|
|
|
|
|
|
# new($TYPE, $KEY, $query) |
55
|
|
|
|
|
|
|
# |
56
|
|
|
|
|
|
|
# Create a new Tie::Google instance. This method should never be |
57
|
|
|
|
|
|
|
# called by outside facing code, only by the TIEFOO methods. |
58
|
|
|
|
|
|
|
# |
59
|
|
|
|
|
|
|
# A Tie::Google instance maintains a few pieces of information: |
60
|
|
|
|
|
|
|
# |
61
|
|
|
|
|
|
|
# 0. The API key of the user |
62
|
|
|
|
|
|
|
# |
63
|
|
|
|
|
|
|
# 1. The type of tie (SCALAR, ARRAY, HASH) |
64
|
|
|
|
|
|
|
# |
65
|
|
|
|
|
|
|
# 2. The query |
66
|
|
|
|
|
|
|
# |
67
|
|
|
|
|
|
|
# 3. Options passed in |
68
|
|
|
|
|
|
|
# |
69
|
|
|
|
|
|
|
# 4. The results of the query. |
70
|
|
|
|
|
|
|
# |
71
|
|
|
|
|
|
|
# 5. The Net::Google instace, created with the API key (item 0) |
72
|
|
|
|
|
|
|
# |
73
|
|
|
|
|
|
|
# The interesting things happen here in new. new must be passed a |
74
|
|
|
|
|
|
|
# type, a key, and a query. If the user is tieing a scalar ("I feel |
75
|
|
|
|
|
|
|
# lucky"), then we are only interested in the first element returned |
76
|
|
|
|
|
|
|
# by the search; if the user is tieing an array, then we want all of |
77
|
|
|
|
|
|
|
# the elements; if the user is tieing a hash, then we want all of the |
78
|
|
|
|
|
|
|
# elements of a number of searches. My "solution" (heh heh heh) is to |
79
|
|
|
|
|
|
|
# store all data in a hashref, indexed into the instance as DATA; if |
80
|
|
|
|
|
|
|
# the user is tieing an array or scalar (Tie::Google treats them |
81
|
|
|
|
|
|
|
# identically), then we store the results in the key named $KEY, so |
82
|
|
|
|
|
|
|
# that we can treat all types of ties consistently; otherwise, search |
83
|
|
|
|
|
|
|
# results are keyed by query. |
84
|
|
|
|
|
|
|
# ---------------------------------------------------------------------- |
85
|
|
|
|
|
|
|
sub new { |
86
|
|
|
|
|
|
|
my ($class, $type, $KEY, $query, $options) = @_; |
87
|
|
|
|
|
|
|
$options = { } unless defined $options && ref($options) eq 'HASH'; |
88
|
|
|
|
|
|
|
my $self = bless [ $KEY, $type, $query, $options, { }, undef, ] => $class; |
89
|
|
|
|
|
|
|
|
90
|
|
|
|
|
|
|
# Is $KEY actually a file? |
91
|
|
|
|
|
|
|
# I do this in DBD::google as well; perhaps there I should submit |
92
|
|
|
|
|
|
|
# a patch to Aaron so that Net::Google can do this directly. |
93
|
|
|
|
|
|
|
if (-e $KEY) { |
94
|
|
|
|
|
|
|
my $fh = gensym; |
95
|
|
|
|
|
|
|
open $fh, $KEY or die "Can't open keyfile $KEY for reading: $!"; |
96
|
|
|
|
|
|
|
chomp($KEY = <$fh>); |
97
|
|
|
|
|
|
|
close $fh or die "Can't close keyfile $KEY: $!"; |
98
|
|
|
|
|
|
|
|
99
|
|
|
|
|
|
|
$self->[KEY] = $KEY; |
100
|
|
|
|
|
|
|
} |
101
|
|
|
|
|
|
|
|
102
|
|
|
|
|
|
|
# Set some reasonable defaults search boundaries, and instantiate |
103
|
|
|
|
|
|
|
# the Net::Google instance. |
104
|
|
|
|
|
|
|
$options->{'starts_at'} = 0 unless defined $options->{'starts_at'}; |
105
|
|
|
|
|
|
|
$options->{'max_results'} ||= $DEFAULT_BATCH_SIZE; |
106
|
|
|
|
|
|
|
|
107
|
|
|
|
|
|
|
$self->[GOOGLE] = Net::Google->new(key => $self->[KEY], |
108
|
|
|
|
|
|
|
debug => $options->{'debug'} || 0); |
109
|
|
|
|
|
|
|
|
110
|
|
|
|
|
|
|
# * If called from TIEHASH, then store the results keyed by |
111
|
|
|
|
|
|
|
# search terms, otherwise keyed by $KEY |
112
|
|
|
|
|
|
|
# |
113
|
|
|
|
|
|
|
# * If called from TIESCALAR, we only want the first result. |
114
|
|
|
|
|
|
|
# |
115
|
|
|
|
|
|
|
# $self->[OPTIONS] contains starts_at and max_results. |
116
|
|
|
|
|
|
|
# |
117
|
|
|
|
|
|
|
if ($type == HASH) { |
118
|
|
|
|
|
|
|
$self->do_search($query, $query, |
119
|
|
|
|
|
|
|
$self->[OPTIONS]->{'starts_at'}, |
120
|
|
|
|
|
|
|
$self->[OPTIONS]->{'max_results'}); |
121
|
|
|
|
|
|
|
} |
122
|
|
|
|
|
|
|
elsif ($type == SCALAR) { |
123
|
|
|
|
|
|
|
$self->do_search($KEY, $query, 0, 1); |
124
|
|
|
|
|
|
|
} |
125
|
|
|
|
|
|
|
else { |
126
|
|
|
|
|
|
|
$self->do_search($KEY, $query, |
127
|
|
|
|
|
|
|
$self->[OPTIONS]->{'starts_at'}, |
128
|
|
|
|
|
|
|
$self->[OPTIONS]->{'max_results'}); |
129
|
|
|
|
|
|
|
} |
130
|
|
|
|
|
|
|
|
131
|
|
|
|
|
|
|
return $self; |
132
|
|
|
|
|
|
|
} |
133
|
|
|
|
|
|
|
|
134
|
|
|
|
|
|
|
# ---------------------------------------------------------------------- |
135
|
|
|
|
|
|
|
# do_search($store_as, $query) |
136
|
|
|
|
|
|
|
# |
137
|
|
|
|
|
|
|
# This is where all the Net::Google magic has to happen. |
138
|
|
|
|
|
|
|
# |
139
|
|
|
|
|
|
|
# do_search will use Net::Google to search for $query, and store the |
140
|
|
|
|
|
|
|
# results in $self->[DATA]->{$store_as}. |
141
|
|
|
|
|
|
|
# ---------------------------------------------------------------------- |
142
|
|
|
|
|
|
|
sub do_search { |
143
|
|
|
|
|
|
|
my ($self, $store_as, $query, $start, $num) = @_; |
144
|
|
|
|
|
|
|
|
145
|
|
|
|
|
|
|
# Preparation for the search |
146
|
|
|
|
|
|
|
# |
147
|
|
|
|
|
|
|
# do_search can conceivably be invoked with one argument, |
148
|
|
|
|
|
|
|
# in which case we use it both as search term and key into the |
149
|
|
|
|
|
|
|
# DATA hash. |
150
|
|
|
|
|
|
|
# |
151
|
|
|
|
|
|
|
# $start and $num will be taken from OPTIONS->{'starts_at'} and |
152
|
|
|
|
|
|
|
# OPTIONS->{'max_results'}, respectively, if they are not |
153
|
|
|
|
|
|
|
# provided. |
154
|
|
|
|
|
|
|
return unless $store_as; |
155
|
|
|
|
|
|
|
$query ||= $store_as; |
156
|
|
|
|
|
|
|
|
157
|
|
|
|
|
|
|
$start = $self->[OPTIONS]->{'starts_at'} |
158
|
|
|
|
|
|
|
unless defined $start; |
159
|
|
|
|
|
|
|
|
160
|
|
|
|
|
|
|
$num ||= $self->[OPTIONS]->{'max_results'}; |
161
|
|
|
|
|
|
|
|
162
|
|
|
|
|
|
|
# The search |
163
|
|
|
|
|
|
|
my $search = $self->[GOOGLE]->search(%{ $self->[OPTIONS] }); |
164
|
|
|
|
|
|
|
$search->query($query); |
165
|
|
|
|
|
|
|
$search->starts_at($start); |
166
|
|
|
|
|
|
|
$search->max_results($num); |
167
|
|
|
|
|
|
|
$self->[DATA]->{$store_as} = [ |
168
|
|
|
|
|
|
|
map { |
169
|
|
|
|
|
|
|
+{ title => $_->title(), |
170
|
|
|
|
|
|
|
URL => $_->URL(), |
171
|
|
|
|
|
|
|
snippet => $_->snippet(), |
172
|
|
|
|
|
|
|
cachedSize => $_->cachedSize(), |
173
|
|
|
|
|
|
|
directoryTitle => $_->directoryTitle(), |
174
|
|
|
|
|
|
|
summary => $_->summary(), |
175
|
|
|
|
|
|
|
hostName => $_->hostName(), |
176
|
|
|
|
|
|
|
directoryCategory => $_->directoryCategory(), |
177
|
|
|
|
|
|
|
} |
178
|
|
|
|
|
|
|
} @{ $search->results } |
179
|
|
|
|
|
|
|
]; |
180
|
|
|
|
|
|
|
} |
181
|
|
|
|
|
|
|
|
182
|
|
|
|
|
|
|
# ---------------------------------------------------------------------- |
183
|
|
|
|
|
|
|
# is_scalar(), is_array(), is_hash() |
184
|
|
|
|
|
|
|
# |
185
|
|
|
|
|
|
|
# Utility methods; is the object a tied scalar, tied array, or tied hash? |
186
|
|
|
|
|
|
|
# ---------------------------------------------------------------------- |
187
|
|
|
|
|
|
|
sub is_scalar { shift->[TYPE] == SCALAR } |
188
|
|
|
|
|
|
|
sub is_array { shift->[TYPE] == ARRAY } |
189
|
|
|
|
|
|
|
sub is_hash { shift->[TYPE] == HASH } |
190
|
|
|
|
|
|
|
|
191
|
|
|
|
|
|
|
# ---------------------------------------------------------------------- |
192
|
|
|
|
|
|
|
# FETCH() # scalar |
193
|
|
|
|
|
|
|
# FETCH($int) # array |
194
|
|
|
|
|
|
|
# FETCH($key) # hash |
195
|
|
|
|
|
|
|
# |
196
|
|
|
|
|
|
|
# In the case of a tied scalar or a tied array, the search should |
197
|
|
|
|
|
|
|
# already have been performed. In the case of a tied hash, that might |
198
|
|
|
|
|
|
|
# not necessarily be the case, so we might have to do a search. |
199
|
|
|
|
|
|
|
# |
200
|
|
|
|
|
|
|
# Needed by tied scalar, tied hash, and tied array implementations. |
201
|
|
|
|
|
|
|
# ---------------------------------------------------------------------- |
202
|
|
|
|
|
|
|
sub FETCH { |
203
|
|
|
|
|
|
|
my ($self, $index) = @_; |
204
|
|
|
|
|
|
|
$index = 0 unless defined $index; |
205
|
|
|
|
|
|
|
|
206
|
|
|
|
|
|
|
if ($self->is_hash) { |
207
|
|
|
|
|
|
|
$self->do_search($index, $index) |
208
|
|
|
|
|
|
|
unless exists $self->[DATA]->{$index}; |
209
|
|
|
|
|
|
|
|
210
|
|
|
|
|
|
|
return $self->[DATA]->{$index}; |
211
|
|
|
|
|
|
|
} |
212
|
|
|
|
|
|
|
|
213
|
|
|
|
|
|
|
return $self->[DATA]->{$self->[KEY]}->[$index]; |
214
|
|
|
|
|
|
|
|
215
|
|
|
|
|
|
|
} |
216
|
|
|
|
|
|
|
|
217
|
|
|
|
|
|
|
# ---------------------------------------------------------------------- |
218
|
|
|
|
|
|
|
# EXISTS($item) |
219
|
|
|
|
|
|
|
# |
220
|
|
|
|
|
|
|
# Returns true if this item exists in the instances search results: |
221
|
|
|
|
|
|
|
# |
222
|
|
|
|
|
|
|
# tie %g, "Tie::Google", $KEY, "perl"; |
223
|
|
|
|
|
|
|
# print exists $g{"perl"}; |
224
|
|
|
|
|
|
|
# |
225
|
|
|
|
|
|
|
# tie @g, "Tie::Google", $KEY, "perl"; |
226
|
|
|
|
|
|
|
# print exists $g[2]; # does this work? |
227
|
|
|
|
|
|
|
# |
228
|
|
|
|
|
|
|
# Needed for tied hash and tied array implementation. |
229
|
|
|
|
|
|
|
# ---------------------------------------------------------------------- |
230
|
|
|
|
|
|
|
sub EXISTS { |
231
|
|
|
|
|
|
|
my ($self, $index) = @_; |
232
|
|
|
|
|
|
|
|
233
|
|
|
|
|
|
|
return exists $self->[DATA]->{$index} |
234
|
|
|
|
|
|
|
if $self->is_hash; |
235
|
|
|
|
|
|
|
|
236
|
|
|
|
|
|
|
return exists $self->[DATA]->{$self->[KEY]}->[$index]; |
237
|
|
|
|
|
|
|
|
238
|
|
|
|
|
|
|
} |
239
|
|
|
|
|
|
|
|
240
|
|
|
|
|
|
|
# ---------------------------------------------------------------------- |
241
|
|
|
|
|
|
|
# CLEAR() |
242
|
|
|
|
|
|
|
# |
243
|
|
|
|
|
|
|
# Clears out the search results: |
244
|
|
|
|
|
|
|
# |
245
|
|
|
|
|
|
|
# tie @g, "Tie::Google", $KEY, "perl"; |
246
|
|
|
|
|
|
|
# @g = (); |
247
|
|
|
|
|
|
|
# |
248
|
|
|
|
|
|
|
# tie %g, "Tie::Google", $KEY, "perl"; |
249
|
|
|
|
|
|
|
# print $g{"apache"}; |
250
|
|
|
|
|
|
|
# print $g{"python"}; |
251
|
|
|
|
|
|
|
# %g = (); |
252
|
|
|
|
|
|
|
# |
253
|
|
|
|
|
|
|
# Needed by the tied hash and tied array interfaces. |
254
|
|
|
|
|
|
|
# ---------------------------------------------------------------------- |
255
|
|
|
|
|
|
|
sub CLEAR { |
256
|
|
|
|
|
|
|
my $self = shift; |
257
|
|
|
|
|
|
|
|
258
|
|
|
|
|
|
|
return %{$self->[DATA]} = () |
259
|
|
|
|
|
|
|
if $self->is_hash; |
260
|
|
|
|
|
|
|
|
261
|
|
|
|
|
|
|
return @{$self->[DATA]->{$self->[KEY]}} = (); |
262
|
|
|
|
|
|
|
} |
263
|
|
|
|
|
|
|
|
264
|
|
|
|
|
|
|
# ---------------------------------------------------------------------- |
265
|
|
|
|
|
|
|
# FIRSTKEY() |
266
|
|
|
|
|
|
|
# |
267
|
|
|
|
|
|
|
# Needed for each(%g). This implementation is taken from Tie::Hash. |
268
|
|
|
|
|
|
|
# |
269
|
|
|
|
|
|
|
# NOTE: This only iterates over keys that are _already defined_! It |
270
|
|
|
|
|
|
|
# _does not_ attempt to iterate over all of Google, or anything silly |
271
|
|
|
|
|
|
|
# like that. Although that would be great fun... |
272
|
|
|
|
|
|
|
# |
273
|
|
|
|
|
|
|
# Needed for tied hash implementation. |
274
|
|
|
|
|
|
|
# ---------------------------------------------------------------------- |
275
|
|
|
|
|
|
|
sub FIRSTKEY { |
276
|
|
|
|
|
|
|
my $self = shift; |
277
|
|
|
|
|
|
|
my $a = scalar keys %{$self->[DATA]}; |
278
|
|
|
|
|
|
|
each %{$self->[DATA]} |
279
|
|
|
|
|
|
|
} |
280
|
|
|
|
|
|
|
|
281
|
|
|
|
|
|
|
# ---------------------------------------------------------------------- |
282
|
|
|
|
|
|
|
# NEXTKEY() |
283
|
|
|
|
|
|
|
# |
284
|
|
|
|
|
|
|
# Needed for each(%g). This implementation is taken from Tie::Hash. |
285
|
|
|
|
|
|
|
# |
286
|
|
|
|
|
|
|
# See NOTE for FIRSTKEY. |
287
|
|
|
|
|
|
|
# |
288
|
|
|
|
|
|
|
# Needed for tied hash implementation. |
289
|
|
|
|
|
|
|
# ---------------------------------------------------------------------- |
290
|
|
|
|
|
|
|
sub NEXTKEY { |
291
|
|
|
|
|
|
|
my $self = shift; |
292
|
|
|
|
|
|
|
each %{$self->[DATA]} |
293
|
|
|
|
|
|
|
} |
294
|
|
|
|
|
|
|
|
295
|
|
|
|
|
|
|
# ---------------------------------------------------------------------- |
296
|
|
|
|
|
|
|
# DELETE($index) |
297
|
|
|
|
|
|
|
# |
298
|
|
|
|
|
|
|
# Remove an item from the search results list. |
299
|
|
|
|
|
|
|
# |
300
|
|
|
|
|
|
|
# Needed for tied hash and tied array implementation. |
301
|
|
|
|
|
|
|
# ---------------------------------------------------------------------- |
302
|
|
|
|
|
|
|
sub DELETE { |
303
|
|
|
|
|
|
|
my ($self, $index) = @_; |
304
|
|
|
|
|
|
|
|
305
|
|
|
|
|
|
|
return delete $self->[DATA]->{$index} |
306
|
|
|
|
|
|
|
if $self->is_hash; |
307
|
|
|
|
|
|
|
|
308
|
|
|
|
|
|
|
return delete $self->[DATA]->{$self->[KEY]}->{$index} |
309
|
|
|
|
|
|
|
if $self->is_array; |
310
|
|
|
|
|
|
|
} |
311
|
|
|
|
|
|
|
|
312
|
|
|
|
|
|
|
# ---------------------------------------------------------------------- |
313
|
|
|
|
|
|
|
# STORE($index, $value) |
314
|
|
|
|
|
|
|
# |
315
|
|
|
|
|
|
|
# Anyone calling this method either misunderstands Google or is |
316
|
|
|
|
|
|
|
# intentionally attempting to push the limits of this module. |
317
|
|
|
|
|
|
|
# |
318
|
|
|
|
|
|
|
# Nothing should be able to store anything here, right? |
319
|
|
|
|
|
|
|
# |
320
|
|
|
|
|
|
|
# NOTE: This means that these instances are effectively static once |
321
|
|
|
|
|
|
|
# they are initialized! |
322
|
|
|
|
|
|
|
# |
323
|
|
|
|
|
|
|
# Needed for tied scalar, tied array, and tied hash implementations. |
324
|
|
|
|
|
|
|
# ---------------------------------------------------------------------- |
325
|
|
|
|
|
|
|
sub STORE { carp("Misguided attempt to modify Google's database") } |
326
|
|
|
|
|
|
|
|
327
|
|
|
|
|
|
|
# ---------------------------------------------------------------------- |
328
|
|
|
|
|
|
|
# STORESIZE($count) |
329
|
|
|
|
|
|
|
# |
330
|
|
|
|
|
|
|
# Called when the user does: |
331
|
|
|
|
|
|
|
# |
332
|
|
|
|
|
|
|
# $#g = 100; |
333
|
|
|
|
|
|
|
# |
334
|
|
|
|
|
|
|
# If $count > current number of elements, then extend the search. |
335
|
|
|
|
|
|
|
# If $count < current number of elements, then drop some. |
336
|
|
|
|
|
|
|
# |
337
|
|
|
|
|
|
|
# Needed for tied array implementation. |
338
|
|
|
|
|
|
|
# ---------------------------------------------------------------------- |
339
|
|
|
|
|
|
|
sub STORESIZE { |
340
|
|
|
|
|
|
|
my ($self, $count) = @_; |
341
|
|
|
|
|
|
|
my $arr = $self->[DATA]->{$self->[KEY]}; |
342
|
|
|
|
|
|
|
my $cur_total = scalar @$arr; |
343
|
|
|
|
|
|
|
|
344
|
|
|
|
|
|
|
if ($count > $cur_total) { |
345
|
|
|
|
|
|
|
$self->do_search($self->[KEY], $self->[QUERY], 0, $count); |
346
|
|
|
|
|
|
|
} |
347
|
|
|
|
|
|
|
elsif ($count == $cur_total) { |
348
|
|
|
|
|
|
|
# la la la... |
349
|
|
|
|
|
|
|
} |
350
|
|
|
|
|
|
|
else { |
351
|
|
|
|
|
|
|
pop @$arr while @$arr > $count; |
352
|
|
|
|
|
|
|
} |
353
|
|
|
|
|
|
|
|
354
|
|
|
|
|
|
|
return $self->FETCHSIZE(); |
355
|
|
|
|
|
|
|
} |
356
|
|
|
|
|
|
|
|
357
|
|
|
|
|
|
|
# ---------------------------------------------------------------------- |
358
|
|
|
|
|
|
|
# FETCHSIZE() |
359
|
|
|
|
|
|
|
# |
360
|
|
|
|
|
|
|
# Needed for tied array implementation. |
361
|
|
|
|
|
|
|
# ---------------------------------------------------------------------- |
362
|
|
|
|
|
|
|
sub FETCHSIZE { |
363
|
|
|
|
|
|
|
my $self = shift; |
364
|
|
|
|
|
|
|
scalar @{$self->[DATA]->{$self->[KEY]}}; |
365
|
|
|
|
|
|
|
} |
366
|
|
|
|
|
|
|
|
367
|
|
|
|
|
|
|
# ---------------------------------------------------------------------- |
368
|
|
|
|
|
|
|
# EXTEND($size) |
369
|
|
|
|
|
|
|
# |
370
|
|
|
|
|
|
|
# Called when the user does: |
371
|
|
|
|
|
|
|
# |
372
|
|
|
|
|
|
|
# @g = 100; |
373
|
|
|
|
|
|
|
# |
374
|
|
|
|
|
|
|
# Needed for tied array implementation. |
375
|
|
|
|
|
|
|
# |
376
|
|
|
|
|
|
|
# XXX This implementation might not be right. |
377
|
|
|
|
|
|
|
# ---------------------------------------------------------------------- |
378
|
|
|
|
|
|
|
sub EXTEND { |
379
|
|
|
|
|
|
|
shift->STORESIZE(@_) |
380
|
|
|
|
|
|
|
} |
381
|
|
|
|
|
|
|
|
382
|
|
|
|
|
|
|
# ---------------------------------------------------------------------- |
383
|
|
|
|
|
|
|
# PUSH($item) |
384
|
|
|
|
|
|
|
# |
385
|
|
|
|
|
|
|
# Needed for tied array implementation. |
386
|
|
|
|
|
|
|
# ---------------------------------------------------------------------- |
387
|
|
|
|
|
|
|
sub PUSH { |
388
|
|
|
|
|
|
|
carp "Can't add results to Google's database -- do it the old " . |
389
|
|
|
|
|
|
|
"fashioned way, please!"; |
390
|
|
|
|
|
|
|
} |
391
|
|
|
|
|
|
|
|
392
|
|
|
|
|
|
|
# ---------------------------------------------------------------------- |
393
|
|
|
|
|
|
|
# POP() |
394
|
|
|
|
|
|
|
# |
395
|
|
|
|
|
|
|
# Removes the last search result from the list of results, and |
396
|
|
|
|
|
|
|
# returns it. |
397
|
|
|
|
|
|
|
# |
398
|
|
|
|
|
|
|
# Needed for tied array implementation. |
399
|
|
|
|
|
|
|
# ---------------------------------------------------------------------- |
400
|
|
|
|
|
|
|
sub POP { |
401
|
|
|
|
|
|
|
my $self = shift; |
402
|
|
|
|
|
|
|
pop @{$self->[DATA]->{$self->[KEY]}}; |
403
|
|
|
|
|
|
|
} |
404
|
|
|
|
|
|
|
|
405
|
|
|
|
|
|
|
# ---------------------------------------------------------------------- |
406
|
|
|
|
|
|
|
# SHIFT() |
407
|
|
|
|
|
|
|
# |
408
|
|
|
|
|
|
|
# Needed for tied array implementation. |
409
|
|
|
|
|
|
|
# ---------------------------------------------------------------------- |
410
|
|
|
|
|
|
|
sub SHIFT { |
411
|
|
|
|
|
|
|
my $self = shift; |
412
|
|
|
|
|
|
|
shift @{$self->[DATA]->{$self->[KEY]}}; |
413
|
|
|
|
|
|
|
} |
414
|
|
|
|
|
|
|
|
415
|
|
|
|
|
|
|
# ---------------------------------------------------------------------- |
416
|
|
|
|
|
|
|
# UNSHIFT($item) |
417
|
|
|
|
|
|
|
# |
418
|
|
|
|
|
|
|
# Needed for tied array implementation. |
419
|
|
|
|
|
|
|
# ---------------------------------------------------------------------- |
420
|
|
|
|
|
|
|
sub UNSHIFT { |
421
|
|
|
|
|
|
|
carp "Trying to stick your results into the head of Google's ". |
422
|
|
|
|
|
|
|
"list, eh? Shame on you!"; |
423
|
|
|
|
|
|
|
} |
424
|
|
|
|
|
|
|
|
425
|
|
|
|
|
|
|
# ---------------------------------------------------------------------- |
426
|
|
|
|
|
|
|
# SPLICE($offset, $limit, @list) |
427
|
|
|
|
|
|
|
# |
428
|
|
|
|
|
|
|
# Needed for tied array implementation. |
429
|
|
|
|
|
|
|
# ---------------------------------------------------------------------- |
430
|
|
|
|
|
|
|
sub SPLICE { |
431
|
|
|
|
|
|
|
my ($self, $offset, $limit) = @_; |
432
|
|
|
|
|
|
|
my $arr = $self->[DATA]->{$self->[KEY]}; |
433
|
|
|
|
|
|
|
|
434
|
|
|
|
|
|
|
if (@_ > 3) { |
435
|
|
|
|
|
|
|
carp "Can't modify search results this way. Please stuff ". |
436
|
|
|
|
|
|
|
"Google the old fashioned way."; |
437
|
|
|
|
|
|
|
return; |
438
|
|
|
|
|
|
|
} |
439
|
|
|
|
|
|
|
|
440
|
|
|
|
|
|
|
splice @$arr, $offset, $limit; |
441
|
|
|
|
|
|
|
} |
442
|
|
|
|
|
|
|
|
443
|
|
|
|
|
|
|
# ---------------------------------------------------------------------- |
444
|
|
|
|
|
|
|
# DESTROY() |
445
|
|
|
|
|
|
|
# |
446
|
|
|
|
|
|
|
# |
447
|
|
|
|
|
|
|
# Needed by the tied hash, tied array, and tied scalar interfaces. |
448
|
|
|
|
|
|
|
# ---------------------------------------------------------------------- |
449
|
|
|
|
|
|
|
sub DESTROY { } |
450
|
|
|
|
|
|
|
|
451
|
|
|
|
|
|
|
1; |
452
|
|
|
|
|
|
|
|
453
|
|
|
|
|
|
|
__END__ |