if (!ps) { char dataPath[2048]; /* XXX Sloppy: should be PATH_MAX. */
UErrorCode err = U_ZERO_ERROR;
ps = 1;
/* Set up our static data - if any */ #ifdefined(UCONVMSG_LINK) && U_PLATFORM != U_PF_OS390 /* On z/OS, this is failing. */
udata_setAppData(UCONVMSG, (constvoid*) uconvmsg_dat, &err); if (U_FAILURE(err)) {
fprintf(stderr, "%s: warning, problem installing our static resource bundle data uconvmsg: %s - trying anyways.\n",
pname, u_errorName(err));
err = U_ZERO_ERROR; /* It may still fail */
} #endif
/* Get messages. */
gBundle = u_wmsg_setPath(UCONVMSG, &err); if (U_FAILURE(err)) {
fprintf(stderr, "%s: warning: couldn't open bundle %s: %s\n",
pname, UCONVMSG, u_errorName(err)); #ifdef UCONVMSG_LINK
fprintf(stderr, "%s: setAppData was called, internal data %s failed to load\n",
pname, UCONVMSG); #endif
err = U_ZERO_ERROR; /* that was try #1, try again with a path */
uprv_strcpy(dataPath, u_getDataDirectory());
uprv_strcat(dataPath, U_FILE_SEP_STRING);
uprv_strcat(dataPath, UCONVMSG);
gBundle = u_wmsg_setPath(dataPath, &err); if (U_FAILURE(err)) {
fprintf(stderr, "%s: warning: still couldn't open bundle %s: %s\n",
pname, dataPath, u_errorName(err));
fprintf(stderr, "%s: warning: messages will not be displayed\n", pname);
}
}
}
}
/* Mapping of callback names to the callbacks passed to the converter
API. */
/* Return a pointer to a callback record given its name. */
staticconststruct callback_ent *findCallback(constchar *name) { int i, count =
UPRV_LENGTHOF(transcode_callbacks);
/* We'll do a linear search, there aren't many of them and bsearch()
may not be that portable. */
for (i = 0; i < count; ++i) { if (!uprv_stricmp(name, transcode_callbacks[i].name)) { return &transcode_callbacks[i];
}
}
return nullptr;
}
/* Print converter information. If lookfor is set, only that converter will beprinted,otherwiseallconverterswillbeprinted.Ifcanonisnon zero,tagsandaliasesforeachconverterareprintedtoo,intheformat
expected for convrters.txt(5). */
/* If there is a specified name, just handle that now. */
if (lookfor) { if (!canon) {
printf("%s\n", lookfor); return0;
} else { /* Because we are printing a canonical name, we need the trueconvertername.We'vedonethatalreadyexceptfor thedefaultname(becausewewanttoprinttheexact nameonewouldgetwhencallingucnv_getDefaultName() innon-canonmode).Butsincewedonotknowatthis pointifwehavethedefaultnameorsomethingelse,we needtonormalizeagaintothecanonicalconverter
name. */
/* Print converter names. We come here for one of two reasons: we areprintingallthenames(lookforwasnull),orwehavea singleconvertertoprintbutincanonmode,henceweneedto
get to it in order to print everything. */
num = ucnv_countAvailable(); if (num <= 0) {
initMsg(pname);
u_wmsg(stderr, "cantGetNames"); return -1;
} if (lookfor) {
num = 1; /* We know where we want to be. */
}
/* Print the current alias so that it looks right. */
printf("%s%s%s", (canon ? (a == 0? "" : "\t" ) : "") ,
alias,
(canon ? "" : " "));
/* Look (slowly, linear searching) for a tag. */
if (canon) { /* -1 to skip the last standard */ for (s = t = 0; s < num_stds-1; ++s) {
UEnumeration *nameEnum = ucnv_openStandardNames(name, stds[s], &err); if (U_SUCCESS(err)) { /* List the standard tags */ constchar *standardName;
UBool isFirst = true;
UErrorCode enumError = U_ZERO_ERROR; while ((standardName = uenum_next(nameEnum, nullptr, &enumError))) { /* See if this alias is supported by this standard. */ if (!strcmp(standardName, alias)) { if (!t) {
printf(" {");
t = 1;
} /* Print a * after the default standard name */
printf(" %s%s", stds[s], (isFirst ? "*" : ""));
}
isFirst = false;
}
}
} if (t) {
printf(" }");
}
} /* Terminate this entry. */ if (canon) {
puts("");
}
/* Move on. */
} /* Terminate this entry. */ if (!canon) {
puts("");
}
}
}
/* Print all available transliterators. If canon is non zero, print
one transliterator per line. */
staticint printTransliterators(UBool canon)
{ #if UCONFIG_NO_TRANSLITERATION
printf("no transliterators available because of UCONFIG_NO_TRANSLITERATION, see uconfig.h\n"); return1; #else
UErrorCode status = U_ZERO_ERROR;
UEnumeration *ids = utrans_openIDs(&status);
int32_t i, numtrans = uenum_count(ids, &status);
char sepchar = canon ? '\n' : ' ';
for (i = 0; U_SUCCESS(status)&& (i < numtrans); ++i) {
int32_t len; constchar *nextTrans = uenum_next(ids, &len, &status);
printf("%s", nextTrans); if (i < numtrans - 1) {
putchar(sepchar);
}
}
staticinline int32_t
getChunkLimit(const UnicodeString &prev, const UnicodeString &s) { // find one of // CR, LF, CRLF, NL, LS, PS // for paragraph ends (see UAX #13/Unicode 4) // and include it in the chunk // all of these characters are on the BMP // do not include FF or VT in case they are part of a paragraph // (important for bidi contexts) staticconst char16_t paraEnds[] = { 0xd, 0xa, 0x85, 0x2028, 0x2029
}; enum {
iCR, iLF, iNL, iLS, iPS, iCount
};
// first, see if there is a CRLF split between prev and s if (prev.endsWith(paraEnds + iCR, 1)) { if (s.startsWith(paraEnds + iLF, 1)) { return1; // split CRLF, include the LF
} elseif (!s.isEmpty()) { return0; // complete the last chunk
} else { return -1; // wait for actual further contents to arrive
}
}
while (u < limit) {
c = *u++; if (
((c < uSP) && (c == uCR || c == uLF)) ||
(c == uNL) ||
((c & uLS) == uLS)
) { if (c == uCR) { // check for CRLF if (u == limit) { return -1; // LF may be in the next chunk
} elseif (*u == uLF) {
++u; // include the LF in this chunk
}
} return static_cast<int32_t>(u - s.getBuffer());
}
}
return -1; // continue collecting the chunk
}
enum {
CNV_NO_FEFF, // cannot convert the U+FEFF Unicode signature character (BOM)
CNV_WITH_FEFF, // can convert the U+FEFF signature character
CNV_ADDS_FEFF // automatically adds/detects the U+FEFF signature character
};
// check the converter's Unicode signature properties; // the fromUnicode side of the converter must be in its initial state // and will be reset again if it was used static int32_t
cnvSigType(UConverter *cnv) {
UErrorCode err;
int32_t result;
// test if the output charset can convert U+FEFF
USet *set = uset_open(1, 0);
err = U_ZERO_ERROR;
ucnv_getUnicodeSet(cnv, set, UCNV_ROUNDTRIP_SET, &err); if (U_SUCCESS(err) && uset_contains(set, uSig)) {
result = CNV_WITH_FEFF;
} else {
result = CNV_NO_FEFF; // an error occurred or U+FEFF cannot be converted
}
uset_close(set);
if (result == CNV_WITH_FEFF) { // test if the output charset emits a signature anyway const char16_t a[1] = { 0x61 }; // "a" const char16_t *in;
char buffer[20]; char *out;
in = a;
out = buffer;
err = U_ZERO_ERROR;
ucnv_fromUnicode(cnv,
&out, buffer + sizeof(buffer),
&in, a + 1,
nullptr, true, &err);
ucnv_resetFromUnicode(cnv);
if (nullptr != ucnv_detectUnicodeSignature(buffer, static_cast<int32_t>(out - buffer), nullptr, &err) &&
U_SUCCESS(err)
) {
result = CNV_ADDS_FEFF;
}
}
#if !UCONFIG_NO_TRANSLITERATION
Transliterator *t = nullptr;// Transliterator acting on Unicode data.
UnicodeString chunk; // One chunk of the text being collected for transformation. #endif
UnicodeString u; // String to do the transliteration.
int32_t ulen;
// use conversion offsets for error messages // unless a transliterator is used - // a text transformation will reorder characters in unpredictable ways
UBool useOffsets = true;
// Open the correct input file or connect to stdin for reading input
if (t) { delete t;
t = nullptr;
} goto error_exit;
}
useOffsets = false;
} #endif
// Create codepage converter. If the codepage or its aliases weren't // available, it returns nullptr and a failure code. We also set the // callbacks, and return errors in the same way.
// Convert the read buffer into the new encoding via Unicode. // After the call 'unibufp' will be placed behind the last // character that was converted in the 'unibuf'. // Also the 'cbufp' is positioned behind the last converted // character. // At the last conversion in the file, flush should be set to // true so that we get all characters converted. // // The converter must be flushed at the end of conversion so // that characters on hold also will be written.
// Use bufsz instead of u.getCapacity() for the targetLimit // so that we don't overflow fromoffsets[].
ucnv_toUnicode(convfrom, &unibufp, unibuf + bufsz, &cbufp,
buf + rd, useOffsets ? fromoffsets : nullptr, flush, &err);
// fromSawEndOfBytes indicates that ucnv_toUnicode() is done // converting all of the input bytes. // It works like this because ucnv_toUnicode() returns only under the // following conditions: // - an error occurred during conversion (an error code is set) // - the target buffer is filled (the error code indicates an overflow) // - the source is consumed // That is, if the error code does not indicate a failure, // not even an overflow, then the source must be consumed entirely.
fromSawEndOfBytes = U_SUCCESS(err);
if (err == U_BUFFER_OVERFLOW_ERROR) {
err = U_ZERO_ERROR;
} elseif (U_FAILURE(err)) { char pos[32], errorBytes[32];
int8_t i, length, errorLength;
// print the input file offset of the start of the error bytes: // input file offset of the current byte buffer + // length of the just consumed bytes - // length of the error bytes
length =
static_cast<int8_t>(snprintf(pos, sizeof(pos), "%d",
static_cast<int>(infoffset + (cbufp - buf) - errorLength)));
// output the bytes that caused the error
UnicodeString str; for (i = 0; i < errorLength; ++i) { if (i > 0) {
str.append(static_cast<char16_t>(uSP));
}
str.append(nibbleToHex(static_cast<uint8_t>(errorBytes[i]) >> 4));
str.append(nibbleToHex(static_cast<uint8_t>(errorBytes[i])));
}
willexit = true;
err = U_ZERO_ERROR; /* reset the error for the rest of the conversion. */
}
// Replaced a check for whether the input was consumed by // looping until it is; message key "premEndInput" now obsolete.
if (ulen == 0) { continue;
}
// remove a U+FEFF Unicode signature character if requested if (sig < 0) { if (u.charAt(0) == uSig) {
u.remove(0, 1);
// account for the removed char16_t and offset
--ulen;
if (useOffsets) { // remove an offset from fromoffsets[] as well // to keep the array parallel with the UChars
memmove(fromoffsets, fromoffsets + 1, ulen * 4);
}
}
sig = 0;
}
#if !UCONFIG_NO_TRANSLITERATION // Transliterate/transform if needed.
// For transformation, we use chunking code - // collect Unicode input until, for example, an end-of-line, // then transform and output-convert that and continue collecting. // This makes the transformation result independent of the buffer size // while avoiding the slower keyboard mode. // The end-of-chunk characters are completely included in the // transformed string in case they are to be transformed themselves. if (t != nullptr) {
UnicodeString out;
int32_t chunkLimit;
do {
chunkLimit = getChunkLimit(chunk, u); if (chunkLimit < 0 && flush && fromSawEndOfBytes) { // use all of the rest at the end of the text
chunkLimit = u.length();
} if (chunkLimit >= 0) { // complete the chunk and transform it
chunk.append(u, 0, chunkLimit);
u.remove(0, chunkLimit);
t->transliterate(chunk);
// append the transformation result to the result and empty the chunk
out.append(chunk);
chunk.remove();
} else { // continue collecting the chunk
chunk.append(u); break;
}
} while (!u.isEmpty());
u = out;
ulen = u.length();
} #endif
// add a U+FEFF Unicode signature character if requested // and possible/necessary if (sig > 0) { if (u.charAt(0) != uSig && cnvSigType(convto) == CNV_WITH_FEFF) {
u.insert(0, static_cast<char16_t>(uSig));
if (useOffsets) { // insert a pseudo-offset into fromoffsets[] as well // to keep the array parallel with the UChars
memmove(fromoffsets + 1, fromoffsets, ulen * 4);
fromoffsets[0] = -1;
}
// account for the additional char16_t and offset
++ulen;
}
sig = 0;
}
// Convert the Unicode buffer into the destination codepage // Again 'bufp' will be placed behind the last converted character // And 'unibufp' will be placed behind the last converted unicode character // At the last conversion flush should be set to true to ensure that // all characters left get converted
unibuf = unibufbp = u.getBuffer();
do {
bufp = outbuf;
// Use fromSawEndOfBytes in addition to the flush flag - // it indicates whether the intermediate Unicode string // contains the very last UChars for the very last input bytes.
ucnv_fromUnicode(convto, &bufp, outbuf + bufsz,
&unibufbp,
unibuf + ulen,
nullptr, static_cast<UBool>(flush && fromSawEndOfBytes), &err);
// toSawEndOfUnicode indicates that ucnv_fromUnicode() is done // converting all of the intermediate UChars. // See comment for fromSawEndOfBytes.
toSawEndOfUnicode = U_SUCCESS(err);
UErrorCode localError = U_ZERO_ERROR;
errorLength = UPRV_LENGTHOF(errorUChars);
ucnv_getInvalidUChars(convto, errorUChars, &errorLength, &localError); if (U_FAILURE(localError) || errorLength == 0) { // need at least 1 so that we don't access beyond the length of fromoffsets[]
errorLength = 1;
}
int32_t ferroffset;
if (useOffsets) { // Unicode buffer offset of the start of the error UChars
ferroffset = static_cast<int32_t>((unibufbp - unibuf) - errorLength); if (ferroffset < 0) { // approximation - the character started in the previous Unicode buffer
ferroffset = 0;
}
// get the corresponding byte offset out of fromoffsets[] // go back if the offset is not known for some of the UChars
int32_t fromoffset; do {
fromoffset = fromoffsets[ferroffset];
} while (fromoffset < 0 && --ferroffset >= 0);
// total input file offset = // input file offset of the current byte buffer + // byte buffer offset of where the current Unicode buffer is converted from + // fromoffsets[Unicode offset]
ferroffset = static_cast<int32_t>(infoffset + (prevbufp - buf) + fromoffset);
errtag = "problemCvtFromU";
} else { // Do not use fromoffsets if (t != nullptr) because the Unicode text may // be different from what the offsets refer to.
willexit = true;
err = U_ZERO_ERROR; /* reset the error for the rest of the conversion. */
}
// Replaced a check for whether the intermediate Unicode characters were all consumed by // looping until they are; message key "premEnd" now obsolete.
// Finally, write the converted buffer to the output file
size_t outlen = static_cast<size_t>(bufp - outbuf);
outfoffset += static_cast<int32_t>(wr = fwrite(outbuf, 1, outlen, outfile)); if (wr != outlen) {
UnicodeString str(strerror(errno));
initMsg(pname);
u_wmsg(stderr, "cantWrite", str.getTerminatedBuffer());
willexit = true;
}
if (willexit) { goto error_exit;
}
} while (!toSawEndOfUnicode);
} while (!fromSawEndOfBytes);
} while (!flush); // Stop when we have flushed the // converters (this means that it's // the end of output)
res = u_wmsg(fp, "usage", mname.getBuffer(), upname.getBuffer()); if (!ecode) { if (!res) {
fputc('\n', fp);
} if (!u_wmsg(fp, "help")) { /* Now dump callbacks and finish. */
int i, count =
UPRV_LENGTHOF(transcode_callbacks); for (i = 0; i < count; ++i) {
fprintf(fp, " %s", transcode_callbacks[i].name);
}
fputc('\n', fp);
}
}
exit(ecode);
}
externint
main(int argc, char **argv)
{
FILE *outfile; int ret = 0;
goto normal_exit;
error_exit: #if !UCONFIG_NO_LEGACY_CONVERSION
ret = 1; #else
fprintf(stderr, "uconv error: UCONFIG_NO_LEGACY_CONVERSION is on. See uconfig.h\n"); #endif
normal_exit:
¤ Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.0.21Bemerkung:
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.