word_trimmer.cc revision 5d1f7b1de12d16ceb2c938c56701a3e8bfa558f7
1// Copyright (c) 2011 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "chrome/browser/spellchecker/word_trimmer.h"
6
7#include <algorithm>
8#include <vector>
9
10#include "base/i18n/break_iterator.h"
11
12base::string16 TrimWords(size_t* start,
13                         size_t end,
14                         const base::string16& text,
15                         size_t keep) {
16  if (*start > text.length() || *start > end)
17    return text;
18  base::i18n::BreakIterator iter(text, base::i18n::BreakIterator::BREAK_WORD);
19  if (!iter.Init())
20    return text;
21  // A circular buffer of the last |keep + 1| words seen before position |start|
22  // in |text|.
23  std::vector<size_t> word_offset(keep + 1, 0);
24  size_t first = std::string::npos;
25  size_t last = std::string::npos;
26  while (iter.Advance()) {
27    if (iter.IsWord()) {
28      word_offset[keep] = iter.prev();
29      if ((*start >= iter.prev() && *start < iter.pos()) ||
30          (end > iter.prev() && end <= iter.pos())) {
31        if (first == std::string::npos)
32          first = word_offset[0];
33        last = iter.pos();
34      }
35      if (first == std::string::npos) {
36        std::rotate(word_offset.begin(),
37                    word_offset.begin() + 1,
38                    word_offset.end());
39      }
40      if (iter.prev() > end && keep) {
41        last = iter.pos();
42        keep--;
43      }
44    }
45  }
46  if (first == std::string::npos)
47    return text;
48  *start -= first;
49  return text.substr(first, last - first);
50}
51