1/*
2 * Copyright (C) 2009 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "../include/utf16reader.h"
18
19namespace ime_pinyin {
20
21#define MIN_BUF_LEN 128
22#define MAX_BUF_LEN 65535
23
24Utf16Reader::Utf16Reader() {
25  fp_ = NULL;
26  buffer_ = NULL;
27  buffer_total_len_ = 0;
28  buffer_next_pos_ = 0;
29  buffer_valid_len_ = 0;
30}
31
32Utf16Reader::~Utf16Reader() {
33  if (NULL != fp_)
34    fclose(fp_);
35
36  if (NULL != buffer_)
37    delete [] buffer_;
38}
39
40
41bool Utf16Reader::open(const char* filename, size_t buffer_len) {
42  if (filename == NULL)
43    return false;
44
45  if (buffer_len < MIN_BUF_LEN)
46    buffer_len = MIN_BUF_LEN;
47  else if (buffer_len > MAX_BUF_LEN)
48    buffer_len = MAX_BUF_LEN;
49
50  buffer_total_len_ = buffer_len;
51
52  if (NULL != buffer_)
53    delete [] buffer_;
54  buffer_ = new char16[buffer_total_len_];
55  if (NULL == buffer_)
56    return false;
57
58  if ((fp_ = fopen(filename, "rb")) == NULL)
59    return false;
60
61  // the UTF16 file header, skip
62  char16 header;
63  if (fread(&header, sizeof(header), 1, fp_) != 1 || header != 0xfeff) {
64    fclose(fp_);
65    fp_ = NULL;
66    return false;
67  }
68
69  return true;
70}
71
72char16* Utf16Reader::readline(char16* read_buf, size_t max_len) {
73  if (NULL == fp_ || NULL == read_buf || 0 == max_len)
74    return NULL;
75
76  size_t ret_len = 0;
77
78  do {
79    if (buffer_valid_len_ == 0) {
80      buffer_next_pos_ = 0;
81      buffer_valid_len_ = fread(buffer_, sizeof(char16),
82                                buffer_total_len_, fp_);
83      if (buffer_valid_len_ == 0) {
84        if (0 == ret_len)
85          return NULL;
86        read_buf[ret_len] = (char16)'\0';
87        return read_buf;
88      }
89    }
90
91    for (size_t i = 0; i < buffer_valid_len_; i++) {
92      if (i == max_len - 1 ||
93          buffer_[buffer_next_pos_ + i] == (char16)'\n') {
94        if (ret_len + i > 0 && read_buf[ret_len + i - 1] == (char16)'\r') {
95          read_buf[ret_len + i - 1] = (char16)'\0';
96        } else {
97          read_buf[ret_len + i] = (char16)'\0';
98        }
99
100        i++;
101        buffer_next_pos_ += i;
102        buffer_valid_len_ -= i;
103        if (buffer_next_pos_ == buffer_total_len_) {
104          buffer_next_pos_ = 0;
105          buffer_valid_len_ = 0;
106        }
107        return read_buf;
108      } else {
109        read_buf[ret_len + i] = buffer_[buffer_next_pos_ + i];
110      }
111    }
112
113    ret_len += buffer_valid_len_;
114    buffer_valid_len_ = 0;
115  } while (true);
116
117  // Never reach here
118  return NULL;
119}
120
121bool Utf16Reader::close() {
122  if (NULL != fp_)
123    fclose(fp_);
124  fp_ = NULL;
125
126  if (NULL != buffer_)
127    delete [] buffer_;
128  buffer_ = NULL;
129  return true;
130}
131}  // namespace ime_pinyin
132