Deal with Unicode
/** @version 1.10 1997-07-01 @author Cay Horstmann */ #include "Printf4.h" #include <string.h> #include <stdlib.h> #include <float.h> /** @param format a string containing a printf format specifier (such as "%8.2f"). Substrings "%%" are skipped. @return a pointer to the format specifier (skipping the '%') or NULL if there wasn't a unique format specifier */ char* find_format(const char format[]) { char* p; char* q; p = strchr(format, '%'); while (p != NULL && *(p + 1) == '%') /* skip %% */ p = strchr(p + 2, '%'); if (p == NULL) return NULL; /* now check that % is unique */ p++; q = strchr(p, '%'); while (q != NULL && *(q + 1) == '%') /* skip %% */ q = strchr(q + 2, '%'); if (q != NULL) return NULL; /* % not unique */ q = p + strspn(p, " -0+#"); /* skip past flags */ q += strspn(q, "0123456789"); /* skip past field width */ if (*q == '.') { q++; q += strspn(q, "0123456789"); } /* skip past precision */ if (strchr("eEfFgG", *q) == NULL) return NULL; /* not a floating-point format */ return p; } JNIEXPORT void JNICALL Java_Printf4_fprint(JNIEnv* env, jclass cl, jobject out, jstring format, jdouble x) { const char* cformat; char* fmt; jclass class_PrintWriter; jmethodID id_print; char* cstr; int width; int i; if (format == NULL) { (*env)->ThrowNew(env, (*env)->FindClass(env, "java/lang/NullPointerException"), "Printf4.fprint: format is null"); return; } cformat = (*env)->GetStringUTFChars(env, format, NULL); fmt = find_format(cformat); if (fmt == NULL) { (*env)->ThrowNew(env, (*env)->FindClass(env, "java/lang/IllegalArgumentException"), "Printf4.fprint: format is invalid"); return; } width = atoi(fmt); if (width == 0) width = DBL_DIG + 10; cstr = (char*)malloc(strlen(cformat) + width); if (cstr == NULL) { (*env)->ThrowNew(env, (*env)->FindClass(env, "java/lang/OutOfMemoryError"), "Printf4.fprint: malloc failed"); return; } sprintf(cstr, cformat, x); (*env)->ReleaseStringUTFChars(env, format, cformat); /* now call ps.print(str) */ /* get the class */ class_PrintWriter = (*env)->GetObjectClass(env, out); /* get the method ID */ id_print = (*env)->GetMethodID(env, class_PrintWriter, "print", "(C)V"); /* call the method */ for (i = 0; cstr[i] != 0 && !(*env)->ExceptionOccurred(env); i++) (*env)->CallVoidMethod(env, out, id_print, cstr[i]); free(cstr); } /* This program is a part of the companion code for Core Java 8th ed. (http://horstmann.com/corejava) This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ import java.io.*; /** * @version 1.10 1997-07-01 * @author Cay Horstmann */ class Printf4 { public static native void fprint(PrintWriter ps, String format, double x); static { System.loadLibrary("Printf4"); } } /* This program is a part of the companion code for Core Java 8th ed. (http://horstmann.com/corejava) This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ import java.io.*; /** * @version 1.10 1997-07-01 * @author Cay Horstmann */ class Printf4Test { public static void main(String[] args) { double price = 44.95; double tax = 7.75; double amountDue = price * (1 + tax / 100); PrintWriter out = new PrintWriter(System.out); /* This call will throw an exception--note the %% */ Printf4.fprint(out, "Amount due = %%8.2f\n", amountDue); out.flush(); } }