tesseract  3.03
/usr/local/google/home/jbreiden/tesseract-ocr-read-only/viewer/svutil.cpp
Go to the documentation of this file.
00001 
00002 // File:        svutil.cpp
00003 // Description: ScrollView Utilities
00004 // Author:      Joern Wanke
00005 // Created:     Thu Nov 29 2007
00006 //
00007 // (C) Copyright 2007, Google Inc.
00008 // Licensed under the Apache License, Version 2.0 (the "License");
00009 // you may not use this file except in compliance with the License.
00010 // You may obtain a copy of the License at
00011 // http://www.apache.org/licenses/LICENSE-2.0
00012 // Unless required by applicable law or agreed to in writing, software
00013 // distributed under the License is distributed on an "AS IS" BASIS,
00014 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00015 // See the License for the specific language governing permissions and
00016 // limitations under the License.
00017 //
00019 //
00020 // SVUtil contains the SVSync and SVNetwork classes, which are used for
00021 // thread/process creation & synchronization and network connection.
00022 
00023 #include <stdio.h>
00024 #ifdef _WIN32
00025 struct addrinfo {
00026   struct sockaddr* ai_addr;
00027   int ai_addrlen;
00028   int ai_family;
00029   int ai_socktype;
00030   int ai_protocol;
00031 };
00032 #else
00033 #include <arpa/inet.h>
00034 #include <netinet/in.h>
00035 #include <pthread.h>
00036 #include <semaphore.h>
00037 #include <signal.h>
00038 #include <stdlib.h>
00039 #include <string.h>
00040 #include <netdb.h>
00041 #include <sys/socket.h>
00042 #ifdef __linux__
00043 #include <sys/prctl.h>
00044 #endif
00045 #include <unistd.h>
00046 #endif
00047 
00048 #include <cstdlib>
00049 #include <cstring>
00050 #include <iostream>
00051 #include <string>
00052 
00053 // Include automatically generated configuration file if running autoconf.
00054 #ifdef HAVE_CONFIG_H
00055 #include "config_auto.h"
00056 #endif
00057 
00058 #ifndef GRAPHICS_DISABLED
00059 
00060 #include "svutil.h"
00061 
00062 const int kBufferSize = 65536;
00063 const int kMaxMsgSize = 4096;
00064 
00065 // Signals a thread to exit.
00066 void SVSync::ExitThread() {
00067 #ifdef _WIN32
00068   // ExitThread(0);
00069 #else
00070   pthread_exit(0);
00071 #endif
00072 }
00073 
00074 // Starts a new process.
00075 void SVSync::StartProcess(const char* executable, const char* args) {
00076   std::string proc;
00077   proc.append(executable);
00078   proc.append(" ");
00079   proc.append(args);
00080   std::cout << "Starting " << proc << std::endl;
00081 #ifdef _WIN32
00082   STARTUPINFO start_info;
00083   PROCESS_INFORMATION proc_info;
00084   GetStartupInfo(&start_info);
00085   if (!CreateProcess(NULL, const_cast<char*>(proc.c_str()), NULL, NULL, FALSE,
00086                 CREATE_NO_WINDOW | DETACHED_PROCESS, NULL, NULL,
00087                 &start_info, &proc_info))
00088     return;
00089 #else
00090   int pid = fork();
00091   if (pid != 0) {   // The father process returns
00092   } else {
00093 #ifdef __linux__
00094     // Make sure the java process terminates on exit, since its
00095     // broken socket detection seems to be useless.
00096     prctl(PR_SET_PDEATHSIG, 2, 0, 0, 0);
00097 #endif
00098     char* mutable_args = strdup(args);
00099     int argc = 1;
00100     for (int i = 0; mutable_args[i]; ++i) {
00101       if (mutable_args[i] == ' ') {
00102         ++argc;
00103       }
00104     }
00105     char** argv = new char*[argc + 2];
00106     argv[0] = strdup(executable);
00107     argv[1] = mutable_args;
00108     argc = 2;
00109     bool inquote = false;
00110     for (int i = 0; mutable_args[i]; ++i) {
00111       if (!inquote && mutable_args[i] == ' ') {
00112         mutable_args[i] = '\0';
00113         argv[argc++] = mutable_args + i + 1;
00114       } else if (mutable_args[i] == '"') {
00115         inquote = !inquote;
00116         mutable_args[i] = ' ';
00117       }
00118     }
00119     argv[argc] = NULL;
00120     execvp(executable, argv);
00121   }
00122 #endif
00123 }
00124 
00125 SVSemaphore::SVSemaphore() {
00126 #ifdef _WIN32
00127   semaphore_ = CreateSemaphore(0, 0, 10, 0);
00128 #elif defined(__APPLE__)
00129   char name[50];
00130   snprintf(name, sizeof(name), "%d", random());
00131   sem_unlink(name);
00132   semaphore_ = sem_open(name, O_CREAT , S_IWUSR, 0);
00133   if (semaphore_ == SEM_FAILED) {
00134     perror("sem_open");
00135   }
00136 #else
00137   sem_init(&semaphore_, 0, 0);
00138 #endif
00139 }
00140 
00141 void SVSemaphore::Signal() {
00142 #ifdef _WIN32
00143   ReleaseSemaphore(semaphore_, 1, NULL);
00144 #elif defined(__APPLE__)
00145   sem_post(semaphore_);
00146 #else
00147   sem_post(&semaphore_);
00148 #endif
00149 }
00150 
00151 void SVSemaphore::Wait() {
00152 #ifdef _WIN32
00153   WaitForSingleObject(semaphore_, INFINITE);
00154 #elif defined(__APPLE__)
00155   sem_wait(semaphore_);
00156 #else
00157   sem_wait(&semaphore_);
00158 #endif
00159 }
00160 
00161 SVMutex::SVMutex() {
00162 #ifdef _WIN32
00163   mutex_ = CreateMutex(0, FALSE, 0);
00164 #else
00165   pthread_mutex_init(&mutex_, NULL);
00166 #endif
00167 }
00168 
00169 void SVMutex::Lock() {
00170 #ifdef _WIN32
00171   WaitForSingleObject(mutex_, INFINITE);
00172 #else
00173   pthread_mutex_lock(&mutex_);
00174 #endif
00175 }
00176 
00177 void SVMutex::Unlock() {
00178 #ifdef _WIN32
00179   ReleaseMutex(mutex_);
00180 #else
00181   pthread_mutex_unlock(&mutex_);
00182 #endif
00183 }
00184 
00185 // Create new thread.
00186 
00187 void SVSync::StartThread(void *(*func)(void*), void* arg) {
00188 #ifdef _WIN32
00189   LPTHREAD_START_ROUTINE f = (LPTHREAD_START_ROUTINE) func;
00190   DWORD threadid;
00191   HANDLE newthread = CreateThread(
00192   NULL,          // default security attributes
00193   0,             // use default stack size
00194   f,             // thread function
00195   arg,           // argument to thread function
00196   0,             // use default creation flags
00197   &threadid);    // returns the thread identifier
00198 #else
00199   pthread_t helper;
00200   pthread_create(&helper, NULL, func, arg);
00201 #endif
00202 }
00203 
00204 // Place a message in the message buffer (and flush it).
00205 void SVNetwork::Send(const char* msg) {
00206   mutex_send_->Lock();
00207   msg_buffer_out_.append(msg);
00208   mutex_send_->Unlock();
00209 }
00210 
00211 // Send the whole buffer.
00212 void SVNetwork::Flush() {
00213   mutex_send_->Lock();
00214   while (msg_buffer_out_.size() > 0) {
00215     int i = send(stream_, msg_buffer_out_.c_str(), msg_buffer_out_.length(), 0);
00216     msg_buffer_out_.erase(0, i);
00217   }
00218   mutex_send_->Unlock();
00219 }
00220 
00221 // Receive a message from the server.
00222 // This will always return one line of char* (denoted by \n).
00223 char* SVNetwork::Receive() {
00224   char* result = NULL;
00225 #ifdef _WIN32
00226   if (has_content) { result = strtok (NULL, "\n"); }
00227 #else
00228   if (buffer_ptr_ != NULL) { result = strtok_r(NULL, "\n", &buffer_ptr_); }
00229 #endif
00230 
00231   // This means there is something left in the buffer and we return it.
00232   if (result != NULL) { return result;
00233   // Otherwise, we read from the stream_.
00234   } else {
00235     buffer_ptr_ = NULL;
00236     has_content = false;
00237 
00238     // The timeout length is not really important since we are looping anyway
00239     // until a new message is delivered.
00240     struct timeval tv;
00241     tv.tv_sec = 10;
00242     tv.tv_usec = 0;
00243 
00244     // Set the flags to return when the stream_ is ready to be read.
00245     fd_set readfds;
00246     FD_ZERO(&readfds);
00247     FD_SET(stream_, &readfds);
00248 
00249     int i = select(stream_+1, &readfds, NULL, NULL, &tv);
00250 
00251     // The stream_ died.
00252     if (i == 0) { return NULL; }
00253 
00254     // Read the message buffer.
00255     i = recv(stream_, msg_buffer_in_, kMaxMsgSize, 0);
00256 
00257     // Server quit (0) or error (-1).
00258     if (i <= 0) { return NULL; }
00259     msg_buffer_in_[i] = '\0';
00260     has_content = true;
00261 #ifdef _WIN32
00262     return strtok(msg_buffer_in_, "\n");
00263 #else
00264     // Setup a new string tokenizer.
00265     return strtok_r(msg_buffer_in_, "\n", &buffer_ptr_);
00266 #endif
00267   }
00268 }
00269 
00270 // Close the connection to the server.
00271 void SVNetwork::Close() {
00272 #ifdef _WIN32
00273   closesocket(stream_);
00274 #else
00275   close(stream_);
00276 #endif
00277 }
00278 
00279 
00280 // The program to invoke to start ScrollView
00281 static const char* ScrollViewProg() {
00282 #ifdef _WIN32
00283   const char* prog = "java -Xms512m -Xmx1024m";
00284 #else
00285   const char* prog = "sh";
00286 #endif
00287   return prog;
00288 }
00289 
00290 
00291 // The arguments to the program to invoke to start ScrollView
00292 static std::string ScrollViewCommand(std::string scrollview_path) {
00293   // The following ugly ifdef is to enable the output of the java runtime
00294   // to be sent down a black hole on non-windows to ignore all the
00295   // exceptions in piccolo. Ideally piccolo would be debugged to make
00296   // this unnecessary.
00297   // Also the path has to be separated by ; on windows and : otherwise.
00298 #ifdef _WIN32
00299   const char* cmd_template = "-Djava.library.path=%s -cp %s/ScrollView.jar;"
00300       "%s/piccolo2d-core-3.0.jar:%s/piccolo2d-extras-3.0.jar"
00301       " com.google.scrollview.ScrollView";
00302 #else
00303   const char* cmd_template = "-c \"trap 'kill %%1' 0 1 2 ; java "
00304       "-Xms1024m -Xmx2048m -Djava.library.path=%s -cp %s/ScrollView.jar:"
00305       "%s/piccolo2d-core-3.0.jar:%s/piccolo2d-extras-3.0.jar"
00306       " com.google.scrollview.ScrollView"
00307       " & wait\"";
00308 #endif
00309   int cmdlen = strlen(cmd_template) + 4*strlen(scrollview_path.c_str()) + 1;
00310   char* cmd = new char[cmdlen];
00311   const char* sv_path = scrollview_path.c_str();
00312   snprintf(cmd, cmdlen, cmd_template, sv_path, sv_path, sv_path, sv_path);
00313   std::string command(cmd);
00314   delete [] cmd;
00315   return command;
00316 }
00317 
00318 
00319 // Platform-independent freeaddrinfo()
00320 static void FreeAddrInfo(struct addrinfo* addr_info) {
00321   #if defined(__linux__)
00322   freeaddrinfo(addr_info);
00323   #else
00324   delete addr_info->ai_addr;
00325   delete addr_info;
00326   #endif
00327 }
00328 
00329 
00330 // Non-linux version of getaddrinfo()
00331 #if !defined(__linux__)
00332 static int GetAddrInfoNonLinux(const char* hostname, int port,
00333                                struct addrinfo** addr_info) {
00334 // Get the host data depending on the OS.
00335   struct sockaddr_in* address;
00336   *addr_info = new struct addrinfo;
00337   memset(*addr_info, 0, sizeof(struct addrinfo));
00338   address = new struct sockaddr_in;
00339   memset(address, 0, sizeof(struct sockaddr_in));
00340 
00341   (*addr_info)->ai_addr = (struct sockaddr*) address;
00342   (*addr_info)->ai_addrlen = sizeof(struct sockaddr);
00343   (*addr_info)->ai_family = AF_INET;
00344   (*addr_info)->ai_socktype = SOCK_STREAM;
00345 
00346   struct hostent *name;
00347 #ifdef _WIN32
00348   WSADATA wsaData;
00349   WSAStartup(MAKEWORD(1, 1), &wsaData);
00350   name = gethostbyname(hostname);
00351 #else
00352   name = gethostbyname(hostname);
00353 #endif
00354 
00355   if (name == NULL) {
00356     FreeAddrInfo(*addr_info);
00357     *addr_info = NULL;
00358     return -1;
00359   }
00360 
00361   // Fill in the appropriate variables to be able to connect to the server.
00362   address->sin_family = name->h_addrtype;
00363   memcpy((char *) &address->sin_addr.s_addr,
00364          name->h_addr_list[0], name->h_length);
00365   address->sin_port = htons(port);
00366   return 0;
00367 }
00368 #endif
00369 
00370 
00371 // Platform independent version of getaddrinfo()
00372 //   Given a hostname:port, produce an addrinfo struct
00373 static int GetAddrInfo(const char* hostname, int port,
00374                        struct addrinfo** address) {
00375 #if defined(__linux__)
00376   char port_str[40];
00377   snprintf(port_str, 40, "%d", port);
00378   return getaddrinfo(hostname, port_str, NULL, address);
00379 #else
00380   return GetAddrInfoNonLinux(hostname, port, address);
00381 #endif
00382 }
00383 
00384 
00385 // Set up a connection to a ScrollView on hostname:port.
00386 SVNetwork::SVNetwork(const char* hostname, int port) {
00387   mutex_send_ = new SVMutex();
00388   msg_buffer_in_ = new char[kMaxMsgSize + 1];
00389   msg_buffer_in_[0] = '\0';
00390 
00391   has_content = false;
00392   buffer_ptr_ = NULL;
00393 
00394   struct addrinfo *addr_info = NULL;
00395 
00396   if (GetAddrInfo(hostname, port, &addr_info) != 0) {
00397     std::cerr << "Error resolving name for ScrollView host "
00398               << std::string(hostname) << ":" << port << std::endl;
00399   }
00400 
00401   stream_ = socket(addr_info->ai_family, addr_info->ai_socktype,
00402                    addr_info->ai_protocol);
00403 
00404   // If server is not there, we will start a new server as local child process.
00405   if (connect(stream_, addr_info->ai_addr, addr_info->ai_addrlen) < 0) {
00406     const char* scrollview_path = getenv("SCROLLVIEW_PATH");
00407     if (scrollview_path == NULL) {
00408 #ifdef SCROLLVIEW_PATH
00409 #define _STR(a) #a
00410 #define _XSTR(a) _STR(a)
00411       scrollview_path = _XSTR(SCROLLVIEW_PATH);
00412 #undef _XSTR
00413 #undef _STR
00414 #else
00415       scrollview_path = ".";
00416 #endif
00417     }
00418     const char *prog = ScrollViewProg();
00419     std::string command = ScrollViewCommand(scrollview_path);
00420     SVSync::StartProcess(prog, command.c_str());
00421 
00422     // Wait for server to show up.
00423     // Note: There is no exception handling in case the server never turns up.
00424 
00425     stream_ = socket(addr_info->ai_family, addr_info->ai_socktype,
00426                    addr_info->ai_protocol);
00427 
00428     while (connect(stream_, addr_info->ai_addr,
00429                    addr_info->ai_addrlen) < 0) {
00430       std::cout << "ScrollView: Waiting for server...\n";
00431 #ifdef _WIN32
00432       Sleep(1000);
00433 #else
00434       sleep(1);
00435 #endif
00436 
00437       stream_ = socket(addr_info->ai_family, addr_info->ai_socktype,
00438                    addr_info->ai_protocol);
00439     }
00440   }
00441   FreeAddrInfo(addr_info);
00442 }
00443 
00444 SVNetwork::~SVNetwork() {
00445   delete[] msg_buffer_in_;
00446   delete mutex_send_;
00447 }
00448 
00449 #endif  // GRAPHICS_DISABLED
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines