Tizen 2.1 base
[platform/core/uifw/ise-engine-sunpinyin.git] / src / slm / ids2ngram / ids2ngram.cpp
1 /*
2  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3  *
4  * Copyright (c) 2007 Sun Microsystems, Inc. All Rights Reserved.
5  *
6  * The contents of this file are subject to the terms of either the GNU Lesser
7  * General Public License Version 2.1 only ("LGPL") or the Common Development and
8  * Distribution License ("CDDL")(collectively, the "License"). You may not use this
9  * file except in compliance with the License. You can obtain a copy of the CDDL at
10  * http://www.opensource.org/licenses/cddl1.php and a copy of the LGPLv2.1 at
11  * http://www.opensource.org/licenses/lgpl-license.php. See the License for the
12  * specific language governing permissions and limitations under the License. When
13  * distributing the software, include this License Header Notice in each file and
14  * include the full text of the License in the License file as well as the
15  * following notice:
16  *
17  * NOTICE PURSUANT TO SECTION 9 OF THE COMMON DEVELOPMENT AND DISTRIBUTION LICENSE
18  * (CDDL)
19  * For Covered Software in this distribution, this License shall be governed by the
20  * laws of the State of California (excluding conflict-of-law provisions).
21  * Any litigation relating to this License shall be subject to the jurisdiction of
22  * the Federal Courts of the Northern District of California and the state courts
23  * of the State of California, with venue lying in Santa Clara County, California.
24  *
25  * Contributor(s):
26  *
27  * If you wish your version of this file to be governed by only the CDDL or only
28  * the LGPL Version 2.1, indicate your decision by adding "[Contributor]" elects to
29  * include this software in this distribution under the [CDDL or LGPL Version 2.1]
30  * license." If you don't indicate a single choice of license, a recipient has the
31  * option to distribute your version of this file under either the CDDL or the LGPL
32  * Version 2.1, or to extend the choice of license to its licensees as provided
33  * above. However, if you add LGPL Version 2.1 code and therefore, elected the LGPL
34  * Version 2 license, then the option applies only if the new code is made subject
35  * to such option by the copyright holder.
36  */
37
38 #ifdef HAVE_CONFIG_H
39 #include "config.h"
40 #endif
41
42 #ifdef HAVE_ASSERT_H
43 #include <assert.h>
44 #endif
45
46 #ifdef HAVE_GETOPT_H
47 #include <getopt.h>
48 #endif
49
50 #include <stdio.h>
51 #include <map>
52 #include <vector>
53 #include <algorithm>
54 #include <climits>
55
56 #include "../sim_fmerge.h"
57 #include "idngram.h"
58 #include "idngram_merge.h"
59
60 template<int N>
61 void
62 WriteOut(FILE* out, std::map<CSIM_Idngram<N>, unsigned int> & map)
63 {
64     typedef typename std::map<CSIM_Idngram<N>,
65                               unsigned int>::iterator TMapIterator;
66     TMapIterator its = map.begin(), ite = map.end();
67     for (; its != ite; ++its) {
68         fwrite(its->first.ids, sizeof(TSIMWordId), N, out);
69         fwrite(&(its->second), sizeof(unsigned int), 1, out);
70     }
71     map.clear();
72 }
73
74 template<int N>
75 void
76 ProcessingRead(FILE *fp,
77                FILE* swap,
78                std::vector<long>& para_offsets,
79                size_t paraMax)
80 {
81     typedef CSIM_Idngram<N> TNgram;
82     typedef typename std::map<CSIM_Idngram<N>, unsigned int> TMap;
83
84     TMap map;
85     TNgram ngram;
86
87     TSIMWordId* ids = ngram.ids;
88     fread(ids, sizeof(TSIMWordId), N - 1, fp);
89     while (fread(ids + N - 1, sizeof(TSIMWordId), 1, fp) == 1) {
90         assert(map[ngram] < UINT_MAX);
91         ++map[ngram];
92         if (map.size() >= paraMax) {
93             printf("."); fflush(stdout);
94             WriteOut(swap, map);
95             para_offsets.push_back(ftell(swap));
96         }
97         for (int i = 0; i < N - 1; ++i) ids[i] = ids[i + 1];
98     }
99     if (map.size() > 0) {
100         printf("."); fflush(stdout);
101         WriteOut(swap, map);
102         para_offsets.push_back(ftell(swap));
103     }
104 }
105
106 static struct option long_options[] =
107 {
108     { "NMax", 1, 0, 'n' },
109     { "out", 1, 0, 'o' },
110     { "swap", 1, 0, 's' },
111     { "para", 1, 0, 'p' },
112     { 0, 0, 0, 0 }
113 };
114
115 static int N = 0;
116 static int paraMax = 0;
117 static char* output = NULL;
118 static char* swapfile = NULL;
119
120 void
121 ShowUsage()
122 {
123     printf("Usage:\n\tids2ngram options idsfile[ idsfile...]\n");
124     printf("\nDescription\n");
125     printf(
126         "   This program generate idngram file, which is a sorted [id1,..idN,freq] array, from binary id stream files.\n");
127     printf("\nInput:\n");
128     printf("\tBinary id stream files looks like [id0,...,idX]\n");
129     printf("\nOptions:\n");
130     printf("\t  -n N               # N-gram\n");
131     printf("\t  -s swapfile        # intermedia temporary file\n");
132     printf(
133         "\t  -o outputfile      # result idngram file [id1, ... idN, freq]*\n");
134     printf("\t  -p para_size       # maxium ngram-items per para\n");
135     printf("\nExample:\n");
136     printf(
137         "   Following example will use three input idstream file idsfile[1,2,3] to generate the idngram file all.id3gram. Each para (internal map size or hash size) would be 1024000, using swap file for temp result. All temp para result would final be merged to got the final result.\n");
138     printf(
139         "\tids2idngram -n 3 -s /tmp/swap -o all.id3gram -p 1024000 idsfile1 idsfile2 idsfile3\n\n");
140     exit(100);
141 }
142
143 static void
144 getParameters(int argc, char* const argv[])
145 {
146     int option_index = 0;
147     int c;
148     while ((c =
149                 getopt_long(argc, argv, "p:n:s:o:", long_options,
150                             &option_index)) != -1) {
151         switch (c) {
152         case 'n':
153             N = atoi(strdup(optarg));
154             break;
155         case 'p':
156             paraMax = atoi(strdup(optarg));
157             break;
158         case 'o':
159             output = strdup(optarg);
160             break;
161         case 's':
162             swapfile = strdup(optarg);
163             break;
164         default:
165             ShowUsage();
166         }
167     }
168     if (N < 1 || N > 3 || paraMax < 1024 || output == NULL || swapfile == NULL)
169         ShowUsage();
170 }
171
172 static std::vector<long> para_offsets;
173
174 int
175 main(int argc, char* argv[])
176 {
177     getParameters(argc, argv);
178     FILE *swap = fopen(swapfile, "wb+");
179     FILE *out = fopen(output, "wb+");
180     if (optind >= argc) ShowUsage();
181     while (optind < argc) {
182         printf("Processing %s:", argv[optind]); fflush(stdout);
183         FILE *fp = fopen(argv[optind], "rb");
184         switch (N) {
185         case 1:
186             ProcessingRead<1>(fp, swap, para_offsets, paraMax);
187             break;
188         case 2:
189             ProcessingRead<2>(fp, swap, para_offsets, paraMax);
190             break;
191         case 3:
192             ProcessingRead<3>(fp, swap, para_offsets, paraMax);
193             break;
194         }
195         fclose(fp);
196         printf("\n"); fflush(stdout);
197         ++optind;
198     }
199     printf("Merging..."); fflush(stdout);
200     switch (N) {
201     case 1:
202         ProcessingIdngramMerge<1>(swap, out, para_offsets);
203         break;
204     case 2:
205         ProcessingIdngramMerge<2>(swap, out, para_offsets);
206         break;
207     case 3:
208         ProcessingIdngramMerge<3>(swap, out, para_offsets);
209         break;
210     }
211     printf("Done\n"); fflush(stdout);
212     fclose(out);
213     fclose(swap);
214     return 0;
215 }
216