[PATCH 3/3] Use 'struct membuffer' for profile info string generation

Linus Torvalds torvalds at linux-foundation.org
Sun Feb 9 10:01:00 UTC 2014


From: Linus Torvalds <torvalds at linux-foundation.org>
Date: Sat, 18 Jan 2014 16:21:13 -0800
Subject: [PATCH 3/3] Use 'struct membuffer' for profile info string generation

The profile info was generated using nasty string concatenation that the
membuffers are much better at anyway.  And membuffers don't need those
arbitrarily sized fixed buffers (500 bytes? Why 500 bytes?).

Signed-off-by: Linus Torvalds <torvalds at linux-foundation.org>
---

Slightly updated from last time: this changes the callers to use 'struct 
mb' too (so that we can get rid of the arbitrary fixed buffer and the 
memcopies), and uses "put_string()" instead of "put_format()" for the 
cases that don't actually have a format string, just a plain string.

The earlier patch was tested by Oscar Isoz <jan.oscar.isoz at gmail.com> for 
the heartrate parts, but it's been changed enough since that I didn't add 
his tested-by.


 display.h                         |   4 +-
 profile.c                         | 113 ++++++++++++++------------------------
 profile.h                         |   3 +-
 qt-ui/profile/divetooltipitem.cpp |  18 ++++--
 4 files changed, 58 insertions(+), 80 deletions(-)

