fapyc 0.7.2__cp313-cp313-win_amd64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- fapyc/__init__.py +166 -0
- fapyc/_fapyc.cp313-win_amd64.pyd +0 -0
- fapyc/include/fapec_comp.h +224 -0
- fapyc/include/fapec_decomp.h +435 -0
- fapyc/include/fapec_opts.h +873 -0
- fapyc/lib/FapecCompress.dll +0 -0
- fapyc/lib/FapecCompress.lib +0 -0
- fapyc/lib/FapecDecompress.dll +0 -0
- fapyc/lib/FapecDecompress.lib +0 -0
- fapyc/lib/libFapecCompress.so +0 -0
- fapyc/lib/libFapecDecompress.so +0 -0
- fapyc-0.7.2.dist-info/LICENSE +120 -0
- fapyc-0.7.2.dist-info/METADATA +534 -0
- fapyc-0.7.2.dist-info/RECORD +17 -0
- fapyc-0.7.2.dist-info/WHEEL +5 -0
- fapyc-0.7.2.dist-info/entry_points.txt +3 -0
- fapyc-0.7.2.dist-info/top_level.txt +1 -0
fapyc/__init__.py
ADDED
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
# Copyright (C) DAPCOM Data Services S.L. - http://www.dapcom.es
|
|
2
|
+
# Contact: fapec@dapcom.es
|
|
3
|
+
#
|
|
4
|
+
# This wrapper has been prepared by DAPCOM
|
|
5
|
+
# for potential customers willing to use FAPEC in
|
|
6
|
+
# their Python code.
|
|
7
|
+
# It can be freely distributed and modified as needed,
|
|
8
|
+
# but this notice must be kept.
|
|
9
|
+
# Commercial use is only permitted if an adequate FAPEC
|
|
10
|
+
# license is acquired.
|
|
11
|
+
#
|
|
12
|
+
|
|
13
|
+
import sys
|
|
14
|
+
|
|
15
|
+
if sys.platform == "win32":
|
|
16
|
+
import os
|
|
17
|
+
lib_path = os.path.join(os.path.dirname(__file__), "lib")
|
|
18
|
+
if (sys.version_info[1] >= 8):
|
|
19
|
+
os.add_dll_directory(lib_path)
|
|
20
|
+
else:
|
|
21
|
+
os.environ['PATH'] = lib_path + os.pathsep + os.environ['PATH']
|
|
22
|
+
|
|
23
|
+
from ._fapyc import *
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def fapyc_entrypoint():
|
|
30
|
+
arguments = sys.argv
|
|
31
|
+
if (len(arguments) == 1):
|
|
32
|
+
print("Usage: fapyc {-ow} {-mt <t>} {-o <fn>} <file/dir>")
|
|
33
|
+
print(" -o <fn> Specify output file name.")
|
|
34
|
+
print(" -ow Overwrite existing output file(s) without asking")
|
|
35
|
+
print(" -mt <t> Force multithread setting (1-16, default=auto)")
|
|
36
|
+
else:
|
|
37
|
+
i = 0
|
|
38
|
+
array_n = len(arguments)
|
|
39
|
+
overwrite = False
|
|
40
|
+
threads = -1
|
|
41
|
+
# Take the input file
|
|
42
|
+
filename = arguments[-1]
|
|
43
|
+
# Default output file
|
|
44
|
+
output_file = filename + ".fapec"
|
|
45
|
+
# First take the options
|
|
46
|
+
while (i < array_n):
|
|
47
|
+
# Activate overwrite without asking
|
|
48
|
+
if (arguments[i] == "-ow"):
|
|
49
|
+
overwrite = True
|
|
50
|
+
i = i + 1
|
|
51
|
+
continue
|
|
52
|
+
# Multithread setting
|
|
53
|
+
if (arguments[i] == "-mt"):
|
|
54
|
+
# Do we have a numerical value with the argument?
|
|
55
|
+
if ((i+1) < array_n and arguments[i + 1].isnumeric()):
|
|
56
|
+
threads = int(arguments[i + 1])
|
|
57
|
+
# Step two indexes instead of 1
|
|
58
|
+
i = i + 2
|
|
59
|
+
continue
|
|
60
|
+
else:
|
|
61
|
+
print("No valid number of threads value.")
|
|
62
|
+
exit(1)
|
|
63
|
+
# Output file name
|
|
64
|
+
if (arguments[i] == "-o"):
|
|
65
|
+
if ((i+1) < array_n):
|
|
66
|
+
output_file = arguments[i+1]
|
|
67
|
+
i = i + 2
|
|
68
|
+
continue
|
|
69
|
+
else:
|
|
70
|
+
print("No valid output file name.")
|
|
71
|
+
exit(1)
|
|
72
|
+
i = i + 1
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
from fapyc import Fapyc
|
|
76
|
+
fp = Fapyc(filename = filename)
|
|
77
|
+
|
|
78
|
+
fp.fapyc_set_askOverwrite(not overwrite)
|
|
79
|
+
fp.fapyc_set_nthreads(threads)
|
|
80
|
+
|
|
81
|
+
fp.compress_auto(output = output_file)
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
def unfapyc_entrypoint():
|
|
90
|
+
arguments = sys.argv
|
|
91
|
+
if (len(arguments) == 1):
|
|
92
|
+
print("Usage: unfapyc {-ow} {-mt <t>} {-list} {-part <i>} {-o <fn>} <file.fapec>")
|
|
93
|
+
print(" -ow Overwrite existing output file(s) without asking")
|
|
94
|
+
print(" -mt <t> Force multithread setting (1-16, default=auto)")
|
|
95
|
+
print(" -list Only list the .fapec file contents")
|
|
96
|
+
print(" -part <i> Decompress one part, give it by the index.")
|
|
97
|
+
print(" -o <fn> Specify output file name.")
|
|
98
|
+
else:
|
|
99
|
+
i = 0
|
|
100
|
+
array_n = len(arguments)
|
|
101
|
+
output_file = "."
|
|
102
|
+
overwrite = False
|
|
103
|
+
threads = -1
|
|
104
|
+
show_list = False
|
|
105
|
+
part = -1
|
|
106
|
+
#Take the fapec file
|
|
107
|
+
fapec_file = arguments[-1]
|
|
108
|
+
# First take the options
|
|
109
|
+
while (i < array_n):
|
|
110
|
+
# Activate overwrite without asking
|
|
111
|
+
if (arguments[i] == "-ow"):
|
|
112
|
+
overwrite = True
|
|
113
|
+
i = i + 1
|
|
114
|
+
continue
|
|
115
|
+
if (arguments[i] == "-mt"):
|
|
116
|
+
# Do we have a numerical value with the argument?
|
|
117
|
+
if ((i+1) < array_n and arguments[i + 1].isnumeric()):
|
|
118
|
+
threads = int(arguments[i + 1])
|
|
119
|
+
# Is the numerical value between 1 and 16?
|
|
120
|
+
if (threads >= 1 and threads <= 16):
|
|
121
|
+
# Step two indexes instead of 1
|
|
122
|
+
i = i + 2
|
|
123
|
+
continue
|
|
124
|
+
else:
|
|
125
|
+
print("The number of threads must be between 1 and 16.")
|
|
126
|
+
exit(1)
|
|
127
|
+
else:
|
|
128
|
+
print("No valid number of threads value.")
|
|
129
|
+
exit(1)
|
|
130
|
+
if (arguments[i] == "-list"):
|
|
131
|
+
show_list = True
|
|
132
|
+
break
|
|
133
|
+
if (arguments[i] == "-part"):
|
|
134
|
+
# Do we have a numerical value with the argument?
|
|
135
|
+
if ((i+1) < array_n and arguments[i + 1].isnumeric()):
|
|
136
|
+
part = int(arguments[i + 1])
|
|
137
|
+
i = i + 2
|
|
138
|
+
continue
|
|
139
|
+
else:
|
|
140
|
+
print("Invalid number part")
|
|
141
|
+
exit(1)
|
|
142
|
+
# Output file name
|
|
143
|
+
if (arguments[i] == "-o"):
|
|
144
|
+
if ((i+1) < array_n):
|
|
145
|
+
output_file = arguments[i+1]
|
|
146
|
+
i = i + 2
|
|
147
|
+
continue
|
|
148
|
+
else:
|
|
149
|
+
print("No valid output file name.")
|
|
150
|
+
exit(1)
|
|
151
|
+
#No valid argument
|
|
152
|
+
i = i + 1
|
|
153
|
+
from fapyc import Unfapyc
|
|
154
|
+
uf = Unfapyc(filename = fapec_file)
|
|
155
|
+
uf.fapyc_set_askOverwrite(not overwrite)
|
|
156
|
+
uf.fapyc_set_nthreads(threads)
|
|
157
|
+
# Get the number of parts in the file
|
|
158
|
+
nparts = uf.fapyc_get_farch_num_parts()
|
|
159
|
+
n = range(nparts)
|
|
160
|
+
# Get the name of the parts
|
|
161
|
+
if show_list:
|
|
162
|
+
for part_i in n:
|
|
163
|
+
pname = uf.fapyc_get_part_name(part_i)
|
|
164
|
+
print("Part: " + str(part_i) + " Name: " + pname)
|
|
165
|
+
exit(0)
|
|
166
|
+
uf.decompress(partindex = part, output = output_file)
|
|
Binary file
|
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
/****************************************************************************
|
|
2
|
+
* FAPEC - Fully Adaptive Prediction Error Coder *
|
|
3
|
+
* (c) DAPCOM Data Services S.L. - http://www.dapcom.es *
|
|
4
|
+
* Entropy coding core patent: US20120166503 A1, 28-June-2012, *
|
|
5
|
+
* "Method for fully adaptive calibration of a prediction error coder". *
|
|
6
|
+
* Contact: jordi.portell@dapcom.es / fapec@dapcom.es *
|
|
7
|
+
****************************************************************************
|
|
8
|
+
* This software is property of DAPCOM Data Services S.L. *
|
|
9
|
+
* This C header file and the associated binary (compiled) libraries are *
|
|
10
|
+
* subject to the license terms you should have received. *
|
|
11
|
+
* In particular, it is prohibited to install, use, integrate in another *
|
|
12
|
+
* software or hardware system, or create derivative works, except as *
|
|
13
|
+
* explicitly allowed by the license terms or by DAPCOM. *
|
|
14
|
+
* It is prohibited to copy, distribute, modify, sublicense, lease, rent, *
|
|
15
|
+
* loan, sell or reverse engineer without explicit permission of DAPCOM. *
|
|
16
|
+
****************************************************************************/
|
|
17
|
+
|
|
18
|
+
/****************************************************************************
|
|
19
|
+
* FAPEC - high-performance professional data compressor and archiver.
|
|
20
|
+
*
|
|
21
|
+
* @file fapec_comp.h:
|
|
22
|
+
*
|
|
23
|
+
* @brief Definition of the main compression functions.
|
|
24
|
+
*
|
|
25
|
+
* FAPEC can be invoked at different levels:
|
|
26
|
+
* - File: similar to invoking the command-line compressor. It takes care of
|
|
27
|
+
* all the headers (metadata) generation, "multi-parts" if applicable
|
|
28
|
+
* (in FAPEC one "part" corresponds to one file and one given compression
|
|
29
|
+
* setup), chunking, multi-thread if requested, etc.
|
|
30
|
+
* It allows compressing directory trees or several files in a directory,
|
|
31
|
+
* if the input parameters request so. It can also be used for compressing
|
|
32
|
+
* just one single file, of course.
|
|
33
|
+
* This is the most "self-contained" case (all metadata automatically
|
|
34
|
+
* handled by FAPEC).
|
|
35
|
+
* - Buffer: equivalent to the File case for just 1 single file.
|
|
36
|
+
* The buffer will be self-contained regarding compression options
|
|
37
|
+
* (unless explicitly deactivated).
|
|
38
|
+
* - Chunk: This is the most basic invocation level for FAPEC; it is the
|
|
39
|
+
* core compression method. Please handle with care: here you need to take
|
|
40
|
+
* care of "chunking" and metadata yourself. That is: a compressed chunk
|
|
41
|
+
* won't be completely self-contained (you'll need to know and provide the
|
|
42
|
+
* compression options when decompressing it). And you need to take care
|
|
43
|
+
* of eventual "chunking" when compressing large buffers or files: you can
|
|
44
|
+
* handle up to 384MB at once, in a single chunk, but preferably you should
|
|
45
|
+
* split it in smaller chunks (typ. 1-16MB). Finally, in some cases
|
|
46
|
+
* (such as KWCD/KMALL, Tab/CSV or FastQ) you should make sure to provide
|
|
47
|
+
* "aligned" chunks (each starting at the actual start of a meaningful data
|
|
48
|
+
* block) to get better compression performance.
|
|
49
|
+
* Here we provide functions to compress from disk to disk (file),
|
|
50
|
+
* from (self-contained) buffer to buffer, from buffer to file, and
|
|
51
|
+
* from raw chunk to compressed chunk.
|
|
52
|
+
****************************************************************************/
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
#ifndef _FAPEC_COMPRESSOR_H_
|
|
56
|
+
#define _FAPEC_COMPRESSOR_H_
|
|
57
|
+
|
|
58
|
+
#include <stdlib.h>
|
|
59
|
+
#include "fapec_opts.h"
|
|
60
|
+
|
|
61
|
+
/* Visibility options */
|
|
62
|
+
#ifndef _WIN32
|
|
63
|
+
#define LINUX_VISIBILITY __attribute__ ((visibility("default")))
|
|
64
|
+
#define WINDOWS_VISIBILITY
|
|
65
|
+
#else
|
|
66
|
+
#define LINUX_VISIBILITY
|
|
67
|
+
#ifdef F_LIB
|
|
68
|
+
#define WINDOWS_VISIBILITY __declspec(dllexport)
|
|
69
|
+
#else
|
|
70
|
+
#define WINDOWS_VISIBILITY
|
|
71
|
+
#endif
|
|
72
|
+
#endif
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Memory-based single-buffer (chunk) compression function
|
|
78
|
+
*
|
|
79
|
+
* It takes the buffer "buff" of size "buffSize" bytes,
|
|
80
|
+
* compresses it with "cmpCfg" configuration (see e.g. fapec_cmpopts_new)
|
|
81
|
+
* and "userOpts" options (see fapec_usropts_new_ck),
|
|
82
|
+
* and returns the compressed buffer in the same "buff" parameter
|
|
83
|
+
* (updating "buffSize" with the compressed buffer size in bytes).
|
|
84
|
+
* It returns zero (or a positive value to indicate some
|
|
85
|
+
* information from the compression) in case of success,
|
|
86
|
+
* or -1 (or another negative value) to indicate a non-successful compression.
|
|
87
|
+
* The user does not have to worry about the buffer allocated in "buff": the
|
|
88
|
+
* routine frees the available pointer there and allocates a new one for
|
|
89
|
+
* the compressed results. It means that such returned buffer must be freed by
|
|
90
|
+
* the user.
|
|
91
|
+
*
|
|
92
|
+
* @param buff Pointer to the buffer with the raw data to be compressed.
|
|
93
|
+
* It will be updated to point to the new buffer with
|
|
94
|
+
* compressed data.
|
|
95
|
+
* @param buffSize Original (raw, uncompressed) size of the buffer. It will
|
|
96
|
+
* be updated to the compressed size.
|
|
97
|
+
* @param userOpts User/runtime options.
|
|
98
|
+
* @param cmpCfg FAPEC compression configuration.
|
|
99
|
+
* @return Zero if successul, 2 if the buffer could not be compressed (in
|
|
100
|
+
* which case the original buffer and size will be returned),
|
|
101
|
+
* negative in case of errors.
|
|
102
|
+
*/
|
|
103
|
+
WINDOWS_VISIBILITY int fapec_compress_chunk(unsigned char **buff, size_t *buffSize,
|
|
104
|
+
int userOpts, void *cmpCfg) LINUX_VISIBILITY;
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Memory-based input+output buffer (chunk) compression function
|
|
109
|
+
*
|
|
110
|
+
* It takes the buffer "inBuff" of size "inBuffSize" bytes,
|
|
111
|
+
* compresses it with "cmpCfg" configuration (see e.g. fapec_cmpopts_new)
|
|
112
|
+
* and "userOpts" options (see fapec_usropts_new_ck),
|
|
113
|
+
* and returns the compressed buffer into the PRE-ALLOCATED "outBuff" parameter
|
|
114
|
+
* (setting "outBuffSize" to the compressed buffer size in bytes).
|
|
115
|
+
* IMPORTANT: outBuff must be preallocated with at least 1.2 x inBuffSize.
|
|
116
|
+
* The value of *outBuffSize does not mind at all.
|
|
117
|
+
* It returns zero (or a positive value to indicate some
|
|
118
|
+
* information from the compression) in case of success,
|
|
119
|
+
* or -1 (or another negative value) to indicate a non-successful compression.
|
|
120
|
+
* Compared to fapec_compress_chunk(), this function is a bit more efficient
|
|
121
|
+
* when we can reuse memory buffers (we avoid the need of allocating+freeing
|
|
122
|
+
* them for every chunk). That is specially interesting when dealing with
|
|
123
|
+
* tiny chunks.
|
|
124
|
+
* Actually, fapec_compress_chunk() calls this function.
|
|
125
|
+
*
|
|
126
|
+
* @param inBuff Input buffer with the raw data to be compressed.
|
|
127
|
+
* @param inBuffSize Size of the input buffer.
|
|
128
|
+
* @param outBuff Pre-allocated output buffer.
|
|
129
|
+
* @param outBuffSize Output buffer size is stored here.
|
|
130
|
+
* @param userOpts User/runtime options.
|
|
131
|
+
* @param cmpCfg FAPEC compression configuration.
|
|
132
|
+
* @return Zero if successul, 2 if the buffer could not be compressed (in
|
|
133
|
+
* which case the original buffer and size will be returned),
|
|
134
|
+
* negative in case of errors.
|
|
135
|
+
*
|
|
136
|
+
*/
|
|
137
|
+
WINDOWS_VISIBILITY int fapec_compress_chunk_reusebuff(unsigned char *inBuff, size_t inBuffSize,
|
|
138
|
+
unsigned char *outBuff, size_t *outBuffSize,
|
|
139
|
+
int userOpts, void *cmpCfg) LINUX_VISIBILITY;
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Generate the FCC External Header.
|
|
144
|
+
* This is useful for users that wish to do their own chunking on a data stream,
|
|
145
|
+
* and later on, decompress the multi-chunk output (compressed buffer or file).
|
|
146
|
+
* These external headers allow to properly identify and handle the chunks,
|
|
147
|
+
* e.g. through fapec_decomp_file or the CLI.
|
|
148
|
+
* @param isComp True if the chunk was actually compressed (see fapec_compress_chunk_reusebuff return value).
|
|
149
|
+
* @param isLast True if it's the last chunk in the stream.
|
|
150
|
+
* @param dataSize Compressed data size.
|
|
151
|
+
* @param edac EDAC option (see e.g. fapec_usropts_new_ck).
|
|
152
|
+
* @param outPtr Pre-allocated output buffer (16 bytes are enough).
|
|
153
|
+
* @return Size of the FCC EH.
|
|
154
|
+
*/
|
|
155
|
+
WINDOWS_VISIBILITY int fapec_gen_fcceh(bool isComp, bool isLast, int dataSize, uint8_t edac,
|
|
156
|
+
uint8_t *outPtr) LINUX_VISIBILITY;
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* Main file-based compression function
|
|
161
|
+
*
|
|
162
|
+
* It takes the input file(s) "inFiles",
|
|
163
|
+
* applies FAPEC on it using the configuration indicated in "cmpCfg",
|
|
164
|
+
* and writes the compressed output on "outFile".
|
|
165
|
+
* Either a fixed or automatic compression configuration will be used depending on "cmpCfg".
|
|
166
|
+
* If autoconfigured, "cmpCfg" is updated to the compression options automatically selected for this file.
|
|
167
|
+
* Compression information (progress, result, etc.) is printed to stdout depending on the 'verbosity' level.
|
|
168
|
+
*
|
|
169
|
+
* @param inFiles Array of null-terminated strings indicating the input file and folder names
|
|
170
|
+
* (including relative or absolute paths if needed) to be compressed.
|
|
171
|
+
* @param numFiles Number of files or folders provided through the inFiles array.
|
|
172
|
+
* @param outFile Output (.fapec) file where all input file(s) will be compressed.
|
|
173
|
+
* @param userOpts User/runtime options.
|
|
174
|
+
* @param cmpCfg FAPEC compression configuration.
|
|
175
|
+
* @return Zero if successful, negative if errors, >=10 if warnings.
|
|
176
|
+
*/
|
|
177
|
+
WINDOWS_VISIBILITY int fapec_compress_file(char **inFiles, int numFiles, char *outFile,
|
|
178
|
+
int userOpts, void *cmpCfg) LINUX_VISIBILITY;
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* Buffer-to-buffer compression function
|
|
183
|
+
*
|
|
184
|
+
* It takes an input buffer *inBuff of inSize bytes,
|
|
185
|
+
* allocates the necessary output buffer *outBuff
|
|
186
|
+
* (which will be at most inSize bytes plus a small overhead of some ~1K),
|
|
187
|
+
* compresses inBuff into outBuff using FAPEC
|
|
188
|
+
* (with the configuration given in "cmpCfg"),
|
|
189
|
+
* resizes the resulting buffer to just the actual size generated,
|
|
190
|
+
* and returns such size through outSize.
|
|
191
|
+
* The user is responsible of freeing *inBuff and *outBuff when done!
|
|
192
|
+
*
|
|
193
|
+
* @param inBuff Input buffer with the data to be compressed.
|
|
194
|
+
* @param outBuff Pointer to the (internally allocated) output, compressed buffer.
|
|
195
|
+
* @param inSize Input buffer size.
|
|
196
|
+
* @param outSize Output (compressed) size will be stored here.
|
|
197
|
+
* @param userOpts User/runtime options.
|
|
198
|
+
* @param cmpCfg FAPEC compression configuration.
|
|
199
|
+
* @return Zero if successful, negative if errors, >=10 if warnings.
|
|
200
|
+
*/
|
|
201
|
+
WINDOWS_VISIBILITY int fapec_compress_buff2buff(unsigned char *inBuff, unsigned char **outBuff,
|
|
202
|
+
int64_t inSize, int64_t *outSize,
|
|
203
|
+
int userOpts, void *cmpCfg) LINUX_VISIBILITY;
|
|
204
|
+
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* Buffer-to-file compression function
|
|
208
|
+
*
|
|
209
|
+
* It takes an input buffer *inBuff of inSize bytes,
|
|
210
|
+
* compresses it with FAPEC using the configuration indicated in "cmpCfg",
|
|
211
|
+
* and writes the compressed output on "outFile".
|
|
212
|
+
* The user is responsible of freeing *inBuff when done!
|
|
213
|
+
* @param inBuff Input buffer with the data to be compressed.
|
|
214
|
+
* @param inSize Input buffer size.
|
|
215
|
+
* @param outFile Output (.fapec) file where input buffer will be compressed.
|
|
216
|
+
* @param userOpts User/runtime options.
|
|
217
|
+
* @param cmpCfg FAPEC compression configuration.
|
|
218
|
+
* @return Zero if successful, negative if errors, >=10 if warnings.
|
|
219
|
+
*/
|
|
220
|
+
WINDOWS_VISIBILITY int fapec_compress_buff2file(unsigned char *inBuff, int64_t inSize,
|
|
221
|
+
char *outFile, int userOpts, void *cmpCfg) LINUX_VISIBILITY;
|
|
222
|
+
|
|
223
|
+
|
|
224
|
+
#endif
|