diff --git a/display.h b/display.h
index 62f0b7dd0cb8..196338bb4125 100644
--- a/display.h
+++ b/display.h
@@ -5,6 +5,8 @@
 extern "C" {
 #endif
 
+struct membuffer;
+
 #define SCALE_SCREEN 1.0
 #define SCALE_PRINT (1.0 / get_screen_dpi())
 
@@ -39,7 +41,7 @@ struct graphics_context {
 typedef enum { SC_SCREEN, SC_PRINT } scale_mode_t;
 
 extern struct divecomputer *select_dc(struct divecomputer *main);
-extern void get_plot_details(struct graphics_context *gc, int time, char *buf, int bufsize);
+extern void get_plot_details(struct graphics_context *gc, int time, struct membuffer *mb);
 
 struct options {
 	enum { PRETTY, TABLE, TWOPERPAGE } type;
diff --git a/profile.c b/profile.c
index db8a89af8eb3..855d16c86497 100644
--- a/profile.c
+++ b/profile.c
@@ -13,6 +13,7 @@
 #include "deco.h"
 #include "libdivecomputer/parser.h"
 #include "libdivecomputer/version.h"
+#include "membuffer.h"
 
 int selected_dive = -1; /* careful: 0 is a valid value */
 char zoomed_plot = 0;
@@ -1399,97 +1400,75 @@ struct divecomputer *select_dc(struct divecomputer *main)
 	return main;
 }
 
-static void plot_string(struct plot_data *entry, char *buf, int bufsize,
-			bool has_ndl)
+static void plot_string(struct plot_data *entry, struct membuffer *b, bool has_ndl)
 {
 	int pressurevalue, mod, ead, end, eadd;
 	const char *depth_unit, *pressure_unit, *temp_unit, *vertical_speed_unit;
-	char *buf2 = malloc(bufsize);
 	double depthvalue, tempvalue, speedvalue;
 
 	depthvalue = get_depth_units(entry->depth, NULL, &depth_unit);
-	snprintf(buf, bufsize, translate("gettextFromC","@:%d:%02d\nD:%.1f %s"), FRACTION(entry->sec, 60), depthvalue, depth_unit);
+	put_format(b, translate("gettextFromC","@:%d:%02d\nD:%.1f %s\n"), FRACTION(entry->sec, 60), depthvalue, depth_unit);
 	if (GET_PRESSURE(entry)) {
 		pressurevalue = get_pressure_units(GET_PRESSURE(entry), &pressure_unit);
-		memcpy(buf2, buf, bufsize);
-		snprintf(buf, bufsize, translate("gettextFromC","%s\nP:%d %s"), buf2, pressurevalue, pressure_unit);
+		put_format(b, translate("gettextFromC","P:%d %s\n"), pressurevalue, pressure_unit);
 	}
 	if (entry->temperature) {
 		tempvalue = get_temp_units(entry->temperature, &temp_unit);
-		memcpy(buf2, buf, bufsize);
-		snprintf(buf, bufsize, translate("gettextFromC","%s\nT:%.1f %s"), buf2, tempvalue, temp_unit);
+		put_format(b, translate("gettextFromC","T:%.1f %s\n"), tempvalue, temp_unit);
 	}
 	speedvalue = get_vertical_speed_units(abs(entry->speed), NULL, &vertical_speed_unit);
-	memcpy(buf2, buf, bufsize);
 	/* Ascending speeds are positive, descending are negative */
 	if (entry->speed > 0)
 		speedvalue *= -1;
-	snprintf(buf, bufsize, translate("gettextFromC","%s\nV:%.2f %s"), buf2, speedvalue, vertical_speed_unit);
-
-	if (entry->sac && prefs.show_sac) {
-		memcpy(buf2, buf, bufsize);
-		snprintf(buf, bufsize, translate("gettextFromC","%s\nSAC:%2.1fl/min"), buf2, entry->sac / 1000.0);
-	}
-	if (entry->cns) {
-		memcpy(buf2, buf, bufsize);
-		snprintf(buf, bufsize, translate("gettextFromC","%s\nCNS:%u%%"), buf2, entry->cns);
-	}
-	if (prefs.pp_graphs.po2) {
-		memcpy(buf2, buf, bufsize);
-		snprintf(buf, bufsize, translate("gettextFromC","%s\npO%s:%.2fbar"), buf2, UTF8_SUBSCRIPT_2, entry->po2);
-	}
-	if (prefs.pp_graphs.pn2) {
-		memcpy(buf2, buf, bufsize);
-		snprintf(buf, bufsize, translate("gettextFromC","%s\npN%s:%.2fbar"), buf2, UTF8_SUBSCRIPT_2, entry->pn2);
-	}
-	if (prefs.pp_graphs.phe) {
-		memcpy(buf2, buf, bufsize);
-		snprintf(buf, bufsize, translate("gettextFromC","%s\npHe:%.2fbar"), buf2, entry->phe);
-	}
+	put_format(b, translate("gettextFromC","V:%.2f %s\n"), speedvalue, vertical_speed_unit);
+
+	if (entry->sac && prefs.show_sac)
+		put_format(b, translate("gettextFromC","SAC:%2.1fl/min\n"), entry->sac / 1000.0);
+	if (entry->cns)
+		put_format(b, translate("gettextFromC","CNS:%u%%\n"), entry->cns);
+	if (prefs.pp_graphs.po2)
+		put_format(b, translate("gettextFromC","pO%s:%.2fbar\n"), UTF8_SUBSCRIPT_2, entry->po2);
+	if (prefs.pp_graphs.pn2)
+		put_format(b, translate("gettextFromC","pN%s:%.2fbar\n"), UTF8_SUBSCRIPT_2, entry->pn2);
+	if (prefs.pp_graphs.phe)
+		put_format(b, translate("gettextFromC","pHe:%.2fbar\n"), entry->phe);
 	if (prefs.mod) {
 		mod = (int)get_depth_units(entry->mod, NULL, &depth_unit);
-		memcpy(buf2, buf, bufsize);
-		snprintf(buf, bufsize, translate("gettextFromC","%s\nMOD:%d%s"), buf2, mod, depth_unit);
+		put_format(b, translate("gettextFromC","MOD:%d%s\n"), mod, depth_unit);
 	}
 	if (prefs.ead) {
 		ead = (int)get_depth_units(entry->ead, NULL, &depth_unit);
 		end = (int)get_depth_units(entry->end, NULL, &depth_unit);
 		eadd = (int)get_depth_units(entry->eadd, NULL, &depth_unit);
-		memcpy(buf2, buf, bufsize);
-		snprintf(buf, bufsize, translate("gettextFromC","%s\nEAD:%d%s\nEND:%d%s\nEADD:%d%s"), buf2, ead, depth_unit, end, depth_unit, eadd, depth_unit);
+		put_format(b, translate("gettextFromC","EAD:%d%s\nEND:%d%s\nEADD:%d%s\n"), ead, depth_unit, end, depth_unit, eadd, depth_unit);
 	}
 	if (entry->stopdepth) {
 		depthvalue = get_depth_units(entry->stopdepth, NULL, &depth_unit);
-		memcpy(buf2, buf, bufsize);
 		if (entry->ndl) {
 			/* this is a safety stop as we still have ndl */
 			if (entry->stoptime)
-				snprintf(buf, bufsize, translate("gettextFromC","%s\nSafetystop:%umin @ %.0f %s"), buf2, DIV_UP(entry->stoptime, 60),
+				put_format(b, translate("gettextFromC","Safetystop:%umin @ %.0f %s\n"), DIV_UP(entry->stoptime, 60),
 					depthvalue, depth_unit);
 			else
-				snprintf(buf, bufsize, translate("gettextFromC","%s\nSafetystop:unkn time @ %.0f %s"), buf2,
+				put_format(b, translate("gettextFromC","Safetystop:unkn time @ %.0f %s\n"),
 					depthvalue, depth_unit);
 		} else {
 			/* actual deco stop */
 			if (entry->stoptime)
-				snprintf(buf, bufsize, translate("gettextFromC","%s\nDeco:%umin @ %.0f %s"), buf2, DIV_UP(entry->stoptime, 60),
+				put_format(b, translate("gettextFromC","Deco:%umin @ %.0f %s\n"), DIV_UP(entry->stoptime, 60),
 					depthvalue, depth_unit);
 			else
-				snprintf(buf, bufsize, translate("gettextFromC","%s\nDeco:unkn time @ %.0f %s"), buf2,
+				put_format(b, translate("gettextFromC","Deco:unkn time @ %.0f %s\n"),
 					depthvalue, depth_unit);
 		}
 	} else if (entry->in_deco) {
-		/* this means we had in_deco set but don't have a stop depth */
-		memcpy(buf2, buf, bufsize);
-		snprintf(buf, bufsize, translate("gettextFromC","%s\nIn deco"), buf2);
+		put_string(b, translate("gettextFromC","In deco\n"));
 	} else if (has_ndl) {
-		memcpy(buf2, buf, bufsize);
-		snprintf(buf, bufsize, translate("gettextFromC","%s\nNDL:%umin"), buf2, DIV_UP(entry->ndl, 60));
+		put_format(b, translate("gettextFromC","NDL:%umin\n"), DIV_UP(entry->ndl, 60));
 	}
 	if (entry->stopdepth_calc && entry->stoptime_calc) {
 		depthvalue = get_depth_units(entry->stopdepth_calc, NULL, &depth_unit);
-		memcpy(buf2, buf, bufsize);
-		snprintf(buf, bufsize, translate("gettextFromC","%s\nDeco:%umin @ %.0f %s (calc)"), buf2, DIV_UP(entry->stoptime_calc, 60),
+		put_format(b, translate("gettextFromC","Deco:%umin @ %.0f %s (calc)\n"), DIV_UP(entry->stoptime_calc, 60),
 				depthvalue, depth_unit);
 	} else if (entry->in_deco_calc) {
 		/* This means that we have no NDL left,
@@ -1497,43 +1476,33 @@ static void plot_string(struct plot_data *entry, char *buf, int bufsize,
 		 * so if we just accend to the surface slowly
 		 * (ascent_mm_per_step / ascent_s_per_step)
 		 * everything will be ok. */
-		memcpy(buf2, buf, bufsize);
-		snprintf(buf, bufsize, translate("gettextFromC","%s\nIn deco (calc)"), buf2);
+		put_string(b, translate("gettextFromC","In deco (calc)\n"));
 	} else if (prefs.calc_ndl_tts && entry->ndl_calc != 0) {
-		memcpy(buf2, buf, bufsize);
-		snprintf(buf, bufsize, translate("gettextFromC","%s\nNDL:%umin (calc)"), buf2, DIV_UP(entry->ndl_calc, 60));
-	}
-	if (entry->tts_calc) {
-		memcpy(buf2, buf, bufsize);
-		snprintf(buf, bufsize, translate("gettextFromC","%s\nTTS:%umin (calc)"), buf2, DIV_UP(entry->tts_calc, 60));
+		put_format(b, translate("gettextFromC","NDL:%umin (calc)\n"), DIV_UP(entry->ndl_calc, 60));
 	}
+	if (entry->tts_calc)
+		put_format(b, translate("gettextFromC","TTS:%umin (calc)\n"), DIV_UP(entry->tts_calc, 60));
 	if (entry->ceiling) {
 		depthvalue = get_depth_units(entry->ceiling, NULL, &depth_unit);
-		memcpy(buf2, buf, bufsize);
-		snprintf(buf, bufsize, translate("gettextFromC","%s\nCalculated ceiling %.0f %s"), buf2, depthvalue, depth_unit);
+		put_format(b, translate("gettextFromC","Calculated ceiling %.0f %s\n"), depthvalue, depth_unit);
 		if (prefs.calc_all_tissues) {
 			int k;
 			for (k=0; k<16; k++) {
 				if (entry->ceilings[k]) {
 					depthvalue = get_depth_units(entry->ceilings[k], NULL, &depth_unit);
-					memcpy(buf2, buf, bufsize);
-					snprintf(buf, bufsize, translate("gettextFromC","%s\nTissue %.0fmin: %.0f %s"), buf2, buehlmann_N2_t_halflife[k], depthvalue, depth_unit);
+					put_format(b, translate("gettextFromC","Tissue %.0fmin: %.0f %s\n"), buehlmann_N2_t_halflife[k], depthvalue, depth_unit);
 				}
 			}
 		}
 	}
-	if (entry->heartbeat) {
-		memcpy(buf2, buf, bufsize);
-		snprintf(buf, bufsize, translate("gettextFromC","%s\nheartbeat:%d"), buf2, entry->heartbeat);
-	}
-	if (entry->bearing) {
-		memcpy(buf2, buf, bufsize);
-		snprintf(buf, bufsize, translate("gettextFromC","%s\nbearing:%d"), buf2, entry->bearing);
-	}
-	free(buf2);
+	if (entry->heartbeat)
+		put_format(b, translate("gettextFromC","heartbeat:%d\n"), entry->heartbeat);
+	if (entry->bearing)
+		put_format(b, translate("gettextFromC","bearing:%d\n"), entry->bearing);
+	strip_mb(b);
 }
 
-void get_plot_details(struct graphics_context *gc, int time, char *buf, int bufsize)
+void get_plot_details(struct graphics_context *gc, int time, struct membuffer *mb)
 {
 	struct plot_info *pi = &gc->pi;
 	struct plot_data *entry = NULL;
@@ -1545,10 +1514,10 @@ void get_plot_details(struct graphics_context *gc, int time, char *buf, int bufs
 			break;
 	}
 	if (entry)
-		plot_string(entry, buf, bufsize, pi->has_ndl);
+		plot_string(entry, mb, pi->has_ndl);
 }
 
-void get_plot_details_new(struct plot_info *pi, int time, char *buf, int bufsize)
+void get_plot_details_new(struct plot_info *pi, int time, struct membuffer *mb)
 {
 	struct plot_data *entry = NULL;
 	int i;
@@ -1559,7 +1528,7 @@ void get_plot_details_new(struct plot_info *pi, int time, char *buf, int bufsize
 			break;
 	}
 	if (entry)
-		plot_string(entry, buf, bufsize, pi->has_ndl);
+		plot_string(entry, mb, pi->has_ndl);
 }
 
 /* Compare two plot_data entries and writes the results into a string */
diff --git a/profile.h b/profile.h
index ef81763bfb62..82d6d58e766c 100644
--- a/profile.h
+++ b/profile.h
@@ -7,6 +7,7 @@ extern "C" {
 
 typedef enum { STABLE, SLOW, MODERATE, FAST, CRAZY } velocity_t;
 
+struct membuffer;
 struct divecomputer;
 struct graphics_context;
 struct plot_info;
@@ -56,7 +57,7 @@ struct plot_data *populate_plot_entries(struct dive *dive, struct divecomputer *
 struct plot_info *analyze_plot_info(struct plot_info *pi);
 void create_plot_info_new(struct dive *dive, struct divecomputer *dc, struct plot_info *pi);
 void calculate_deco_information(struct dive *dive, struct divecomputer *dc, struct plot_info *pi, bool print_mode);
-void get_plot_details_new(struct plot_info *pi, int time, char *buf, int bufsize);
+void get_plot_details_new(struct plot_info *pi, int time, struct membuffer *);
 
 struct ev_select {
 	char *ev_name;
diff --git a/qt-ui/profile/divetooltipitem.cpp b/qt-ui/profile/divetooltipitem.cpp
index 26d19ecc3b3d..0cec0b982ef5 100644
--- a/qt-ui/profile/divetooltipitem.cpp
+++ b/qt-ui/profile/divetooltipitem.cpp
@@ -1,6 +1,8 @@
 #include "divetooltipitem.h"
 #include "divecartesianaxis.h"
 #include "profile.h"
+#include "dive.h"
+#include "membuffer.h"
 #include <QPropertyAnimation>
 #include <QGraphicsSceneMouseEvent>
 #include <QPen>
@@ -39,9 +41,11 @@ void ToolTipItem::refresh(struct graphics_context *gc, QPointF pos)
 {
 	clear();
 	int time = (pos.x() * gc->maxtime) / gc->maxx;
-	char buffer[500];
-	get_plot_details(gc, time, buffer, 500);
-	addToolTip(QString(buffer));
+	struct membuffer mb = { 0 };
+
+	get_plot_details(gc, time, &mb);
+	addToolTip(QString::fromUtf8(mb.buffer, mb.len));
+	free_buffer(&mb);
 
 	QList<QGraphicsItem*> items = scene()->items(pos, Qt::IntersectsItemShape, Qt::DescendingOrder, transform());
 	Q_FOREACH(QGraphicsItem *item, items) {
@@ -225,9 +229,11 @@ void ToolTipItem::refresh(const QPointF& pos)
 {
 	clear();
 	int time = timeAxis->valueAt( pos );
-	char buffer[500];
-	get_plot_details_new(&pInfo, time, buffer, 500);
-	addToolTip(QString(buffer));
+	struct membuffer mb = { 0 };
+
+	get_plot_details_new(&pInfo, time, &mb);
+	addToolTip(QString::fromUtf8(mb.buffer, mb.len));
+	free_buffer(&mb);
 
 	QList<QGraphicsItem*> items = scene()->items(pos, Qt::IntersectsItemShape, Qt::DescendingOrder, transform());
 	Q_FOREACH(QGraphicsItem *item, items) {
-- 
1.9.0.rc3




More information about the subsurface mailing list